@continuous-excellence/ze-great-dashboard-client 0.30.1 → 0.30.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index-B_h_VkbO.js","names":[],"sources":["../../../shared/dist/index.js","../../src/App.module.css","../../src/attention.ts","../../src/Diagnostics.module.css","../../src/Diagnostics.tsx","../../src/release-version.ts","../../src/dashboard-fetch.ts","../../src/browser-storage.ts","../../src/diagnostics-summary.ts","../../src/diagnostics.ts","../../src/AuthBoundary.module.css","../../src/oidc-manager.ts","../../src/OidcGate.tsx","../../src/PanelFrame.module.css","../../src/PanelPlaceholder.tsx","../../src/error-presentation.ts","../../src/HttpValuePanel.module.css","../../src/panel-layout.ts","../../src/panel-symbols.ts","../../src/PanelFrame.tsx","../../src/TimeAge.tsx","../../src/HttpValuePanel.tsx","../../src/PipelineAnimationDemoPanel.module.css","../../src/FallingShapesField.module.css","../../src/falling-shapes.ts","../../src/FallingShapesField.tsx","../../src/ReleaseTransitField.module.css","../../src/ReleaseTransitField.tsx","../../src/RunningField.module.css","../../src/SnowmanField.module.css","../../src/snowman-timing.ts","../../src/snowman.ts","../../src/snowman-canvas.ts","../../src/SnowmanField.tsx","../../src/StatusWeatherField.module.css","../../src/StatusWeatherField.tsx","../../src/PhasedProgressMarker.module.css","../../src/PhasedProgressMarker.tsx","../../src/TelemetryBloomField.module.css","../../src/TelemetryBloomField.tsx","../../src/RunningField.tsx","../../src/running-timing.ts","../../src/RunningFieldTiming.tsx","../../src/RunningProgress.module.css","../../src/RunningProgress.tsx","../../src/visual-seed.ts","../../src/PipelineAnimationDemoPanel.tsx","../../src/PipelinePanel.module.css","../../src/panel-status.ts","../../src/pipeline-activity.ts","../../src/PipelinePanel.tsx","../../src/PullRequestHealthPanel.module.css","../../src/panel-formatting.ts","../../src/pull-request-health.ts","../../src/PullRequestHealthPanel.tsx","../../src/panel-registry.tsx","../../src/SecurityNotice.module.css","../../src/SecurityNotice.tsx","../../src/UpdateActivity.module.css","../../src/update-activity.ts","../../src/update-activity-presentation.ts","../../src/UpdateActivity.tsx","../../src/useClientUpdate.ts","../../src/panel-diagnostics.ts","../../src/panel-memory.ts","../../src/panel-observation.ts","../../src/pipeline-reconciliation.ts","../../src/polling-panels.ts","../../src/polling-schedule.ts","../../src/pull-request-rollup.ts","../../src/usePanelSignals.ts","../../src/App.tsx","../../src/ConfigError.module.css","../../src/ConfigError.tsx","../../src/main.tsx"],"sourcesContent":["// packages/shared/src/board-config.ts\nimport { z as z2 } from \"zod\";\n\n// packages/shared/src/duration.ts\nimport { z } from \"zod\";\nvar DURATION_PATTERN = /^([1-9][0-9]*)(ms|s|m|h)$/;\nvar UNIT_MILLIS = {\n ms: 1,\n s: 1e3,\n m: 6e4,\n h: 36e5\n};\nfunction parseDuration(value) {\n const match = DURATION_PATTERN.exec(value);\n if (!match) return null;\n const [, rawAmount, rawUnit] = match;\n if (rawAmount === void 0 || rawUnit === void 0) return null;\n const amount = Number(rawAmount);\n if (amount <= 0) return null;\n return amount * UNIT_MILLIS[rawUnit];\n}\nvar durationSchema = z.string().regex(/^[1-9][0-9]*(?:ms|s|m|h)$/, {\n message: 'must be a positive duration like \"30s\", \"5m\", or \"1h\"'\n}).brand();\n\n// packages/shared/src/board-config.ts\nvar positionSchema = z2.union([\n z2.object({\n x: z2.number().int().min(0),\n y: z2.number().int().min(0),\n w: z2.number().int().min(1).max(12),\n h: z2.number().int().min(1)\n }),\n z2.object({ x: z2.literal(0), y: z2.literal(0), w: z2.literal(0), h: z2.literal(0) })\n]);\nvar panelDensities = [\"auto\", \"comfortable\", \"compact\"];\nvar panelDensitySchema = z2.enum(panelDensities);\nvar attentionTreatments = [\"beacon\", \"alarm\", \"steady\"];\nvar attentionTreatmentSchema = z2.enum(attentionTreatments);\nvar httpValueJsonPathSchema = z2.string().regex(/^\\$(?:\\.[A-Za-z_][A-Za-z0-9_]*|\\[\\d+\\])*$/, \"must be a simple JSON path\");\nvar httpValueFactSchema = z2.object({\n /** Stable address below the panel; labels and ordering may change without repointing it. */\n id: z2.string().min(1),\n label: z2.string().min(1),\n /** Public destination; the proxy continues to read only `url`. */\n link: z2.url().optional(),\n url: z2.url(),\n json_path: httpValueJsonPathSchema.optional()\n});\nvar httpValuePanelIdentitySchema = z2.object({\n id: z2.string().min(1),\n type: z2.literal(\"http-value\")\n});\nvar httpValueScalarPanelSchema = httpValuePanelIdentitySchema.extend({\n url: z2.url(),\n json_path: httpValueJsonPathSchema.optional(),\n link: z2.url().optional()\n});\nvar httpValueGroupedPanelSchema = httpValuePanelIdentitySchema.extend({\n facts: z2.array(httpValueFactSchema).min(1).max(4)\n});\nvar visibleRunningAnimations = [\n \"radial\",\n \"runway\",\n \"orbit\",\n \"signal-field\",\n \"telemetry-bloom\",\n \"release-transit\",\n \"status-weather\",\n \"falling-shapes\",\n \"snowman\"\n];\nvar runningAnimationSchema = z2.enum([...visibleRunningAnimations, \"off\"]);\nvar panelSchema = z2.looseObject({\n /** Presentation-only wall label. `id` remains the stable proxy and allowlist address. */\n label: z2.string().min(1).optional(),\n id: z2.string().min(1),\n type: z2.string().min(1),\n source: z2.string().min(1).optional(),\n pipeline: z2.union([z2.string(), z2.number()]).optional(),\n /** Resolved public source branch, supplied by the board endpoint for client memory scoping. */\n branch: z2.string().min(1).optional(),\n /** Content-density bias; position still controls the panel's explicit grid placement. */\n density: panelDensitySchema.optional(),\n /** Opt in to the board's presentation-only attention cue when this reading is unhealthy. */\n attention: z2.literal(true).optional(),\n /** Advisory in v1 — a panel without a position renders in config order rather than not at all. */\n position: positionSchema.optional(),\n refresh: durationSchema.optional(),\n /** Active pipeline runs are checked more often than normal panels. */\n running_refresh: durationSchema.optional(),\n /** Polling cadence around the estimated completion boundary. */\n running_completion_refresh: durationSchema.optional(),\n /** Maximum length of the tighter completion polling burst. */\n running_completion_window: durationSchema.optional(),\n /** Optional active-run treatment. Omitted selects a visible treatment at random. */\n running_animation: runningAnimationSchema.optional(),\n /** Local animation-demo cycle duration; ignored by other panel types. */\n demo_run_duration: durationSchema.optional(),\n /** Local animation-demo focused-review duration; ignored by other panel types. */\n demo_review_duration: durationSchema.optional(),\n /** A deliberate override only. Adapters derive links; hand-written ones drift. */\n link: z2.url().optional(),\n /** Source-agnostic endpoint used by the http-value signal. */\n url: z2.url().optional(),\n /** Small, deliberate JSON path subset: $.version, $.deployment.version, or $.response.docs[0].latestVersion. */\n json_path: httpValueJsonPathSchema.optional(),\n /** Up to four independently fetched source-agnostic readings in one visual panel. */\n facts: httpValueGroupedPanelSchema.shape.facts.optional()\n}).superRefine((panel, ctx) => {\n if (\"display\" in panel) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"display\"],\n message: \"display was removed; use density\",\n params: { constraint: \"display was removed; use density\" }\n });\n }\n if (panel.type !== \"http-value\") return;\n if (panel.facts) {\n if (panel.url !== void 0)\n ctx.addIssue({\n code: \"custom\",\n path: [\"url\"],\n message: \"use facts URLs for grouped panels\",\n params: { constraint: \"use facts URLs for grouped panels\" }\n });\n if (panel.json_path !== void 0)\n ctx.addIssue({\n code: \"custom\",\n path: [\"json_path\"],\n message: \"use facts json_path values for grouped panels\",\n params: { constraint: \"use facts json_path values for grouped panels\" }\n });\n const seen = /* @__PURE__ */ new Map();\n panel.facts.forEach((fact, index) => {\n const first = seen.get(fact.id);\n if (first === void 0) seen.set(fact.id, index);\n else\n ctx.addIssue({\n code: \"custom\",\n path: [\"facts\", index, \"id\"],\n message: `duplicate fact id \"${fact.id}\" (already used by fact at index ${first})`,\n params: { constraint: \"Use a unique fact id within this panel.\" }\n });\n });\n }\n});\nvar githubAppSchema = z2.object({\n app_id_env: z2.string().min(1),\n private_key_env: z2.string().min(1),\n installation_id_env: z2.string().min(1)\n});\nvar sourceAuthenticationSchema = {\n /** Credentials are never in the config — only the name of the env var holding one. */\n token_env: z2.string().min(1).optional(),\n github_app: githubAppSchema.optional()\n};\nfunction exactlyOneGithubAuthenticationMode(source, ctx) {\n if (source.token_env && source.github_app)\n ctx.addIssue({\n code: \"custom\",\n message: \"configure token_env or github_app, not both\",\n params: { constraint: \"configure token_env or github_app, not both\" }\n });\n}\nvar githubActionsSourceSchema = z2.looseObject({\n type: z2.literal(\"github-actions\"),\n repo: z2.string().regex(/^[^/\\s]+\\/[^/\\s]+$/, \"must be an owner/repository pair\"),\n /** The branch whose workflow health the dashboard represents. */\n branch: z2.string().min(1).optional(),\n ...sourceAuthenticationSchema\n}).superRefine(exactlyOneGithubAuthenticationMode);\nvar azureDevOpsSourceSchema = z2.looseObject({\n type: z2.literal(\"azure-devops\"),\n /** Azure DevOps organization name, used as one URL path segment. */\n organization: z2.string().regex(/^[^/\\s]+$/, \"must be an organization name\"),\n project: z2.string().min(1),\n /** The branch whose build health the dashboard represents. */\n branch: z2.string().min(1).optional(),\n /** A PAT environment variable. The adapter sends it with Basic authentication. */\n token_env: z2.string().min(1).optional(),\n /** An environment variable naming a local, short-lived delegated-token file. */\n entra_token_file_env: z2.string().min(1).optional()\n}).superRefine((source, ctx) => {\n if (source.token_env && source.entra_token_file_env) {\n ctx.addIssue({\n code: \"custom\",\n message: \"configure token_env or entra_token_file_env, not both\",\n params: { constraint: \"configure token_env or entra_token_file_env, not both\" }\n });\n }\n if (!source.token_env && !source.entra_token_file_env) {\n ctx.addIssue({\n code: \"custom\",\n message: \"configure token_env or entra_token_file_env\",\n params: { constraint: \"configure token_env or entra_token_file_env\" }\n });\n }\n});\nvar gitlabInstanceUrlSchema = z2.url().superRefine((value, ctx) => {\n const url = new URL(value);\n if (url.protocol !== \"https:\")\n ctx.addIssue({\n code: \"custom\",\n message: \"must be an HTTPS GitLab instance URL\",\n params: { constraint: \"must be an HTTPS GitLab instance URL\" }\n });\n if (url.username || url.password)\n ctx.addIssue({\n code: \"custom\",\n message: \"must not include credentials\",\n params: { constraint: \"must not include credentials\" }\n });\n if (url.search)\n ctx.addIssue({\n code: \"custom\",\n message: \"must not include a query string\",\n params: { constraint: \"must not include a query string\" }\n });\n if (url.hash)\n ctx.addIssue({\n code: \"custom\",\n message: \"must not include a fragment\",\n params: { constraint: \"must not include a fragment\" }\n });\n});\nvar gitlabCiSourceSchema = z2.looseObject({\n type: z2.literal(\"gitlab-ci\"),\n /** GitLab project path, including any nested groups. */\n project: z2.string().regex(/^[^/\\s]+(?:\\/[^/\\s]+)+$/, \"must be a namespace/project path\"),\n /** A GitLab personal, project, or group access-token environment variable. */\n token_env: z2.string().min(1),\n /** The branch or tag whose newest pipeline the dashboard represents. */\n branch: z2.string().min(1).optional(),\n /** HTTPS GitLab.com or a self-managed instance, optionally below a path prefix. */\n url: gitlabInstanceUrlSchema.optional().default(\"https://gitlab.com\")\n});\nvar sourceSchema = z2.looseObject({ type: z2.string().min(1), ...sourceAuthenticationSchema }).superRefine(exactlyOneGithubAuthenticationMode);\nfunction credentialEnvironmentNames(source) {\n const githubApp = githubAppSchema.safeParse(source.github_app);\n return [\n ...source.token_env ? [source.token_env] : [],\n ...githubApp.success ? [\n githubApp.data.app_id_env,\n githubApp.data.private_key_env,\n githubApp.data.installation_id_env\n ] : []\n ];\n}\nvar boardSchema = z2.object({\n refresh: durationSchema.optional(),\n running_refresh: durationSchema.optional(),\n running_completion_refresh: durationSchema.optional(),\n running_completion_window: durationSchema.optional(),\n /** One board-wide treatment keeps simultaneous important failures unambiguous. */\n attention: z2.object({ treatment: attentionTreatmentSchema }).optional(),\n panels: z2.array(panelSchema).min(1).superRefine((panels, ctx) => {\n const seen = /* @__PURE__ */ new Map();\n panels.forEach((panel, index) => {\n const firstIndex = seen.get(panel.id);\n if (firstIndex === void 0) {\n seen.set(panel.id, index);\n return;\n }\n ctx.addIssue({\n code: \"custom\",\n path: [index, \"id\"],\n message: `duplicate panel id \"${panel.id}\" (already used by panel at index ${firstIndex})`,\n params: { constraint: \"Use a unique panel id within this board.\" }\n });\n });\n })\n}).superRefine((board, ctx) => {\n if (board.panels.some((panel) => panel.attention) && !board.attention)\n ctx.addIssue({\n code: \"custom\",\n path: [\"attention\"],\n message: \"configure attention.treatment when one or more panels opt into attention\",\n params: { constraint: \"Important panels require one board attention treatment.\" }\n });\n});\nvar authSchema = z2.strictObject({\n issuer: z2.url(),\n /** Browser SPA client id. It is public, unlike every source credential. */\n client_id: z2.string().min(1),\n /** The separately registered API resource accepted by the dashboard proxy. */\n audience: z2.string().min(1),\n /** A deliberately portable, explicit identity boundary for the first direct-OIDC release. */\n allow: z2.strictObject({ subjects: z2.array(z2.string().min(1)).min(1) })\n});\nvar securityPolicies = [\"warn\", \"required\", \"unsecured\"];\nvar securityPolicySchema = z2.enum(securityPolicies);\nvar boardConfigSchema = z2.object({\n sources: z2.record(z2.string().min(1), sourceSchema).default({}),\n boards: z2.record(z2.string().min(1), boardSchema),\n auth: authSchema.optional(),\n security: securityPolicySchema.optional()\n}).superRefine((config, ctx) => {\n if (config.security === \"unsecured\" && config.auth) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"security\"],\n message: \"security: unsecured cannot be combined with auth\",\n params: { constraint: \"Remove auth or select warn or required.\" }\n });\n }\n for (const [sourceName, source] of Object.entries(config.sources)) {\n const sourceSchema2 = source.type === \"azure-devops\" ? azureDevOpsSourceSchema : source.type === \"gitlab-ci\" ? gitlabCiSourceSchema : void 0;\n if (!sourceSchema2) continue;\n const parsedSource = sourceSchema2.safeParse(source);\n if (!parsedSource.success) {\n for (const issue of parsedSource.error.issues) {\n ctx.addIssue({\n ...issue,\n path: [\"sources\", sourceName, ...issue.path]\n });\n }\n }\n }\n for (const [boardName, board] of Object.entries(config.boards)) {\n board.panels.forEach((panel, panelIndex) => {\n const source = panel.source ? config.sources[panel.source] : void 0;\n if (panel.type !== \"pipeline-status\" || source?.type !== \"azure-devops\") return;\n if (typeof panel.pipeline !== \"number\" || !Number.isInteger(panel.pipeline) || panel.pipeline <= 0) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"boards\", boardName, \"panels\", panelIndex, \"pipeline\"],\n message: \"Azure DevOps pipeline-status panels require a positive numeric pipeline definition id\",\n params: {\n constraint: \"Provide a positive numeric Azure DevOps pipeline definition id.\"\n }\n });\n }\n });\n }\n});\nvar boardConfigRuntimeRules = [\n {\n category: \"yaml-modeline-and-schema-version\",\n description: \"YAML parsing and a first-line modeline that names the selected release schema.\"\n },\n {\n category: \"unique-panel-and-fact-ids\",\n description: \"Panel IDs are unique within a board and fact IDs are unique within a panel.\"\n },\n {\n category: \"cross-field-configuration\",\n description: \"Mutually exclusive and paired fields, including grouped HTTP value fields and credential modes.\"\n },\n {\n category: \"panel-source-relationships\",\n description: \"Panel/source compatibility and source-specific requirements.\"\n },\n {\n category: \"panel-admission-and-bounded-adapter-operations\",\n description: \"Supported panel admission and the proxy operations each adapter is permitted to perform.\"\n },\n {\n category: \"environment-and-external-availability\",\n description: \"Environment-selected boards, credential resolution, and availability of external services.\"\n }\n];\nfunction boardConfigJsonSchema() {\n return {\n ...z2.toJSONSchema(boardConfigSchema, { target: \"draft-2020-12\" }),\n $id: \"board-config.schema.json\",\n title: \"Ze Great Dashboard board configuration\",\n \"x-dashboard-runtime-rules\": boardConfigRuntimeRules.map((rule) => ({ ...rule }))\n };\n}\nfunction serializeBoardConfigJsonSchema() {\n return `${JSON.stringify(boardConfigJsonSchema(), null, 2)}\n`;\n}\nfunction resolveRefreshMillis(args) {\n const requested = args.panelOverrideMillis ?? args.boardDefaultMillis;\n return Math.max(requested, args.adapterFloorMillis);\n}\n\n// packages/shared/src/board-config-modeline.ts\nvar MODEL_LINE = /^# yaml-language-server:\\s*\\$schema=(\\S+)\\s*$/;\nvar SCHEMA_FILE = \"board-config.schema.json\";\nfunction schemaUrlForAssetPath(assetPath) {\n return `${assetPath.replace(/\\/+$/, \"\")}/${SCHEMA_FILE}`;\n}\nfunction readBoardSchemaModeline(source, expectedSchemaUrl) {\n const line = source.split(/\\r?\\n/)[0];\n if (!line?.includes(\"yaml-language-server\"))\n throw new Error(\n `Board configuration must include a ${SCHEMA_FILE} modeline. Add this as the first line:\n# yaml-language-server: $schema=${expectedSchemaUrl ?? `https://<asset-host>/dashboard/<release-version>/${SCHEMA_FILE}`}`\n );\n const match = MODEL_LINE.exec(line);\n if (!match?.[1]) {\n throw new Error(\n `Malformed board schema modeline; expected \"# yaml-language-server: $schema=<URL>/${SCHEMA_FILE}\"`\n );\n }\n let url;\n try {\n url = new URL(match[1]);\n } catch {\n throw new Error(`Malformed board schema modeline; schema URL is not a valid URL: ${match[1]}`);\n }\n if (![\"http:\", \"https:\"].includes(url.protocol) || !url.pathname.endsWith(`/${SCHEMA_FILE}`)) {\n throw new Error(`Malformed board schema modeline; URL must end in /${SCHEMA_FILE}: ${match[1]}`);\n }\n return match[1];\n}\nfunction boardSchemaModeline(url) {\n return `# yaml-language-server: $schema=${url}`;\n}\nvar boardSchemaFileName = SCHEMA_FILE;\n\n// packages/shared/src/client-env.ts\nimport { z as z3 } from \"zod\";\nvar clientSecurityStates = [\"warning\", \"blocked\"];\nvar clientSecurityStateSchema = z3.enum(clientSecurityStates);\nvar clientEnvSchema = z3.object({\n /** Where the immutable client assets live. The one variable that repoints the whole client. */\n assetPath: z3.string().min(1),\n /** Opaque SHA-256 fingerprint of the canonical asset path, for diagnostic correlation only. */\n assetPathId: z3.string().regex(/^sha256:[a-f0-9]{64}$/),\n /** Same-origin path the proxy is mounted at, so there is no CORS and no cookie problem. */\n proxyPath: z3.string().min(1),\n /** Which board this is, resolved server-side so the client parses no URLs. */\n board: z3.string().min(1),\n /** Omitted entirely when unauthenticated — presence is what turns auth on. */\n auth: z3.object({\n issuer: z3.string().min(1),\n clientId: z3.string().min(1),\n audience: z3.string().min(1)\n }).optional(),\n /** Public deployment posture; it contains no board, source, or credential details. */\n security: clientSecurityStateSchema.optional()\n});\nvar clientIdentityResponseSchema = clientEnvSchema.pick({ assetPath: true, assetPathId: true }).extend({ serverVersion: z3.string().min(1) });\nfunction readClientEnv(source = globalThis.window?.env) {\n const result = clientEnvSchema.safeParse(source);\n if (!result.success) {\n throw new Error(\n `window.env is missing or invalid \\u2014 the server did not inject usable configuration.\n${z3.prettifyError(result.error)}`\n );\n }\n return result.data;\n}\n\n// packages/shared/src/envelope.ts\nimport { z as z4 } from \"zod\";\nvar errorKindSchema = z4.enum([\n \"unreachable\",\n \"unauthorized\",\n \"not-found\",\n \"no-runs\",\n \"upstream-error\"\n]);\nvar envelopeErrorSchema = z4.object({\n kind: errorKindSchema,\n message: z4.string()\n});\nvar envelopeSchema = z4.discriminatedUnion(\"state\", [\n z4.object({\n panelId: z4.string().min(1),\n state: z4.literal(\"ok\"),\n /** From the upstream response `Date`. A cached value must never be shown without its age. */\n observedAt: z4.iso.datetime(),\n /** Adapter-derived. The authority for this panel; the dashboard itself asserts nothing. */\n link: z4.url().nullable(),\n signal: z4.unknown()\n }),\n z4.object({\n panelId: z4.string().min(1),\n state: z4.literal(\"error\"),\n /**\n * Populated even on error: knowing *when* a failure was observed is the difference between\n * \"broken just now\" and \"broken all morning\", and a panel that can't reach its source is\n * exactly when a viewer most wants to click through.\n */\n observedAt: z4.iso.datetime(),\n link: z4.url().nullable(),\n error: envelopeErrorSchema\n })\n]);\nvar pipelineActivitySchema = z4.object({\n kind: z4.enum([\"job\", \"stage\", \"step\"]),\n name: z4.string().min(1),\n parent: z4.string().min(1).optional()\n});\nvar pipelineStatusSchema = z4.object({\n type: z4.literal(\"pipeline-status\"),\n status: z4.enum([\"passed\", \"failed\", \"warning\", \"running\", \"cancelled\", \"unknown\"]),\n /** The source's unmodified status/result vocabulary, for an honest display. */\n rawStatus: z4.string(),\n name: z4.string().min(1),\n /** The branch represented by this status, when the upstream supplies or filters by one. */\n branch: z4.string().min(1).optional(),\n /** Elapsed execution time, supplied only after the upstream run has completed. */\n durationMs: z4.number().int().nonnegative().optional(),\n /** When an active run began, so the client can advance its elapsed display between polls. */\n runStartedAt: z4.iso.datetime().optional(),\n /** Stable source-run identity, when the adapter provides one. */\n sourceRunId: z4.string().min(1).optional(),\n /** Best-effort live work detail; adapters may describe a job, stage, or step. */\n activity: pipelineActivitySchema.optional(),\n /** Advisory duration from recent completed runs remembered by this browser. */\n estimatedDurationMs: z4.number().int().positive().optional(),\n /** When this workflow run was last updated by its source, distinct from our observation time. */\n sourceUpdatedAt: z4.iso.datetime().optional()\n});\nvar pipelineStatusPriorities = {\n passed: 0,\n cancelled: 1,\n unknown: 2,\n running: 3,\n warning: 4,\n failed: 5\n};\nfunction pipelineStatusPriority(status) {\n return pipelineStatusPriorities[status];\n}\nvar pullRequestHealthItemSchema = z4.object({\n label: z4.string().min(1),\n status: pipelineStatusSchema.shape.status,\n detail: z4.string().min(1),\n link: z4.url().nullable()\n});\nvar pullRequestHealthSchema = z4.object({\n type: z4.literal(\"pull-request-health\"),\n status: pipelineStatusSchema.shape.status,\n summary: z4.string().min(1),\n workflows: z4.array(pullRequestHealthItemSchema),\n pullRequests: z4.array(pullRequestHealthItemSchema),\n /** Missing component reads remain visible even when the evidence we did get is reassuring. */\n incompleteObservations: z4.array(z4.object({ label: z4.string().min(1), message: z4.string().min(1) })).optional(),\n /** The latest component reading, disclosed beside the oldest aggregate evidence. */\n newestObservedAt: z4.iso.datetime().optional()\n});\nvar pullRequestCandidateSchema = z4.object({\n number: z4.number().int().positive(),\n branch: z4.string().min(1),\n link: z4.url()\n});\nvar pullRequestCandidatesSchema = z4.object({\n type: z4.literal(\"pull-request-candidates\"),\n pullRequests: z4.array(pullRequestCandidateSchema),\n /** GitHub's first page is a deliberate bounded observation, not proof that no later PR exists. */\n truncated: z4.boolean().optional()\n});\nvar pullRequestWorkflowObservationSchema = z4.object({\n type: z4.literal(\"pull-request-workflow\"),\n workflow: z4.string().min(1),\n item: pullRequestHealthItemSchema\n});\nvar pullRequestBuildObservationSchema = z4.object({\n type: z4.literal(\"pull-request-build\"),\n branch: z4.string().min(1),\n item: pullRequestHealthItemSchema\n});\nvar httpValueSchema = z4.object({\n type: z4.literal(\"http-value\"),\n value: z4.union([z4.string(), z4.number(), z4.boolean()])\n});\n\n// packages/shared/src/layout.ts\nvar columnCount = 12;\nvar rowCount = 12;\nfunction analyzeBoardLayout(panels) {\n const issues = panels.flatMap((panel) => {\n if (!panel.position || isZeroPosition(panel.position) || isPositionInCanvas(panel.position))\n return [];\n return [\n {\n panelId: panel.id,\n kind: \"out-of-bounds\",\n position: panel.position,\n conflictsWith: []\n }\n ];\n });\n const overlapIssues = /* @__PURE__ */ new Map();\n for (let leftIndex = 0; leftIndex < panels.length; leftIndex++) {\n const left = panels[leftIndex];\n if (!left?.position || isZeroPosition(left.position)) continue;\n for (let rightIndex = leftIndex + 1; rightIndex < panels.length; rightIndex++) {\n const right = panels[rightIndex];\n if (!right?.position || isZeroPosition(right.position)) continue;\n if (!overlaps(left.position, right.position)) continue;\n const key = `${right.id}\\0overlap`;\n const issue = overlapIssues.get(key);\n if (issue) issue.conflictsWith.push(left.id);\n else {\n const nextIssue = {\n panelId: right.id,\n kind: \"overlap\",\n position: right.position,\n conflictsWith: [left.id]\n };\n overlapIssues.set(key, nextIssue);\n issues.push(nextIssue);\n }\n }\n }\n return { issues };\n}\nfunction normalizeBoardLayout(panels) {\n const positioned = panels.flatMap((panel) => {\n if (!panel.position || isZeroPosition(panel.position)) return [];\n return [{ ...panel.position, panelId: panel.id }];\n });\n if (positioned.length === 0) return panels.map((panel) => ({ ...panel }));\n const minX = Math.min(...positioned.map((rectangle) => rectangle.x));\n const minY = Math.min(...positioned.map((rectangle) => rectangle.y));\n const maxX = Math.max(...positioned.map((rectangle) => rectangle.x + rectangle.w));\n const maxY = Math.max(...positioned.map((rectangle) => rectangle.y + rectangle.h));\n const scaleX = maxX - minX > columnCount ? columnCount / (maxX - minX) : 1;\n const scaleY = maxY - minY > rowCount ? rowCount / (maxY - minY) : 1;\n const accepted = [];\n return panels.map((panel) => {\n const position = panel.position;\n if (!position || isZeroPosition(position)) return { ...panel };\n const desired = scaleRectangle(position, minX, minY, scaleX, scaleY);\n const legal = nearestLegalRectangle(desired, accepted);\n if (!legal) return { ...panel, position: zeroPosition };\n accepted.push({ ...legal, panelId: panel.id });\n return { ...panel, position: legal };\n });\n}\nfunction isZeroPosition(position) {\n return position?.x === 0 && position.y === 0 && position.w === 0 && position.h === 0;\n}\nvar zeroPosition = { x: 0, y: 0, w: 0, h: 0 };\nfunction isPositionInCanvas(position) {\n return !isZeroPosition(position) && position.x + position.w <= columnCount && position.y + position.h <= rowCount;\n}\nfunction overlaps(left, right) {\n return left.x < right.x + right.w && left.x + left.w > right.x && left.y < right.y + right.h && left.y + left.h > right.y;\n}\nfunction scaleRectangle(position, minX, minY, scaleX, scaleY) {\n const x = scaleCoordinate(position.x, minX, scaleX);\n const y = scaleCoordinate(position.y, minY, scaleY);\n const right = scaleCoordinate(position.x + position.w, minX, scaleX);\n const bottom = scaleCoordinate(position.y + position.h, minY, scaleY);\n return {\n x,\n y,\n w: Math.max(1, right - x),\n h: Math.max(1, bottom - y)\n };\n}\nfunction scaleCoordinate(value, origin, scale) {\n return Math.round((value - origin) * scale);\n}\nfunction nearestLegalRectangle(desired, accepted) {\n const candidates = [];\n for (let width = desired.w; width >= 1; width--) {\n for (let height = desired.h; height >= 1; height--) {\n const shrink = desired.w - width + (desired.h - height);\n for (let y = 0; y <= rowCount - height; y++) {\n for (let x = 0; x <= columnCount - width; x++) {\n const candidate2 = { x, y, w: width, h: height };\n if (accepted.some((rectangle) => overlaps(candidate2, rectangle))) continue;\n candidates.push({\n ...candidate2,\n shrink,\n distance: Math.abs(x - desired.x) + Math.abs(y - desired.y)\n });\n }\n }\n }\n }\n candidates.sort(\n (left, right) => left.shrink - right.shrink || left.distance - right.distance || left.y - right.y || left.x - right.x\n );\n const [candidate] = candidates;\n if (!candidate) return void 0;\n return { x: candidate.x, y: candidate.y, w: candidate.w, h: candidate.h };\n}\n\n// packages/shared/src/polling-policy.ts\nvar pollingDefaults = {\n refreshMillis: 6e4,\n runningRefreshMillis: 15e3,\n runningCompletionRefreshMillis: 5e3,\n runningCompletionWindowMillis: 12e4\n};\nfunction resolvePollingSettings(board, panel) {\n const duration = (value, fallback) => parseDuration(value ?? \"\") ?? fallback;\n const panelValue = (key, boardValue, fallback) => duration(panel[key], duration(board[boardValue], fallback));\n return {\n refreshMillis: panelValue(\"refresh\", \"refresh\", pollingDefaults.refreshMillis),\n runningRefreshMillis: panelValue(\n \"running_refresh\",\n \"running_refresh\",\n pollingDefaults.runningRefreshMillis\n ),\n runningCompletionRefreshMillis: panelValue(\n \"running_completion_refresh\",\n \"running_completion_refresh\",\n pollingDefaults.runningCompletionRefreshMillis\n ),\n runningCompletionWindowMillis: panelValue(\n \"running_completion_window\",\n \"running_completion_window\",\n pollingDefaults.runningCompletionWindowMillis\n )\n };\n}\nexport {\n analyzeBoardLayout,\n attentionTreatmentSchema,\n attentionTreatments,\n authSchema,\n azureDevOpsSourceSchema,\n boardConfigJsonSchema,\n boardConfigRuntimeRules,\n boardConfigSchema,\n boardSchema,\n boardSchemaFileName,\n boardSchemaModeline,\n clientEnvSchema,\n clientIdentityResponseSchema,\n clientSecurityStateSchema,\n clientSecurityStates,\n credentialEnvironmentNames,\n durationSchema,\n envelopeSchema,\n errorKindSchema,\n githubActionsSourceSchema,\n githubAppSchema,\n gitlabCiSourceSchema,\n httpValueFactSchema,\n httpValueGroupedPanelSchema,\n httpValueScalarPanelSchema,\n httpValueSchema,\n isZeroPosition,\n normalizeBoardLayout,\n panelDensities,\n panelDensitySchema,\n panelSchema,\n parseDuration,\n pipelineActivitySchema,\n pipelineStatusPriority,\n pipelineStatusSchema,\n pollingDefaults,\n positionSchema,\n pullRequestBuildObservationSchema,\n pullRequestCandidateSchema,\n pullRequestCandidatesSchema,\n pullRequestHealthSchema,\n pullRequestWorkflowObservationSchema,\n readBoardSchemaModeline,\n readClientEnv,\n resolvePollingSettings,\n resolveRefreshMillis,\n runningAnimationSchema,\n schemaUrlForAssetPath,\n securityPolicies,\n securityPolicySchema,\n serializeBoardConfigJsonSchema,\n sourceSchema,\n visibleRunningAnimations\n};\n",".board {\n display: flex;\n flex-direction: column;\n gap: var(--gap);\n height: 100dvh;\n min-height: 0;\n padding: var(--gap);\n overflow-x: hidden;\n overflow-y: auto;\n}\n.header {\n display: flex;\n align-items: baseline;\n border-bottom: 1px solid var(--edge);\n padding-bottom: var(--gap);\n flex: 0 0 auto;\n}\n.attentionRail {\n display: flex;\n align-items: flex-start;\n gap: 0.45em;\n margin-inline-start: auto;\n padding: 0.35em 0.55em;\n border: 0.14rem solid var(--status-critical);\n border-radius: var(--radius);\n color: var(--ink-primary);\n background: var(--surface-raised);\n font-size: 0.7em;\n line-height: 1.3;\n}\n.attentionRail ul {\n margin: 0;\n padding-left: 1.1em;\n}\n.attentionRail a {\n color: inherit;\n text-decoration-color: var(--status-critical);\n}\n.attentionRail a:focus-visible {\n outline: 0.14rem solid var(--ink-primary);\n outline-offset: 0.12rem;\n}\n.attentionGlyph {\n color: var(--status-critical);\n}\n.attention-beacon {\n outline: 0.16rem solid var(--status-critical);\n outline-offset: -0.16rem;\n animation: attention-beacon 1.8s ease-in-out infinite;\n}\n.attention-alarm {\n outline: 0.22rem solid var(--status-critical);\n outline-offset: -0.22rem;\n animation: attention-alarm 0.75s steps(2, jump-none) infinite;\n}\n.attention-alarm .attentionRail {\n background: color-mix(in srgb, var(--status-critical) 18%, var(--surface-raised));\n}\n.attention-steady {\n outline: 0.22rem solid var(--status-critical);\n outline-offset: -0.22rem;\n}\n@keyframes attention-beacon {\n 50% {\n outline-color: var(--status-serious);\n }\n}\n@keyframes attention-alarm {\n 50% {\n outline-color: var(--ink-primary);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .attention-beacon,\n .attention-alarm {\n animation: none;\n outline: 0.22rem solid var(--status-critical);\n outline-offset: -0.22rem;\n }\n}\n.title {\n margin: 0;\n font-size: 1.75em;\n font-weight: 650;\n letter-spacing: -0.01em;\n}\n.grid {\n display: grid;\n grid-template-columns: repeat(12, minmax(0, 1fr));\n grid-template-rows: repeat(12, minmax(0, 1fr));\n grid-auto-rows: minmax(0, 1fr);\n gap: var(--gap);\n flex: 1;\n min-height: 0;\n align-content: stretch;\n}\n.footerTools {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n.layoutWarning {\n position: relative;\n}\n.layoutWarningButton {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.2em;\n min-width: 2em;\n min-height: 2em;\n border: 1px solid var(--status-warning);\n border-radius: 50%;\n color: var(--status-warning);\n background: var(--surface-raised);\n font: inherit;\n cursor: pointer;\n}\n.layoutWarningButton:hover,\n.layoutWarningButton:focus-visible {\n background: var(--surface);\n}\n.layoutWarningDialog {\n position: absolute;\n z-index: 10;\n right: 0;\n bottom: calc(100% + 0.75rem);\n width: min(32rem, calc(100vw - 2 * var(--gap)));\n padding: 0.8rem;\n border: 1px solid var(--status-warning);\n border-radius: var(--radius);\n color: var(--ink-secondary);\n background: var(--surface-raised);\n box-shadow: 0 0.5rem 1.5rem rgb(0 0 0 / 35%);\n}\n.layoutWarningHeading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 1rem;\n}\n.layoutWarningHeading strong {\n color: var(--status-warning);\n}\n.layoutWarningDialog p {\n margin: 0.6rem 0;\n}\n.layoutWarningDialog ul {\n margin: 0.35rem 0 0.75rem;\n padding-left: 1.25rem;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 0.85em;\n}\n.layoutWarningClose {\n border: 0;\n color: var(--ink-muted);\n background: transparent;\n font-size: 1.25em;\n line-height: 1;\n cursor: pointer;\n}\n.layoutWarningDownloads {\n display: grid;\n gap: 0.35rem;\n}\n.layoutWarningDownloads button {\n border: 1px solid var(--edge);\n border-radius: 0.25rem;\n background: var(--surface-raised);\n color: var(--ink-secondary);\n font: inherit;\n padding: 0.3em 0.55em;\n text-align: center;\n text-decoration: none;\n}\n.layoutWarningDownloads button:hover,\n.layoutWarningDownloads button:focus-visible {\n border-color: var(--ink-secondary);\n color: var(--ink-primary);\n}\n.layoutWarningNote {\n color: var(--ink-muted);\n font-size: 0.85em;\n}\n.footer {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n color: var(--ink-muted);\n font-size: 0.75em;\n flex: 0 0 auto;\n}\n@media (max-width: 64rem) {\n .board {\n height: auto;\n min-height: 100dvh;\n overflow: visible;\n }\n .grid {\n grid-template-columns: 1fr;\n grid-template-rows: none;\n grid-auto-rows: auto;\n flex: 0 0 auto;\n min-height: auto;\n }\n .header {\n align-items: flex-start;\n flex-direction: column;\n }\n .attentionRail {\n margin-inline-start: 0;\n }\n .layoutWarningDialog {\n position: fixed;\n right: var(--gap);\n bottom: calc(var(--gap) + 3rem);\n }\n}\n","import {\n type Board,\n type Envelope,\n httpValueSchema,\n pipelineStatusSchema,\n pullRequestHealthSchema,\n} from '@ze-great-dashboard/shared'\nimport type { HttpValueFactObservation, PanelUpdateHealth } from './panel-props.ts'\n\nexport type AttentionDriver = {\n panelId: string\n label: string\n reason: string\n factId?: string\n}\n\n/**\n * Projects only public, already-rendered evidence into the board's opt-in attention rail.\n * It intentionally never infers a source condition from loading, warning, or unknown states.\n */\nexport function projectAttention(args: {\n board: Board | undefined\n signals: Record<string, Envelope | undefined>\n updateHealth: Record<string, PanelUpdateHealth | undefined>\n factSignals: Record<string, Record<string, HttpValueFactObservation | undefined> | undefined>\n}): AttentionDriver[] {\n if (!args.board?.attention) return []\n return args.board.panels.flatMap((panel) => {\n if (!panel.attention) return []\n const label = panel.label ?? panel.id\n if (panel.type === 'http-value' && panel.facts)\n return panel.facts.flatMap((fact) => {\n const observation = args.factSignals[panel.id]?.[fact.id]\n const reason = unreadableFactReason(observation)\n return reason\n ? [{ panelId: panel.id, label, reason: `${fact.label}: ${reason}`, factId: fact.id }]\n : []\n })\n const reason = unreadablePanelReason(\n panel.type,\n args.signals[panel.id],\n args.updateHealth[panel.id],\n )\n return reason ? [{ panelId: panel.id, label, reason }] : []\n })\n}\n\nfunction unreadableFactReason(observation: HttpValueFactObservation | undefined) {\n if (observation?.failure) return `Updates unavailable — ${observation.failure}`\n if (observation?.updateHealth) return `Updates unavailable — ${observation.updateHealth.message}`\n if (!observation?.envelope) return undefined\n if (observation.envelope.state === 'error') return observation.envelope.error.message\n return httpValueSchema.safeParse(observation.envelope.signal).success\n ? undefined\n : 'Invalid value'\n}\n\nfunction unreadablePanelReason(\n type: string,\n envelope: Envelope | undefined,\n updateHealth: PanelUpdateHealth | undefined,\n) {\n if (updateHealth) return `Updates unavailable — ${updateHealth.message}`\n if (!envelope) return undefined\n if (envelope.state === 'error') return envelope.error.message\n if (type === 'pipeline-status') {\n const signal = pipelineStatusSchema.safeParse(envelope.signal)\n if (!signal.success) return 'Invalid signal'\n return signal.data.status === 'failed' ? 'Pipeline failed' : undefined\n }\n if (type === 'pull-request-health') {\n const signal = pullRequestHealthSchema.safeParse(envelope.signal)\n if (!signal.success) return 'Invalid signal'\n if (signal.data.status === 'failed') return signal.data.summary\n const missing = signal.data.incompleteObservations?.[0]\n return missing ? `${missing.label}: ${missing.message}` : undefined\n }\n if (type === 'http-value')\n return httpValueSchema.safeParse(envelope.signal).success ? undefined : 'Invalid value'\n return undefined\n}\n",".diagnostics {\n position: relative;\n}\n\n.button {\n border: 1px solid var(--edge);\n border-radius: 0.25rem;\n background: var(--surface-raised);\n color: var(--ink-secondary);\n font: inherit;\n padding: 0.3em 0.55em;\n}\n\n.area {\n position: absolute;\n z-index: 1;\n right: 0;\n bottom: calc(100% + 0.5rem);\n width: min(24rem, 90vw);\n padding: 0.75rem;\n border: 1px solid var(--edge);\n border-radius: var(--radius);\n background: var(--surface-raised);\n box-shadow: 0 0.5rem 1.5rem #0008;\n}\n\n.area p {\n margin: 0 0 0.5rem;\n}\n\n.warning {\n color: var(--status-warning);\n}\n\n.panels {\n max-height: 12rem;\n overflow-y: auto;\n border-top: 1px solid var(--edge);\n margin: 0.5rem 0;\n padding-top: 0.5rem;\n}\n\n.actions {\n display: flex;\n gap: 0.5rem;\n}\n","import { useState, useSyncExternalStore } from 'react'\nimport styles from './Diagnostics.module.css'\nimport type { BrowserDiagnosticStore } from './diagnostics.ts'\nimport type { UpdateActivitySnapshot } from './update-activity.ts'\n\nexport function Diagnostics({\n log,\n updateActivity,\n}: {\n log: BrowserDiagnosticStore\n updateActivity?: () => UpdateActivitySnapshot\n}) {\n const [open, setOpen] = useState(false)\n useSyncExternalStore(log.subscribe, log.snapshot, log.snapshot)\n const count = log.count()\n const githubConsistencyIncidents = log.githubConsistencyIncidentCount()\n const summary = log.summary()\n const download = () => {\n const blob = new Blob(\n [\n JSON.stringify(\n log.export(updateActivity ? { updateActivity: updateActivity() } : {}),\n null,\n 2,\n ),\n ],\n { type: 'application/json' },\n )\n const url = URL.createObjectURL(blob)\n const link = document.createElement('a')\n link.href = url\n link.download = `dashboard-diagnostics-${new Date().toISOString().replaceAll(':', '-')}.json`\n link.click()\n URL.revokeObjectURL(url)\n }\n const clear = () => {\n if (!window.confirm('Clear this browser’s retained dashboard diagnostics?')) return\n log.clear()\n }\n\n return (\n <section className={styles.diagnostics}>\n <button\n className={styles.button}\n type=\"button\"\n aria-expanded={open}\n onClick={() => setOpen(!open)}\n >\n Diagnostics ({count})\n {githubConsistencyIncidents > 0 && ` · GitHub consistency ${githubConsistencyIncidents}`}\n </button>\n {open && (\n <div className={styles.area}>\n <p>\n Client {log.clientVersion()} · assets {log.assetPath()}\n </p>\n <p>\n {summary.retained.eventCount} retained browser-local events across{' '}\n {summary.retained.sessionCount} session{summary.retained.sessionCount === 1 ? '' : 's'}\n {summary.retained.firstEventAt && summary.retained.lastEventAt\n ? ` (${formatWindow(summary.retained.firstEventAt, summary.retained.lastEventAt)})`\n : ''}\n . They are never uploaded.\n </p>\n {summary.retained.evidenceMayBeIncomplete && (\n <p className={styles.warning} role=\"alert\">\n Earlier evidence was pruned: {summary.retained.retention.eventsPrunedByCount} at the\n 2,000-event cap and {summary.retained.retention.eventsPrunedByAge} by the 7-day age\n limit. “No failures” applies only to the retained window.\n </p>\n )}\n <p>\n Update failures: {summary.failures.clientUpdate}; board fetch failures:{' '}\n {summary.failures.boardFetch}.\n </p>\n {log.githubConsistencyIncidentCount() > 0 && (\n <p className={styles.warning} role=\"alert\">\n GitHub API consistency incidents: {log.githubConsistencyIncidentCount()}. A response\n older than the last accepted run was rejected; download diagnostics to report it.\n </p>\n )}\n {summary.panels.length > 0 && (\n <div className={styles.panels}>\n {summary.panels.map((panel) => (\n <p key={panel.panelId}>\n <strong>{panel.panelId}</strong> — {panel.requests} requests\n {Object.keys(panel.httpStatuses).length\n ? `; HTTP ${Object.entries(panel.httpStatuses)\n .map(([status, count]) => `${status}×${count}`)\n .join(', ')}`\n : ''}\n ; parse/network failures {panel.parseFailures}/{panel.networkFailures}; visible\n changes {panel.visibleStateChanges}; latest{' '}\n {panel.latestRendered\n ? `${panel.latestRendered.state}${panel.latestRendered.status ? `/${panel.latestRendered.status}` : ''}`\n : 'not rendered'}\n .\n {panel.latestFailedObservation && (\n <>\n {' '}\n Failure: {panel.latestFailedObservation.reason}. Support reference:{' '}\n <code>\n {panel.latestFailedObservation.supportReference ?? 'not provided'}\n </code>\n .\n </>\n )}\n </p>\n ))}\n </div>\n )}\n <div className={styles.actions}>\n <button className={styles.button} type=\"button\" onClick={download}>\n Download\n </button>\n <button className={styles.button} type=\"button\" onClick={clear}>\n Clear\n </button>\n </div>\n </div>\n )}\n </section>\n )\n}\n\nfunction formatWindow(first: string, last: string) {\n return first === last ? first : `${first} to ${last}`\n}\n","/** Embedded in the immutable client artifact; never supplied by the server at runtime. */\nexport const clientReleaseVersion = import.meta.env.RELEASE_VERSION ?? 'dev'\n","import type { ClientEnv } from '@ze-great-dashboard/shared'\nimport { clientReleaseVersion } from './release-version.ts'\n\nexport type DashboardAuth = {\n accessToken?: string\n onAuthenticationFailure?: (status: 401 | 403) => void\n}\n\n/**\n * Adds browser-supplied diagnostic claims to same-origin dashboard API requests. These headers\n * are deliberately not credentials or authorization inputs: the server treats them as untrusted\n * evidence and normalizes only safe values before logging.\n */\nexport function dashboardFetch(\n env: ClientEnv,\n input: RequestInfo | URL,\n init?: RequestInit,\n fetcher: typeof fetch = globalThis.fetch,\n auth: DashboardAuth = {},\n): Promise<Response> {\n const headers = new Headers(init?.headers)\n headers.set('X-Dashboard-Client-Version', clientReleaseVersion)\n headers.set('X-Dashboard-Client-Origin', globalThis.window.location.origin)\n headers.set('X-Dashboard-Client-Asset-Id', env.assetPathId)\n if (auth.accessToken) headers.set('authorization', `Bearer ${auth.accessToken}`)\n return fetcher(input, { ...init, headers }).then((response) => {\n if (response.status === 401 || response.status === 403)\n auth.onAuthenticationFailure?.(response.status)\n return response\n })\n}\n","export type BrowserStorageLike = Pick<Storage, 'getItem' | 'setItem'>\n\nexport function browserLocalStorage(): BrowserStorageLike | undefined {\n try {\n return window.localStorage\n } catch {\n return undefined\n }\n}\n\nexport function readBrowserJson<T>(\n storage: BrowserStorageLike | undefined,\n key: string,\n): T | undefined {\n try {\n const raw = storage?.getItem(key)\n return raw ? (JSON.parse(raw) as T) : undefined\n } catch {\n return undefined\n }\n}\n\nexport function writeBrowserJson(\n storage: BrowserStorageLike | undefined,\n key: string,\n value: unknown,\n) {\n try {\n storage?.setItem(key, JSON.stringify(value))\n } catch {\n // Browser storage is an optimization; callers retain their in-memory state.\n }\n}\n\nexport function removeBrowserValue(storage: Pick<Storage, 'removeItem'> | undefined, key: string) {\n try {\n storage?.removeItem(key)\n } catch {\n // Storage can be unavailable in private browsing or restricted frames.\n }\n}\n","import type {\n DiagnosticEvent,\n DiagnosticRetention,\n FailedObservation,\n RenderedPanelDiagnostic,\n} from './diagnostics.ts'\n\nexport type PanelDiagnosticsSummary = {\n panelId: string\n requests: number\n httpStatuses: Record<string, number>\n parseFailures: number\n networkFailures: number\n visibleStateChanges: number\n latestRendered?: RenderedPanelDiagnostic\n latestFailedObservation?: FailedObservation\n}\n\nexport type DiagnosticsSummary = {\n githubConsistencyIncidents: number\n retained: {\n eventCount: number\n firstEventAt?: string\n lastEventAt?: string\n sessionCount: number\n retention: DiagnosticRetention\n evidenceMayBeIncomplete: boolean\n }\n failures: {\n clientUpdate: number\n boardFetch: number\n }\n panels: PanelDiagnosticsSummary[]\n}\n\n/** Summarizes retained browser evidence only; omitted history is disclosed through retention. */\nexport function summarizeDiagnostics(\n events: readonly DiagnosticEvent[],\n retention: DiagnosticRetention,\n githubConsistencyIncidents = 0,\n): DiagnosticsSummary {\n const panels = new Map<string, PanelDiagnosticsSummary>()\n const sessions = new Set<string>()\n let clientUpdate = 0\n let boardFetch = 0\n\n for (const event of events) {\n sessions.add(event.sessionId)\n if (event.kind === 'client-update-failure') clientUpdate++\n if (event.kind === 'board-fetch-failure' || event.kind === 'board-fetch-parse-failure')\n boardFetch++\n if (!('panelId' in event)) continue\n\n const panel = panels.get(event.panelId) ?? {\n panelId: event.panelId,\n requests: 0,\n httpStatuses: {},\n parseFailures: 0,\n networkFailures: 0,\n visibleStateChanges: 0,\n }\n if (event.kind === 'panel-fetch-start') panel.requests++\n if (event.kind === 'panel-fetch-response') {\n if (event.status !== undefined) {\n const status = String(event.status)\n panel.httpStatuses[status] = (panel.httpStatuses[status] ?? 0) + 1\n }\n if (event.failure) panel.latestFailedObservation = event.failure\n }\n if (event.kind === 'panel-fetch-parse-failure') panel.parseFailures++\n if (event.kind === 'panel-fetch-failure') panel.networkFailures++\n if (event.kind === 'panel-rendered') {\n panel.visibleStateChanges++\n panel.latestRendered = event.rendered\n }\n panels.set(event.panelId, panel)\n }\n\n const timestamps = events.map((event) => event.at).sort()\n const discarded = retention.eventsPrunedByAge + retention.eventsPrunedByCount\n return {\n githubConsistencyIncidents,\n retained: {\n eventCount: events.length,\n firstEventAt: timestamps[0],\n lastEventAt: timestamps.at(-1),\n sessionCount: sessions.size,\n retention,\n evidenceMayBeIncomplete: discarded > 0,\n },\n failures: { clientUpdate, boardFetch },\n panels: [...panels.values()].sort((left, right) => left.panelId.localeCompare(right.panelId)),\n }\n}\n","import type { ClientEnv, Envelope } from '@ze-great-dashboard/shared'\nimport {\n type BrowserStorageLike,\n browserLocalStorage,\n readBrowserJson,\n removeBrowserValue,\n writeBrowserJson,\n} from './browser-storage.ts'\nimport { type DiagnosticsSummary, summarizeDiagnostics } from './diagnostics-summary.ts'\nimport { clientReleaseVersion } from './release-version.ts'\n\nconst storageKey = 'ze-great-dashboard.diagnostics.v2'\nconst legacyStorageKey = 'ze-great-dashboard.diagnostics.v1'\nexport const diagnosticsSchemaVersion = 2\nconst maximumEvents = 2_000\nconst maximumAgeMillis = 7 * 24 * 60 * 60 * 1_000\nconst diagnosticKinds = [\n 'session-start',\n 'client-update-check',\n 'client-update-response',\n 'client-update-failure',\n 'client-update-detected',\n 'board-fetch-start',\n 'board-fetch-response',\n 'board-fetch-parse-failure',\n 'board-fetch-failure',\n 'layout-analyzed',\n 'panel-fetch-start',\n 'panel-fetch-response',\n 'panel-fetch-parse-failure',\n 'panel-fetch-failure',\n 'panel-rendered',\n] as const\n\nexport type CacheMetadata = Partial<\n Record<'cacheControl' | 'etag' | 'lastModified' | 'date' | 'age', string>\n>\n\nexport type GithubConsistencyIncident = {\n at: string\n board: string\n panelId: string\n endpoint: string\n identity: { source: string; workflow: string; branch: string }\n accepted: { sourceUpdatedAt: string; status: string; link: string | null }\n regressed: { sourceUpdatedAt: string; status: string; link: string | null }\n response: { httpStatus?: number; date?: string; etag?: string; cacheControl?: string }\n}\n\ntype EventMetadata = {\n schemaVersion: typeof diagnosticsSchemaVersion\n at: string\n sessionId: string\n board: string\n clientVersion: string\n clientAssetPath: string\n clientAssetPathId: string\n}\n\nexport type RenderedPanelDiagnostic = {\n state: Envelope['state']\n status?: string\n link: string | null\n facts?: Array<{ id: string; state: 'ok' | 'error' | 'unavailable'; link: string | null }>\n}\n\nexport type FailedObservation = {\n reason: string\n supportReference?: string\n}\n\nexport type DiagnosticEventInput =\n | { kind: 'session-start' }\n | { kind: 'client-update-check'; path: string }\n | {\n kind: 'client-update-response'\n path: string\n serverVersion: string\n assetPathIdMatches: boolean\n }\n | { kind: 'client-update-failure'; path: string; message: string }\n | {\n kind: 'client-update-detected'\n path: string\n current: { assetPath: string }\n next: { assetPath: string }\n }\n | { kind: 'board-fetch-start'; path: string }\n | {\n kind: 'board-fetch-response'\n path: string\n status?: number\n cache?: CacheMetadata\n boardSummary?: { panelCount: number; panelIds: string[] }\n }\n | { kind: 'board-fetch-parse-failure'; path: string; message: string }\n | { kind: 'board-fetch-failure'; path: string; message: string }\n | { kind: 'layout-analyzed'; issueCount: number; affectedPanelIds: string[] }\n | { kind: 'panel-fetch-start'; panelId: string; path: string }\n | {\n kind: 'panel-fetch-response'\n panelId: string\n path: string\n status?: number\n cache?: CacheMetadata\n envelope?: Envelope\n failure?: FailedObservation\n }\n | { kind: 'panel-fetch-parse-failure'; panelId: string; path: string; message: string }\n | { kind: 'panel-fetch-failure'; panelId: string; path: string; message: string }\n | {\n kind: 'panel-rendered'\n panelId: string\n path: string\n rendered: RenderedPanelDiagnostic\n }\n\nexport type DiagnosticEvent = DiagnosticEventInput extends infer Event\n ? Event extends DiagnosticEventInput\n ? Event & EventMetadata\n : never\n : never\n\n/** The only interface client features need in order to emit browser diagnostics. */\nexport interface DiagnosticSink {\n record(event: DiagnosticEventInput): void\n recordGithubConsistencyIncident(incident: Omit<GithubConsistencyIncident, 'at' | 'board'>): void\n}\n\ntype PersistedDiagnosticEvent = Omit<DiagnosticEvent, 'schemaVersion'> & { schemaVersion?: number }\nexport type DiagnosticRetention = {\n eventsPrunedByAge: number\n eventsPrunedByCount: number\n}\nexport type RetainedDiagnosticEvidence = {\n events: DiagnosticEvent[]\n retention: DiagnosticRetention\n}\n\ntype StoredDiagnostics = {\n schemaVersion: number\n events: PersistedDiagnosticEvent[]\n retention?: Partial<DiagnosticRetention>\n githubConsistencyIncidents?: GithubConsistencyIncident[]\n}\n\ntype StorageLike = BrowserStorageLike & Pick<Storage, 'removeItem'>\n\n/** Browser-local diagnostic evidence. It deliberately has no server or shared-contract counterpart. */\nexport class BrowserDiagnosticStore implements DiagnosticSink {\n private events: DiagnosticEvent[] = []\n private retention: DiagnosticRetention = emptyRetention()\n private revision = 0\n private incidents: GithubConsistencyIncident[] = []\n private readonly listeners = new Set<() => void>()\n private readonly sessionId = crypto.randomUUID?.() ?? `${Date.now()}-${Math.random()}`\n\n constructor(\n private readonly env: ClientEnv,\n private readonly storage: StorageLike | undefined = browserLocalStorage() as\n | StorageLike\n | undefined,\n private readonly now: () => Date = () => new Date(),\n ) {\n // v1 could retain upstream-provided error text. It is intentionally not migrated.\n removeBrowserValue(this.storage, legacyStorageKey)\n this.events = this.read()\n this.record({ kind: 'session-start' })\n }\n\n recordGithubConsistencyIncident(incident: Omit<GithubConsistencyIncident, 'at' | 'board'>) {\n this.incidents.push({ ...incident, at: this.now().toISOString(), board: this.env.board })\n this.persist()\n this.revision++\n this.notify()\n }\n\n githubConsistencyIncidentCount = () => this.incidents.length\n\n record(event: DiagnosticEventInput) {\n const pruned = prune(\n [\n ...this.events,\n {\n ...event,\n schemaVersion: diagnosticsSchemaVersion,\n at: this.now().toISOString(),\n sessionId: this.sessionId,\n board: this.env.board,\n clientVersion: clientReleaseVersion,\n clientAssetPath: this.env.assetPath,\n clientAssetPathId: this.env.assetPathId,\n },\n ],\n this.now(),\n this.retention,\n )\n this.events = pruned.events\n this.retention = pruned.retention\n this.persist()\n this.revision++\n this.notify()\n }\n\n count = () => {\n return this.events.length\n }\n\n clientVersion = () => clientReleaseVersion\n\n assetPath = () => this.env.assetPath\n\n snapshot = () => this.revision\n\n summary = (): DiagnosticsSummary =>\n summarizeDiagnostics(this.events, this.retention, this.incidents.length)\n\n retainedEvidence = (): RetainedDiagnosticEvidence => ({\n events: [...this.events],\n retention: { ...this.retention },\n })\n\n clear() {\n this.events = []\n this.incidents = []\n this.retention = emptyRetention()\n removeBrowserValue(this.storage, storageKey)\n this.revision++\n this.notify()\n }\n\n subscribe = (listener: () => void) => {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n export = <TSupplement extends object = object>(supplement?: TSupplement) => {\n return {\n schemaVersion: diagnosticsSchemaVersion,\n exportedAt: this.now().toISOString(),\n client: {\n version: clientReleaseVersion,\n assetPath: this.env.assetPath,\n assetPathId: this.env.assetPathId,\n board: this.env.board,\n sessionId: this.sessionId,\n },\n events: this.events,\n githubConsistencyIncidents: this.incidents,\n summary: this.summary(),\n ...supplement,\n }\n }\n\n private read(): DiagnosticEvent[] {\n const parsed = readBrowserJson<Partial<StoredDiagnostics>>(this.storage, storageKey)\n if (\n !parsed ||\n parsed.schemaVersion !== diagnosticsSchemaVersion ||\n !Array.isArray(parsed.events)\n ) {\n removeBrowserValue(this.storage, storageKey)\n return []\n }\n if (!parsed.events.every(isDiagnosticEvent)) {\n removeBrowserValue(this.storage, storageKey)\n return []\n }\n // v1 retained events predate per-event versions. Their containing store was already v1, so\n // retain them and normalize on the next write rather than discarding viewer evidence.\n const pruned = prune(\n parsed.events.map(\n (event) => ({ ...event, schemaVersion: diagnosticsSchemaVersion }) as DiagnosticEvent,\n ),\n this.now(),\n validRetention(parsed.retention),\n )\n this.retention = pruned.retention\n this.incidents = validIncidents(parsed.githubConsistencyIncidents)\n return pruned.events\n }\n\n private persist() {\n writeBrowserJson(this.storage, storageKey, {\n schemaVersion: diagnosticsSchemaVersion,\n events: this.events,\n retention: this.retention,\n githubConsistencyIncidents: this.incidents,\n })\n }\n\n private notify() {\n for (const listener of this.listeners) listener()\n }\n}\n\nfunction validIncidents(value: unknown): GithubConsistencyIncident[] {\n if (!Array.isArray(value)) return []\n return value.filter((incident): incident is GithubConsistencyIncident => {\n if (!incident || typeof incident !== 'object') return false\n const item = incident as Partial<GithubConsistencyIncident>\n return (\n typeof item.at === 'string' &&\n typeof item.board === 'string' &&\n typeof item.panelId === 'string' &&\n typeof item.endpoint === 'string' &&\n !!item.accepted &&\n !!item.regressed &&\n !!item.response\n )\n })\n}\n\nexport function cacheMetadata(headers: Headers): CacheMetadata | undefined {\n const entries = [\n ['cacheControl', 'cache-control'],\n ['etag', 'etag'],\n ['lastModified', 'last-modified'],\n ['date', 'date'],\n ['age', 'age'],\n ] as const\n const metadata = Object.fromEntries(\n entries.flatMap(([key, header]) => {\n const value = headers.get(header)\n return value ? [[key, value]] : []\n }),\n ) as CacheMetadata\n return Object.keys(metadata).length ? metadata : undefined\n}\n\nfunction emptyRetention(): DiagnosticRetention {\n return { eventsPrunedByAge: 0, eventsPrunedByCount: 0 }\n}\n\nfunction validRetention(value: unknown): DiagnosticRetention {\n if (!value || typeof value !== 'object') return emptyRetention()\n const retention = value as Partial<DiagnosticRetention>\n return {\n eventsPrunedByAge:\n typeof retention.eventsPrunedByAge === 'number' && retention.eventsPrunedByAge >= 0\n ? retention.eventsPrunedByAge\n : 0,\n eventsPrunedByCount:\n typeof retention.eventsPrunedByCount === 'number' && retention.eventsPrunedByCount >= 0\n ? retention.eventsPrunedByCount\n : 0,\n }\n}\n\nfunction prune(events: DiagnosticEvent[], now: Date, priorRetention: DiagnosticRetention) {\n const cutoff = now.valueOf() - maximumAgeMillis\n const current = events.filter(\n (event) =>\n Number.isFinite(new Date(event.at).valueOf()) && new Date(event.at).valueOf() >= cutoff,\n )\n const discardedByAge = events.length - current.length\n const discardedByCount = Math.max(0, current.length - maximumEvents)\n return {\n events: current.slice(-maximumEvents),\n retention: {\n eventsPrunedByAge: priorRetention.eventsPrunedByAge + discardedByAge,\n eventsPrunedByCount: priorRetention.eventsPrunedByCount + discardedByCount,\n },\n }\n}\n\nfunction isDiagnosticEvent(value: unknown): value is PersistedDiagnosticEvent {\n if (!value || typeof value !== 'object') return false\n const event = value as Partial<DiagnosticEvent>\n return (\n (event.schemaVersion === undefined || event.schemaVersion === diagnosticsSchemaVersion) &&\n typeof event.at === 'string' &&\n Number.isFinite(new Date(event.at).valueOf()) &&\n typeof event.sessionId === 'string' &&\n typeof event.board === 'string' &&\n diagnosticKinds.includes(event.kind as (typeof diagnosticKinds)[number])\n )\n}\n",".auth {\n display: grid;\n place-content: center;\n min-height: 100dvh;\n gap: 0.75rem;\n padding: 2rem;\n color: var(--ink-primary);\n background: var(--surface);\n}\n.auth h1,\n.auth p {\n margin: 0;\n}\n.auth button {\n justify-self: start;\n border: 1px solid var(--edge);\n border-radius: var(--radius);\n padding: 0.5em 0.8em;\n color: var(--ink-primary);\n background: var(--surface-raised);\n font: inherit;\n cursor: pointer;\n}\n.signout {\n position: fixed;\n z-index: 20;\n top: var(--gap);\n right: var(--gap);\n border: 1px solid var(--edge);\n border-radius: var(--radius);\n padding: 0.35em 0.6em;\n color: var(--ink-secondary);\n background: var(--surface-raised);\n font: inherit;\n cursor: pointer;\n}\n","import type { ClientEnv } from '@ze-great-dashboard/shared'\nimport { type StateStore, UserManager, WebStorageStateStore } from 'oidc-client-ts'\n\nclass MemoryStore implements StateStore {\n private readonly values = new Map<string, string>()\n async set(key: string, value: string) {\n this.values.set(key, value)\n }\n async get(key: string) {\n return this.values.get(key) ?? null\n }\n async remove(key: string) {\n const value = this.values.get(key) ?? null\n this.values.delete(key)\n return value\n }\n async getAllKeys() {\n return [...this.values.keys()]\n }\n}\n\n/** Creates the standards client; tokens remain in this tab's memory rather than browser storage. */\nexport function createOidcManager(auth: NonNullable<ClientEnv['auth']>) {\n return new UserManager({\n authority: auth.issuer,\n client_id: auth.clientId,\n redirect_uri: `${window.location.origin}/`,\n post_logout_redirect_uri: `${window.location.origin}/`,\n response_type: 'code',\n scope: 'openid profile offline_access',\n resource: auth.audience,\n extraQueryParams: { audience: auth.audience },\n userStore: new MemoryStore(),\n // PKCE transaction data, not tokens, must survive the provider redirect.\n stateStore: new WebStorageStateStore({ store: window.sessionStorage }),\n automaticSilentRenew: true,\n })\n}\n","import type { ClientEnv } from '@ze-great-dashboard/shared'\nimport { type ReactNode, useCallback, useEffect, useMemo, useState } from 'react'\nimport { AuthProvider, useAuth } from 'react-oidc-context'\nimport styles from './AuthBoundary.module.css'\nimport { createOidcManager } from './oidc-manager.ts'\n\nexport function OidcGate({\n env,\n auth,\n children,\n}: {\n env: ClientEnv\n auth: NonNullable<ClientEnv['auth']>\n children: (token: string, denied: () => void) => ReactNode\n}) {\n const manager = useMemo(() => createOidcManager(auth), [auth])\n return (\n <AuthProvider\n userManager={manager}\n onSigninCallback={() =>\n window.history.replaceState({}, document.title, window.location.pathname)\n }\n >\n <AuthScreen env={env}>{children}</AuthScreen>\n </AuthProvider>\n )\n}\n\nfunction AuthScreen({\n env,\n children,\n}: {\n env: ClientEnv\n children: (token: string, denied: () => void) => ReactNode\n}) {\n const auth = useAuth()\n const [denied, setDenied] = useState(false)\n const deny = useCallback(() => setDenied(true), [])\n useEffect(() => {\n if (!auth.isAuthenticated) setDenied(false)\n }, [auth.isAuthenticated])\n if (auth.isLoading)\n return (\n <main className={styles.auth} aria-live=\"polite\">\n Signing in…\n </main>\n )\n if (denied)\n return (\n <main className={styles.auth}>\n <h1>Access denied</h1>\n <p>Your authenticated identity is not permitted to view this dashboard.</p>\n </main>\n )\n if (!auth.isAuthenticated || !auth.user?.access_token)\n return (\n <main className={styles.auth}>\n <h1>{env.board}</h1>\n <p>Sign in to view the dashboard.</p>\n <button type=\"button\" onClick={() => void auth.signinRedirect()}>\n Sign in\n </button>\n </main>\n )\n return (\n <>\n <button className={styles.signout} type=\"button\" onClick={() => void auth.signoutRedirect()}>\n Sign out\n </button>\n {children(auth.user.access_token, deny)}\n </>\n )\n}\n",".panel {\n grid-column: var(--panel-column, span 6);\n grid-row: var(--panel-row, auto);\n display: flex;\n flex-direction: column;\n /* A panel reads from its upper edge; the remaining lower area is deliberate breathing room. */\n justify-content: flex-start;\n gap: 0.15em;\n min-width: 0;\n min-height: 0;\n padding: clamp(0.5rem, 0.8vw, var(--gap));\n border: 1px solid var(--edge);\n border-radius: var(--radius);\n background: var(--surface-raised);\n position: relative;\n isolation: isolate;\n overflow: hidden;\n line-height: 1.2;\n container-name: panel;\n container-type: size;\n}\n.attentionActive {\n outline: 0.14rem solid var(--status-critical);\n outline-offset: 0.16rem;\n}\n.content {\n position: relative;\n z-index: 1;\n display: flex;\n flex: 0 1 auto;\n flex-direction: column;\n justify-content: flex-start;\n gap: 0.1em;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n}\n.evidence {\n display: contents;\n}\n/* The source link owns its corner, so the label and evidence never render beneath it. */\n.panel:has(.sourceAction) .content {\n padding-inline-end: 2.25em;\n}\n.content > *,\n.details > * {\n min-width: 0;\n max-width: 100%;\n}\n.content:has([data-running-progress=\"runway\"]),\n.content:has([data-running-progress=\"signal-field\"]) {\n flex: 1 1 0;\n}\n.statusBand {\n display: grid;\n flex: 1 1 0;\n grid-template-rows: 2.6em minmax(0, 1fr) auto;\n gap: 0;\n}\n.statusBand > [data-panel-anchor=\"status\"] {\n position: absolute;\n inset-inline: 0;\n top: 50%;\n grid-row: 2;\n align-self: center;\n transform: translateY(-50%);\n}\n.statusBand > [data-panel-anchor=\"evidence\"] {\n display: block;\n grid-row: 3;\n align-self: end;\n}\n.content:not(.statusBand) > [data-panel-anchor=\"status\"] {\n display: contents;\n}\n.statusBand > [data-panel-anchor=\"status\"],\n.statusBand > [data-panel-anchor=\"evidence\"] {\n min-width: 0;\n}\n.error {\n border-color: var(--status-serious);\n}\n.wide {\n grid-column: span 12;\n}\n.density-comfortable {\n padding: 0.65em;\n gap: 0.1em;\n}\n.density-comfortable .content {\n gap: 0.1em;\n}\n.density-compact {\n min-height: 3.5em;\n padding: 0.2em;\n gap: 0;\n line-height: 1.05;\n justify-content: flex-start;\n}\n.density-compact .content {\n gap: 0;\n}\n.label {\n margin: 0;\n overflow-wrap: anywhere;\n font-size: 1em;\n font-weight: 600;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n color: var(--ink-secondary);\n}\n.statusBand .label {\n grid-row: 1;\n}\n.typeGlyph {\n display: none;\n}\n.identityText {\n overflow-wrap: anywhere;\n}\n.density-compact .label {\n font-size: 0.8em;\n}\n.hint {\n margin: 0;\n font-size: 0.75em;\n color: var(--ink-muted);\n overflow-wrap: anywhere;\n}\n.branch {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n overflow-wrap: anywhere;\n}\n.observed {\n display: flex;\n flex-wrap: wrap;\n gap: 0.35em;\n align-items: center;\n}\n.meta {\n display: var(--panel-meta-display, block);\n}\n.metaValue {\n min-width: 0;\n overflow-wrap: anywhere;\n}\n.compactValue {\n display: none;\n}\n.warning {\n color: var(--status-warning);\n}\n.serious {\n color: var(--status-serious);\n}\n.status {\n margin: 0;\n font-size: 1.35em;\n font-weight: 650;\n}\n.statusGlyph {\n display: inline-block;\n}\n.compactOnlyStatus {\n display: none;\n}\n.density-compact .status {\n font-size: 1.1em;\n}\n.passed {\n color: var(--status-good);\n}\n.failed {\n color: var(--status-critical);\n}\n.warning,\n.running {\n color: var(--status-warning);\n}\n.cancelled,\n.unknown {\n color: var(--ink-secondary);\n}\n.sourceAction {\n position: absolute;\n z-index: 2;\n top: 0.35em;\n right: 0.35em;\n display: inline-grid;\n width: 2em;\n height: 2em;\n place-items: center;\n border-radius: 0.3em;\n color: var(--ink-secondary);\n font-size: 0.85em;\n font-weight: 600;\n line-height: 1;\n text-decoration: none;\n}\n.sourceAction:hover {\n color: var(--ink-primary);\n background: color-mix(in srgb, var(--ink-primary) 8%, transparent);\n}\n.sourceAction:focus-visible {\n outline: 2px solid var(--ink-primary);\n outline-offset: 2px;\n}\n\n.density-comfortable :is(.hint, .observed),\n.density-compact :is(.hint, .observed) {\n font-size: 0.65em;\n}\n@container panel (min-width: 48rem) {\n .density-comfortable.shallow,\n .density-auto.shallow {\n padding: 0.45em 0.65em;\n }\n .density-comfortable.shallow .content,\n .density-auto.shallow .content {\n flex-direction: row;\n flex-wrap: wrap;\n align-items: baseline;\n column-gap: 0.7em;\n row-gap: 0.15em;\n }\n .density-comfortable.shallow .status,\n .density-auto.shallow .status {\n flex: 0 0 auto;\n font-size: 1em;\n }\n .density-comfortable.shallow :is(.label, .observed),\n .density-auto.shallow :is(.label, .observed) {\n flex: 0 0 auto;\n }\n}\n@container panel (min-width: 12rem) {\n .density-compact.shallow .content,\n .density-auto.shallow .content {\n flex-direction: row;\n flex-wrap: wrap;\n align-items: baseline;\n column-gap: 0.7em;\n row-gap: 0.15em;\n }\n .density-compact.shallow :is(.label, .observed),\n .density-auto.shallow :is(.label, .observed) {\n flex: 0 0 auto;\n }\n}\n/* Width and height use the same scale steps, so a narrow or tall cell gets the same text budget. */\n@container panel (max-width: 22rem) {\n .content,\n .sourceAction {\n font-size: 0.8em;\n }\n}\n@container panel (max-width: 15rem) {\n .content,\n .sourceAction {\n font-size: 0.9em;\n }\n}\n@container panel (max-height: 10rem) {\n .content,\n .sourceAction {\n font-size: 0.8em;\n }\n}\n@container panel (max-height: 7rem) {\n .content,\n .sourceAction {\n font-size: 0.9em;\n }\n}\n/* Responsive layout may flow authored cells into one column; content never escapes its cell. */\n@media (max-width: 64rem) {\n .panel {\n grid-column: 1 / -1;\n grid-row: auto;\n min-height: 6em;\n --stacked-card-reading-line-height: 1.25;\n /* Desktop cells need size containment to honor their assigned grid height. Stacked cards\n instead need their readable evidence to contribute to height; retain inline queries for\n width-responsive treatments without containing the block axis. */\n container-type: inline-size;\n }\n /* Stacked cards grow for their evidence; the panel still clips only its decorative field. */\n .content {\n flex-shrink: 0;\n min-height: auto;\n overflow: visible;\n line-height: var(--stacked-card-reading-line-height);\n }\n .density-comfortable .content,\n .density-compact .content,\n .density-auto .content {\n flex-direction: column;\n align-items: stretch;\n }\n}\n\n@container panel (max-width: 11rem) and (max-height: 9rem) {\n .content {\n --panel-meta-display: flex;\n }\n .label {\n font-size: 0.85em;\n }\n .status {\n font-size: 1.05em;\n }\n}\n@container panel (max-height: 5rem) {\n .content {\n --panel-meta-display: flex;\n }\n .label {\n font-size: 0.85em;\n }\n .status {\n font-size: 1.05em;\n }\n}\n\n@container panel (max-width: 13rem) {\n .density-compact .content {\n --panel-meta-display: flex;\n }\n .density-compact .content > .meta {\n font-size: 0.6em;\n }\n}\n@container panel (max-width: 13rem) {\n /* Compact evidence keeps its full wording for assistive technology and the hover title. */\n .meta:has(.compactValue) .fullValue {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n .meta:has(.compactValue) .compactValue {\n display: inline;\n }\n}\n@container panel (max-width: 8rem) {\n /* Text-light is an internal sub-mode: secondary text remains in the accessibility tree. */\n .content {\n --panel-meta-display: flex;\n gap: 0.05em;\n }\n}\n@container panel (min-height: 24rem) and (max-width: 13rem) {\n .content {\n --panel-meta-display: flex;\n gap: 0.05em;\n }\n\n .statusBand {\n grid-template-rows: 2.6em minmax(0, 1fr) 5em;\n }\n}\n@container panel (max-height: 4rem) {\n .content {\n --panel-meta-display: flex;\n gap: 0.05em;\n }\n}\n\n@container panel (max-width: 13rem) and (max-height: 10rem) {\n .density-comfortable .content > .meta {\n font-size: 0.68em;\n }\n}\n\n@container panel (max-width: 18rem) and (max-height: 10rem) {\n .density-compact .content > .meta {\n font-size: 0.6em;\n }\n}\n\n.meta {\n align-items: center;\n gap: 0.2em;\n min-width: 0;\n}\n.metaValue {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Portrait cells retain their authored footprint but become a symbol-led scan surface. */\n@container panel (max-width: 13rem) and (min-height: 10rem) and (max-aspect-ratio: 3 / 4) {\n .content {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, max-content));\n grid-template-rows: min-content;\n align-content: start;\n justify-content: center;\n gap: 0.45em;\n }\n .label {\n grid-column: 1;\n grid-row: 1;\n margin: 0;\n }\n .typeGlyph {\n display: inline-block;\n color: var(--ink-secondary);\n font-size: 1.8em;\n line-height: 1;\n }\n .status {\n grid-column: 2;\n grid-row: 1;\n margin: 0;\n font-size: 1.8em;\n line-height: 1;\n }\n .compactOnlyStatus {\n display: block;\n }\n /* Text-light portrait treatments retain their full wording for assistive technology. */\n .identityText,\n .statusText,\n .content > [data-panel-evidence-priority=\"secondary\"] > :not([data-panel-status]),\n .content > [data-panel-anchor=\"evidence\"][data-panel-evidence-priority=\"secondary\"] {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n .content > [data-panel-anchor=\"status\"] {\n grid-column: 2;\n grid-row: 1;\n align-self: start;\n }\n /* Health tiles keep their upright identity while preserving the shared scan bands. */\n .statusBand {\n display: grid;\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: 2.8em minmax(0, 1fr) 5em;\n align-content: stretch;\n justify-content: stretch;\n gap: 0;\n }\n .statusBand .label {\n display: flex;\n flex-direction: column;\n grid-column: 1;\n grid-row: 1;\n width: 100%;\n align-items: start;\n justify-content: center;\n gap: 0.1em;\n font-size: 0.78em;\n line-height: 1.15;\n text-align: center;\n }\n .statusBand .identityText {\n /* The title gets its own line, so the large type glyph cannot reduce it to one character. */\n flex: none;\n width: 100%;\n min-width: 0;\n position: static;\n height: auto;\n padding: 0;\n margin: 0;\n overflow: visible;\n clip: auto;\n white-space: normal;\n }\n .statusBand > [data-panel-anchor=\"status\"] {\n position: static;\n inset-inline: auto;\n top: auto;\n grid-column: 1;\n grid-row: 2;\n align-self: center;\n justify-self: center;\n transform: none;\n }\n .statusBand > [data-panel-anchor=\"evidence\"] {\n position: static;\n display: block;\n grid-column: 1;\n grid-row: 3;\n width: auto;\n height: auto;\n padding: 0;\n margin: 0;\n overflow: hidden;\n clip: auto;\n white-space: normal;\n }\n .statusBand .status {\n font-size: 2.1em;\n }\n}\n","/**\n * A panel-shaped hole, so the grid can be looked at and argued with before any signal exists.\n * Replaced by real panels in Stage 2 — nothing here is meant to survive.\n */\nexport function PanelPlaceholder({\n label,\n hint,\n wide = false,\n}: {\n label: string\n hint: string\n wide?: boolean\n}) {\n return (\n <section\n className={`${styles.panel} ${wide ? styles.wide : ''}`}\n data-panel\n data-panel-id=\"placeholder\"\n >\n <h2 className={styles.label}>{label}</h2>\n <p className={styles.hint}>{hint}</p>\n </section>\n )\n}\n\nimport styles from './PanelFrame.module.css'\n","import type { ErrorKind } from '@ze-great-dashboard/shared'\n\nexport function errorPresentation(kind: ErrorKind) {\n switch (kind) {\n case 'unauthorized':\n return { label: 'Access denied', emphasis: 'serious' as const }\n case 'not-found':\n return { label: 'Source not found', emphasis: 'serious' as const }\n case 'unreachable':\n case 'upstream-error':\n return { label: 'Source unavailable', emphasis: 'serious' as const }\n case 'no-runs':\n return { label: 'No workflow runs', emphasis: 'warning' as const }\n }\n}\n",".fact {\n display: contents;\n}\n\n.facts {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 0.35em 0.6em;\n min-width: 0;\n}\n\n.factCell {\n position: relative;\n min-width: 0;\n padding: 0.1em 1.8em 0.1em 0;\n}\n\n.factCell h3 {\n margin: 0;\n color: var(--ink-secondary);\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 0.65em;\n font-weight: 600;\n overflow-wrap: anywhere;\n}\n\n.factCell :global([data-panel-meta]) {\n font-size: 0.55em;\n}\n\n.factSource {\n position: absolute;\n top: 0.1em;\n right: 0.15em;\n display: grid;\n width: 1.5em;\n height: 1.5em;\n place-items: center;\n border-radius: 0.25em;\n color: var(--ink-secondary);\n font-size: 0.7em;\n text-decoration: none;\n}\n\n.factSource:hover,\n.factSource:focus-visible {\n color: var(--ink-primary);\n background: color-mix(in srgb, var(--ink-primary) 8%, transparent);\n}\n\n@container panel (max-width: 13rem) {\n .facts {\n grid-template-columns: 1fr;\n }\n}\n@container panel (min-width: 48rem) {\n :global([data-density=\"compact\"][data-shallow=\"true\"]) .fact > *,\n :global([data-density=\"auto\"][data-shallow=\"true\"]) .fact > * {\n margin: 0;\n }\n}\n@container panel (min-width: 12rem) {\n :global([data-density=\"compact\"][data-shallow=\"true\"]) .fact > *,\n :global([data-density=\"auto\"][data-shallow=\"true\"]) .fact > * {\n margin: 0;\n }\n}\n","import type { Panel } from '@ze-great-dashboard/shared'\nimport type { CSSProperties } from 'react'\n\n/** Convert the advisory board position into CSS grid placement. */\nexport function panelLayout(panel: Panel): CSSProperties | undefined {\n const position = panel.position\n if (!position) return undefined\n\n return {\n '--panel-column': `${position.x + 1} / span ${position.w}`,\n '--panel-row': `${position.y + 1} / span ${position.h}`,\n } as CSSProperties\n}\n","import type { PipelineStatus } from '@ze-great-dashboard/shared'\n\n/**\n * The compact tile contract. These are primary scan symbols, so a glyph has one meaning here.\n * Secondary metadata may reuse familiar symbols only when it retains that same meaning.\n */\nexport const panelTypeSymbols = {\n 'pipeline-status': { glyph: '▣', label: 'Pipeline status' },\n 'pull-request-health': { glyph: '⌘', label: 'Pull request health' },\n 'http-value': { glyph: '◌', label: 'HTTP value' },\n 'pipeline-animation-demo': { glyph: '✦', label: 'Pipeline animation demo' },\n} as const\n\n/** Renderable client panel types are defined by the compact identity contract. */\nexport type RenderablePanelType = keyof typeof panelTypeSymbols\n\nexport const statusSymbols: Record<PipelineStatus['status'], { glyph: string; label: string }> = {\n passed: { glyph: '✓', label: 'Passed' },\n failed: { glyph: '✕', label: 'Failed' },\n warning: { glyph: '⚠', label: 'Warning' },\n running: { glyph: '↻', label: 'Running' },\n cancelled: { glyph: '⊘', label: 'Cancelled' },\n unknown: { glyph: '?', label: 'Unknown' },\n}\n\nexport function panelTypeSymbol(type: string) {\n return panelTypeSymbols[type as keyof typeof panelTypeSymbols]\n}\n\n/** Every primary glyph and its single semantic meaning, useful for keeping the registry auditable. */\nexport const primarySymbolMeanings = [\n ...Object.entries(panelTypeSymbols).map(([type, symbol]) => ({\n glyph: symbol.glyph,\n meaning: `panel type: ${type}`,\n })),\n ...Object.entries(statusSymbols).map(([status, symbol]) => ({\n glyph: symbol.glyph,\n meaning: `status: ${status}`,\n })),\n]\n","import type { Envelope, Panel, PipelineStatus } from '@ze-great-dashboard/shared'\nimport type { ReactNode } from 'react'\nimport styles from './PanelFrame.module.css'\nimport { panelLayout } from './panel-layout.ts'\nimport { panelTypeSymbol } from './panel-symbols.ts'\n\ntype PanelStatusKind = PipelineStatus['status']\ntype CompactEvidence = { kind: 'short-value'; value: ReactNode } | { kind: 'glyph-only' }\n\nexport function PanelHint({\n children,\n className,\n title,\n}: {\n children: ReactNode\n className?: string\n title?: string\n}) {\n return (\n <p className={`${styles.hint} ${className ?? ''}`} title={title}>\n {children}\n </p>\n )\n}\n\n/** A concise metadata row with one visible glyph and the full value retained in the DOM. */\nexport function PanelMetadata({\n glyph,\n label,\n value,\n compact,\n title,\n observed = false,\n emphasis,\n className,\n}: {\n glyph: string\n label: string\n value: ReactNode\n /** A text-light visual alternative; the full value remains available to assistive technology. */\n compact?: CompactEvidence\n title?: string\n observed?: boolean\n emphasis?: 'warning' | 'serious'\n className?: string\n}) {\n return (\n <p\n className={`${styles.hint} ${observed ? styles.observed : ''} ${emphasis ? styles[emphasis] : ''} ${styles.meta} ${className ?? ''}`}\n data-panel-meta\n >\n <span aria-hidden=\"true\">{glyph}</span> <span className=\"screen-reader-only\">{label}: </span>\n <span className={styles.metaValue} title={title}>\n <span className={styles.fullValue}>{value}</span>\n {compact && (\n <span className={styles.compactValue} aria-hidden=\"true\">\n {compact.kind === 'short-value' ? compact.value : null}\n </span>\n )}\n </span>\n </p>\n )\n}\n\n/** Stable layout slot for a panel's ordinary readable evidence. */\nexport function PanelEvidence({\n children,\n className,\n priority = 'secondary',\n anchor,\n}: {\n children: ReactNode\n className?: string\n /** Evidence can be intentionally suppressed by a symbol-led compact composition. */\n priority?: 'primary' | 'secondary'\n /** Place this evidence in an opt-in PanelFrame layout slot. */\n anchor?: 'evidence'\n}) {\n return (\n <div\n className={`${styles.evidence} ${className ?? ''}`}\n data-panel-evidence\n data-panel-evidence-priority={priority}\n data-panel-anchor={anchor}\n >\n {children}\n </div>\n )\n}\n\nexport function PanelStatus({\n status,\n emphasis,\n glyph,\n label,\n compactOnly = false,\n}: {\n status?: PanelStatusKind\n emphasis?: 'warning' | 'serious'\n glyph: string\n label: string\n /** Render a compact state only in a portrait tile without changing ordinary cards. */\n compactOnly?: boolean\n}) {\n return (\n <p\n className={`${styles.status} ${status ? styles[status] : ''} ${emphasis ? styles[emphasis] : ''} ${compactOnly ? styles.compactOnlyStatus : ''}`}\n data-panel-status\n >\n {glyph && (\n <span className={styles.statusGlyph} aria-hidden=\"true\">\n {glyph}\n </span>\n )}\n {glyph && label && ' '}\n <span className={styles.statusText}>{label}</span>\n </p>\n )\n}\n\n/** A prominent fact or loading message; unlike PanelStatus, this carries no state semantics. */\nexport function PanelValue({\n children,\n emphasis,\n}: {\n children: ReactNode\n emphasis?: 'warning' | 'serious'\n}) {\n return <p className={`${styles.status} ${emphasis ? styles[emphasis] : ''}`}>{children}</p>\n}\n\nexport function PanelFrame({\n panel,\n envelope,\n attentionActive = false,\n error = false,\n field,\n layout,\n children,\n}: {\n panel: Panel\n envelope?: Envelope\n attentionActive?: boolean\n error?: boolean\n /** Decorative active-run layer. It is intentionally a sibling of readable panel content. */\n field?: ReactNode\n /** Opt-in slots for health panels with a shared identity, state, and evidence band. */\n layout?: 'status-band'\n children: ReactNode\n}) {\n const density = panel.density ?? 'auto'\n const position = panel.position\n const typeSymbol = panelTypeSymbol(panel.type)\n const shallow = position !== undefined && position.h <= 2\n const short = position !== undefined && position.h <= 3\n return (\n <section\n className={`${styles.panel} ${styles[`density-${density}`]} ${shallow ? styles.shallow : ''} ${short ? styles.short : ''} ${error ? styles.error : ''} ${attentionActive ? styles.attentionActive : ''}`}\n id={`panel-${panel.id}`}\n style={panelLayout(panel)}\n aria-busy={envelope ? undefined : true}\n data-panel\n data-panel-id={panel.id}\n data-panel-position={\n position ? `${position.x},${position.y},${position.w},${position.h}` : undefined\n }\n data-density={density}\n data-shallow={shallow}\n data-short={short}\n data-error={error || undefined}\n data-panel-type={panel.type}\n data-attention-active={attentionActive || undefined}\n >\n {field}\n <PanelSourceLink panelId={panel.id} link={envelope?.link} />\n <div\n className={`${styles.content} ${layout === 'status-band' ? styles.statusBand : ''}`}\n data-panel-content\n data-panel-layout={layout}\n >\n <h2 className={styles.label} data-panel-anchor=\"identity\">\n {typeSymbol && (\n <span\n className={styles.typeGlyph}\n aria-hidden=\"true\"\n title={typeSymbol.label}\n data-panel-type-glyph\n >\n {typeSymbol.glyph}\n </span>\n )}\n <span className={styles.identityText} data-panel-identity-text>\n {panel.label ?? panel.id}\n </span>\n </h2>\n {children}\n </div>\n </section>\n )\n}\n\nfunction PanelSourceLink({ panelId, link }: { panelId: string; link?: string | null }) {\n if (!link) return null\n\n return (\n <a\n className={styles.sourceAction}\n href={link}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={`View source for ${panelId} (opens in a new tab)`}\n title={`View source for ${panelId} (opens in a new tab)`}\n data-panel-action=\"source\"\n data-panel-link\n >\n <span aria-hidden=\"true\">↗</span>\n <span className=\"screen-reader-only\">View source</span>\n </a>\n )\n}\n","import { PanelMetadata } from './PanelFrame.tsx'\nimport type { PanelUpdateHealth } from './panel-props.ts'\n\nexport function ObservedAt({ value, label = 'Observed' }: { value: string; label?: string }) {\n return <TimeAge value={value} label={label} />\n}\n\nexport function PipelineAge({\n sourceUpdatedAt,\n observedAt,\n running,\n runStartedAt,\n}: {\n sourceUpdatedAt?: string\n observedAt: string\n running: boolean\n runStartedAt?: string\n}) {\n if (running && runStartedAt) return <TimeAge value={runStartedAt} label=\"Started\" />\n return (\n <TimeAge\n value={sourceUpdatedAt ?? observedAt}\n label={sourceUpdatedAt ? 'Last update' : 'Observed'}\n />\n )\n}\n\nexport function UpdateHealth({ health }: { health: PanelUpdateHealth }) {\n const unavailable = health.consecutiveFailures >= 3\n const label = unavailable ? 'Updates unavailable' : 'Updates delayed'\n return (\n <>\n <PanelMetadata\n glyph=\"⚠\"\n label={label}\n value={`${label} · ${health.message}`}\n title={health.message}\n emphasis={unavailable ? 'serious' : 'warning'}\n />\n <TimeAge value={health.lastConfirmedAt} label=\"Last confirmed\" />\n </>\n )\n}\n\nfunction TimeAge({ value, label }: { value: string; label: string }) {\n const observed = new Date(value)\n const formatted = observed.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n const age = Date.now() - observed.getTime()\n const content = `${label} ${formatAge(age)}`\n return (\n <PanelMetadata\n glyph=\"◷\"\n label={label}\n value={content}\n compact={{ kind: 'short-value', value: formatCompactAge(age) }}\n title={`${label} at ${formatted}`}\n observed\n />\n )\n}\n\nexport function formatAge(milliseconds: number) {\n if (milliseconds < 60_000) return 'just now'\n const minutes = Math.floor(milliseconds / 60_000)\n if (minutes < 60) return `${minutes}m ago`\n const hours = Math.floor(minutes / 60)\n return `${hours}h ${minutes % 60}m ago`\n}\n\nfunction formatCompactAge(milliseconds: number) {\n if (milliseconds < 60_000) return 'now'\n const minutes = Math.floor(milliseconds / 60_000)\n if (minutes < 60) return `${minutes}m`\n const hours = Math.floor(minutes / 60)\n return `${hours}h ${minutes % 60}m`\n}\n","import { httpValueSchema } from '@ze-great-dashboard/shared'\nimport { errorPresentation } from './error-presentation.ts'\nimport styles from './HttpValuePanel.module.css'\nimport { PanelEvidence, PanelFrame, PanelHint, PanelStatus, PanelValue } from './PanelFrame.tsx'\nimport type { HttpValueFactObservation, PanelProps } from './panel-props.ts'\nimport { ObservedAt, UpdateHealth } from './TimeAge.tsx'\n\nexport function HttpValuePanel({\n panel,\n envelope,\n attentionActive,\n updateHealth,\n facts,\n}: PanelProps) {\n if (panel.facts)\n return <GroupedHttpValuePanel panel={panel} attentionActive={attentionActive} facts={facts} />\n if (!envelope)\n return (\n <PanelFrame panel={panel} attentionActive={attentionActive}>\n <PanelEvidence>\n <PanelHint>Loading…</PanelHint>\n </PanelEvidence>\n </PanelFrame>\n )\n if (envelope.state === 'error') {\n const presentation = errorPresentation(envelope.error.kind)\n return (\n <PanelFrame panel={panel} envelope={envelope} attentionActive={attentionActive} error>\n <PanelEvidence>\n <PanelStatus glyph=\"⚠\" label={presentation.label} emphasis={presentation.emphasis} />\n <PanelHint>{envelope.error.message}</PanelHint>\n </PanelEvidence>\n </PanelFrame>\n )\n }\n const signal = httpValueSchema.safeParse(envelope.signal)\n if (!signal.success)\n return (\n <PanelFrame panel={panel} envelope={envelope} attentionActive={attentionActive} error>\n <PanelEvidence>\n <PanelStatus glyph=\"⚠\" label=\"Invalid value\" />\n </PanelEvidence>\n </PanelFrame>\n )\n return (\n <PanelFrame panel={panel} envelope={envelope} attentionActive={attentionActive}>\n <PanelEvidence className={styles.fact}>\n <PanelStatus glyph=\"✓\" label=\"Value read\" compactOnly />\n <PanelValue>{String(signal.data.value)}</PanelValue>\n <ObservedAt value={envelope.observedAt} />\n {updateHealth && <UpdateHealth health={updateHealth} />}\n </PanelEvidence>\n </PanelFrame>\n )\n}\n\nfunction GroupedHttpValuePanel({\n panel,\n attentionActive,\n facts,\n}: Pick<PanelProps, 'panel' | 'attentionActive' | 'facts'>) {\n if (!panel.facts) return null\n return (\n <PanelFrame panel={panel} attentionActive={attentionActive}>\n <PanelEvidence>\n <div className={styles.facts} data-http-value-facts>\n {panel.facts.map((fact) => (\n <HttpValueFactCell key={fact.id} label={fact.label} observation={facts?.[fact.id]} />\n ))}\n </div>\n </PanelEvidence>\n </PanelFrame>\n )\n}\n\nfunction HttpValueFactCell({\n label,\n observation,\n}: {\n label: string\n observation: HttpValueFactObservation | undefined\n}) {\n const envelope = observation?.envelope\n if (!envelope)\n return (\n <section className={styles.factCell} data-http-value-fact>\n <h3>{label}</h3>\n <PanelValue emphasis={observation?.failure ? 'serious' : undefined}>\n {observation?.failure ? '⚠ Updates unavailable' : 'Loading…'}\n </PanelValue>\n {observation?.updateHealth && <UpdateHealth health={observation.updateHealth} />}\n </section>\n )\n if (envelope.state === 'error') {\n const presentation = errorPresentation(envelope.error.kind)\n return (\n <section className={styles.factCell} data-http-value-fact data-error>\n <FactSourceLink label={label} link={envelope.link} />\n <h3>{label}</h3>\n <PanelStatus glyph=\"⚠\" label={presentation.label} emphasis={presentation.emphasis} />\n <PanelHint>{envelope.error.message}</PanelHint>\n <ObservedAt value={envelope.observedAt} />\n </section>\n )\n }\n const signal = httpValueSchema.safeParse(envelope.signal)\n if (!signal.success)\n return (\n <section className={styles.factCell} data-http-value-fact data-error>\n <FactSourceLink label={label} link={envelope.link} />\n <h3>{label}</h3>\n <PanelStatus glyph=\"⚠\" label=\"Invalid value\" emphasis=\"serious\" />\n <ObservedAt value={envelope.observedAt} />\n </section>\n )\n return (\n <section className={styles.factCell} data-http-value-fact>\n <FactSourceLink label={label} link={envelope.link} />\n <h3>{label}</h3>\n <PanelValue>{String(signal.data.value)}</PanelValue>\n <ObservedAt value={envelope.observedAt} />\n </section>\n )\n}\n\nfunction FactSourceLink({ label, link }: { label: string; link: string | null }) {\n if (!link) return null\n return (\n <a\n className={styles.factSource}\n href={link}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={`View source for ${label} (opens in a new tab)`}\n title={`View source for ${label} (opens in a new tab)`}\n >\n <span aria-hidden=\"true\">↗</span>\n <span className=\"screen-reader-only\">View source</span>\n </a>\n )\n}\n",".variant {\n margin: 0;\n color: var(--ink-muted);\n font-size: 0.72em;\n text-transform: capitalize;\n transition: color 180ms ease;\n}\n@container panel (max-width: 13rem) {\n .variantPrefix {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .variant {\n transition: none;\n }\n}\n",".field {\n position: absolute;\n z-index: 0;\n inset: 0;\n overflow: hidden;\n pointer-events: none;\n contain: layout paint;\n color: var(--status-warning);\n}\n.grid {\n position: absolute;\n inset: 10%;\n}\n.piece {\n position: absolute;\n left: calc((var(--piece-x) / var(--shape-columns)) * 100%);\n top: calc((var(--piece-y) / var(--shape-rows)) * 100%);\n width: calc((var(--piece-width) / var(--shape-columns)) * 100%);\n height: calc((var(--piece-height) / var(--shape-rows)) * 100%);\n transition:\n left 120ms linear,\n top 120ms linear;\n}\n.field[data-recycling=\"true\"] .piece {\n transition:\n left 500ms cubic-bezier(0.22, 1, 0.36, 1),\n top 500ms cubic-bezier(0.22, 1, 0.36, 1),\n opacity 180ms ease;\n}\n.field[data-overdue=\"true\"] .piece[data-piece-phase=\"settled\"] {\n opacity: 0.72;\n border-color: currentColor;\n}\n.field[data-overdue=\"true\"] .cell {\n background: color-mix(in srgb, currentColor 38%, transparent);\n box-shadow: 0 0 0.6em color-mix(in srgb, currentColor 48%, transparent);\n}\n.field[data-overdue=\"true\"] .clearingCell {\n animation-duration: 900ms;\n}\n/* biome-ignore lint/style/noDescendingSpecificity: base cell rules follow the overdue override intentionally. */\n.cell {\n position: absolute;\n left: calc((var(--cell-x) / var(--piece-width)) * 100% + 0.12em);\n top: calc((var(--cell-y) / var(--piece-height)) * 100% + 0.12em);\n width: calc(100% / var(--piece-width) - 0.24em);\n height: calc(100% / var(--piece-height) - 0.24em);\n border: 1px solid color-mix(in srgb, currentColor 55%, transparent);\n border-radius: 0.12em;\n background: color-mix(in srgb, currentColor 28%, transparent);\n box-shadow: 0 0 0.45em color-mix(in srgb, currentColor 35%, transparent);\n}\n/* biome-ignore lint/style/noDescendingSpecificity: base clearing rules follow the overdue override intentionally. */\n.clearingCell {\n position: absolute;\n left: calc((var(--clear-x) / var(--shape-columns)) * 100% + 0.12em);\n top: calc((var(--clear-y) / var(--shape-rows)) * 100% + 0.12em);\n width: calc(100% / var(--shape-columns) - 0.24em);\n height: calc(100% / var(--shape-rows) - 0.24em);\n border: 1px solid color-mix(in srgb, currentColor 55%, transparent);\n border-radius: 0.12em;\n background: color-mix(in srgb, currentColor 28%, transparent);\n animation: clear-cell 500ms ease-out forwards;\n}\n.piece[data-piece-phase=\"entry\"] {\n opacity: 0.35;\n}\n.piece[data-piece-phase=\"align\"] {\n opacity: 0.65;\n}\n.piece[data-piece-phase=\"travel\"] {\n opacity: 0.9;\n}\n/* biome-ignore lint/style/noDescendingSpecificity: settled phase is the base state for the overdue override. */\n.piece[data-piece-phase=\"settled\"] {\n opacity: 0.5;\n}\n@media (prefers-reduced-motion: reduce) {\n .piece,\n .field[data-recycling=\"true\"] .piece {\n transition: none;\n }\n .field[data-overdue=\"true\"] .clearingCell {\n animation: none;\n opacity: 0;\n }\n /* biome-ignore lint/style/noDescendingSpecificity: reduced-motion base rule follows the overdue override. */\n .clearingCell {\n animation: none;\n opacity: 0;\n }\n}\n\n@keyframes clear-cell {\n to {\n opacity: 0;\n transform: scale(0.35);\n }\n}\n","export type FallingDirection = 'horizontal' | 'vertical'\nexport type FallingCell = { x: number; y: number }\nexport type FallingShape = {\n id: number\n bornAt: number\n cells: FallingCell[]\n x: number\n y: number\n targetX?: number\n targetY?: number\n phase: 'entry' | 'align' | 'travel' | 'settled'\n}\n\nexport const FALLING_TARGET_FILL = 0.85\n\nconst shapes: FallingCell[][] = [\n [\n { x: 0, y: 0 },\n { x: 1, y: 0 },\n ],\n [\n { x: 0, y: 0 },\n { x: 0, y: 1 },\n ],\n [\n { x: 0, y: 0 },\n { x: 1, y: 0 },\n { x: 0, y: 1 },\n ],\n [\n { x: 0, y: 0 },\n { x: 1, y: 0 },\n { x: 2, y: 0 },\n ],\n [\n { x: 0, y: 0 },\n { x: 0, y: 1 },\n { x: 1, y: 1 },\n ],\n]\n\nexport function fallingDirection(width: number, height: number): FallingDirection {\n return width > height ? 'horizontal' : 'vertical'\n}\n\nexport function fallingGrid(\n direction: FallingDirection,\n width = direction === 'horizontal' ? 12 : 3,\n height = direction === 'horizontal' ? 3 : 12,\n): { columns: number; rows: number } {\n const fieldWidth = Math.max(1, width * 0.8)\n const fieldHeight = Math.max(1, height * 0.8)\n const cellSize = Math.max(24, Math.min(42, Math.min(fieldWidth, fieldHeight) / 4))\n const columns = Math.max(3, Math.min(24, Math.round(fieldWidth / cellSize)))\n const rows = Math.max(3, Math.min(16, Math.round(fieldHeight / cellSize)))\n return direction === 'horizontal'\n ? { columns: Math.max(columns, rows), rows }\n : { columns, rows: Math.max(rows, columns) }\n}\n\nexport function shapeFits(shape: FallingCell[], columns: number, rows: number): boolean {\n const maxX = Math.max(...shape.map((cell) => cell.x))\n const maxY = Math.max(...shape.map((cell) => cell.y))\n return maxX < columns && maxY < rows\n}\n\nexport function overlaps(left: FallingShape, right: FallingShape): boolean {\n return left.cells.some((leftCell) =>\n right.cells.some(\n (rightCell) =>\n left.x + leftCell.x === right.x + rightCell.x &&\n left.y + leftCell.y === right.y + rightCell.y,\n ),\n )\n}\n\nexport function chooseShape(seed: number, columns: number, rows: number): FallingCell[] {\n const candidates = shapes.filter((shape) => shapeFits(shape, columns, rows))\n return candidates[randomIndex(seed, candidates.length)] ?? [{ x: 0, y: 0 }]\n}\n\nexport function findDestination(\n shape: FallingCell[],\n direction: FallingDirection,\n columns: number,\n rows: number,\n settled: readonly FallingShape[],\n seed = 0,\n requireSupported = false,\n): { x: number; y: number } | undefined {\n const width = Math.max(...shape.map((cell) => cell.x)) + 1\n const height = Math.max(...shape.map((cell) => cell.y)) + 1\n const candidates: Array<{ x: number; y: number; support: number }> = []\n for (let y = 0; y <= rows - height; y++) {\n for (let x = 0; x <= columns - width; x++) {\n const candidate = { id: -1, bornAt: 0, cells: shape, x, y, phase: 'settled' as const }\n if (settled.some((item) => overlaps(candidate, item))) continue\n if (!clearPath(shape, direction, columns, rows, candidate, settled)) continue\n const support =\n direction === 'vertical'\n ? shape.filter(\n (cell) =>\n y + cell.y === rows - 1 ||\n settled.some((item) =>\n item.cells.some(\n (other) =>\n item.x + other.x === x + cell.x && item.y + other.y === y + cell.y + 1,\n ),\n ),\n ).length\n : shape.filter(\n (cell) =>\n x + cell.x === 0 ||\n settled.some((item) =>\n item.cells.some(\n (other) =>\n item.x + other.x === x + cell.x - 1 && item.y + other.y === y + cell.y,\n ),\n ),\n ).length\n if (requireSupported && support < leadingEdgeCount(shape, direction)) continue\n candidates.push({ x, y, support })\n }\n }\n candidates.sort(\n (left, right) =>\n right.support - left.support ||\n (direction === 'vertical'\n ? right.y - left.y || left.x - right.x\n : left.x - right.x || left.y - right.y),\n )\n const bestSupport = candidates[0]?.support\n const best = candidates.filter((candidate) => candidate.support === bestSupport)\n const destination = best[randomIndex(seed, best.length)]\n return destination ? { x: destination.x, y: destination.y } : undefined\n}\n\nexport function findPlacement(\n direction: FallingDirection,\n columns: number,\n rows: number,\n settled: readonly FallingShape[],\n seed: number,\n requireSupported: boolean,\n): { shape: FallingCell[]; destination: { x: number; y: number } } | undefined {\n const candidates = shapes.flatMap((shape, index) => {\n if (!shapeFits(shape, columns, rows)) return []\n const destination = findDestination(\n shape,\n direction,\n columns,\n rows,\n settled,\n seed + index * 31,\n requireSupported,\n )\n return destination ? [{ shape, destination }] : []\n })\n if (candidates.length === 0) return undefined\n return candidates[randomIndex(seed, candidates.length)]\n}\n\nexport function targetCellCount(columns: number, rows: number, progress: number): number {\n return Math.ceil(columns * rows * FALLING_TARGET_FILL * Math.min(1, Math.max(0, progress)))\n}\n\nexport function occupiedCellCount(shapes: readonly FallingShape[]): number {\n return shapes.reduce((count, shape) => count + shape.cells.length, 0)\n}\n\nexport type LineClear = {\n shapes: FallingShape[]\n cleared: FallingCell[]\n complete: boolean\n}\n\n/** Clears only cells in the trailing edge line and slides the surviving field into it. */\nexport function clearTrailingLine(\n direction: FallingDirection,\n columns: number,\n rows: number,\n settled: readonly FallingShape[],\n allowPartial: boolean,\n): LineClear | undefined {\n const edgeLine = direction === 'vertical' ? rows - 1 : 0\n const occupied = new Set(\n settled.flatMap((item) =>\n item.cells\n .filter((cell) =>\n direction === 'vertical' ? item.y + cell.y === edgeLine : item.x + cell.x === edgeLine,\n )\n .map((cell) => (direction === 'vertical' ? item.x + cell.x : item.y + cell.y)),\n ),\n )\n const lineWidth = direction === 'vertical' ? columns : rows\n const complete = occupied.size === lineWidth\n if (!complete && !allowPartial) return undefined\n if (occupied.size === 0) return undefined\n\n const cleared: FallingCell[] = []\n const shapes = settled.flatMap((item) => {\n const remaining = item.cells.filter((cell) => {\n const onLine =\n direction === 'vertical' ? item.y + cell.y === edgeLine : item.x + cell.x === edgeLine\n if (onLine) {\n cleared.push({ x: item.x + cell.x, y: item.y + cell.y })\n }\n return !onLine\n })\n if (remaining.length === 0) return []\n return [\n {\n ...item,\n cells: remaining,\n y: direction === 'vertical' ? item.y + 1 : item.y,\n x: direction === 'horizontal' ? item.x - 1 : item.x,\n },\n ]\n })\n return { shapes, cleared, complete }\n}\n\nexport function buildStaticField(\n direction: FallingDirection,\n columns: number,\n rows: number,\n seed: number,\n count: number,\n): FallingShape[] {\n const settled: FallingShape[] = []\n for (let id = 0; id < count; id += 1) {\n const pieceSeed = seed + id * 17\n const shape = chooseShape(pieceSeed, columns, rows)\n const destination = findDestination(shape, direction, columns, rows, settled, pieceSeed + 1)\n if (!destination) break\n settled.push({\n id,\n bornAt: 0,\n cells: shape,\n x: destination.x,\n y: destination.y,\n phase: 'settled',\n })\n }\n return settled\n}\n\nfunction leadingEdgeCount(shape: FallingCell[], direction: FallingDirection): number {\n if (direction === 'vertical') {\n return new Set(shape.map((cell) => cell.x)).size\n }\n return new Set(shape.map((cell) => cell.y)).size\n}\n\nfunction clearPath(\n shape: FallingCell[],\n direction: FallingDirection,\n columns: number,\n rows: number,\n destination: FallingShape,\n settled: readonly FallingShape[],\n): boolean {\n const width = Math.max(...shape.map((cell) => cell.x)) + 1\n const height = Math.max(...shape.map((cell) => cell.y)) + 1\n if (direction === 'vertical') {\n for (let y = 0; y <= destination.y; y += 1) {\n if (settled.some((item) => overlaps({ ...destination, y }, item))) return false\n }\n return destination.y + height <= rows\n }\n for (let x = columns - width; x >= destination.x; x -= 1) {\n if (settled.some((item) => overlaps({ ...destination, x }, item))) return false\n }\n return destination.x + width <= columns\n}\n\nfunction randomIndex(seed: number, length: number): number {\n if (length <= 1) return 0\n const value = Math.sin(seed * 12.9898 + 78.233) * 43_758.5453\n return Math.floor((value - Math.floor(value)) * length)\n}\n","import type { CSSProperties } from 'react'\nimport { useEffect, useRef, useState } from 'react'\nimport styles from './FallingShapesField.module.css'\nimport {\n buildStaticField,\n clearTrailingLine,\n type FallingDirection,\n type FallingShape,\n fallingDirection,\n fallingGrid,\n findPlacement,\n occupiedCellCount,\n targetCellCount,\n} from './falling-shapes.ts'\n\nconst TICK_MS = 50\nconst PIECE_INTERVAL_MS = 1_250\nconst ENTRY_MS = 250\nconst TRAVEL_MS = 850\nconst RECYCLE_MS = 500\n\nexport function FallingShapesField({\n progress,\n estimatedDurationMs,\n overdue,\n seed = 0,\n}: {\n progress: number\n estimatedDurationMs?: number\n overdue: boolean\n seed?: number\n}) {\n const rootRef = useRef<HTMLDivElement>(null)\n const [geometry, setGeometry] = useState<{\n columns: number\n rows: number\n direction: FallingDirection\n }>({\n ...fallingGrid('vertical'),\n direction: 'vertical' as const,\n })\n const [pieces, setPieces] = useState<FallingShape[]>([])\n const [recycling, setRecycling] = useState(false)\n const [clearingCells, setClearingCells] = useState<{ x: number; y: number }[]>([])\n const [reducedMotion, setReducedMotion] = useState(false)\n const geometryRef = useRef(geometry)\n const previousGeometryRef = useRef(geometry)\n const progressRef = useRef(progress)\n const seedRef = useRef(seed)\n const directionRef = useRef<FallingDirection | undefined>(undefined)\n const piecesRef = useRef<FallingShape[]>([])\n const recyclingRef = useRef(false)\n const simulation = useRef({\n startedAt: Date.now(),\n nextPieceAt: PIECE_INTERVAL_MS,\n recycleUntil: 0,\n id: 0,\n settled: [] as FallingShape[],\n })\n\n useEffect(() => {\n progressRef.current = progress\n }, [progress])\n\n useEffect(() => {\n seedRef.current = seed\n }, [seed])\n\n useEffect(() => {\n const root = rootRef.current\n if (!root) return\n const update = () => {\n const rect = root.getBoundingClientRect()\n if (rect.width === 0 || rect.height === 0) return\n setGeometry((_current) => {\n const direction = directionRef.current ?? fallingDirection(rect.width, rect.height)\n directionRef.current = direction\n const next = { ...fallingGrid(direction, rect.width, rect.height), direction }\n geometryRef.current = next\n return next\n })\n }\n update()\n if (typeof ResizeObserver === 'undefined') return\n const observer = new ResizeObserver(update)\n observer.observe(root)\n return () => observer.disconnect()\n }, [])\n\n useEffect(() => {\n const media = window.matchMedia('(prefers-reduced-motion: reduce)')\n const update = () => setReducedMotion(media.matches)\n update()\n media.addEventListener?.('change', update)\n return () => media.removeEventListener?.('change', update)\n }, [])\n\n useEffect(() => {\n const previous = previousGeometryRef.current\n const changed =\n previous.direction !== geometry.direction ||\n previous.columns !== geometry.columns ||\n previous.rows !== geometry.rows\n previousGeometryRef.current = geometry\n if (!changed || reducedMotion) return\n simulation.current = {\n startedAt: Date.now(),\n nextPieceAt: PIECE_INTERVAL_MS,\n id: 0,\n recycleUntil: 0,\n settled: [],\n }\n piecesRef.current = []\n setPieces([])\n setRecycling(false)\n setClearingCells([])\n recyclingRef.current = false\n }, [geometry, reducedMotion])\n\n useEffect(() => {\n if (!reducedMotion) return\n const staticPieces = buildStaticField(\n geometry.direction,\n geometry.columns,\n geometry.rows,\n seedRef.current,\n Math.max(1, Math.floor(progressRef.current * 6)),\n )\n piecesRef.current = staticPieces\n simulation.current.settled = staticPieces\n setPieces(staticPieces)\n }, [geometry, reducedMotion])\n\n useEffect(() => {\n if (reducedMotion) return\n const timer = window.setInterval(() => {\n const state = simulation.current\n const elapsed = Date.now() - state.startedAt\n const currentGeometry = geometryRef.current\n const currentProgress = progressRef.current\n const target = targetCellCount(currentGeometry.columns, currentGeometry.rows, currentProgress)\n let next = [...state.settled]\n let active = piecesRef.current.filter((piece) => piece.phase !== 'settled')\n if (elapsed < state.recycleUntil) return\n if (recyclingRef.current) {\n recyclingRef.current = false\n setRecycling(false)\n setClearingCells([])\n }\n if (elapsed >= state.nextPieceAt && active.length === 0) {\n if (currentProgress < 1 && occupiedCellCount(next) >= target) {\n return\n }\n const id = state.id\n const pieceSeed = seedRef.current + id * 17\n const placement = findPlacement(\n currentGeometry.direction,\n currentGeometry.columns,\n currentGeometry.rows,\n next,\n pieceSeed + 1,\n !overdue,\n )\n if (!placement && (currentProgress >= 1 || estimatedDurationMs === undefined)) {\n const cleared = clearTrailingLine(\n currentGeometry.direction,\n currentGeometry.columns,\n currentGeometry.rows,\n next,\n true,\n )\n if (cleared) {\n next = cleared.shapes\n state.settled = next\n state.recycleUntil = elapsed + RECYCLE_MS\n state.nextPieceAt = state.recycleUntil\n piecesRef.current = next\n recyclingRef.current = true\n setClearingCells(cleared.cleared)\n setPieces(next)\n setRecycling(true)\n return\n }\n }\n if (placement) {\n state.id += 1\n const { shape, destination } = placement\n const height = Math.max(...shape.map((cell) => cell.y)) + 1\n active = [\n ...active,\n {\n id,\n bornAt: elapsed,\n cells: shape,\n x:\n currentGeometry.direction === 'horizontal'\n ? currentGeometry.columns - Math.max(...shape.map((cell) => cell.x)) - 0.5\n : destination.x,\n y: currentGeometry.direction === 'vertical' ? -height + 0.5 : destination.y,\n targetX: destination.x,\n targetY: destination.y,\n phase: 'entry',\n },\n ]\n }\n state.nextPieceAt += pieceInterval(estimatedDurationMs, currentGeometry)\n }\n active = active.map((piece) => {\n const age = elapsed - piece.bornAt\n const destination =\n piece.targetX === undefined || piece.targetY === undefined\n ? undefined\n : { x: piece.targetX, y: piece.targetY }\n if (!destination) return piece\n const amount = Math.min(1, Math.max(0, (age - ENTRY_MS) / TRAVEL_MS))\n if (amount >= 1) {\n next = [\n ...next,\n { ...piece, x: destination.x, y: destination.y, phase: 'settled' as const },\n ]\n return { ...piece, x: destination.x, y: destination.y, phase: 'settled' as const }\n }\n const startX =\n currentGeometry.direction === 'horizontal'\n ? currentGeometry.columns - Math.max(...piece.cells.map((cell) => cell.x)) - 1\n : destination.x\n const startY = currentGeometry.direction === 'vertical' ? 0 : destination.y\n const lifecycleAmount = Math.min(1, Math.max(0, age / (ENTRY_MS + TRAVEL_MS)))\n return {\n ...piece,\n x:\n currentGeometry.direction === 'horizontal'\n ? startX + (destination.x - startX) * amount\n : startX,\n y:\n currentGeometry.direction === 'vertical'\n ? startY + (destination.y - startY) * amount\n : startY,\n phase: age < ENTRY_MS ? 'entry' : lifecycleAmount < 0.35 ? 'align' : 'travel',\n }\n })\n state.settled = next\n const visible = [...next, ...active.filter((piece) => piece.phase !== 'settled')]\n piecesRef.current = visible\n setPieces(visible)\n }, TICK_MS)\n return () => window.clearInterval(timer)\n }, [estimatedDurationMs, overdue, reducedMotion])\n\n return (\n <div\n ref={rootRef}\n className={styles.field}\n data-running-part=\"falling-shapes-field\"\n data-overdue={overdue || undefined}\n data-direction={geometry.direction}\n data-recycling={recycling || undefined}\n style={\n { '--shape-columns': geometry.columns, '--shape-rows': geometry.rows } as CSSProperties\n }\n >\n <div className={styles.grid}>\n {clearingCells.map((cell) => (\n <span\n key={`${cell.x}-${cell.y}`}\n className={styles.clearingCell}\n style={{ '--clear-x': cell.x, '--clear-y': cell.y } as CSSProperties}\n />\n ))}\n {pieces.map((piece) => (\n <div\n key={piece.id}\n className={styles.piece}\n data-piece={piece.id}\n data-piece-phase={piece.phase}\n style={\n {\n '--piece-x': piece.x,\n '--piece-y': piece.y,\n '--piece-width': Math.max(...piece.cells.map((cell) => cell.x)) + 1,\n '--piece-height': Math.max(...piece.cells.map((cell) => cell.y)) + 1,\n } as CSSProperties\n }\n >\n {piece.cells.map((cell) => (\n <span\n key={`${cell.x}-${cell.y}`}\n className={styles.cell}\n style={{ '--cell-x': cell.x, '--cell-y': cell.y } as CSSProperties}\n />\n ))}\n </div>\n ))}\n </div>\n </div>\n )\n}\n\nfunction pieceInterval(\n estimatedDurationMs: number | undefined,\n geometry: { columns: number; rows: number },\n) {\n const target = Math.ceil(geometry.columns * geometry.rows * 0.85)\n if (estimatedDurationMs === undefined || target <= 0) return PIECE_INTERVAL_MS\n return Math.max(400, estimatedDurationMs / Math.max(1, Math.ceil(target / 3)))\n}\n",".frontier {\n position: absolute;\n inset: 0 auto 0 0;\n width: var(--running-progress);\n background: linear-gradient(\n 90deg,\n color-mix(in srgb, currentColor 16%, transparent),\n transparent\n );\n border-right: 1px solid color-mix(in srgb, currentColor 75%, transparent);\n}\n.now {\n position: absolute;\n top: 10%;\n bottom: 10%;\n left: 70%;\n width: 1px;\n background: color-mix(in srgb, var(--ink-primary) 45%, transparent);\n}\n.routes {\n position: absolute;\n inset: 18% 8%;\n display: grid;\n align-content: space-between;\n}\n.route {\n height: 1px;\n background: linear-gradient(\n 90deg,\n transparent,\n color-mix(in srgb, var(--ink-muted) 45%, transparent),\n transparent\n );\n}\n.route:nth-child(2) {\n transform: translateX(8%);\n}\n.route:nth-child(3) {\n transform: translateX(-6%);\n}\n.trail,\n.packet {\n position: absolute;\n top: 50%;\n left: -10%;\n border-radius: 999px;\n animation: packet 4.8s ease-in-out infinite alternate;\n}\n.trail {\n width: 18%;\n height: 2px;\n background: linear-gradient(90deg, transparent, currentColor);\n opacity: 0.65;\n}\n.packet {\n width: 0.48em;\n height: 0.48em;\n background: currentColor;\n box-shadow: 0 0 0.65em currentColor;\n}\n@container running-field (max-width: 40rem) {\n .routes,\n .trail,\n .packet,\n .now {\n display: none;\n }\n .frontier {\n width: 0.28em;\n border-right: 0;\n background: currentColor;\n }\n}\n[data-overdue=\"true\"] .frontier {\n width: 70%;\n background: linear-gradient(\n 90deg,\n color-mix(in srgb, currentColor 28%, transparent),\n transparent\n );\n}\n[data-overdue=\"true\"] .packet {\n left: 70%;\n animation: packet-stall 1.8s ease-in-out infinite alternate;\n}\n[data-overdue=\"true\"] .trail {\n left: 43%;\n width: 27%;\n animation: trail-backup 1.8s ease-in-out infinite alternate;\n}\n@keyframes packet {\n from {\n transform: translate(-10cqw, -50%);\n }\n to {\n transform: translate(120cqw, -50%);\n }\n}\n@keyframes packet-stall {\n from {\n transform: translate(-50%, -50%) scale(0.82);\n opacity: 0.72;\n }\n to {\n transform: translate(-50%, -50%) scale(1.12);\n opacity: 1;\n }\n}\n@keyframes trail-backup {\n from {\n transform: translate(-8%, -50%);\n opacity: 0.5;\n }\n to {\n transform: translate(8%, -50%);\n opacity: 0.95;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n [data-overdue=\"true\"] .trail,\n [data-overdue=\"true\"] .packet,\n .trail,\n .packet {\n animation: none;\n }\n .frontier {\n transition: none;\n }\n}\n","import styles from './ReleaseTransitField.module.css'\n\nexport function ReleaseTransitField() {\n return (\n <>\n <span className={styles.frontier} data-running-part=\"frontier\" />\n <span className={styles.now} data-running-part=\"transit-now\" />\n <span className={styles.routes} data-running-part=\"transit-routes\">\n {[0, 1, 2].map((route) => (\n <span className={styles.route} key={route} />\n ))}\n </span>\n <span className={styles.trail} data-running-part=\"transit-trail\" />\n <span className={styles.packet} data-running-part=\"transit-packet\" />\n </>\n )\n}\n",".field {\n position: absolute;\n z-index: 0;\n inset: 0;\n overflow: hidden;\n pointer-events: none;\n container-type: size;\n container-name: running-field;\n color: var(--status-warning);\n}\n.overdue {\n color: var(--status-serious);\n}\n.timing {\n width: min(12ch, 100%);\n max-width: 100%;\n min-width: 0;\n flex: 0 1 12ch;\n margin: 0;\n color: var(--ink-secondary);\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 0.72em;\n font-variant-numeric: tabular-nums;\n text-align: end;\n white-space: nowrap;\n overflow: hidden;\n}\n.timingOverdue {\n color: var(--status-serious);\n}\n",".field {\n position: absolute;\n inset: 0;\n overflow: hidden;\n contain: layout paint;\n}\n.canvas {\n display: block;\n width: 100%;\n height: 100%;\n}\n","export type SnowmanScheduleMode = 'snowfall' | 'arrival' | 'hop' | 'full'\n\nexport type SnowmanSchedule = {\n mode: SnowmanScheduleMode\n bodyStart: number\n bodyEnd: number\n headStart: number\n hopStart: number\n land: number\n settleEnd: number\n end: number\n}\n\n/** Derive one deterministic choreography from the complete expected run duration. */\nexport function snowmanSchedule(duration: number): SnowmanSchedule {\n const bodyWindow = duration * 0.25\n const headWindow = duration * 0.2\n const mode: SnowmanScheduleMode =\n bodyWindow < 700 || headWindow < 350\n ? 'snowfall'\n : headWindow < 530\n ? 'arrival'\n : headWindow < 1030\n ? 'hop'\n : 'full'\n const scale = clamp(\n (headWindow - (mode === 'full' ? 1030 : 530)) / (mode === 'full' ? 1620 : 620),\n 0,\n 1,\n )\n const roll = mode === 'full' ? 500 + 1000 * scale : 0\n const tail = mode === 'arrival' ? 0 : 180 + 70 * scale\n const hop = mode === 'arrival' ? Math.min(900, headWindow) : 350 + 550 * scale\n const end = duration * 0.95\n const land = end - tail\n return {\n mode,\n bodyStart: duration * 0.75 - Math.min(2500, bodyWindow),\n bodyEnd: duration * 0.75,\n headStart: land - hop - roll,\n hopStart: land - hop,\n land,\n settleEnd: land + (tail ? 120 + 60 * scale : 0),\n end,\n }\n}\n\nexport function scheduleAmount(time: number, start: number, end: number) {\n return end === start ? Number(time >= end) : clamp((time - start) / (end - start), 0, 1)\n}\n\nexport function smoothScheduleAmount(value: number) {\n return value * value * (3 - 2 * value)\n}\n\nfunction clamp(value: number, low: number, high: number) {\n return Math.max(low, Math.min(high, value))\n}\n","export type SnowmanPhase = 'drift' | 'snowing' | 'assembling' | 'complete' | 'overdue'\nexport type SnowCellOwner = 'ground' | 'body' | 'head' | 'snowman'\nexport type SnowmanDimensions = { width: number; height: number }\n\nexport type SnowCell = {\n id: number\n x: number\n y: number\n owner: SnowCellOwner\n /** Coordinates relative to a rolling ball. Ground and accumulated snow omit these. */\n localX?: number\n localY?: number\n targetLocalX?: number\n targetLocalY?: number\n packed?: boolean\n}\nexport type AirborneFlake = { id: number; x: number; y: number; bornAt: number }\nexport type Snowball = {\n kind: 'body' | 'head'\n x: number\n y: number\n radius: number\n angle: number\n /** A placed ball no longer follows the relaxing terrain beneath it. */\n locked: boolean\n /** The final support position captured when the body locks. */\n supportY?: number\n launch?: { x: number; y: number }\n}\nexport type SnowmanSimulation = {\n nextAt: number\n id: number\n lastElapsed: number\n grid: { columns: number; rows: number }\n flakes: AirborneFlake[]\n cells: SnowCell[]\n body?: Snowball\n head?: Snowball\n toppling?: { startedAt: number; angle: number; pivotX: number; pivotY: number }\n toppled: boolean\n hat?: { x: number; y: number; angle: number }\n}\n\nexport { snowmanSchedule } from './snowman-timing.ts'\n\nimport {\n scheduleAmount as amount,\n smoothScheduleAmount as ease,\n snowmanSchedule,\n} from './snowman-timing.ts'\n\nconst STEP_MS = 25\nconst ASSEMBLY_START = 0.5\nconst HAT_AT = 0.95\n/** Attached snowfall at which the completed decorative figure falls and stays down. */\nexport const SNOWMAN_TOPPLE_LOAD = 60\n\nexport function createSnowmanSimulation(\n dimensions: SnowmanDimensions = { width: 360, height: 180 },\n): SnowmanSimulation {\n return {\n nextAt: 0,\n id: 0,\n lastElapsed: 0,\n grid: snowmanGrid(dimensions),\n flakes: [],\n cells: [],\n toppled: false,\n }\n}\n\nexport function snowmanGrid(dimensions: SnowmanDimensions) {\n // Four device-independent pixels gives fine grain without making a compact field expensive.\n const columns = clamp(Math.round(dimensions.width / 4), 48, 180)\n const rows = clamp(Math.round(dimensions.height / 4), 28, 100)\n return { columns, rows }\n}\n\nexport function snowmanScenePhase(\n progress: number,\n estimatedDurationMs: number | undefined,\n overdue: boolean,\n): SnowmanPhase {\n if (overdue) return 'overdue'\n if (estimatedDurationMs === undefined) return 'snowing'\n if (snowmanSchedule(estimatedDurationMs).mode === 'snowfall') return 'snowing'\n if (progress >= HAT_AT) return 'complete'\n if (progress >= ASSEMBLY_START) return 'assembling'\n return 'drift'\n}\n\n/** A permanent slight breeze plus seed-stable, visibly stronger intermittent gusts. */\nexport function snowmanWind(seed: number, elapsed: number) {\n const direction = random(seed + 41) < 0.5 ? -1 : 1\n const breeze = direction * (0.72 + random(seed + 43) * 0.45)\n const smallVariation = Math.sin(elapsed / 1_600 + random(seed + 47) * Math.PI * 2) * 0.4\n const gustWave = Math.max(0, Math.sin(elapsed / 3_100 + random(seed + 53) * Math.PI * 2))\n const gust = direction * gustWave ** 7 * (3.2 + random(seed + 59) * 1.8)\n return breeze + smallVariation + gust\n}\n\nexport function snowmanMaterialCount(dimensions: SnowmanDimensions) {\n const grid = snowmanGrid(dimensions)\n return Math.round(grid.columns * grid.rows * 0.18)\n}\n\nexport function snowmanSpawnInterval(\n estimatedDurationMs: number | undefined,\n dimensions: SnowmanDimensions,\n overdue = false,\n elapsed = 0,\n) {\n if (estimatedDurationMs === undefined) return overdue ? 30 : 60\n const ordinary = (estimatedDurationMs * HAT_AT) / snowmanMaterialCount(dimensions)\n if (overdue) return ordinary / 2\n const schedule = snowmanSchedule(estimatedDurationMs)\n if (schedule.mode !== 'snowfall' && elapsed >= Math.max(0, schedule.bodyStart - 500)) {\n return ordinary * 4\n }\n return ordinary\n}\n\n/** Advances a fixed-step cellular snow simulation without reading the DOM or a browser clock. */\nexport function advanceSnowmanSimulation(\n previous: SnowmanSimulation,\n {\n elapsed,\n progress,\n estimatedDurationMs,\n overdue,\n seed,\n dimensions,\n }: {\n elapsed: number\n progress: number\n estimatedDurationMs?: number\n overdue: boolean\n seed: number\n dimensions: SnowmanDimensions\n },\n): SnowmanSimulation {\n const grid = snowmanGrid(dimensions)\n let simulation =\n previous.grid.columns === grid.columns && previous.grid.rows === grid.rows\n ? clone(previous)\n : createSnowmanSimulation(dimensions)\n const targetElapsed = Math.max(simulation.lastElapsed, elapsed)\n for (let time = simulation.lastElapsed + STEP_MS; time <= targetElapsed; time += STEP_MS) {\n simulation = step(\n simulation,\n time,\n estimatedDurationMs === undefined ? progress : time / estimatedDurationMs,\n estimatedDurationMs,\n overdue && (estimatedDurationMs === undefined || time >= estimatedDurationMs),\n seed,\n dimensions,\n )\n simulation.lastElapsed = time\n }\n return simulation\n}\n\nexport function snowmanLoad(cells: readonly SnowCell[]) {\n return cells.filter((cell) => cell.owner === 'snowman').length\n}\n\nexport function resolvedCells(simulation: SnowmanSimulation) {\n return simulation.cells.map((cell) => {\n const ball =\n cell.owner === 'body' ? simulation.body : cell.owner === 'head' ? simulation.head : undefined\n const resolved =\n ball && cell.localX !== undefined && cell.localY !== undefined\n ? {\n ...cell,\n x: ball.x + cell.localX * Math.cos(ball.angle) - cell.localY * Math.sin(ball.angle),\n y: ball.y + cell.localX * Math.sin(ball.angle) + cell.localY * Math.cos(ball.angle),\n }\n : cell\n return simulation.toppling && resolved.owner !== 'ground'\n ? rotateAround(resolved, simulation.toppling)\n : resolved\n })\n}\n\nexport function resolvedBallCenter(simulation: SnowmanSimulation, ball: Snowball) {\n return simulation.toppling ? rotateAround(ball, simulation.toppling) : ball\n}\n\nfunction step(\n simulation: SnowmanSimulation,\n elapsed: number,\n progress: number,\n estimatedDurationMs: number | undefined,\n overdue: boolean,\n seed: number,\n dimensions: SnowmanDimensions,\n) {\n const phase = snowmanScenePhase(progress, estimatedDurationMs, overdue)\n const interval = snowmanSpawnInterval(estimatedDurationMs, dimensions, overdue, elapsed)\n while (elapsed >= simulation.nextAt) {\n simulation.flakes.push({\n id: simulation.id++,\n x: random(seed + simulation.id * 17) * simulation.grid.columns,\n y: -1 - random(seed + simulation.id * 23) * 6,\n bornAt: simulation.nextAt,\n })\n simulation.nextAt += interval\n }\n\n updateBalls(simulation, progress, estimatedDurationMs, overdue)\n const occupied = occupiedCells(simulation)\n const wind = snowmanWind(seed, elapsed) * (STEP_MS / 1_000)\n const fall =\n estimatedDurationMs === undefined\n ? 0.52\n : Math.max(0.52, ((simulation.grid.rows + 7) * STEP_MS) / (estimatedDurationMs * 0.25))\n const nextFlakes: AirborneFlake[] = []\n for (const flake of simulation.flakes) {\n const moved = { ...flake, x: flake.x + wind, y: flake.y + fall }\n const ball = hitBall(simulation, moved)\n if (ball) {\n joinBall(simulation, ball, flake.id, moved.x - ball.x, moved.y - ball.y)\n continue\n }\n const resting = findRestingCell(moved, occupied, simulation.grid, wind, seed)\n if (!resting) {\n nextFlakes.push({ ...moved, x: clamp(moved.x, 0, simulation.grid.columns - 1) })\n continue\n }\n const belowOwner = occupied.get(key(resting.x, resting.y + 1))\n simulation.cells.push({\n id: flake.id,\n x: resting.x,\n y: resting.y,\n owner:\n belowOwner === 'body' || belowOwner === 'head' || belowOwner === 'snowman'\n ? 'snowman'\n : 'ground',\n })\n occupied.set(key(resting.x, resting.y), simulation.cells.at(-1)?.owner ?? 'ground')\n }\n simulation.flakes = nextFlakes\n if (estimatedDurationMs !== undefined && phase !== 'drift' && phase !== 'snowing')\n collectTouchedGround(simulation)\n compactBallCells(simulation)\n // A small cascade closes a swept gap promptly without making the whole bank flow at once.\n relaxSettledSnow(simulation, seed, elapsed)\n relaxSettledSnow(simulation, seed, elapsed + STEP_MS / 2)\n const body = simulation.body\n if (body?.locked) {\n body.supportY ??= restingBallY(simulation, body.x, body.radius, body.y + body.radius)\n body.y = body.supportY\n }\n if (\n overdue &&\n !simulation.toppling &&\n !simulation.toppled &&\n snowmanLoad(simulation.cells) >= SNOWMAN_TOPPLE_LOAD\n )\n beginTopple(simulation, elapsed)\n advanceTopple(simulation, elapsed)\n return simulation\n}\n\nfunction updateBalls(\n simulation: SnowmanSimulation,\n progress: number,\n estimatedDurationMs: number | undefined,\n _overdue: boolean,\n) {\n if (estimatedDurationMs === undefined) return\n const schedule = snowmanSchedule(estimatedDurationMs)\n if (schedule.mode === 'snowfall') return\n const time = progress * estimatedDurationMs\n const { columns, rows } = simulation.grid\n const bodyAmount = ease(amount(time, schedule.bodyStart, schedule.bodyEnd))\n if (time >= schedule.bodyStart && !simulation.body) {\n const x = columns * 0.14\n simulation.body = {\n kind: 'body',\n x,\n y: restingBallY(simulation, x, 2, rows - 1),\n radius: 2,\n angle: 0,\n locked: false,\n }\n }\n const body = simulation.body\n if (body && !body.locked) {\n body.radius = Math.max(body.radius, ballRadius(simulation, 'body', 2))\n const x = columns * (0.14 + 0.38 * bodyAmount)\n rollBallTo(body, x, restingBallY(simulation, x, body.radius, rows - 1))\n body.locked = time >= schedule.bodyEnd\n }\n if (time >= schedule.headStart && !simulation.head) {\n const x = columns * (schedule.mode === 'full' ? 0.88 : 0.66)\n simulation.head = {\n kind: 'head',\n x,\n y: restingBallY(simulation, x, 1.7, rows - 1),\n radius: 1.7,\n angle: 0,\n locked: false,\n }\n collectTouchedGround(simulation)\n }\n const head = simulation.head\n if (head && body && !head.locked) {\n head.radius = Math.max(head.radius, ballRadius(simulation, 'head', 1.7))\n if (time < schedule.hopStart) {\n const rolling = ease(amount(time, schedule.headStart, schedule.hopStart))\n const x = columns * (0.88 - 0.22 * rolling)\n rollBallTo(head, x, restingBallY(simulation, x, head.radius, rows - 1))\n } else {\n head.launch ??= { x: head.x, y: head.y }\n const hop = amount(time, schedule.hopStart, schedule.land)\n const seatY = body.y - body.radius - head.radius + 0.5\n head.x = head.launch.x + (body.x - head.launch.x) * ease(hop)\n head.y =\n head.launch.y +\n (seatY - head.launch.y) * ease(hop) -\n Math.sin(Math.PI * hop) * Math.max(5, body.radius * 1.5)\n if (time >= schedule.land) {\n const settle = amount(time, schedule.land, schedule.settleEnd)\n head.y += Math.sin(Math.PI * settle) * 0.45\n }\n head.locked = time >= schedule.settleEnd\n }\n }\n if (head && time >= schedule.land) {\n const drop = amount(time, schedule.land, schedule.end)\n simulation.hat = {\n x: head.x,\n y: head.y - head.radius - 1 - 5 * (1 - drop * drop),\n angle: (1 - ease(drop)) * -0.22,\n }\n }\n}\n\nfunction rollBallTo(ball: Snowball, x: number, y: number) {\n const nextY = moveToward(ball.y, y, 0.16)\n const dx = x - ball.x\n ball.angle += (Math.sign(dx) * Math.hypot(dx, nextY - ball.y)) / Math.max(ball.radius, 1)\n ball.x = x\n ball.y = nextY\n}\n\nfunction collectTouchedGround(simulation: SnowmanSimulation) {\n const resolved = resolvedCells(simulation)\n const originals = new Map(simulation.cells.map((cell) => [cell.id, cell]))\n const groundCoordinates = new Set(\n resolved\n .filter((cell) => cell.owner === 'ground')\n .map((cell) => key(Math.round(cell.x), Math.round(cell.y))),\n )\n const exposedGround = new Set(\n resolved\n .filter((cell) => cell.owner === 'ground')\n .filter((cell) => !groundCoordinates.has(key(Math.round(cell.x), Math.round(cell.y) - 1)))\n .map((cell) => cell.id),\n )\n for (const ball of [simulation.body, simulation.head]) {\n if (!ball || ball.locked) continue\n const owner = ball.kind\n const captureRadius = ball.radius + 0.75\n for (const cell of resolved) {\n if (!canCollect(simulation, ball)) break\n if (cell.owner !== 'ground') continue\n const dx = cell.x - ball.x\n const dy = cell.y - ball.y\n const distance = Math.hypot(dx, dy)\n // The roller takes only exposed grains on its lower, leading contact arc. Capturing buried\n // cells makes the ball appear to hook loose snow into the air behind it.\n if (!exposedGround.has(cell.id) || distance > captureRadius || dy < -ball.radius * 0.2)\n continue\n const original = originals.get(cell.id)\n if (!original) continue\n joinBall(simulation, ball, original.id, dx, dy)\n }\n ball.radius = Math.max(\n ball.radius,\n ballRadius(simulation, owner, ball.kind === 'body' ? 2 : 1.7),\n )\n }\n}\n\nfunction canCollect(simulation: SnowmanSimulation, ball: Snowball) {\n if (ball.kind === 'body' || !simulation.body) return true\n const bodyRadius = simulation.body.radius\n const targetHeadRadius = bodyRadius * 0.72\n const maxHeadCount = Math.max(\n 12,\n Math.round(Math.PI * (Math.max(0, targetHeadRadius - 1.7) / 0.6) ** 2),\n )\n return simulation.cells.filter((cell) => cell.owner === 'head').length < maxHeadCount\n}\n\nfunction hitBall(simulation: SnowmanSimulation, flake: AirborneFlake) {\n const candidates = [simulation.body, simulation.head].filter(\n (ball): ball is Snowball => ball !== undefined && !ball.locked,\n )\n return candidates.find(\n (ball) =>\n canCollect(simulation, ball) && Math.hypot(flake.x - ball.x, flake.y - ball.y) <= ball.radius,\n )\n}\n\nfunction joinBall(\n simulation: SnowmanSimulation,\n ball: Snowball,\n id: number,\n localX: number,\n localY: number,\n) {\n const cosine = Math.cos(-ball.angle)\n const sine = Math.sin(-ball.angle)\n const rotatedX = localX * cosine - localY * sine\n localY = localX * sine + localY * cosine\n localX = rotatedX\n const cell = simulation.cells.find((candidate) => candidate.id === id)\n const target = ballInteriorSlot(simulation, ball, id)\n const start = openBallPosition(simulation, ball, localX, localY, id)\n const next = {\n id,\n x: ball.x + start.x,\n y: ball.y + start.y,\n owner: ball.kind,\n localX: start.x,\n localY: start.y,\n targetLocalX: target.x,\n targetLocalY: target.y,\n }\n if (cell) Object.assign(cell, next)\n else simulation.cells.push(next)\n ball.radius = Math.max(\n ball.radius,\n ballRadius(simulation, ball.kind, ball.kind === 'body' ? 2 : 1.7),\n )\n rebalanceBallTargets(simulation, ball)\n}\n\nfunction openBallPosition(\n simulation: SnowmanSimulation,\n ball: Snowball,\n localX: number,\n localY: number,\n id: number,\n) {\n const cells = simulation.cells.filter((cell) => cell.id !== id && cell.owner === ball.kind)\n const free = (x: number, y: number) =>\n cells.every((cell) => Math.hypot((cell.localX ?? 0) - x, (cell.localY ?? 0) - y) >= 0.75)\n if (free(localX, localY)) return { x: localX, y: localY }\n // Search outward from the contact, retaining already packed grains in their material frame.\n for (let radius = 0.75; ; radius += 0.75) {\n for (let i = 0; i < 32; i++) {\n const angle = (i * Math.PI) / 16\n const x = localX + Math.cos(angle) * radius\n const y = localY + Math.sin(angle) * radius\n if ((Math.hypot(x, y) <= ball.radius + 0.75 || radius > ball.radius * 2) && free(x, y)) {\n ball.radius = Math.max(ball.radius, Math.hypot(x, y) - 0.5)\n return { x, y }\n }\n }\n }\n}\n\nfunction ballInteriorSlot(simulation: SnowmanSimulation, ball: Snowball, id: number) {\n const existing = simulation.cells.filter(\n (cell) =>\n cell.owner === ball.kind &&\n cell.targetLocalX !== undefined &&\n cell.targetLocalY !== undefined,\n )\n const free = (x: number, y: number, minDistance = 0.72) =>\n existing.every(\n (cell) =>\n Math.hypot((cell.targetLocalX ?? 0) - x, (cell.targetLocalY ?? 0) - y) >= minDistance,\n )\n for (let attempt = 0; attempt < 64; attempt += 1) {\n const angle = random(id * 31 + attempt * 17) * Math.PI * 2\n const distance = Math.sqrt(random(id * 37 + attempt * 19)) * Math.max(0.4, ball.radius - 0.35)\n const x = Math.cos(angle) * distance\n const y = Math.sin(angle) * distance\n if (free(x, y)) return { x, y }\n }\n for (let radius = 0.4; radius <= ball.radius - 0.35; radius += 0.5) {\n const steps = Math.max(6, Math.round((2 * Math.PI * radius) / 0.72))\n for (let i = 0; i < steps; i++) {\n const angle = (i * Math.PI * 2) / steps + random(id * 13)\n const x = Math.cos(angle) * radius\n const y = Math.sin(angle) * radius\n if (free(x, y, 0.6)) return { x, y }\n }\n }\n return { x: 0, y: 0 }\n}\n\nfunction compactBallCells(simulation: SnowmanSimulation) {\n for (const cell of simulation.cells) {\n if (\n cell.packed ||\n cell.localX === undefined ||\n cell.localY === undefined ||\n cell.targetLocalX === undefined ||\n cell.targetLocalY === undefined\n )\n continue\n const x = moveToward(cell.localX, cell.targetLocalX, 0.25)\n const y = moveToward(cell.localY, cell.targetLocalY, 0.25)\n cell.localX = x\n cell.localY = y\n cell.packed = x === cell.targetLocalX && y === cell.targetLocalY\n }\n}\n\n/** Reassigns the material to a dense lattice so newly collected snow compresses older grains. */\nfunction rebalanceBallTargets(simulation: SnowmanSimulation, ball: Snowball) {\n const cells = simulation.cells.filter(\n (cell) => cell.owner === ball.kind && cell.localX !== undefined && cell.localY !== undefined,\n )\n const slots = denseBallSlots(ball.radius, cells.length)\n cells.sort((first, second) => first.id - second.id)\n for (const [index, cell] of cells.entries()) {\n const slot = slots[index]\n if (!slot) break\n cell.targetLocalX = slot.x\n cell.targetLocalY = slot.y\n cell.packed = false\n }\n}\n\nfunction denseBallSlots(radius: number, count: number) {\n const boundary = Math.max(0.2, radius - 0.1)\n const candidates: Array<{ x: number; y: number }> = []\n const spacing = 0.9\n const vertical = (spacing * Math.sqrt(3)) / 2\n for (let row = -Math.ceil(boundary / vertical); row <= Math.ceil(boundary / vertical); row += 1) {\n const y = row * vertical\n const offset = (row & 1) === 0 ? 0 : spacing / 2\n for (\n let column = -Math.ceil(boundary / spacing);\n column <= Math.ceil(boundary / spacing);\n column += 1\n ) {\n const x = column * spacing + offset\n if (Math.hypot(x, y) <= boundary) candidates.push({ x, y })\n }\n }\n candidates.sort((first, second) => Math.hypot(first.x, first.y) - Math.hypot(second.x, second.y))\n const slots: Array<{ x: number; y: number }> = []\n for (const candidate of candidates) {\n if (slots.every((slot) => Math.hypot(slot.x - candidate.x, slot.y - candidate.y) >= 0.82))\n slots.push(candidate)\n if (slots.length === count) break\n }\n return slots\n}\n\nexport function resolvedHat(simulation: SnowmanSimulation) {\n if (!simulation.hat) return undefined\n return simulation.toppling\n ? {\n ...rotateAround(simulation.hat, simulation.toppling),\n angle: simulation.hat.angle + simulation.toppling.angle,\n }\n : simulation.hat\n}\n\n/** Interpolate presentation only; particle identities and physics remain on the fixed clock. */\nexport function interpolateSnowman(\n previous: SnowmanSimulation,\n next: SnowmanSimulation,\n fraction: number,\n) {\n const scene = clone(next)\n const mix = (a: number, b: number) => a + (b - a) * clamp(fraction, 0, 1)\n for (const kind of ['body', 'head'] as const) {\n const a = previous[kind],\n b = scene[kind]\n if (a && b) {\n b.x = mix(a.x, b.x)\n b.y = mix(a.y, b.y)\n b.angle = mix(a.angle, b.angle)\n }\n }\n const oldFlakes = new Map(previous.flakes.map((flake) => [flake.id, flake]))\n for (const flake of scene.flakes) {\n const old = oldFlakes.get(flake.id)\n if (old) {\n flake.x = mix(old.x, flake.x)\n flake.y = mix(old.y, flake.y)\n }\n }\n if (scene.toppling && previous.toppling)\n scene.toppling.angle = mix(previous.toppling.angle, scene.toppling.angle)\n if (scene.hat && previous.hat)\n scene.hat = {\n x: mix(previous.hat.x, scene.hat.x),\n y: mix(previous.hat.y, scene.hat.y),\n angle: mix(previous.hat.angle, scene.hat.angle),\n }\n return scene\n}\n\nfunction occupiedCells(simulation: SnowmanSimulation) {\n const occupied = new Map<string, SnowCellOwner>()\n for (const cell of resolvedCells(simulation))\n occupied.set(key(Math.round(cell.x), Math.round(cell.y)), cell.owner)\n return occupied\n}\n\n/** Lets a settled bank creep into a newly cleared trench instead of preserving impossible voids. */\nfunction relaxSettledSnow(simulation: SnowmanSimulation, seed: number, elapsed: number) {\n const occupied = occupiedCells(simulation)\n const ground = simulation.cells\n .filter((cell) => cell.owner === 'ground')\n .sort((first, second) => second.y - first.y || first.x - second.x)\n for (const cell of ground) {\n const below = key(cell.x, cell.y + 1)\n if (cell.y < simulation.grid.rows - 1 && !occupied.has(below)) {\n occupied.delete(key(cell.x, cell.y))\n cell.y += 1\n occupied.set(key(cell.x, cell.y), cell.owner)\n continue\n }\n const preferred = random(seed + cell.id * 29 + elapsed) < 0.5 ? -1 : 1\n for (const direction of [preferred, -preferred]) {\n const x = cell.x + direction\n if (\n x < 0 ||\n x >= simulation.grid.columns ||\n cell.y >= simulation.grid.rows - 1 ||\n occupied.has(key(x, cell.y)) ||\n occupied.has(key(x, cell.y + 1))\n )\n continue\n occupied.delete(key(cell.x, cell.y))\n cell.x = x\n cell.y += 1\n occupied.set(key(cell.x, cell.y), cell.owner)\n break\n }\n }\n}\n\nfunction findRestingCell(\n flake: AirborneFlake,\n occupied: Map<string, SnowCellOwner>,\n grid: SnowmanSimulation['grid'],\n wind: number,\n seed: number,\n) {\n const x = Math.round(flake.x)\n const y = Math.round(flake.y)\n if (y < 0) return undefined\n if (y >= grid.rows - 1) return { x, y: grid.rows - 1 }\n if (!occupied.has(key(x, y + 1))) return undefined\n const preferred = wind >= 0 ? 1 : -1\n const alternate = random(seed + flake.id * 71 + y) > 0.5 ? preferred : -preferred\n for (const offset of [alternate, -alternate]) {\n const side = x + offset\n if (\n side >= 0 &&\n side < grid.columns &&\n !occupied.has(key(side, y + 1)) &&\n !occupied.has(key(side, y))\n )\n return { x: side, y: y + 1 }\n }\n return occupied.has(key(x, y)) ? { x, y: Math.max(0, y - 1) } : { x, y }\n}\n\nfunction restingBallY(simulation: SnowmanSimulation, x: number, radius: number, fallback: number) {\n const cells = resolvedCells(simulation).filter(\n (cell) => cell.owner === 'ground' && Math.abs(cell.x - x) <= radius,\n )\n const surface = cells.length ? Math.min(...cells.map((cell) => cell.y)) : fallback\n return surface - radius\n}\nfunction ballRadius(simulation: SnowmanSimulation, owner: 'body' | 'head', minimum: number) {\n const count = simulation.cells.filter((cell) => cell.owner === owner).length\n return minimum + Math.sqrt(count / Math.PI) * 0.5\n}\nfunction beginTopple(simulation: SnowmanSimulation, elapsed: number) {\n const body = simulation.body\n if (!body) return\n simulation.toppling = {\n startedAt: elapsed,\n angle: 0,\n pivotX: body.x,\n pivotY: body.y + body.radius * 0.72,\n }\n}\n\nfunction advanceTopple(simulation: SnowmanSimulation, elapsed: number) {\n const toppling = simulation.toppling\n if (!toppling) return\n const progress = clamp((elapsed - toppling.startedAt) / 750, 0, 1)\n // Ease-in keeps the initial loss of balance readable; ease-out lets the body settle rather than snap.\n toppling.angle = (1 - (1 - progress) ** 3) * (Math.PI / 2)\n if (progress === 1) simulation.toppled = true\n}\n\nfunction rotateAround<T extends { x: number; y: number }>(\n point: T,\n toppling: NonNullable<SnowmanSimulation['toppling']>,\n) {\n const cosine = Math.cos(toppling.angle)\n const sine = Math.sin(toppling.angle)\n const x = point.x - toppling.pivotX\n const y = point.y - toppling.pivotY\n return {\n ...point,\n x: toppling.pivotX + x * cosine - y * sine,\n y: toppling.pivotY + x * sine + y * cosine,\n }\n}\nfunction clone(simulation: SnowmanSimulation): SnowmanSimulation {\n return {\n ...simulation,\n grid: { ...simulation.grid },\n hat: simulation.hat && { ...simulation.hat },\n flakes: simulation.flakes.map((flake) => ({ ...flake })),\n cells: simulation.cells.map((cell) => ({ ...cell })),\n body: simulation.body && { ...simulation.body },\n head: simulation.head && { ...simulation.head },\n toppling: simulation.toppling && { ...simulation.toppling },\n }\n}\nfunction key(x: number, y: number) {\n return `${x}:${y}`\n}\nfunction clamp(value: number, low: number, high: number) {\n return Math.max(low, Math.min(high, value))\n}\nfunction moveToward(current: number, target: number, maximumStep: number) {\n if (Math.abs(target - current) <= maximumStep) return target\n return current + Math.sign(target - current) * maximumStep\n}\nfunction random(value: number) {\n const sine = Math.sin(value * 12.9898) * 43758.5453\n return sine - Math.floor(sine)\n}\n","import { resolvedCells, resolvedHat, type SnowmanSimulation } from './snowman.ts'\n\nexport function drawSnowmanCanvas(\n canvas: HTMLCanvasElement | null,\n simulation: SnowmanSimulation,\n dimensions: { width: number; height: number },\n) {\n if (!canvas) return\n const context = canvas.getContext('2d')\n if (!context) return\n const scale = window.devicePixelRatio || 1\n const width = Math.max(1, Math.round(dimensions.width))\n const height = Math.max(1, Math.round(dimensions.height))\n if (canvas.width !== width * scale || canvas.height !== height * scale) {\n canvas.width = width * scale\n canvas.height = height * scale\n canvas.style.width = `${width}px`\n canvas.style.height = `${height}px`\n }\n context.setTransform(scale, 0, 0, scale, 0, 0)\n context.clearRect(0, 0, width, height)\n const cellWidth = width / simulation.grid.columns\n const cellHeight = height / simulation.grid.rows\n context.fillStyle = 'rgba(244, 241, 223, 0.52)'\n for (const cell of resolvedCells(simulation))\n drawDot(context, (cell.x + 0.5) * cellWidth, (cell.y + 0.5) * cellHeight, cellWidth, cellHeight)\n context.fillStyle = 'rgba(244, 241, 223, 0.76)'\n for (const flake of simulation.flakes)\n drawDot(\n context,\n (flake.x + 0.5) * cellWidth,\n (flake.y + 0.5) * cellHeight,\n cellWidth * 0.72,\n cellHeight * 0.72,\n )\n const hat = resolvedHat(simulation)\n if (hat && simulation.head) {\n const radius = simulation.head.radius\n context.save()\n context.translate(hat.x * cellWidth, hat.y * cellHeight)\n context.scale(cellWidth, cellHeight)\n context.rotate(hat.angle)\n context.fillStyle = 'rgba(27, 31, 24, 0.78)'\n context.fillRect(-radius * 0.65, -2, radius * 1.3, 2)\n context.fillRect(-radius, -0.3, radius * 2, 0.45)\n context.restore()\n }\n}\n\nfunction drawDot(\n context: CanvasRenderingContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n) {\n context.beginPath()\n context.arc(x, y, Math.max(0.8, Math.min(width, height) * 0.42), 0, Math.PI * 2)\n context.fill()\n}\n","import { useEffect, useRef, useState } from 'react'\nimport styles from './SnowmanField.module.css'\nimport {\n advanceSnowmanSimulation,\n createSnowmanSimulation,\n interpolateSnowman,\n snowmanScenePhase,\n} from './snowman.ts'\nimport { drawSnowmanCanvas } from './snowman-canvas.ts'\n\n/** A dense, seeded canvas snow scene. It remains decorative and never holds panel data. */\nexport function SnowmanField({\n progress,\n estimatedDurationMs,\n overdue,\n seed = 0,\n}: {\n progress: number\n estimatedDurationMs?: number\n overdue: boolean\n seed?: number\n}) {\n const rootRef = useRef<HTMLDivElement>(null)\n const canvasRef = useRef<HTMLCanvasElement>(null)\n const [dimensions, setDimensions] = useState({ width: 360, height: 180 })\n const [reducedMotion, setReducedMotion] = useState(\n () => window.matchMedia('(prefers-reduced-motion: reduce)').matches,\n )\n\n const progressRef = useRef(progress)\n const overdueRef = useRef(overdue)\n const state = useRef({\n startedAt: Date.now(),\n progressAt: Date.now(),\n progress,\n simulation: createSnowmanSimulation(),\n })\n\n useEffect(() => {\n progressRef.current = progress\n state.current.progressAt = Date.now()\n state.current.progress = progress\n }, [progress])\n useEffect(() => {\n overdueRef.current = overdue\n }, [overdue])\n useEffect(() => {\n const media = window.matchMedia('(prefers-reduced-motion: reduce)')\n const update = () => setReducedMotion(media.matches)\n update()\n media.addEventListener?.('change', update)\n return () => media.removeEventListener?.('change', update)\n }, [])\n useEffect(() => {\n const root = rootRef.current\n if (!root) return\n const update = () => {\n const rect = root.getBoundingClientRect()\n if (rect.width > 0 && rect.height > 0)\n setDimensions({ width: rect.width, height: rect.height })\n }\n update()\n if (typeof ResizeObserver === 'undefined') return\n const observer = new ResizeObserver(update)\n observer.observe(root)\n return () => observer.disconnect()\n }, [])\n useEffect(() => {\n if (reducedMotion) return\n state.current.simulation = createSnowmanSimulation(dimensions)\n let frame = 0\n const paint = () => {\n const current = state.current\n const elapsed =\n estimatedDurationMs === undefined\n ? Date.now() - current.startedAt\n : current.progress * estimatedDurationMs + (Date.now() - current.progressAt)\n const options = {\n progress: progressRef.current,\n estimatedDurationMs,\n overdue: overdueRef.current,\n seed,\n dimensions,\n }\n const next = advanceSnowmanSimulation(current.simulation, { ...options, elapsed })\n current.simulation = next\n const future = advanceSnowmanSimulation(next, { ...options, elapsed: next.lastElapsed + 25 })\n const scene = interpolateSnowman(next, future, (elapsed - next.lastElapsed) / 25)\n drawSnowmanCanvas(canvasRef.current, scene, dimensions)\n const root = rootRef.current\n if (root) {\n root.dataset.snowCellCount = String(next.cells.length)\n root.dataset.snowDensity = next.grid.columns < 65 ? 'compact' : 'full'\n if (next.toppled) root.dataset.snowmanToppled = 'true'\n else delete root.dataset.snowmanToppled\n }\n if (!reducedMotion) frame = window.requestAnimationFrame(paint)\n }\n frame = window.requestAnimationFrame(paint)\n return () => window.cancelAnimationFrame(frame)\n }, [dimensions, estimatedDurationMs, reducedMotion, seed])\n useEffect(() => {\n if (!reducedMotion) return\n const scene = advanceSnowmanSimulation(createSnowmanSimulation(dimensions), {\n elapsed: estimatedDurationMs === undefined ? 4800 : progress * estimatedDurationMs,\n progress,\n estimatedDurationMs,\n overdue,\n seed,\n dimensions,\n })\n drawSnowmanCanvas(canvasRef.current, scene, dimensions)\n if (rootRef.current) {\n rootRef.current.dataset.snowCellCount = String(scene.cells.length)\n if (scene.toppled) rootRef.current.dataset.snowmanToppled = 'true'\n else delete rootRef.current.dataset.snowmanToppled\n }\n }, [dimensions, estimatedDurationMs, overdue, progress, reducedMotion, seed])\n const phase = snowmanScenePhase(progress, estimatedDurationMs, overdue)\n return (\n <div\n ref={rootRef}\n className={styles.field}\n data-running-part=\"snowman-field\"\n data-snowman-phase={phase}\n data-reduced-motion={reducedMotion || undefined}\n >\n <canvas ref={canvasRef} className={styles.canvas} data-running-part=\"snowman-canvas\" />\n </div>\n )\n}\n",".haze {\n position: absolute;\n inset: -15%;\n background:\n radial-gradient(\n ellipse at 18% 44%,\n color-mix(in srgb, currentColor 19%, transparent),\n transparent 42%\n ),\n radial-gradient(\n ellipse at 74% 63%,\n color-mix(in srgb, currentColor 12%, transparent),\n transparent 38%\n );\n animation: haze 15s ease-in-out infinite alternate;\n}\n.pressure {\n display: none;\n}\n.band {\n position: absolute;\n right: -15%;\n left: -15%;\n height: 1px;\n background: linear-gradient(\n 90deg,\n transparent,\n color-mix(in srgb, currentColor 32%, transparent),\n transparent\n );\n animation: band 10s ease-in-out infinite alternate;\n}\n.bandOne {\n top: 32%;\n}\n.bandTwo {\n top: 67%;\n animation-delay: -4s;\n}\n.bandThree {\n top: 49%;\n animation-delay: -7s;\n opacity: 0.55;\n}\n.drift {\n position: absolute;\n width: clamp(0.34em, 0.9cqw, 0.7em);\n height: clamp(0.34em, 0.9cqw, 0.7em);\n border: 1px solid color-mix(in srgb, currentColor 78%, transparent);\n border-radius: 50%;\n box-shadow: 0 0 0.55em color-mix(in srgb, currentColor 55%, transparent);\n animation: drift 11s ease-in-out infinite alternate;\n}\n.driftOne {\n top: 25%;\n left: 12%;\n}\n.driftTwo {\n top: 72%;\n left: 58%;\n width: 0.34em;\n height: 0.34em;\n animation-duration: 14s;\n animation-delay: -4s;\n opacity: 0.6;\n}\n.driftThree {\n top: 18%;\n left: 74%;\n width: 0.7em;\n height: 0.7em;\n animation-duration: 17s;\n animation-delay: -9s;\n opacity: 0.55;\n}\n.driftFour {\n top: 58%;\n left: 31%;\n width: 0.42em;\n height: 0.42em;\n animation-duration: 9s;\n animation-delay: -2s;\n opacity: 0.75;\n}\n.driftFive {\n top: 84%;\n left: 83%;\n width: 0.58em;\n height: 0.58em;\n animation-duration: 13s;\n animation-delay: -6s;\n opacity: 0.45;\n}\n@container running-field (max-width: 40rem) or (max-height: 6rem) {\n .drift,\n .band {\n display: none;\n }\n .haze {\n inset: auto 0 0 auto;\n width: 2.5em;\n height: 2.5em;\n opacity: 0.65;\n }\n}\n[data-overdue=\"true\"] .haze {\n inset: -30%;\n background:\n radial-gradient(\n ellipse at 22% 48%,\n color-mix(in srgb, currentColor 34%, transparent),\n transparent 42%\n ),\n radial-gradient(\n ellipse at 78% 58%,\n color-mix(in srgb, currentColor 25%, transparent),\n transparent 36%\n );\n}\n[data-overdue=\"true\"] .pressure {\n display: block;\n position: absolute;\n inset: 20% 0;\n border-top: 1px solid color-mix(in srgb, currentColor 65%, transparent);\n border-bottom: 1px solid color-mix(in srgb, currentColor 65%, transparent);\n background: repeating-linear-gradient(\n 180deg,\n transparent 0 0.55em,\n color-mix(in srgb, currentColor 14%, transparent) 0.55em 0.62em\n );\n opacity: 0.75;\n animation: pressure 3.4s ease-in-out infinite alternate;\n}\n[data-overdue=\"true\"] .band {\n background: linear-gradient(90deg, transparent, currentColor, transparent);\n animation-name: storm-band;\n}\n[data-overdue=\"true\"] .drift {\n transform: translate(12cqw, -2cqh) scale(0.82);\n}\n@keyframes haze {\n to {\n transform: translate(9%, -4%);\n }\n}\n@keyframes band {\n to {\n transform: translateX(8%);\n opacity: 0.45;\n }\n}\n@keyframes drift {\n to {\n transform: translate(10cqw, -2cqh);\n }\n}\n@keyframes pressure {\n from {\n transform: scaleY(0.72);\n opacity: 0.45;\n }\n to {\n transform: scaleY(1.12);\n opacity: 0.9;\n }\n}\n@keyframes storm-band {\n to {\n transform: translateX(-14%);\n opacity: 0.9;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n [data-overdue=\"true\"] .pressure,\n .haze,\n .band,\n .drift {\n animation: none;\n }\n .pressure {\n animation: none;\n }\n}\n","import styles from './StatusWeatherField.module.css'\n\nexport function StatusWeatherField() {\n return (\n <>\n <span className={styles.haze} data-running-part=\"weather-haze\" />\n <span className={styles.pressure} data-running-part=\"weather-pressure\" />\n <span className={`${styles.band} ${styles.bandOne}`} />\n <span className={`${styles.band} ${styles.bandTwo}`} />\n <span className={`${styles.band} ${styles.bandThree}`} />\n <span className={`${styles.drift} ${styles.driftOne}`} />\n <span className={`${styles.drift} ${styles.driftTwo}`} />\n <span className={`${styles.drift} ${styles.driftThree}`} />\n <span className={`${styles.drift} ${styles.driftFour}`} />\n <span className={`${styles.drift} ${styles.driftFive}`} />\n </>\n )\n}\n",".anchor {\n position: absolute;\n top: 50%;\n left: var(--running-progress);\n}\n.body {\n position: absolute;\n inset: 0;\n animation: phased-marker 3.2s ease-in-out infinite alternate;\n animation-delay: var(--phased-marker-delay, 0s);\n will-change: transform;\n}\n@keyframes phased-marker {\n from {\n transform: translate(var(--phased-marker-travel, -10em), -50%);\n }\n to {\n transform: translate(-50%, -50%);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .body {\n animation: none;\n }\n}\n","import type { CSSProperties } from 'react'\nimport styles from './PhasedProgressMarker.module.css'\n\n/**\n * A progress-anchored decorative marker. The anchor owns live progress geometry; the body owns\n * its independent phase animation, so a timing render cannot replace its transform.\n */\nexport function PhasedProgressMarker({\n anchorClassName,\n bodyClassName,\n delay,\n anchorPart,\n bodyPart,\n}: {\n anchorClassName: string | undefined\n bodyClassName: string | undefined\n delay?: string\n anchorPart?: string\n bodyPart: string\n}) {\n const style = delay ? ({ '--phased-marker-delay': delay } as CSSProperties) : undefined\n return (\n <span className={`${styles.anchor} ${anchorClassName ?? ''}`} data-running-part={anchorPart}>\n <span\n className={`${styles.body} ${bodyClassName ?? ''}`}\n data-running-part={bodyPart}\n style={style}\n />\n </span>\n )\n}\n",".frontier {\n position: absolute;\n inset: 0 auto 0 0;\n width: var(--running-progress);\n background: linear-gradient(\n 90deg,\n color-mix(in srgb, currentColor 16%, transparent),\n transparent\n );\n border-right: 1px solid color-mix(in srgb, currentColor 75%, transparent);\n}\n.flare {\n display: none;\n}\n.lanes {\n position: absolute;\n inset: 13% 7%;\n display: grid;\n align-content: space-between;\n}\n.lane {\n position: relative;\n height: 1px;\n background: linear-gradient(\n 90deg,\n transparent,\n color-mix(in srgb, var(--edge) 90%, transparent),\n transparent\n );\n}\n.markerAnchor {\n width: 0.42em;\n height: 0.25em;\n}\n.markerBody {\n --phased-marker-travel: -10cqw;\n border-radius: 999px;\n background: currentColor;\n box-shadow: 0 0 0.6em currentColor;\n}\n.lane:nth-child(2) .markerBody {\n opacity: 0.7;\n}\n.lane:nth-child(3) .markerBody {\n opacity: 0.5;\n}\n.lane:nth-child(4) .markerBody {\n opacity: 0.8;\n}\n@container running-field (max-width: 40rem) or (max-height: 6rem) {\n .lanes {\n display: none;\n }\n .frontier {\n width: 0.28em;\n border-right: 0;\n background: currentColor;\n }\n}\n[data-overdue=\"true\"] .frontier {\n width: 100%;\n background: linear-gradient(\n 90deg,\n color-mix(in srgb, currentColor 34%, transparent),\n transparent\n );\n border-right-color: currentColor;\n}\n[data-overdue=\"true\"] .flare {\n display: block;\n position: absolute;\n top: 0;\n left: 100%;\n width: 2.4em;\n height: 100%;\n background: radial-gradient(ellipse, currentColor 0, transparent 68%);\n transform: translateX(-50%);\n animation: bloom-flare 1.6s ease-in-out infinite alternate;\n}\n[data-overdue=\"true\"] .markerBody {\n --phased-marker-travel: -22.5cqw;\n animation-duration: 0.72s;\n animation-timing-function: ease-in-out;\n}\n@media (prefers-reduced-motion: reduce) {\n .frontier {\n transition: none;\n }\n [data-overdue=\"true\"] .flare,\n [data-overdue=\"true\"] .markerBody {\n animation: none;\n }\n}\n@keyframes bloom-flare {\n from {\n opacity: 0.42;\n transform: translateX(-50%) scale(0.8);\n }\n to {\n opacity: 0.95;\n transform: translateX(-50%) scale(1.15);\n }\n}\n","import { PhasedProgressMarker } from './PhasedProgressMarker.tsx'\nimport styles from './TelemetryBloomField.module.css'\n\nexport function TelemetryBloomField() {\n return (\n <>\n <span className={styles.frontier} data-running-part=\"frontier\" />\n <span className={styles.flare} data-running-part=\"bloom-flare\" />\n <span className={styles.lanes} data-running-part=\"bloom-lanes\">\n {[0, 1, 2, 3].map((lane) => (\n <span className={styles.lane} key={lane} data-running-part=\"bloom-lane\">\n <PhasedProgressMarker\n anchorClassName={styles.markerAnchor}\n bodyClassName={styles.markerBody}\n delay={[undefined, '-0.8s', '-1.7s', '-2.4s'][lane]}\n anchorPart=\"bloom-marker-anchor\"\n bodyPart=\"bloom-marker\"\n />\n </span>\n ))}\n </span>\n </>\n )\n}\n","import type { RunningAnimation } from '@ze-great-dashboard/shared'\nimport type { CSSProperties } from 'react'\nimport { FallingShapesField } from './FallingShapesField.tsx'\nimport { ReleaseTransitField } from './ReleaseTransitField.tsx'\nimport styles from './RunningField.module.css'\nimport { SnowmanField } from './SnowmanField.tsx'\nimport { StatusWeatherField } from './StatusWeatherField.tsx'\nimport { TelemetryBloomField } from './TelemetryBloomField.tsx'\n\nexport type RunningFieldAnimation = Extract<\n RunningAnimation,\n 'telemetry-bloom' | 'release-transit' | 'status-weather' | 'falling-shapes' | 'snowman'\n>\n\nexport function isRunningFieldAnimation(\n animation: Exclude<RunningAnimation, 'off'>,\n): animation is RunningFieldAnimation {\n return [\n 'telemetry-bloom',\n 'release-transit',\n 'status-weather',\n 'falling-shapes',\n 'snowman',\n ].includes(animation)\n}\n\nexport function RunningField({\n animation,\n progress,\n estimatedDurationMs,\n overdue,\n indeterminate,\n seed,\n}: {\n animation: RunningFieldAnimation\n progress: number\n estimatedDurationMs?: number\n overdue: boolean\n indeterminate: boolean\n seed?: number\n}) {\n const style = {\n '--running-progress': `${progress * 100}%`,\n } as CSSProperties\n return (\n <div\n className={`${styles.field} ${overdue ? styles.overdue : ''}`}\n data-animation={animation}\n data-running-field\n data-overdue={overdue || undefined}\n data-indeterminate={indeterminate || undefined}\n aria-hidden=\"true\"\n style={style}\n >\n {animation === 'telemetry-bloom' && <TelemetryBloomField />}\n {animation === 'release-transit' && <ReleaseTransitField />}\n {animation === 'status-weather' && <StatusWeatherField />}\n {animation === 'falling-shapes' && (\n <FallingShapesField\n progress={progress}\n estimatedDurationMs={estimatedDurationMs}\n overdue={overdue}\n seed={seed}\n />\n )}\n {animation === 'snowman' && (\n <SnowmanField\n progress={progress}\n estimatedDurationMs={estimatedDurationMs}\n overdue={overdue}\n seed={seed}\n />\n )}\n </div>\n )\n}\n","import { useEffect, useState } from 'react'\n\nconst VISUAL_TICK_MS = 20\n\nexport type RunningTiming = {\n elapsedMs: number | undefined\n estimatedDurationMs: number | undefined\n hasEstimate: boolean\n overdue: boolean\n progress: number\n}\n\nexport function useRunningTiming(\n runStartedAt?: string,\n estimatedDurationMs?: number,\n): RunningTiming {\n const now = useClock(Boolean(runStartedAt))\n const startedAt = runStartedAt ? new Date(runStartedAt).valueOf() : Number.NaN\n const elapsedMs = Number.isFinite(startedAt) ? Math.max(0, now - startedAt) : undefined\n const hasEstimate = elapsedMs !== undefined && estimatedDurationMs !== undefined\n const overdue = hasEstimate && elapsedMs > estimatedDurationMs\n const progress = hasEstimate ? Math.min(elapsedMs / estimatedDurationMs, 1) : 0\n return { elapsedMs, estimatedDurationMs, hasEstimate, overdue, progress }\n}\n\nfunction useClock(enabled: boolean) {\n const [now, setNow] = useState(() => Date.now())\n useEffect(() => {\n if (!enabled) return\n setNow(Date.now())\n // The timing text rounds to seconds, but progress gets display-cadence intermediate positions.\n // This avoids the visible sawtooth created by a coarse timer and CSS transition.\n const interval = window.setInterval(() => setNow(Date.now()), VISUAL_TICK_MS)\n return () => window.clearInterval(interval)\n }, [enabled])\n return now\n}\n\nexport function timingDescription(\n elapsedMs: number | undefined,\n estimatedDurationMs: number | undefined,\n overdue: boolean,\n) {\n const elapsed =\n elapsedMs === undefined ? 'Run in progress' : `Elapsed ${formatDuration(elapsedMs)}`\n const expected =\n estimatedDurationMs === undefined\n ? 'Expected duration unavailable'\n : `Expected ≈ ${formatDuration(estimatedDurationMs)}`\n return `${elapsed} · ${expected}${overdue ? ' · Over estimate' : ''}`\n}\n\nexport function compactTiming(\n elapsedMs: number | undefined,\n estimatedDurationMs: number | undefined,\n overdue: boolean,\n) {\n const elapsed = elapsedMs === undefined ? '—' : formatClockDuration(elapsedMs)\n const expected =\n estimatedDurationMs === undefined ? '?' : `~${formatClockDuration(estimatedDurationMs)}`\n return `${overdue ? '⚠' : '\\u00a0'}${elapsed}/${expected}`\n}\n\nfunction formatDuration(durationMs: number) {\n const totalSeconds = Math.floor(durationMs / 1_000)\n const hours = Math.floor(totalSeconds / 3_600)\n const minutes = Math.floor((totalSeconds % 3_600) / 60)\n const seconds = totalSeconds % 60\n if (hours > 0) return `${hours}h ${minutes}m`\n if (minutes > 0) return `${minutes}m ${seconds}s`\n return `${seconds}s`\n}\n\nfunction formatClockDuration(durationMs: number) {\n const totalSeconds = Math.floor(durationMs / 1_000)\n const hours = Math.floor(totalSeconds / 3_600)\n const minutes = Math.floor((totalSeconds % 3_600) / 60)\n const seconds = totalSeconds % 60\n const clock = `${minutes}:${String(seconds).padStart(2, '0')}`\n return hours > 0 ? `${hours}:${clock.padStart(5, '0')}` : clock\n}\n","import styles from './RunningField.module.css'\nimport { compactTiming, timingDescription } from './running-timing.ts'\n\n/** The sole readable timing projection for panel-scale decorative fields. */\nexport function RunningFieldTiming({\n elapsedMs,\n estimatedDurationMs,\n overdue,\n}: {\n elapsedMs: number | undefined\n estimatedDurationMs: number | undefined\n overdue: boolean\n}) {\n return (\n <p className={`${styles.timing} ${overdue ? styles.timingOverdue : ''}`}>\n <span className=\"screen-reader-only\">\n {timingDescription(elapsedMs, estimatedDurationMs, overdue)}\n </span>\n <span aria-hidden=\"true\">{compactTiming(elapsedMs, estimatedDurationMs, overdue)}</span>\n </p>\n )\n}\n",".progress {\n display: flex;\n align-items: center;\n gap: 0.6em;\n min-width: 0;\n color: var(--status-warning);\n}\n.visual {\n position: relative;\n flex: 0 0 auto;\n}\n.timing {\n margin: 0;\n color: var(--ink-secondary);\n font-size: 0.72em;\n}\n.overdue {\n color: var(--status-serious);\n}\n.overdue .timing {\n color: var(--status-serious);\n}\n.readout {\n width: 12ch;\n flex: 0 0 12ch;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-variant-numeric: tabular-nums;\n text-align: end;\n white-space: nowrap;\n}\n.radial .visual {\n width: 2.35em;\n height: 2.35em;\n border: 0.14em solid var(--edge);\n border-radius: 50%;\n background: conic-gradient(var(--status-warning) var(--running-progress), var(--edge) 0);\n box-shadow:\n inset 0 0 0 0.22em var(--surface-raised),\n 0 0 0.55em color-mix(in srgb, var(--status-warning) 45%, transparent);\n}\n.radial .visual::after {\n content: \"\";\n position: absolute;\n inset: -0.14em;\n border-radius: 50%;\n border-top: 0.14em solid var(--status-warning);\n animation: sweep 1.7s linear infinite;\n}\n.overdue.radial .visual::before {\n content: \"\";\n position: absolute;\n inset: -0.42em;\n border: 0.1em solid var(--status-serious);\n border-radius: 50%;\n box-shadow: 0 0 0.55em color-mix(in srgb, var(--status-serious) 65%, transparent);\n animation: alarm-ring 1.8s ease-in-out infinite;\n}\n.radialCore {\n position: absolute;\n inset: 0.68em;\n border-radius: 50%;\n background: var(--status-warning);\n box-shadow: 0 0 0.45em var(--status-warning);\n}\n.overdue .radialCore {\n background: var(--status-serious);\n box-shadow: 0 0 0.55em var(--status-serious);\n animation: reactor-breathe 1.8s ease-in-out infinite alternate;\n}\n.runway {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-self: stretch;\n container-type: inline-size;\n}\n.runway .visual {\n width: min(12em, 100%);\n max-width: 100%;\n height: 0.8em;\n overflow: hidden;\n border: 1px solid var(--edge);\n border-radius: 999px;\n background: linear-gradient(90deg, var(--status-warning) var(--running-progress), var(--edge) 0);\n}\n.runway .visual::after {\n content: \"\";\n position: absolute;\n top: -0.25em;\n bottom: -0.25em;\n left: calc(var(--running-progress) - 0.06em);\n width: 0.12em;\n background: var(--ink-primary);\n box-shadow: 0 0 0.45em var(--ink-primary);\n}\n.overdue.runway .visual::before {\n content: \"\";\n position: absolute;\n inset: -0.2em 0;\n left: calc(100% - 0.55em);\n width: 0.55em;\n background: repeating-linear-gradient(\n -45deg,\n var(--status-serious) 0 0.12em,\n var(--surface) 0.12em 0.24em\n );\n box-shadow: 0 0 0.5em color-mix(in srgb, var(--status-serious) 70%, transparent);\n animation: barrier-pulse 1.4s ease-in-out infinite alternate;\n}\n.overdue.runway .visual::after {\n background: var(--status-serious);\n box-shadow: 0 0 0.55em var(--status-serious);\n animation: barrier-pulse 1.4s ease-in-out infinite alternate;\n}\n.spark {\n position: absolute;\n top: 50%;\n left: -0.5em;\n width: 0.35em;\n height: 0.35em;\n border-radius: 50%;\n background: var(--ink-primary);\n box-shadow: 0 0 0.4em var(--status-warning);\n animation: spark 1.5s linear infinite;\n}\n.overdue.runway .spark {\n animation-duration: 1s;\n}\n.sparkTwo {\n display: none;\n animation-delay: -0.5s;\n}\n.overdue.runway .sparkTwo {\n display: block;\n}\n.orbit .visual {\n width: 2.4em;\n height: 2.4em;\n border: 1px solid var(--edge);\n border-radius: 50%;\n}\n/* biome-ignore lint/style/noDescendingSpecificity: the radial overdue ring precedes this separate legacy treatment. */\n.orbit .visual::before {\n content: \"\";\n position: absolute;\n inset: 0.18em;\n border: 0.12em solid transparent;\n border-top-color: var(--status-warning);\n border-radius: 50%;\n transform: rotate(var(--running-degrees));\n}\n.orbitCore {\n position: absolute;\n inset: 0.75em;\n border-radius: 50%;\n background: var(--status-warning);\n box-shadow: 0 0 0.45em var(--status-warning);\n}\n.overdue .orbitCore {\n background: var(--status-serious);\n box-shadow: 0 0 0.55em var(--status-serious);\n animation: reactor-breathe 1.15s ease-in-out infinite alternate;\n}\n.particle {\n position: absolute;\n top: 0.25em;\n left: calc(50% - 0.16em);\n width: 0.32em;\n height: 0.32em;\n border-radius: 50%;\n background: var(--ink-primary);\n transform-origin: 0.16em 0.95em;\n animation: orbit 1.8s linear infinite;\n}\n.particleTwo {\n animation-delay: -0.9s;\n background: var(--status-warning);\n}\n.overdue.orbit .visual::after {\n content: \"\";\n position: absolute;\n inset: 0.42em;\n border: 0.08em solid color-mix(in srgb, var(--status-serious) 75%, transparent);\n border-radius: 50%;\n box-shadow: 0 0 0.6em color-mix(in srgb, var(--status-serious) 55%, transparent);\n animation: gravity-well 1.15s ease-in-out infinite alternate;\n}\n.overdue.orbit .particle {\n transform-origin: 0.16em 0.7em;\n animation-duration: 0.95s;\n}\n.indeterminate .visual {\n background-image: repeating-linear-gradient(\n 135deg,\n color-mix(in srgb, var(--status-warning) 70%, transparent) 0 0.25em,\n var(--edge) 0.25em 0.5em\n );\n animation: shift 1s linear infinite;\n}\n.signalField {\n container-type: size;\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-self: stretch;\n flex: 1 1 auto;\n min-height: 0;\n max-height: 100%;\n}\n.signalField .visual {\n width: auto;\n height: 1em;\n max-height: 100%;\n overflow: hidden;\n border: 1px solid var(--edge);\n border-radius: 999px;\n background: var(--surface);\n}\n.rail {\n position: absolute;\n inset: 0;\n background: linear-gradient(90deg, var(--status-warning) var(--running-progress), var(--edge) 0);\n opacity: 0.75;\n}\n.lead {\n position: absolute;\n top: -0.2em;\n bottom: -0.2em;\n left: calc(var(--running-progress) - 0.08em);\n width: 0.16em;\n border-radius: 999px;\n background: var(--ink-primary);\n box-shadow: 0 0 0.5em var(--status-warning);\n}\n.pulse {\n position: absolute;\n top: 50%;\n left: -0.5em;\n width: 0.3em;\n height: 0.3em;\n border-radius: 50%;\n background: var(--ink-primary);\n box-shadow: 0 0 0.4em var(--status-warning);\n animation: pulse 2.4s ease-in-out infinite alternate;\n}\n.pulseTwo {\n animation-delay: -1.2s;\n}\n.tracks {\n display: none;\n}\n@container panel (min-width: 26rem) {\n .runway .visual {\n flex: 1 1 auto;\n width: auto;\n height: clamp(1.1em, 7cqw, 2.7em);\n box-shadow: inset 0 0 1em color-mix(in srgb, var(--status-warning) 16%, transparent);\n }\n .runway .visual::after {\n left: calc(var(--running-progress) - 0.08em);\n width: 0.16em;\n }\n .spark {\n animation-name: sparkWide;\n }\n}\n@container panel (max-width: 18rem) {\n .signalField {\n flex: 0 1 auto;\n min-height: 0;\n }\n .signalField .visual {\n width: 2.65em;\n height: 1.15em;\n }\n .signalField .rail {\n background: var(--edge);\n }\n .signalField .lead {\n top: 0.2em;\n bottom: 0.2em;\n width: 0.38em;\n border-radius: 50%;\n }\n .pulse {\n display: none;\n }\n}\n@container panel (max-height: 5rem) {\n .signalField {\n flex: 0 1 auto;\n min-height: 0;\n }\n .signalField .visual {\n width: 2.65em;\n height: 1.15em;\n }\n .signalField .rail {\n background: var(--edge);\n }\n .signalField .lead {\n top: 0.2em;\n bottom: 0.2em;\n width: 0.38em;\n border-radius: 50%;\n }\n .pulse {\n display: none;\n }\n}\n/* A size-contained signal field cannot use its own intrinsic height as a query input: its\n auto-sized content would always satisfy the compact branch. Width is the stable panel-scale\n discriminator; the field's parent already controls its available height. */\n@container panel (min-width: 26rem) {\n .signalField .visual {\n height: 100%;\n min-height: 0;\n border-radius: 0.25em;\n background: linear-gradient(\n 180deg,\n color-mix(in srgb, var(--edge) 60%, transparent),\n transparent\n );\n }\n .signalField .visual::before {\n content: \"\";\n position: absolute;\n inset: 0 auto 0 0;\n width: var(--running-progress);\n background:\n repeating-linear-gradient(\n 0deg,\n transparent 0 0.55em,\n color-mix(in srgb, var(--status-warning) 16%, transparent) 0.55em 0.6em\n ),\n linear-gradient(\n 90deg,\n color-mix(in srgb, var(--status-warning) 19%, transparent),\n color-mix(in srgb, var(--status-warning) 7%, transparent)\n );\n box-shadow: inset -0.8em 0 1em color-mix(in srgb, var(--status-warning) 22%, transparent);\n }\n .signalField .rail {\n top: 50%;\n bottom: auto;\n height: 1px;\n }\n .signalField .lead {\n top: calc(50% - 0.45em);\n bottom: auto;\n height: 0.9em;\n }\n .pulse {\n display: none;\n }\n .tracks {\n position: absolute;\n inset: 0.8em 0;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n }\n .track {\n position: relative;\n height: 1px;\n background: linear-gradient(\n 90deg,\n transparent,\n color-mix(in srgb, var(--edge) 85%, transparent),\n transparent\n );\n }\n .markerAnchor {\n width: 0.38em;\n height: 0.22em;\n }\n .markerBody {\n border-radius: 0.06em;\n background: var(--status-warning);\n box-shadow: 0 0 0.4em var(--status-warning);\n }\n .track:nth-child(2) .markerBody {\n animation-delay: -0.8s;\n opacity: 0.7;\n }\n .track:nth-child(3) .markerBody {\n animation-delay: -1.7s;\n opacity: 0.45;\n }\n .track:nth-child(4) .markerBody {\n animation-delay: -2.4s;\n opacity: 0.7;\n }\n .track:nth-child(5) .markerBody {\n animation-delay: -0.35s;\n opacity: 0.55;\n }\n}\n.overdue.signalField .rail {\n background: linear-gradient(90deg, var(--status-serious) 0 100%);\n opacity: 0.42;\n}\n.overdue.signalField .lead {\n background: var(--status-serious);\n box-shadow: 0 0 0.7em var(--status-serious);\n animation: endpoint-pulse 1.2s ease-in-out infinite alternate;\n}\n.overdue.signalField .markerBody {\n --phased-marker-travel: -10em;\n background: var(--status-serious);\n box-shadow: 0 0 0.55em var(--status-serious);\n animation-duration: 0.68s;\n animation-timing-function: ease-in-out;\n}\n.short .signalField .visual {\n height: 1em;\n}\n@keyframes sweep {\n to {\n transform: rotate(360deg);\n }\n}\n@keyframes alarm-ring {\n from {\n transform: scale(0.92);\n opacity: 0.45;\n }\n to {\n transform: scale(1.08);\n opacity: 1;\n }\n}\n@keyframes reactor-breathe {\n from {\n transform: scale(0.84);\n opacity: 0.7;\n }\n to {\n transform: scale(1.12);\n opacity: 1;\n }\n}\n@keyframes barrier-pulse {\n from {\n opacity: 0.55;\n }\n to {\n opacity: 1;\n }\n}\n@keyframes gravity-well {\n from {\n transform: scale(0.82);\n opacity: 0.45;\n }\n to {\n transform: scale(1.08);\n opacity: 0.95;\n }\n}\n@keyframes endpoint-pulse {\n from {\n transform: scaleY(0.75);\n opacity: 0.65;\n }\n to {\n transform: scaleY(1.15);\n opacity: 1;\n }\n}\n@keyframes spark {\n to {\n transform: translateX(13em);\n }\n}\n@keyframes sparkWide {\n to {\n transform: translateX(100cqw);\n }\n}\n@keyframes orbit {\n to {\n transform: rotate(360deg);\n }\n}\n@keyframes shift {\n to {\n background-position: 1em 0;\n }\n}\n@keyframes pulse {\n from {\n transform: translate(-0.5em, -50%);\n }\n to {\n transform: translate(calc(var(--running-progress) + 0.5em), -50%);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .radial .visual::after,\n .overdue.radial .visual::before,\n .overdue .radialCore,\n .spark,\n .runway .visual::after,\n .overdue.runway .visual::before,\n .overdue.runway .visual::after,\n .particle,\n .overdue.orbit .visual::after,\n .pulse,\n .lead,\n .overdue.signalField .lead,\n .overdue.signalField .markerBody,\n /* biome-ignore lint/style/noDescendingSpecificity: the shared reduced-motion list intentionally follows themed overrides. */\n .signalField .visual::before,\n .indeterminate .visual {\n animation: none;\n }\n}\n","import type { RunningAnimation } from '@ze-great-dashboard/shared'\nimport type { CSSProperties } from 'react'\nimport { PhasedProgressMarker } from './PhasedProgressMarker.tsx'\nimport styles from './RunningProgress.module.css'\nimport { compactTiming, type RunningTiming, timingDescription } from './running-timing.ts'\n\nexport function RunningProgress({\n animation,\n timing,\n}: {\n animation: LegacyRunningAnimation\n timing: RunningTiming\n}) {\n const { elapsedMs, estimatedDurationMs, hasEstimate, overdue, progress } = timing\n const usesReadout = animation === 'runway' || animation === 'signal-field'\n const timingText = timingDescription(elapsedMs, estimatedDurationMs, overdue)\n const style = {\n '--running-progress': `${progress * 100}%`,\n '--running-degrees': `${progress * 360}deg`,\n } as CSSProperties\n const animationStyle = animation === 'signal-field' ? styles.signalField : styles[animation]\n\n return (\n <div\n className={`${styles.progress} ${animationStyle} ${overdue ? styles.overdue : ''} ${hasEstimate ? '' : styles.indeterminate}`}\n style={style}\n data-running-progress={animation}\n data-overdue={overdue || undefined}\n data-indeterminate={!hasEstimate || undefined}\n >\n <div className={styles.visual} aria-hidden=\"true\" data-running-visual>\n {animation === 'radial' && <span className={styles.radialCore} />}\n {animation === 'runway' && (\n <>\n <span className={styles.spark} data-running-part=\"runway-spark\" />\n <span\n className={`${styles.spark} ${styles.sparkTwo}`}\n data-running-part=\"runway-spark-two\"\n />\n </>\n )}\n {animation === 'orbit' && (\n <>\n <span className={styles.orbitCore} />\n <span className={styles.particle} />\n <span className={`${styles.particle} ${styles.particleTwo}`} />\n </>\n )}\n {animation === 'signal-field' && (\n <>\n <span className={styles.rail} />\n <span className={styles.lead} />\n <span className={styles.pulse} />\n <span className={`${styles.pulse} ${styles.pulseTwo}`} />\n <span className={styles.tracks} data-running-part=\"signal-tracks\">\n {[0, 1, 2, 3, 4].map((track) => (\n <span className={styles.track} key={track} data-running-part=\"signal-track\">\n <PhasedProgressMarker\n anchorClassName={styles.markerAnchor}\n bodyClassName={styles.markerBody}\n delay={[undefined, '-0.8s', '-1.7s', '-2.4s', '-0.35s'][track]}\n anchorPart=\"signal-marker-anchor\"\n bodyPart=\"signal-marker\"\n />\n </span>\n ))}\n </span>\n </>\n )}\n </div>\n <p className={`${styles.timing} ${usesReadout ? styles.readout : ''}`}>\n {usesReadout ? (\n <>\n <span className=\"screen-reader-only\">{timingText}</span>\n <span aria-hidden=\"true\">{compactTiming(elapsedMs, estimatedDurationMs, overdue)}</span>\n </>\n ) : (\n timingText\n )}\n </p>\n </div>\n )\n}\n\n/** The compact, inline treatments retained for existing boards. */\nexport type LegacyRunningAnimation = Extract<\n RunningAnimation,\n 'radial' | 'runway' | 'orbit' | 'signal-field'\n>\n\nexport function isLegacyRunningAnimation(\n animation: RunningAnimation,\n): animation is LegacyRunningAnimation {\n return ['radial', 'runway', 'orbit', 'signal-field'].includes(animation)\n}\n","/** A stable numeric variation seed for decorative fields keyed by a panel's public id. */\nexport function visualSeed(value: string): number {\n return Array.from(value).reduce(\n (hash, character) => (hash * 31 + character.charCodeAt(0)) >>> 0,\n 7,\n )\n}\n","import { type Panel, parseDuration } from '@ze-great-dashboard/shared'\nimport { useEffect, useState } from 'react'\nimport { PanelEvidence, PanelFrame, PanelStatus } from './PanelFrame.tsx'\nimport styles from './PipelineAnimationDemoPanel.module.css'\nimport { isRunningFieldAnimation, RunningField } from './RunningField.tsx'\nimport { RunningFieldTiming } from './RunningFieldTiming.tsx'\nimport { RunningProgress } from './RunningProgress.tsx'\nimport { useRunningTiming } from './running-timing.ts'\nimport { visualSeed } from './visual-seed.ts'\n\nconst DEFAULT_RUN_DURATION_MS = 20_000\nconst ESTIMATED_DURATION_MS = 15_000\nconst DEFAULT_REVIEW_DURATION_MS = 300_000\nconst REVIEW_CYCLE_MULTIPLIER = 1.25\nconst variants = [\n 'radial',\n 'runway',\n 'orbit',\n 'signal-field',\n 'telemetry-bloom',\n 'release-transit',\n 'status-weather',\n 'falling-shapes',\n 'snowman',\n] as const\n\n/**\n * A local comparison aid for the active-run treatments. It deliberately creates no signal or\n * diagnostic evidence: its state is derived only from the wall clock and repeats forever.\n */\nexport function PipelineAnimationDemoPanel({ panel }: { panel: Panel }) {\n const now = useClock()\n // A configured visible treatment turns the local comparison aid into a stable review panel.\n // `off` retains the rotating default: the demo exists to render a treatment.\n const fixedAnimation =\n panel.running_animation === undefined || panel.running_animation === 'off'\n ? undefined\n : panel.running_animation\n const runDurationMs = durationMillis(panel.demo_run_duration, DEFAULT_RUN_DURATION_MS)\n const reviewDurationMs = durationMillis(panel.demo_review_duration, DEFAULT_REVIEW_DURATION_MS)\n const durationMs = fixedAnimation\n ? Math.ceil(reviewDurationMs * REVIEW_CYCLE_MULTIPLIER)\n : runDurationMs\n const runNumber = Math.floor(now / durationMs)\n const animation = fixedAnimation ?? variants[runNumber % variants.length] ?? 'radial'\n const runStartedAt = runNumber * durationMs\n\n return (\n <DemoRun\n panel={panel}\n animation={animation}\n runStartedAt={runStartedAt}\n estimatedDurationMs={fixedAnimation ? reviewDurationMs : ESTIMATED_DURATION_MS}\n />\n )\n}\n\nfunction durationMillis(value: Panel['demo_run_duration'], fallback: number): number {\n if (!value) return fallback\n return parseDuration(value) ?? fallback\n}\n\nfunction DemoRun({\n panel,\n animation,\n runStartedAt,\n estimatedDurationMs,\n}: {\n panel: Panel\n animation: (typeof variants)[number]\n runStartedAt: number\n estimatedDurationMs: number\n}) {\n const startedAt = new Date(runStartedAt).toISOString()\n const timing = useRunningTiming(startedAt, estimatedDurationMs)\n const usesField = isRunningFieldAnimation(animation)\n return (\n <PanelFrame\n panel={panel}\n field={\n usesField ? (\n <RunningField\n key={`${animation}-${runStartedAt}`}\n animation={animation}\n progress={timing.progress}\n estimatedDurationMs={timing.estimatedDurationMs}\n overdue={timing.overdue}\n indeterminate={!timing.hasEstimate}\n seed={visualSeed(panel.id)}\n />\n ) : undefined\n }\n >\n <PanelEvidence>\n <PanelStatus status=\"running\" glyph=\"↻\" label=\"Running\" />\n <p className={styles.variant}>\n <span className={styles.variantPrefix}>Demo treatment · </span>\n {animation}\n </p>\n {usesField ? (\n <RunningFieldTiming\n elapsedMs={timing.elapsedMs}\n estimatedDurationMs={estimatedDurationMs}\n overdue={timing.overdue}\n />\n ) : (\n <RunningProgress animation={animation} timing={timing} />\n )}\n </PanelEvidence>\n </PanelFrame>\n )\n}\n\nfunction useClock() {\n const [now, setNow] = useState(() => Date.now())\n useEffect(() => {\n const interval = window.setInterval(() => setNow(Date.now()), 1_000)\n return () => window.clearInterval(interval)\n }, [])\n return now\n}\n",".details {\n display: contents;\n}\n.details > :global(.hint) {\n line-height: 1.1;\n}\n.activity,\n.duration {\n overflow-wrap: anywhere;\n}\n@container panel (min-width: 48rem) {\n :global([data-density=\"comfortable\"][data-shallow=\"true\"]) .details > *,\n :global([data-density=\"auto\"][data-shallow=\"true\"]) .details > * {\n margin: 0;\n }\n}\n","import type { PipelineStatus } from '@ze-great-dashboard/shared'\nimport { statusSymbols } from './panel-symbols.ts'\n\nexport type PanelStatusKind = PipelineStatus['status']\n\nexport function statusPresentation(status: PanelStatusKind, passedLabel = 'Passed') {\n const presentation = statusSymbols[status]\n return status === 'passed' ? { ...presentation, label: passedLabel } : presentation\n}\n","import type { PipelineActivity } from '@ze-great-dashboard/shared'\n\nexport function formatPipelineActivity(activity: PipelineActivity | undefined) {\n if (!activity) return 'Activity unavailable'\n return activity.parent ? `${activity.parent} › ${activity.name}` : activity.name\n}\n","import {\n type Envelope,\n type Panel,\n type PipelineStatus,\n pipelineStatusSchema,\n type RunningAnimation,\n visibleRunningAnimations,\n} from '@ze-great-dashboard/shared'\nimport { useRef, useState } from 'react'\nimport { errorPresentation } from './error-presentation.ts'\nimport { PanelEvidence, PanelFrame, PanelHint, PanelMetadata, PanelStatus } from './PanelFrame.tsx'\nimport styles from './PipelinePanel.module.css'\nimport type { PanelProps } from './panel-props.ts'\nimport { statusPresentation } from './panel-status.ts'\nimport { formatPipelineActivity } from './pipeline-activity.ts'\nimport { isRunningFieldAnimation, RunningField } from './RunningField.tsx'\nimport { RunningFieldTiming } from './RunningFieldTiming.tsx'\nimport { isLegacyRunningAnimation, RunningProgress } from './RunningProgress.tsx'\nimport { useRunningTiming } from './running-timing.ts'\nimport { PipelineAge, UpdateHealth } from './TimeAge.tsx'\nimport { visualSeed } from './visual-seed.ts'\n\nexport function PipelinePanel({ panel, envelope, attentionActive, updateHealth }: PanelProps) {\n if (!envelope)\n return (\n <PanelFrame panel={panel} attentionActive={attentionActive}>\n <PanelEvidence>\n <PanelHint>Loading…</PanelHint>\n </PanelEvidence>\n </PanelFrame>\n )\n if (envelope.state === 'error') {\n const presentation = errorPresentation(envelope.error.kind)\n return (\n <PanelFrame\n panel={panel}\n envelope={envelope}\n attentionActive={attentionActive}\n error\n layout=\"status-band\"\n >\n <div data-panel-anchor=\"status\">\n <PanelStatus glyph=\"⚠\" label={presentation.label} emphasis={presentation.emphasis} />\n </div>\n <PanelEvidence anchor=\"evidence\">\n <PanelHint>{envelope.error.message}</PanelHint>\n </PanelEvidence>\n </PanelFrame>\n )\n }\n\n const signal = pipelineStatusSchema.safeParse(envelope.signal)\n if (!signal.success)\n return (\n <PanelFrame\n panel={panel}\n envelope={envelope}\n attentionActive={attentionActive}\n error\n layout=\"status-band\"\n >\n <div data-panel-anchor=\"status\">\n <PanelStatus glyph=\"⚠\" label=\"Invalid signal\" />\n </div>\n <PanelEvidence anchor=\"evidence\">\n <PanelHint>The received pipeline status could not be read.</PanelHint>\n </PanelEvidence>\n </PanelFrame>\n )\n return (\n <PipelineSignalPanel\n panel={panel}\n envelope={envelope}\n signal={signal.data}\n updateHealth={updateHealth}\n attentionActive={attentionActive}\n />\n )\n}\n\nfunction PipelineSignalPanel({\n panel,\n envelope,\n signal,\n updateHealth,\n attentionActive,\n}: {\n panel: Panel\n envelope: Envelope\n signal: PipelineStatus\n updateHealth?: PanelProps['updateHealth']\n attentionActive?: boolean\n}) {\n const presentation = statusPresentation(signal.status)\n const [defaultAnimation, setDefaultAnimation] = useState<RunningAnimation | undefined>(() =>\n signal.status === 'running' ? selectDefaultRunningAnimation() : undefined,\n )\n const previousStatusRef = useRef(signal.status)\n if (signal.status !== previousStatusRef.current) {\n const wasRunning = previousStatusRef.current === 'running'\n previousStatusRef.current = signal.status\n if (panel.running_animation === undefined && !wasRunning && signal.status === 'running') {\n setDefaultAnimation((previousAnimation) => selectDefaultRunningAnimation(previousAnimation))\n }\n }\n const animation = panel.running_animation ?? defaultAnimation ?? 'off'\n const activeRun = signal.status === 'running' && animation !== 'off'\n const timing = useRunningTiming(signal.runStartedAt, signal.estimatedDurationMs)\n const usesField = activeRun && isRunningFieldAnimation(animation)\n const usesLegacyProgress = activeRun && isLegacyRunningAnimation(animation)\n return (\n <PanelFrame\n panel={panel}\n envelope={envelope}\n attentionActive={attentionActive}\n layout={usesField || usesLegacyProgress ? undefined : 'status-band'}\n field={\n usesField ? (\n <RunningField\n animation={animation}\n progress={timing.progress}\n estimatedDurationMs={timing.estimatedDurationMs}\n overdue={timing.overdue}\n indeterminate={!timing.hasEstimate}\n seed={visualSeed(panel.id)}\n />\n ) : undefined\n }\n >\n <div data-panel-anchor=\"status\">\n <PanelStatus status={signal.status} glyph={presentation.glyph} label={presentation.label} />\n </div>\n <PanelEvidence className={styles.details} anchor=\"evidence\">\n {signal.status === 'running' && (\n <PanelMetadata\n glyph=\"⚙\"\n label=\"Activity\"\n value={formatPipelineActivity(signal.activity)}\n compact={{ kind: 'glyph-only' }}\n title={`Activity: ${formatPipelineActivity(signal.activity)}`}\n className={styles.activity}\n />\n )}\n {signal.branch && (\n <PanelMetadata\n glyph=\"⎇\"\n label=\"Branch\"\n value={<span className={styles.branch}>{signal.branch}</span>}\n compact={{\n kind: 'short-value',\n value: <span className={styles.branch}>{signal.branch}</span>,\n }}\n title={`Branch: ${signal.branch}`}\n />\n )}\n {usesField && (\n <RunningFieldTiming\n elapsedMs={timing.elapsedMs}\n estimatedDurationMs={signal.estimatedDurationMs}\n overdue={timing.overdue}\n />\n )}\n {usesLegacyProgress && <RunningProgress animation={animation} timing={timing} />}\n {signal.status !== 'running' && signal.durationMs !== undefined && (\n <PanelMetadata\n glyph=\"◷\"\n label=\"Duration\"\n value={`Took ${formatDuration(signal.durationMs)}`}\n compact={{ kind: 'short-value', value: formatDuration(signal.durationMs) }}\n title={`Duration: Took ${formatDuration(signal.durationMs)}`}\n className={styles.duration}\n />\n )}\n <PipelineAge\n sourceUpdatedAt={signal.sourceUpdatedAt}\n observedAt={envelope.observedAt}\n running={signal.status === 'running'}\n runStartedAt={signal.runStartedAt}\n />\n {updateHealth && <UpdateHealth health={updateHealth} />}\n </PanelEvidence>\n </PanelFrame>\n )\n}\n\nfunction selectDefaultRunningAnimation(previousAnimation?: RunningAnimation) {\n const candidates = visibleRunningAnimations.filter((animation) => animation !== previousAnimation)\n return candidates[Math.floor(Math.random() * candidates.length)] ?? 'telemetry-bloom'\n}\n\nfunction formatDuration(durationMs: number) {\n const totalSeconds = Math.floor(durationMs / 1_000)\n const hours = Math.floor(totalSeconds / 3_600)\n const minutes = Math.floor((totalSeconds % 3_600) / 60)\n const seconds = totalSeconds % 60\n\n if (hours > 0) return `${hours}h ${minutes}m`\n if (minutes > 0) return `${minutes}m ${seconds}s`\n return `${seconds}s`\n}\n",".compactFacts {\n display: none;\n min-width: 0;\n flex-direction: column;\n gap: 0.1em;\n}\n\n.incomplete {\n color: var(--warning-text);\n}\n\n.compactFact {\n min-width: 0;\n margin: 0;\n font-size: 0.7em;\n color: var(--ink-muted);\n}\n\n.failedItem {\n min-width: 0;\n margin: 0;\n color: var(--ink-primary);\n font-size: 0.85em;\n font-weight: 600;\n}\n\n.evidence,\n.freshness {\n display: flex;\n min-width: 0;\n flex-direction: column;\n gap: 0.1em;\n}\n\n@container panel (max-width: 13rem) and (min-height: 24rem) {\n .statusAnchor :global([class*=\"status\"]) {\n font-size: 1.7em;\n }\n\n .compactFacts {\n display: flex;\n }\n\n .fullSummary {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n}\n\n@container panel (max-width: 13rem) and (max-height: 10rem) {\n :global([data-density=\"compact\"]) .compactFacts ~ :global([data-panel-meta]) {\n display: none;\n }\n}\n","export function formatCount(count: number, singular: string, plural = `${singular}s`) {\n return `${count} ${count === 1 ? singular : plural}`\n}\n","import type { PullRequestHealth } from '@ze-great-dashboard/shared'\nimport { formatCount } from './panel-formatting.ts'\n\nexport type PullRequestHealthCompactFacts = {\n workflow: string\n pullRequests: string\n primary: string\n secondary: string\n primaryDetail?: string\n primaryKind?: 'failed' | 'warning'\n title: string\n}\n\n/**\n * Keep the wall-facing version of this aggregate signal short without making the\n * server's prose summary part of the client contract.\n */\nexport function compactPullRequestHealthFacts(\n signal: PullRequestHealth,\n): PullRequestHealthCompactFacts {\n const attentionItem = [...signal.workflows, ...signal.pullRequests].find(\n (item) => item.status === 'failed' || item.status === 'warning',\n )\n\n if (attentionItem) {\n return {\n workflow: formatCount(signal.workflows.length, 'workflow'),\n pullRequests: formatCount(signal.pullRequests.length, 'open PR'),\n primary: `${attentionItem.label} ${attentionItem.status}`,\n secondary: `${formatCount(signal.workflows.length, 'workflow')} · ${formatCount(signal.pullRequests.length, 'open PR')}`,\n primaryDetail: attentionItem.detail,\n primaryKind: attentionItem.status === 'warning' ? 'warning' : 'failed',\n title: `${signal.summary} — ${attentionItem.label}: ${attentionItem.detail}`,\n }\n }\n\n return {\n workflow: formatCount(signal.workflows.length, 'workflow'),\n pullRequests: formatCount(signal.pullRequests.length, 'open PR'),\n primary: formatCount(signal.workflows.length, 'workflow'),\n secondary: formatCount(signal.pullRequests.length, 'open PR'),\n title: signal.summary,\n }\n}\n","import { pullRequestHealthSchema } from '@ze-great-dashboard/shared'\nimport { errorPresentation } from './error-presentation.ts'\nimport { PanelEvidence, PanelFrame, PanelHint, PanelMetadata, PanelStatus } from './PanelFrame.tsx'\nimport styles from './PullRequestHealthPanel.module.css'\nimport type { PanelProps } from './panel-props.ts'\nimport { statusPresentation } from './panel-status.ts'\nimport { compactPullRequestHealthFacts } from './pull-request-health.ts'\nimport { ObservedAt, UpdateHealth } from './TimeAge.tsx'\n\nexport function PullRequestHealthPanel({\n panel,\n envelope,\n attentionActive,\n updateHealth,\n}: PanelProps) {\n if (!envelope)\n return (\n <PanelFrame panel={panel} attentionActive={attentionActive}>\n <PanelEvidence>\n <PanelHint>Loading…</PanelHint>\n </PanelEvidence>\n </PanelFrame>\n )\n if (envelope.state === 'error') {\n const presentation = errorPresentation(envelope.error.kind)\n return (\n <PanelFrame\n panel={panel}\n envelope={envelope}\n attentionActive={attentionActive}\n error\n layout=\"status-band\"\n >\n <div data-panel-anchor=\"status\">\n <PanelStatus glyph=\"⚠\" label={presentation.label} emphasis={presentation.emphasis} />\n </div>\n <PanelEvidence anchor=\"evidence\">\n <PanelHint>{envelope.error.message}</PanelHint>\n </PanelEvidence>\n </PanelFrame>\n )\n }\n const signal = pullRequestHealthSchema.safeParse(envelope.signal)\n if (!signal.success)\n return (\n <PanelFrame\n panel={panel}\n envelope={envelope}\n attentionActive={attentionActive}\n error\n layout=\"status-band\"\n >\n <div data-panel-anchor=\"status\">\n <PanelStatus glyph=\"⚠\" label=\"Invalid signal\" />\n </div>\n <PanelEvidence anchor=\"evidence\">\n <PanelHint>The received pull-request health status could not be read.</PanelHint>\n </PanelEvidence>\n </PanelFrame>\n )\n const presentation = statusPresentation(signal.data.status, 'Healthy')\n const compactFacts = compactPullRequestHealthFacts(signal.data)\n return (\n <PanelFrame\n panel={panel}\n envelope={envelope}\n attentionActive={attentionActive}\n layout=\"status-band\"\n >\n <div className={styles.statusAnchor} data-panel-anchor=\"status\">\n <PanelStatus\n status={signal.data.status}\n glyph={presentation.glyph}\n label={presentation.label}\n />\n </div>\n <div\n className={styles.evidence}\n data-panel-anchor=\"evidence\"\n data-panel-evidence-priority=\"secondary\"\n >\n <PanelHint className={styles.fullSummary} title={signal.data.summary}>\n {signal.data.summary}\n </PanelHint>\n <div className={styles.compactFacts} title={compactFacts.title} data-compact-facts>\n {compactFacts.primaryDetail && (\n <p className={styles.failedItem} title={compactFacts.primaryDetail}>\n <span aria-hidden=\"true\">⚠</span>{' '}\n <span className=\"screen-reader-only\">\n {compactFacts.primaryKind === 'warning' ? 'Warning' : 'Failed'} item:{' '}\n </span>\n {compactFacts.primary}\n <span className=\"screen-reader-only\">. Detail: {compactFacts.primaryDetail}</span>\n </p>\n )}\n <PanelMetadata\n glyph=\"⚙\"\n label=\"Update workflows\"\n value={compactFacts.workflow}\n compact={{ kind: 'short-value', value: signal.data.workflows.length }}\n title={`Update workflows: ${compactFacts.workflow}`}\n className={styles.compactFact}\n />\n <PanelMetadata\n glyph=\"⎇\"\n label=\"Open update pull requests\"\n value={compactFacts.pullRequests}\n compact={{ kind: 'short-value', value: signal.data.pullRequests.length }}\n title={`Open update pull requests: ${compactFacts.pullRequests}`}\n className={styles.compactFact}\n />\n </div>\n <div className={styles.freshness}>\n <ObservedAt value={envelope.observedAt} label=\"Observed (oldest evidence)\" />\n {signal.data.newestObservedAt && (\n <span className=\"screen-reader-only\">\n Newest evidence observed {signal.data.newestObservedAt}.\n </span>\n )}\n {updateHealth && <UpdateHealth health={updateHealth} />}\n </div>\n {signal.data.incompleteObservations && (\n <div role=\"status\">\n <PanelHint className={styles.incomplete}>\n ⚠ Incomplete observations:{' '}\n {signal.data.incompleteObservations\n .map(({ label, message }) => `${label}: ${message}`)\n .join(' · ')}\n </PanelHint>\n </div>\n )}\n </div>\n </PanelFrame>\n )\n}\n","import type { ComponentType } from 'react'\nimport { HttpValuePanel } from './HttpValuePanel.tsx'\nimport { PanelPlaceholder } from './PanelPlaceholder.tsx'\nimport { PipelineAnimationDemoPanel } from './PipelineAnimationDemoPanel.tsx'\nimport { PipelinePanel } from './PipelinePanel.tsx'\nimport { PullRequestHealthPanel } from './PullRequestHealthPanel.tsx'\nimport type { PanelProps } from './panel-props.ts'\nimport type { RenderablePanelType } from './panel-symbols.ts'\n\ntype PanelRendererProps = PanelProps\n\n/** The one client-side dispatch point for panel types. */\nexport const panelRenderers: Record<RenderablePanelType, ComponentType<PanelRendererProps>> = {\n 'pipeline-status': PipelinePanel,\n 'pull-request-health': PullRequestHealthPanel,\n 'http-value': HttpValuePanel,\n 'pipeline-animation-demo': PipelineAnimationDemoPanel,\n}\n\nexport function PanelRenderer({\n panel,\n envelope,\n attentionActive,\n updateHealth,\n facts,\n}: PanelRendererProps) {\n const Renderer = panelRenderers[panel.type as RenderablePanelType]\n return Renderer ? (\n <Renderer\n panel={panel}\n envelope={envelope}\n attentionActive={attentionActive}\n updateHealth={updateHealth}\n facts={facts}\n />\n ) : (\n <PanelPlaceholder label={panel.type} hint=\"Not wired yet\" wide />\n )\n}\n",".notice {\n display: flex;\n align-items: flex-start;\n gap: 0.45em;\n margin-inline-start: auto;\n padding: 0.35em 0.55em;\n border: 0.14rem solid var(--status-critical);\n border-radius: var(--radius);\n color: var(--ink-primary);\n background: var(--surface-raised);\n font-size: 0.7em;\n line-height: 1.3;\n}\n.notice > span:first-child {\n color: var(--status-critical);\n}\n.notice a,\n.blocked a {\n color: inherit;\n text-decoration-color: var(--status-critical);\n}\n.blocked {\n max-width: 42rem;\n margin: 12vh auto;\n padding: 2rem;\n border: 0.25rem solid var(--status-critical);\n border-radius: var(--radius);\n background: var(--surface-raised);\n}\n.blocked h1 {\n color: var(--status-critical);\n}\n@media (max-width: 64rem) {\n .notice {\n margin-inline-start: 0;\n }\n}\n","import type { ClientSecurityState } from '@ze-great-dashboard/shared'\nimport styles from './SecurityNotice.module.css'\n\nconst authenticationGuide =\n 'https://github.com/robertfmurdock/ze-great-dashboard/blob/main/docs/oidc-authentication.md'\n\n/** Deployment-level posture, intentionally separate from panel health and diagnostics. */\nexport function SecurityNotice({ mode }: { mode: ClientSecurityState }) {\n if (mode === 'blocked')\n return (\n <main className={styles.blocked} role=\"alert\">\n <h1>⚠ Authentication configuration required</h1>\n <p>\n This dashboard is blocked because authentication is required but has not been configured.\n </p>\n <p>No dashboard data was loaded.</p>\n <p>\n <a href={authenticationGuide}>Read the authentication setup guide</a>.\n </p>\n </main>\n )\n return (\n <aside className={styles.notice} role=\"alert\" aria-label=\"Unauthenticated deployment warning\">\n <span aria-hidden=\"true\">⚠</span>\n <span>\n <strong>This deployment has no authentication.</strong> If this is reachable on a public\n network and reveals important information, take it down now. Configure the board’s{' '}\n <code>auth</code> block and <code>security: required</code>, or set{' '}\n <code>security: unsecured</code> to explicitly acknowledge intentional public access.{' '}\n <a href={authenticationGuide}>Read the authentication setup guide</a>.\n </span>\n </aside>\n )\n}\n",".trigger,\n.close {\n border: 1px solid var(--edge);\n border-radius: 0.25rem;\n background: var(--surface-raised);\n color: var(--ink-secondary);\n font: inherit;\n padding: 0.3em 0.55em;\n cursor: pointer;\n}\n.dialog {\n position: fixed;\n z-index: 20;\n inset: 0;\n display: grid;\n grid-template-rows: auto minmax(0, 1fr);\n padding: var(--gap);\n background: var(--surface);\n color: var(--ink-secondary);\n font-size: clamp(0.8rem, 1vw, 1.15rem);\n}\n.dialogHeader {\n display: flex;\n align-items: start;\n justify-content: space-between;\n gap: 1rem;\n border-bottom: 1px solid var(--edge);\n padding-bottom: var(--gap);\n}\n.dialogHeader h2,\n.dialogHeader p,\n.note,\n.empty {\n margin: 0;\n}\n.dialogHeader h2 {\n color: var(--ink-primary);\n font-size: 1.35em;\n}\n.dialogHeader p {\n margin-top: 0.2rem;\n}\n.body {\n min-height: 0;\n overflow: auto;\n padding-top: var(--gap);\n}\n.legend,\n.note,\n.empty {\n color: var(--ink-muted);\n}\n.legend {\n display: block;\n font-size: 0.9em;\n}\n.axis {\n display: flex;\n justify-content: space-between;\n margin: 0.45rem 0 0.15rem max(10rem, 28%);\n color: var(--ink-muted);\n font-size: 0.85em;\n}\n.lanes {\n display: grid;\n gap: 0.2rem;\n}\n.lane {\n display: grid;\n grid-template-columns: minmax(9rem, 28%) minmax(0, 1fr);\n gap: 0.55rem;\n align-items: center;\n min-width: 0;\n}\n.laneLabel {\n overflow-wrap: anywhere;\n}\n.track {\n position: relative;\n display: block;\n min-width: 0;\n height: 0.8rem;\n border-bottom: 1px solid var(--edge);\n}\n.observed,\n.expected {\n position: absolute;\n top: 0.1rem;\n width: 0.55rem;\n height: 0.55rem;\n transform: translateX(-50%);\n}\n.observed {\n border-radius: 50%;\n background: var(--ink-primary);\n}\n.expected {\n border: 1px solid var(--ink-secondary);\n transform: translateX(-50%) rotate(45deg);\n}\n.note {\n margin-top: 0.8rem;\n font-size: 0.9em;\n}\n@media (max-width: 40rem) {\n .axis {\n margin-left: 0;\n }\n .lane {\n grid-template-columns: 1fr;\n }\n .legend {\n justify-self: start;\n }\n}\n","import type { DiagnosticEvent, DiagnosticRetention } from './diagnostics.ts'\nimport type { PollingScheduleSnapshot } from './polling-schedule.ts'\n\nexport const updateActivityWindowMillis = 10 * 60 * 1_000\n\nexport type UpdateActivitySnapshot = {\n capturedAt: string\n window: { from: string; to: string }\n schedules: PollingScheduleSnapshot[]\n}\n\nexport type UpdateActivityLane = PollingScheduleSnapshot & {\n observed: Array<{ path: string; starts: string[] }>\n hasRetainedEvidence: boolean\n}\n\nexport function projectUpdateActivity({\n schedules,\n events,\n retention,\n now = new Date(),\n}: {\n schedules: PollingScheduleSnapshot[]\n events: DiagnosticEvent[]\n retention: DiagnosticRetention\n now?: Date\n}): UpdateActivitySnapshot & {\n lanes: UpdateActivityLane[]\n evidenceMayBeIncomplete: boolean\n} {\n const toMillis = now.valueOf()\n const fromMillis = toMillis - updateActivityWindowMillis\n const starts = events.filter(\n (event): event is Extract<DiagnosticEvent, { kind: 'panel-fetch-start' }> =>\n event.kind === 'panel-fetch-start' &&\n Number.isFinite(Date.parse(event.at)) &&\n Date.parse(event.at) >= fromMillis &&\n Date.parse(event.at) <= toMillis,\n )\n const lanes = schedules.map((schedule) => {\n const paths = new Map<string, string[]>()\n for (const event of starts) {\n if (event.panelId !== schedule.panelId) continue\n const observed = paths.get(event.path) ?? []\n observed.push(event.at)\n paths.set(event.path, observed)\n }\n return {\n ...schedule,\n observed: [...paths.entries()].map(([path, requestStarts]) => ({\n path,\n starts: requestStarts,\n })),\n hasRetainedEvidence: paths.size > 0,\n }\n })\n return {\n capturedAt: now.toISOString(),\n window: { from: new Date(fromMillis).toISOString(), to: now.toISOString() },\n schedules,\n lanes,\n evidenceMayBeIncomplete: retention.eventsPrunedByAge > 0 || retention.eventsPrunedByCount > 0,\n }\n}\n","import type { PollingScheduleSnapshot } from './polling-schedule.ts'\nimport { type UpdateActivityLane, updateActivityWindowMillis } from './update-activity.ts'\n\nexport function activityMarkerPosition(at: string, now: Date) {\n return Math.max(\n 0,\n Math.min(\n 100,\n ((Date.parse(at) - (now.valueOf() - updateActivityWindowMillis)) /\n updateActivityWindowMillis) *\n 100,\n ),\n )\n}\n\nexport function activityLaneLabel(lane: UpdateActivityLane, now: Date) {\n return `${lane.label}, panel ${lane.panelId}; ${cadenceLabel(lane.cadence)} cadence; ${lane.inFlight ? 'request in flight' : lane.nextDueAt ? relativeDue(lane.nextDueAt, now) : 'awaiting first request'}; ${lane.observed.length ? `${lane.observed.length} observed proxy path${lane.observed.length === 1 ? '' : 's'}` : 'no retained requests in the last 10 minutes'}`\n}\n\nfunction cadenceLabel(cadence: PollingScheduleSnapshot['cadence']) {\n return cadence === 'completion-window'\n ? 'Completion-window'\n : cadence === 'running'\n ? 'Running'\n : 'Normal'\n}\n\nfunction relativeDue(at: string, now: Date) {\n const millis = Date.parse(at) - now.valueOf()\n return millis < 0 ? `Overdue by ${formatMillis(-millis)}` : `Next poll in ${formatMillis(millis)}`\n}\n\nfunction formatMillis(millis: number) {\n return millis % 60_000 === 0\n ? `${Math.round(millis / 60_000)}m`\n : `${Math.max(1, Math.round(millis / 1_000))}s`\n}\n","import type { Board } from '@ze-great-dashboard/shared'\nimport { useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'\nimport type { BrowserDiagnosticStore } from './diagnostics.ts'\nimport type { PollingScheduleSnapshot } from './polling-schedule.ts'\nimport styles from './UpdateActivity.module.css'\nimport { projectUpdateActivity } from './update-activity.ts'\nimport { activityLaneLabel, activityMarkerPosition } from './update-activity-presentation.ts'\n\n/** A browser-local polling timeline, available on demand. Diagnostics retains the exportable detail. */\nexport function UpdateActivity({\n board,\n schedules,\n log,\n}: {\n board: Board | undefined\n schedules: PollingScheduleSnapshot[]\n log: BrowserDiagnosticStore\n}) {\n const [now, setNow] = useState(() => new Date())\n const [open, setOpen] = useState(false)\n const triggerRef = useRef<HTMLButtonElement>(null)\n const dialogRef = useRef<HTMLElement>(null)\n const closeRef = useRef<HTMLButtonElement>(null)\n const wasOpenRef = useRef(false)\n useSyncExternalStore(log.subscribe, log.snapshot, log.snapshot)\n useEffect(() => {\n if (!open) return\n const interval = window.setInterval(() => setNow(new Date()), 1_000)\n return () => window.clearInterval(interval)\n }, [open])\n const activity = useMemo(\n () => projectUpdateActivity({ schedules, ...log.retainedEvidence(), now }),\n [log, now, schedules],\n )\n\n useEffect(() => {\n if (!open) {\n if (wasOpenRef.current) triggerRef.current?.focus()\n wasOpenRef.current = false\n return\n }\n\n wasOpenRef.current = true\n const dismiss = () => setOpen(false)\n let timeout = window.setTimeout(dismiss, 60_000)\n const resetDismissal = () => {\n window.clearTimeout(timeout)\n timeout = window.setTimeout(dismiss, 60_000)\n }\n const closeOnEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') dismiss()\n }\n const containFocus = (event: KeyboardEvent) => {\n if (event.key !== 'Tab') return\n const focusable = [\n ...(dialogRef.current?.querySelectorAll<HTMLElement>(\n 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])',\n ) ?? []),\n ]\n const first = focusable.at(0)\n const last = focusable.at(-1)\n if (!first || !last) return\n if (event.shiftKey && document.activeElement === first) {\n event.preventDefault()\n last?.focus()\n } else if (!event.shiftKey && document.activeElement === last) {\n event.preventDefault()\n first.focus()\n }\n }\n const dialog = dialogRef.current\n dialog?.addEventListener('pointerdown', resetDismissal)\n dialog?.addEventListener('keydown', resetDismissal)\n dialog?.addEventListener('focusin', resetDismissal)\n dialog?.addEventListener('keydown', containFocus)\n window.addEventListener('keydown', closeOnEscape)\n closeRef.current?.focus()\n return () => {\n window.clearTimeout(timeout)\n dialog?.removeEventListener('pointerdown', resetDismissal)\n dialog?.removeEventListener('keydown', resetDismissal)\n dialog?.removeEventListener('focusin', resetDismissal)\n dialog?.removeEventListener('keydown', containFocus)\n window.removeEventListener('keydown', closeOnEscape)\n }\n }, [open])\n\n return (\n <>\n <button\n ref={triggerRef}\n className={styles.trigger}\n type=\"button\"\n aria-expanded={open}\n aria-controls=\"update-activity-dialog\"\n onClick={() => {\n setNow(new Date())\n setOpen(true)\n }}\n >\n Update activity\n </button>\n {open && (\n <section\n ref={dialogRef}\n className={styles.dialog}\n data-update-activity\n id=\"update-activity-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"update-activity-title\"\n >\n <div className={styles.dialogHeader}>\n <div>\n <h2 id=\"update-activity-title\">Update activity</h2>\n <p>\n Browser-local proxy reads from the last 10 minutes. Panels schedule independently.\n </p>\n </div>\n <button\n ref={closeRef}\n className={styles.close}\n type=\"button\"\n onClick={() => setOpen(false)}\n >\n Close\n </button>\n </div>\n <div className={styles.body}>\n <span className={styles.legend}>● observed · ◇ expected</span>\n {board && activity.lanes.length === 0 && (\n <p className={styles.empty}>No visible polling panels are configured.</p>\n )}\n {activity.lanes.length > 0 && (\n <>\n <div className={styles.axis} aria-hidden=\"true\">\n <span>10m ago</span>\n <span>now</span>\n </div>\n <div className={styles.lanes}>\n {activity.lanes.map((lane) => (\n <div className={styles.lane} data-update-activity-lane key={lane.panelId}>\n <span className={styles.laneLabel}>{lane.label}</span>\n <span\n className={styles.track}\n role=\"img\"\n aria-label={activityLaneLabel(lane, now)}\n >\n {lane.observed.flatMap(({ path, starts }) =>\n starts.map((start) => (\n <i\n className={styles.observed}\n key={`${path}-${start}`}\n style={{ left: `${activityMarkerPosition(start, now)}%` }}\n title={`Observed request: ${path}`}\n />\n )),\n )}\n {lane.nextDueAt && (\n <i\n className={styles.expected}\n style={{ left: `${activityMarkerPosition(lane.nextDueAt, now)}%` }}\n title=\"Expected next poll\"\n />\n )}\n </span>\n </div>\n ))}\n </div>\n </>\n )}\n {activity.evidenceMayBeIncomplete && (\n <p className={styles.note}>\n Older browser evidence was pruned, so an empty lane only means no retained request\n in this window.\n </p>\n )}\n <p className={styles.note}>\n Observed markers are requests this browser started; the outlined marker is the current\n expected next poll, not an observed request.\n </p>\n </div>\n </section>\n )}\n </>\n )\n}\n","import { type ClientEnv, clientIdentityResponseSchema } from '@ze-great-dashboard/shared'\nimport { useEffect } from 'react'\nimport type { DashboardAuth } from './dashboard-fetch.ts'\nimport { dashboardFetch } from './dashboard-fetch.ts'\nimport type { DiagnosticSink } from './diagnostics.ts'\n\nconst clientUpdateIntervalMillis = 60_000\nconst clientUpdateTimeoutMillis = 10_000\nconst defaultReload = () => globalThis.window.location.reload()\n\nexport function useClientUpdate({\n env,\n diagnostics,\n fetcher,\n reload = defaultReload,\n auth,\n}: {\n env: ClientEnv\n diagnostics: DiagnosticSink\n fetcher?: typeof fetch\n reload?: () => void\n auth?: DashboardAuth\n}) {\n useEffect(() => {\n let cancelled = false\n let inFlight = false\n let activeController: AbortController | undefined\n const path = `${env.proxyPath}/client`\n\n const check = async () => {\n if (cancelled || inFlight) return\n inFlight = true\n const controller = new AbortController()\n activeController = controller\n const timeout = globalThis.setTimeout(() => controller.abort(), clientUpdateTimeoutMillis)\n diagnostics.record({ kind: 'client-update-check', path })\n try {\n const response = await dashboardFetch(\n env,\n path,\n {\n cache: 'no-store',\n signal: controller.signal,\n },\n fetcher ?? globalThis.fetch,\n auth,\n )\n if (!response.ok) throw new Error(`Client identity returned ${response.status}`)\n const parsed = clientIdentityResponseSchema.safeParse(await response.json())\n if (!parsed.success) throw new Error('Client identity response was invalid')\n if (cancelled) return\n diagnostics.record({\n kind: 'client-update-response',\n path,\n serverVersion: parsed.data.serverVersion,\n assetPathIdMatches: parsed.data.assetPathId === env.assetPathId,\n })\n if (parsed.data.assetPath !== env.assetPath) {\n diagnostics.record({\n kind: 'client-update-detected',\n path,\n current: { assetPath: env.assetPath },\n next: parsed.data,\n })\n reload()\n }\n } catch (error) {\n if (!cancelled && !(error instanceof DOMException && error.name === 'AbortError')) {\n diagnostics.record({\n kind: 'client-update-failure',\n path,\n message: error instanceof Error ? error.message : String(error),\n })\n }\n } finally {\n globalThis.clearTimeout(timeout)\n inFlight = false\n if (activeController === controller) activeController = undefined\n if (!cancelled) globalThis.setTimeout(() => void check(), clientUpdateIntervalMillis)\n }\n }\n\n void check()\n return () => {\n cancelled = true\n activeController?.abort()\n }\n }, [auth, diagnostics, env, fetcher, reload])\n}\n","import {\n type Envelope,\n type Panel,\n pipelineStatusSchema,\n pullRequestHealthSchema,\n} from '@ze-great-dashboard/shared'\nimport type { RenderedPanelDiagnostic } from './diagnostics.ts'\nimport type { HttpValueFactObservation } from './panel-props.ts'\n\n/**\n * The compact public fact a viewer saw. Keep new panel projections here beside their\n * presentation boundary; this is intentionally not a source or server event contract.\n */\nexport function projectPanelDiagnostic(panel: Panel, envelope: Envelope): RenderedPanelDiagnostic {\n if (envelope.state === 'error') return { state: envelope.state, link: envelope.link }\n\n if (panel.type === 'pipeline-status') {\n const signal = pipelineStatusSchema.safeParse(envelope.signal)\n return {\n state: envelope.state,\n status: signal.success ? signal.data.status : undefined,\n link: envelope.link,\n }\n }\n\n if (panel.type === 'pull-request-health') {\n const signal = pullRequestHealthSchema.safeParse(envelope.signal)\n return {\n state: envelope.state,\n status: signal.success ? signal.data.status : undefined,\n link: envelope.link,\n }\n }\n\n return { state: envelope.state, link: envelope.link }\n}\n\nexport function panelDiagnosticChanged(\n previous: Envelope | undefined,\n panel: Panel,\n next: Envelope,\n) {\n if (!previous) return true\n const before = projectPanelDiagnostic(panel, previous)\n const after = projectPanelDiagnostic(panel, next)\n return (\n before.state !== after.state || before.status !== after.status || before.link !== after.link\n )\n}\n\n/** Public evidence for a visual group whose sources were observed independently. */\nexport function projectHttpValueFactsDiagnostic(\n facts: Record<string, HttpValueFactObservation | undefined>,\n): RenderedPanelDiagnostic {\n const projected = Object.entries(facts).map(([id, observation]) => {\n if (!observation?.envelope) return { id, state: 'unavailable' as const, link: null }\n return { id, state: observation.envelope.state, link: observation.envelope.link }\n })\n return {\n state: projected.some((fact) => fact.state === 'ok') ? 'ok' : 'error',\n link: null,\n facts: projected,\n }\n}\n\nexport function httpValueFactsDiagnosticChanged(\n previous: Record<string, HttpValueFactObservation | undefined> | undefined,\n next: Record<string, HttpValueFactObservation | undefined>,\n) {\n return (\n JSON.stringify(previous && projectHttpValueFactsDiagnostic(previous)) !==\n JSON.stringify(projectHttpValueFactsDiagnostic(next))\n )\n}\n","import type { Panel, PipelineStatus } from '@ze-great-dashboard/shared'\nimport { browserLocalStorage, readBrowserJson, writeBrowserJson } from './browser-storage.ts'\n\nconst storageKey = 'ze-great-dashboard.panel-memory.v1'\nconst schemaVersion = 1\nconst historyWindowMillis = 14 * 24 * 60 * 60 * 1_000\n\nexport type PanelMemoryIdentity = {\n board: string\n panelId: string\n source: string\n workflow: string\n branch: string\n}\n\nexport type AcceptedPipeline = {\n sourceUpdatedAt: string\n status: PipelineStatus['status']\n link: string | null\n}\n\nexport type DurationSample = {\n link: string | null\n sourceRunId?: string\n durationMs: number\n sourceUpdatedAt: string\n}\ntype History = {\n latest?: AcceptedPipeline\n durations: Record<string, DurationSample>\n latestCompleted?: DurationSample\n}\ntype StoredMemory = { schemaVersion: number; histories: Record<string, History> }\ntype StorageLike = Pick<Storage, 'getItem' | 'setItem'>\n\nexport class BrowserPanelMemory {\n private histories: Record<string, History>\n private readonly storage: StorageLike | undefined\n\n constructor(\n storage: StorageLike | undefined = browserLocalStorage(),\n private readonly now: () => Date = () => new Date(),\n ) {\n this.storage = storage\n this.histories = this.read()\n this.pruneAll()\n }\n\n latest(identity: PanelMemoryIdentity): AcceptedPipeline | undefined {\n return this.history(identity).latest\n }\n\n rememberLatest(identity: PanelMemoryIdentity, latest: AcceptedPipeline) {\n this.history(identity).latest = latest\n this.persist()\n }\n\n recordRun(identity: PanelMemoryIdentity, sample: DurationSample, successful = false) {\n const history = this.history(identity)\n if (successful) history.durations[sampleKey(sample)] = sample\n const previous = history.latestCompleted\n if (!previous || isAtLeastAsRecent(sample.sourceUpdatedAt, previous.sourceUpdatedAt)) {\n history.latestCompleted = sample\n }\n this.pruneHistory(history)\n this.persist()\n }\n\n recordSuccessfulRun(identity: PanelMemoryIdentity, sample: DurationSample) {\n this.recordRun(identity, sample, true)\n }\n\n recordCompletedRun(identity: PanelMemoryIdentity, sample: DurationSample) {\n this.recordRun(identity, sample)\n }\n\n medianDuration(identity: PanelMemoryIdentity): number | undefined {\n const history = this.history(identity)\n this.pruneHistory(history)\n const durations = Object.values(history.durations)\n .map(({ durationMs }) => durationMs)\n .sort((left, right) => left - right)\n if (durations.length === 0) return undefined\n const middle = Math.floor(durations.length / 2)\n if (durations.length % 2 === 1) return durations[middle]\n const lower = durations[middle - 1]\n const upper = durations[middle]\n return lower === undefined || upper === undefined ? undefined : Math.floor((lower + upper) / 2)\n }\n\n resolveEstimatedDuration(identity: PanelMemoryIdentity): number | undefined {\n const successful = this.medianDuration(identity)\n if (successful !== undefined) return successful\n\n const history = this.history(identity)\n this.pruneHistory(history)\n return history.latestCompleted?.durationMs\n }\n\n private history(identity: PanelMemoryIdentity) {\n const key = identityKey(identity)\n const existing = this.histories[key]\n if (existing) return existing\n const created: History = { durations: {} }\n this.histories[key] = created\n return created\n }\n\n private pruneAll() {\n for (const history of Object.values(this.histories)) this.pruneHistory(history)\n this.persist()\n }\n\n private pruneHistory(history: History) {\n const cutoff = this.now().valueOf() - historyWindowMillis\n for (const [link, sample] of Object.entries(history.durations)) {\n const at = sourceTimestamp(sample.sourceUpdatedAt)\n if (at === undefined || at < cutoff) delete history.durations[link]\n }\n const latestCompletedAt = history.latestCompleted\n ? sourceTimestamp(history.latestCompleted.sourceUpdatedAt)\n : undefined\n if (\n history.latestCompleted &&\n (latestCompletedAt === undefined || latestCompletedAt < cutoff)\n ) {\n delete history.latestCompleted\n }\n }\n\n private read(): Record<string, History> {\n const parsed = readBrowserJson<Partial<StoredMemory>>(this.storage, storageKey)\n if (parsed?.schemaVersion !== schemaVersion || !parsed.histories) return {}\n return isHistories(parsed.histories) ? parsed.histories : {}\n }\n\n private persist() {\n writeBrowserJson(this.storage, storageKey, { schemaVersion, histories: this.histories })\n }\n}\n\nfunction sampleKey(sample: DurationSample) {\n return sample.sourceRunId ?? sample.link ?? sample.sourceUpdatedAt\n}\n\nfunction isAtLeastAsRecent(left: string, right: string) {\n const leftAt = sourceTimestamp(left)\n const rightAt = sourceTimestamp(right)\n return leftAt !== undefined && (rightAt === undefined || leftAt >= rightAt)\n}\n\nfunction sourceTimestamp(value: string) {\n const timestamp = Date.parse(value)\n return Number.isFinite(timestamp) ? timestamp : undefined\n}\n\nexport function resolvePanelMemoryIdentity(board: string, panel: Panel): PanelMemoryIdentity {\n return {\n board,\n panelId: panel.id,\n source: panel.source ?? '',\n workflow:\n typeof panel.pipeline === 'string' || typeof panel.pipeline === 'number'\n ? String(panel.pipeline)\n : '',\n branch: panel.branch ?? '',\n }\n}\n\nfunction identityKey(identity: PanelMemoryIdentity) {\n return JSON.stringify([\n identity.board,\n identity.panelId,\n identity.source,\n identity.workflow,\n identity.branch,\n ])\n}\n\nfunction isHistories(value: unknown): value is Record<string, History> {\n if (!isRecord(value)) return false\n return Object.values(value).every(isHistory)\n}\n\nfunction isHistory(value: unknown): value is History {\n if (!isRecord(value) || !isRecord(value.durations)) return false\n if (!Object.values(value.durations).every(isDurationSample)) return false\n return value.latestCompleted === undefined || isDurationSample(value.latestCompleted)\n}\n\nfunction isDurationSample(value: unknown): value is DurationSample {\n if (!isRecord(value)) return false\n return (\n (typeof value.link === 'string' || value.link === null) &&\n (value.sourceRunId === undefined || typeof value.sourceRunId === 'string') &&\n typeof value.durationMs === 'number' &&\n Number.isInteger(value.durationMs) &&\n value.durationMs >= 0 &&\n typeof value.sourceUpdatedAt === 'string' &&\n sourceTimestamp(value.sourceUpdatedAt) !== undefined\n )\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n","import { type Envelope, envelopeSchema } from '@ze-great-dashboard/shared'\nimport { cacheMetadata, type DiagnosticSink } from './diagnostics.ts'\n\nexport type ComponentObservation = { envelope?: Envelope; error?: string }\n\n/**\n * Reads one bounded panel component while retaining its browser cache conversation and public\n * diagnostics. Composite panels use this instead of inventing an aggregate source response.\n */\nexport async function readPanelObservation(args: {\n diagnostics: DiagnosticSink\n panelId: string\n path: string\n signal?: AbortSignal\n cache: Map<string, Envelope>\n fetcher: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>\n}): Promise<ComponentObservation> {\n args.diagnostics.record({ kind: 'panel-fetch-start', panelId: args.panelId, path: args.path })\n try {\n const response = await args.fetcher(args.path, { signal: args.signal })\n const transport = {\n kind: 'panel-fetch-response' as const,\n panelId: args.panelId,\n path: args.path,\n status: response.status,\n cache: cacheMetadata(response.headers),\n }\n if (response.status === 304) {\n args.diagnostics.record(transport)\n const cached = args.cache.get(args.path)\n return cached\n ? { envelope: cached }\n : { error: 'Source returned not modified before an initial observation.' }\n }\n const parsed = envelopeSchema.safeParse(await response.json())\n if (!parsed.success) {\n args.diagnostics.record(transport)\n args.diagnostics.record({\n kind: 'panel-fetch-parse-failure',\n panelId: args.panelId,\n path: args.path,\n message: 'Response was not a valid signal envelope.',\n })\n return { error: 'Response was not a valid signal envelope.' }\n }\n const envelope = parsed.data\n args.diagnostics.record({\n ...transport,\n envelope,\n ...(envelope.state === 'error' ? { failure: failedObservation(envelope, response) } : {}),\n })\n if (envelope.state === 'ok') args.cache.set(args.path, envelope)\n return { envelope }\n } catch (error) {\n if (!args.signal?.aborted)\n args.diagnostics.record({\n kind: 'panel-fetch-failure',\n panelId: args.panelId,\n path: args.path,\n message: errorMessage(error),\n })\n return { error: errorMessage(error) }\n }\n}\n\nfunction failedObservation(envelope: Extract<Envelope, { state: 'error' }>, response: Response) {\n const supportReference = response.headers.get('x-dashboard-request-id')\n return {\n reason: envelope.error.message,\n ...(supportReference ? { supportReference } : {}),\n }\n}\n\nfunction errorMessage(error: unknown) {\n return error instanceof Error ? error.message : String(error)\n}\n","import type { Envelope, PipelineStatus } from '@ze-great-dashboard/shared'\nimport { pipelineStatusSchema } from '@ze-great-dashboard/shared'\nimport type { AcceptedPipeline } from './panel-memory.ts'\n\nexport type PipelineDurationSample = {\n link: string | null\n sourceRunId?: string\n durationMs: number\n sourceUpdatedAt: string\n}\n\nexport type PipelineReconciliation =\n | { kind: 'not-pipeline'; envelope: Envelope }\n | {\n kind: 'rejected'\n envelope: Extract<Envelope, { state: 'ok' }>\n signal: PipelineStatus & { sourceUpdatedAt: string }\n }\n | {\n kind: 'accepted'\n envelope: Envelope\n signal: PipelineStatus\n accepted?: AcceptedPipeline\n durationSample?: PipelineDurationSample\n }\n\nexport function reconcilePipelineResponse(args: {\n envelope: Envelope\n accepted?: AcceptedPipeline\n estimatedDurationMs?: number\n}): PipelineReconciliation {\n const signal = pipelineStatus(args.envelope)\n if (!signal) return { kind: 'not-pipeline', envelope: args.envelope }\n if (\n args.accepted &&\n signal.sourceUpdatedAt &&\n Date.parse(signal.sourceUpdatedAt) < Date.parse(args.accepted.sourceUpdatedAt)\n ) {\n if (args.envelope.state !== 'ok' || !signal.sourceUpdatedAt)\n return { kind: 'not-pipeline', envelope: args.envelope }\n return {\n kind: 'rejected',\n envelope: args.envelope,\n signal: { ...signal, sourceUpdatedAt: signal.sourceUpdatedAt },\n }\n }\n\n const accepted = signal.sourceUpdatedAt\n ? { sourceUpdatedAt: signal.sourceUpdatedAt, status: signal.status, link: args.envelope.link }\n : undefined\n const durationSample =\n signal.status !== 'running' &&\n signal.durationMs !== undefined &&\n signal.sourceUpdatedAt &&\n Number.isFinite(Date.parse(signal.sourceUpdatedAt))\n ? {\n link: args.envelope.link,\n ...(signal.sourceRunId ? { sourceRunId: signal.sourceRunId } : {}),\n durationMs: signal.durationMs,\n sourceUpdatedAt: signal.sourceUpdatedAt,\n }\n : undefined\n const envelope =\n signal.status === 'running' &&\n args.estimatedDurationMs !== undefined &&\n args.envelope.state === 'ok'\n ? { ...args.envelope, signal: { ...signal, estimatedDurationMs: args.estimatedDurationMs } }\n : args.envelope\n return { kind: 'accepted', envelope, signal, accepted, durationSample }\n}\n\nexport function pipelineStatus(envelope: Envelope): PipelineStatus | undefined {\n if (envelope.state !== 'ok') return undefined\n const result = pipelineStatusSchema.safeParse(envelope.signal)\n return result.success ? result.data : undefined\n}\n","import {\n type Board,\n type ClientEnv,\n isZeroPosition,\n resolvePollingSettings,\n} from '@ze-great-dashboard/shared'\nimport type { PollingScheduleSnapshot } from './polling-schedule.ts'\n\ntype PollingPanel = Board['panels'][number] & {\n type: 'pipeline-status' | 'pull-request-health' | 'http-value'\n}\n\n/** The exact visible panel types that originate proxy polling in this client. */\nexport function pollingPanels(board: Board): PollingPanel[] {\n return board.panels.filter(\n (panel): panel is PollingPanel =>\n !isZeroPosition(panel.position) &&\n (panel.type === 'pipeline-status' ||\n panel.type === 'pull-request-health' ||\n panel.type === 'http-value'),\n )\n}\n\nexport function panelProxyPath(env: ClientEnv, panelId: string) {\n return `${env.proxyPath}/panel/${encodeURIComponent(env.board)}/${encodeURIComponent(panelId)}`\n}\n\n/** Build the initial schedule without claiming branch-dependent fan-out before it is observed. */\nexport function initialPollingSchedule(\n board: Board,\n env: ClientEnv,\n panel: PollingPanel,\n): PollingScheduleSnapshot {\n const path = panelProxyPath(env, panel.id)\n const knownPaths =\n panel.type === 'http-value' && panel.facts\n ? panel.facts.map((fact) => `${path}/facts/${encodeURIComponent(fact.id)}`)\n : panel.type === 'pull-request-health'\n ? [\n `${path}/pull-requests`,\n ...readUpdateWorkflows(panel).map(\n ({ workflow }) => `${path}/update-workflow/${encodeURIComponent(workflow)}`,\n ),\n ]\n : [path]\n return {\n panelId: panel.id,\n label: panel.label ?? panel.id,\n settings: resolvePollingSettings(board, panel),\n cadence: 'normal',\n inFlight: false,\n knownPaths,\n }\n}\n\nexport function readUpdateWorkflows(panel: unknown) {\n const value =\n typeof panel === 'object' && panel !== null\n ? (panel as { update_workflows?: unknown }).update_workflows\n : undefined\n if (!Array.isArray(value)) return []\n return value.flatMap((entry) =>\n typeof entry === 'object' &&\n entry !== null &&\n typeof (entry as { workflow?: unknown }).workflow === 'string'\n ? [{ workflow: (entry as { workflow: string }).workflow }]\n : [],\n )\n}\n","import {\n type Envelope,\n type PipelineStatus,\n type PollingSettings,\n pipelineStatusSchema,\n} from '@ze-great-dashboard/shared'\n\n/** Ephemeral scheduling state; polling owns it and views may project it. */\nexport type PollingScheduleSnapshot = {\n panelId: string\n label: string\n settings: PollingSettings\n cadence: PollingCadence\n inFlight: boolean\n lastRequestStartedAt?: string\n nextDueAt?: string\n /** Paths known before this cycle; dynamic fan-out is disclosed only once observed. */\n knownPaths: string[]\n}\n\n/** Return the next delay for a panel, keeping active runs responsive without polling forever at burst speed. */\nexport function nextPollDelayMillis(\n envelope: Envelope | undefined,\n nowMillis: number,\n settings: PollingSettings,\n): number {\n return resolveNextPoll(envelope, nowMillis, settings).delayMillis\n}\n\nexport type PollingCadence = 'normal' | 'running' | 'completion-window'\n\n/** The scheduler and activity view share this resolved cadence; neither infers it from history. */\nexport function resolveNextPoll(\n envelope: Envelope | undefined,\n nowMillis: number,\n settings: PollingSettings,\n): { delayMillis: number; cadence: PollingCadence } {\n const pipeline = runningPipeline(envelope)\n if (!pipeline) return { delayMillis: settings.refreshMillis, cadence: 'normal' }\n\n const completionAt = estimatedCompletionAt(pipeline)\n if (completionAt === undefined)\n return { delayMillis: settings.runningRefreshMillis, cadence: 'running' }\n\n if (nowMillis < completionAt) {\n return {\n delayMillis: Math.min(settings.runningRefreshMillis, completionAt - nowMillis),\n cadence: 'running',\n }\n }\n if (nowMillis < completionAt + settings.runningCompletionWindowMillis) {\n return { delayMillis: settings.runningCompletionRefreshMillis, cadence: 'completion-window' }\n }\n return { delayMillis: settings.runningRefreshMillis, cadence: 'running' }\n}\n\nfunction runningPipeline(envelope: Envelope | undefined): PipelineStatus | undefined {\n if (envelope?.state !== 'ok') return undefined\n const result = pipelineStatusSchema.safeParse(envelope.signal)\n return result.success && result.data.status === 'running' ? result.data : undefined\n}\n\nfunction estimatedCompletionAt(signal: PipelineStatus): number | undefined {\n if (!signal.runStartedAt || signal.estimatedDurationMs === undefined) return undefined\n const startedAt = Date.parse(signal.runStartedAt)\n return Number.isFinite(startedAt) ? startedAt + signal.estimatedDurationMs : undefined\n}\n","import type {\n Envelope,\n PipelineStatus,\n PullRequestCandidate,\n PullRequestHealth,\n} from '@ze-great-dashboard/shared'\nimport {\n pipelineStatusPriority,\n pullRequestBuildObservationSchema,\n pullRequestCandidatesSchema,\n pullRequestWorkflowObservationSchema,\n} from '@ze-great-dashboard/shared'\n\ntype Observation = { envelope?: Envelope; error?: string }\n\n/** Purely combines normalized, public component observations; it never constructs source URLs. */\nexport function rollupPullRequestHealth(args: {\n panelId: string\n link: string | null\n workflows: Array<{ workflow: string; observation: Observation }>\n candidates: Observation\n builds: Map<string, Observation>\n}): Envelope | undefined {\n const incomplete: Array<{ label: string; message: string }> = []\n const workflows = args.workflows.map(({ workflow, observation }) => {\n const signal = observationItem(observation.envelope, 'pull-request-workflow')\n if (signal) return signal.item as PullRequestHealth['workflows'][number]\n const message = observation.error ?? 'No usable observation is available.'\n incomplete.push({ label: `Update workflow ${workflow}`, message })\n return {\n label: workflow,\n status: 'unknown' as const,\n detail: `Update workflow ${workflow} · Unavailable: ${message}`,\n link: null,\n }\n })\n const candidatesSignal = candidateSignal(args.candidates.envelope)\n if (!candidatesSignal) {\n const message = args.candidates.error ?? 'No usable observation is available.'\n incomplete.push({ label: 'Open update PR candidates', message })\n if (workflows.every((item) => item.status === 'unknown')) return undefined\n return buildEnvelope(\n args,\n workflows,\n [],\n incomplete,\n observationDates(args.workflows.map(({ observation }) => observation)),\n )\n }\n if (candidatesSignal.truncated)\n incomplete.push({\n label: 'Open update PR candidates',\n message: 'The first 100 candidates were observed; additional open update PRs may exist.',\n })\n const pullRequests = candidatesSignal.pullRequests.map((candidate: PullRequestCandidate) => {\n const observation = args.builds.get(candidate.branch)\n const signal = observationItem(observation?.envelope, 'pull-request-build')\n if (signal)\n return {\n ...signal.item,\n label: `PR #${candidate.number}`,\n detail: signal.item.detail,\n link: candidate.link,\n }\n const message = observation?.error ?? 'No usable observation is available.'\n incomplete.push({ label: `PR #${candidate.number}`, message })\n return {\n label: `PR #${candidate.number}`,\n status: 'unknown' as const,\n detail: `${candidate.branch} · Unavailable: ${message}`,\n link: candidate.link,\n }\n })\n return buildEnvelope(\n args,\n workflows,\n pullRequests,\n incomplete,\n observationDates([\n ...args.workflows.map(({ observation }) => observation),\n args.candidates,\n ...args.builds.values(),\n ]),\n )\n}\n\nfunction buildEnvelope(\n args: Parameters<typeof rollupPullRequestHealth>[0],\n workflows: PullRequestHealth['workflows'],\n pullRequests: PullRequestHealth['pullRequests'],\n incomplete: Array<{ label: string; message: string }>,\n dates: string[],\n) {\n const status = aggregateStatus([...workflows, ...pullRequests].map((item) => item.status))\n const attentionItem = [...workflows, ...pullRequests].find((item) => item.status === status)\n const summary =\n status !== 'passed' && attentionItem\n ? `${attentionItem.label}: ${attentionItem.detail}`\n : pullRequests.length === 0\n ? `${workflows.length} update workflow${workflows.length === 1 ? '' : 's'} · No open update PRs`\n : `${workflows.length} update workflow${workflows.length === 1 ? '' : 's'} · ${pullRequests.length} open update PR${pullRequests.length === 1 ? '' : 's'}`\n const sorted = dates.sort()\n return {\n panelId: args.panelId,\n state: 'ok' as const,\n observedAt: sorted[0] ?? new Date().toISOString(),\n link: args.link,\n signal: {\n type: 'pull-request-health' as const,\n status,\n summary,\n workflows,\n pullRequests,\n ...(incomplete.length ? { incompleteObservations: incomplete } : {}),\n ...(sorted.length > 1 ? { newestObservedAt: sorted.at(-1) } : {}),\n } satisfies PullRequestHealth,\n }\n}\n\nfunction observationItem(\n envelope: Envelope | undefined,\n type: 'pull-request-workflow' | 'pull-request-build',\n): { item: PullRequestHealth['workflows'][number] } | undefined {\n if (envelope?.state !== 'ok') return undefined\n const schema =\n type === 'pull-request-workflow'\n ? pullRequestWorkflowObservationSchema\n : pullRequestBuildObservationSchema\n const result = schema.safeParse(envelope.signal)\n return result.success ? { item: result.data.item } : undefined\n}\nfunction candidateSignal(\n envelope: Envelope | undefined,\n): { pullRequests: PullRequestCandidate[]; truncated?: boolean } | undefined {\n if (envelope?.state !== 'ok') return undefined\n const result = pullRequestCandidatesSchema.safeParse(envelope.signal)\n return result.success ? result.data : undefined\n}\nfunction observationDates(observations: Observation[]) {\n return observations.flatMap(({ envelope }) =>\n envelope?.state === 'ok' ? [envelope.observedAt] : [],\n )\n}\nfunction aggregateStatus(statuses: PipelineStatus['status'][]): PipelineStatus['status'] {\n return statuses.reduce(\n (mostUrgent, status) =>\n pipelineStatusPriority(status) > pipelineStatusPriority(mostUrgent) ? status : mostUrgent,\n 'passed' as const,\n )\n}\n","import {\n type Board,\n type ClientEnv,\n type Envelope,\n envelopeSchema,\n} from '@ze-great-dashboard/shared'\nimport { useEffect, useRef, useState } from 'react'\nimport type { DashboardAuth } from './dashboard-fetch.ts'\nimport { dashboardFetch } from './dashboard-fetch.ts'\nimport { cacheMetadata, type DiagnosticSink } from './diagnostics.ts'\nimport {\n httpValueFactsDiagnosticChanged,\n panelDiagnosticChanged,\n projectHttpValueFactsDiagnostic,\n projectPanelDiagnostic,\n} from './panel-diagnostics.ts'\nimport { BrowserPanelMemory, resolvePanelMemoryIdentity } from './panel-memory.ts'\nimport { readPanelObservation } from './panel-observation.ts'\nimport type { HttpValueFactObservation, PanelUpdateHealth } from './panel-props.ts'\nimport { reconcilePipelineResponse } from './pipeline-reconciliation.ts'\nimport {\n initialPollingSchedule,\n panelProxyPath,\n pollingPanels,\n readUpdateWorkflows,\n} from './polling-panels.ts'\nimport { type PollingScheduleSnapshot, resolveNextPoll } from './polling-schedule.ts'\nimport { rollupPullRequestHealth } from './pull-request-rollup.ts'\n\nexport function usePanelSignals({\n board,\n env,\n diagnostics,\n memory,\n auth,\n}: {\n board: Board | undefined\n env: ClientEnv\n diagnostics: DiagnosticSink\n memory?: BrowserPanelMemory\n auth?: DashboardAuth\n}) {\n const [signals, setSignals] = useState<Record<string, Envelope | undefined>>({})\n const [updateHealth, setUpdateHealth] = useState<Record<string, PanelUpdateHealth | undefined>>(\n {},\n )\n const [factSignals, setFactSignals] = useState<\n Record<string, Record<string, HttpValueFactObservation | undefined> | undefined>\n >({})\n const [schedules, setSchedules] = useState<PollingScheduleSnapshot[]>([])\n const signalsRef = useRef<Record<string, Envelope | undefined>>({})\n const factSignalsRef = useRef<\n Record<string, Record<string, HttpValueFactObservation | undefined> | undefined>\n >({})\n const memoryRef = useRef<BrowserPanelMemory | null>(null)\n if (!memoryRef.current) memoryRef.current = memory ?? new BrowserPanelMemory()\n\n useEffect(() => {\n signalsRef.current = {}\n factSignalsRef.current = {}\n setSignals({})\n setUpdateHealth({})\n setFactSignals({})\n setSchedules([])\n if (!board) return\n\n let cancelled = false\n const timers = new Set<number>()\n const abortControllers = new Set<AbortController>()\n const panels = pollingPanels(board)\n const initialSchedules = panels.map((panel) => initialPollingSchedule(board, env, panel))\n const schedulesByPanelId = new Map(\n initialSchedules.map((schedule) => [schedule.panelId, schedule]),\n )\n setSchedules(initialSchedules)\n const updateSchedule = (panelId: string, update: Partial<PollingScheduleSnapshot>) => {\n if (cancelled) return\n setSchedules((current) =>\n current.map((schedule) =>\n schedule.panelId === panelId ? { ...schedule, ...update } : schedule,\n ),\n )\n }\n for (const panel of panels) {\n let inFlight = false\n const memory = memoryRef.current\n if (!memory) return\n const schedule = schedulesByPanelId.get(panel.id)\n if (!schedule) continue\n const { settings } = schedule\n const path = panelProxyPath(env, panel.id)\n let lastEnvelope: Envelope | undefined\n let lastConfirmedAt: string | undefined\n const recordConfirmedUpdate = () => {\n lastConfirmedAt = new Date().toISOString()\n if (!cancelled)\n setUpdateHealth((current) => {\n if (!current[panel.id]) return current\n const next = { ...current }\n delete next[panel.id]\n return next\n })\n }\n const recordUpdateFailure = (error: unknown) => {\n const confirmedAt = lastConfirmedAt\n if (cancelled || !confirmedAt) return\n const message = errorMessage(error)\n setUpdateHealth((current) => {\n const previous = current[panel.id]\n return {\n ...current,\n [panel.id]: {\n consecutiveFailures: (previous?.consecutiveFailures ?? 0) + 1,\n message,\n lastConfirmedAt: confirmedAt,\n },\n }\n })\n }\n if (panel.type === 'http-value' && panel.facts) {\n const facts = panel.facts\n const components = new Map<string, Envelope>()\n let activeController: AbortController | undefined\n const refreshFacts = async () => {\n if (cancelled || inFlight) return\n inFlight = true\n updateSchedule(panel.id, {\n inFlight: true,\n lastRequestStartedAt: new Date().toISOString(),\n nextDueAt: undefined,\n })\n activeController = new AbortController()\n abortControllers.add(activeController)\n const root = `${path}/facts`\n const observations = await Promise.all(\n facts.map(async (fact) => {\n const factPath = `${root}/${encodeURIComponent(fact.id)}`\n const result = await readPanelObservation({\n diagnostics,\n panelId: panel.id,\n path: factPath,\n signal: activeController?.signal,\n cache: components,\n fetcher: (input, init) => dashboardFetch(env, input, init, globalThis.fetch, auth),\n })\n return [fact.id, result.error ? { failure: result.error } : result] as const\n }),\n )\n if (!cancelled && !activeController.signal.aborted) {\n const next = Object.fromEntries(observations)\n const previous = factSignalsRef.current[panel.id]\n if (httpValueFactsDiagnosticChanged(previous, next))\n diagnostics.record({\n kind: 'panel-rendered',\n panelId: panel.id,\n path,\n rendered: projectHttpValueFactsDiagnostic(next),\n })\n factSignalsRef.current = { ...factSignalsRef.current, [panel.id]: next }\n setFactSignals(factSignalsRef.current)\n }\n inFlight = false\n abortControllers.delete(activeController)\n if (!cancelled) {\n const due = Date.now() + settings.refreshMillis\n updateSchedule(panel.id, {\n inFlight: false,\n cadence: 'normal',\n nextDueAt: new Date(due).toISOString(),\n })\n const timer = window.setTimeout(() => {\n timers.delete(timer)\n void refreshFacts()\n }, settings.refreshMillis)\n timers.add(timer)\n }\n }\n void refreshFacts()\n continue\n }\n if (panel.type === 'pull-request-health') {\n const workflows = readUpdateWorkflows(panel)\n const components = new Map<string, Envelope>()\n let activeController: AbortController | undefined\n const request = async (componentPath: string) => {\n const result = await readPanelObservation({\n diagnostics,\n panelId: panel.id,\n path: componentPath,\n signal: activeController?.signal,\n cache: components,\n fetcher: (input, init) => dashboardFetch(env, input, init, globalThis.fetch, auth),\n })\n if (result.envelope?.state === 'error') return { error: result.envelope.error.message }\n return result\n }\n const refreshPullRequestHealth = async () => {\n if (cancelled || inFlight) return\n inFlight = true\n updateSchedule(panel.id, {\n inFlight: true,\n lastRequestStartedAt: new Date().toISOString(),\n nextDueAt: undefined,\n })\n activeController = new AbortController()\n abortControllers.add(activeController)\n const root = path\n const [candidateResult, ...workflowResults] = await Promise.all([\n request(`${root}/pull-requests`),\n ...workflows.map(({ workflow }) =>\n request(`${root}/update-workflow/${encodeURIComponent(workflow)}`),\n ),\n ])\n const candidates =\n candidateResult.envelope?.state === 'ok' &&\n isCandidates(candidateResult.envelope.signal)\n ? candidateResult.envelope.signal.pullRequests\n : []\n if (cancelled || activeController.signal.aborted) {\n abortControllers.delete(activeController)\n return\n }\n const buildResults = await Promise.all(\n candidates.map(\n async (candidate) =>\n [\n candidate.branch,\n await request(\n `${root}/pull-request-build?branch=${encodeURIComponent(candidate.branch)}`,\n ),\n ] as const,\n ),\n )\n const rolled = rollupPullRequestHealth({\n panelId: panel.id,\n link: candidateResult.envelope?.link ?? null,\n workflows: workflows.map(({ workflow }, index) => ({\n workflow,\n observation: workflowResults[index] ?? { error: 'Missing workflow result.' },\n })),\n candidates: candidateResult,\n builds: new Map(buildResults),\n })\n if (cancelled || activeController.signal.aborted) {\n abortControllers.delete(activeController)\n return\n }\n if (rolled && !cancelled) {\n lastEnvelope = rolled\n recordConfirmedUpdate()\n const previous = signalsRef.current[panel.id]\n if (panelDiagnosticChanged(previous, panel, rolled))\n diagnostics.record({\n kind: 'panel-rendered',\n panelId: panel.id,\n path,\n rendered: projectPanelDiagnostic(panel, rolled),\n })\n signalsRef.current = { ...signalsRef.current, [panel.id]: rolled }\n setSignals(signalsRef.current)\n } else if (!cancelled) recordUpdateFailure('No usable pull-request observations.')\n inFlight = false\n abortControllers.delete(activeController)\n if (!cancelled) {\n const next = resolveNextPoll(lastEnvelope, Date.now(), settings)\n const due = Date.now() + next.delayMillis\n updateSchedule(panel.id, {\n inFlight: false,\n cadence: next.cadence,\n nextDueAt: new Date(due).toISOString(),\n })\n const nextTimer = window.setTimeout(() => {\n timers.delete(nextTimer)\n void refreshPullRequestHealth()\n }, next.delayMillis)\n timers.add(nextTimer)\n }\n }\n void refreshPullRequestHealth()\n continue\n }\n const refresh = () => {\n if (cancelled || inFlight) return\n inFlight = true\n updateSchedule(panel.id, {\n inFlight: true,\n lastRequestStartedAt: new Date().toISOString(),\n nextDueAt: undefined,\n })\n diagnostics.record({ kind: 'panel-fetch-start', panelId: panel.id, path })\n dashboardFetch(env, path, undefined, globalThis.fetch, auth)\n .then(async (response) => {\n const transport = {\n kind: 'panel-fetch-response' as const,\n panelId: panel.id,\n path,\n status: response.status,\n cache: cacheMetadata(response.headers),\n }\n if (response.status === 304) {\n diagnostics.record(transport)\n recordConfirmedUpdate()\n return undefined\n }\n try {\n const value: unknown = await response.json()\n const envelope = parseEnvelope(value)\n if (!envelope) {\n diagnostics.record(transport)\n diagnostics.record({\n kind: 'panel-fetch-parse-failure',\n panelId: panel.id,\n path,\n message: 'Response was not a valid signal envelope.',\n })\n recordUpdateFailure('Response was not a valid signal envelope.')\n return undefined\n }\n diagnostics.record({\n ...transport,\n envelope,\n ...(envelope.state === 'error'\n ? { failure: failedObservation(envelope, response) }\n : {}),\n })\n recordConfirmedUpdate()\n return { envelope, cache: transport.cache, status: response.status }\n } catch (error) {\n diagnostics.record(transport)\n diagnostics.record({\n kind: 'panel-fetch-parse-failure',\n panelId: panel.id,\n path,\n message: errorMessage(error),\n })\n throw new DiagnosticParseFailure(error)\n }\n })\n .then((result) => {\n if (!result) return\n let envelope = result.envelope\n if (panel.type === 'pipeline-status') {\n const identity = resolvePanelMemoryIdentity(env.board, panel)\n const accepted = memory.latest(identity)\n const reconciliation = reconcilePipelineResponse({\n envelope,\n accepted,\n estimatedDurationMs: memory.resolveEstimatedDuration(identity),\n })\n if (reconciliation.kind === 'rejected' && accepted) {\n const signal = reconciliation.signal\n diagnostics.recordGithubConsistencyIncident({\n panelId: panel.id,\n endpoint: path,\n identity: {\n source: identity.source,\n workflow: identity.workflow,\n branch: identity.branch,\n },\n accepted,\n regressed: {\n sourceUpdatedAt: signal.sourceUpdatedAt,\n status: signal.status,\n link: envelope.link,\n },\n response: {\n httpStatus: result.status,\n date: result.cache?.date,\n etag: result.cache?.etag,\n cacheControl: result.cache?.cacheControl,\n },\n })\n return\n }\n if (reconciliation.kind === 'accepted') {\n envelope = reconciliation.envelope\n if (reconciliation.accepted)\n memory.rememberLatest(identity, reconciliation.accepted)\n if (reconciliation.durationSample) {\n const sample = {\n link: reconciliation.durationSample.link,\n ...(reconciliation.durationSample.sourceRunId\n ? { sourceRunId: reconciliation.durationSample.sourceRunId }\n : {}),\n durationMs: reconciliation.durationSample.durationMs,\n sourceUpdatedAt: reconciliation.durationSample.sourceUpdatedAt,\n }\n memory.recordRun(identity, sample, reconciliation.signal.status === 'passed')\n }\n }\n }\n lastEnvelope = envelope\n if (!cancelled) {\n const previous = signalsRef.current[panel.id]\n if (panelDiagnosticChanged(previous, panel, envelope)) {\n diagnostics.record({\n kind: 'panel-rendered',\n panelId: panel.id,\n path,\n rendered: projectPanelDiagnostic(panel, envelope),\n })\n }\n signalsRef.current = { ...signalsRef.current, [panel.id]: envelope }\n setSignals(signalsRef.current)\n }\n })\n .catch((error) => {\n recordUpdateFailure(error)\n if (!(error instanceof DiagnosticParseFailure)) {\n diagnostics.record({\n kind: 'panel-fetch-failure',\n panelId: panel.id,\n path,\n message: errorMessage(error),\n })\n }\n })\n .finally(() => {\n inFlight = false\n if (!cancelled) {\n const next = resolveNextPoll(lastEnvelope, Date.now(), settings)\n const due = Date.now() + next.delayMillis\n updateSchedule(panel.id, {\n inFlight: false,\n cadence: next.cadence,\n nextDueAt: new Date(due).toISOString(),\n })\n const nextTimer = window.setTimeout(() => {\n timers.delete(nextTimer)\n refresh()\n }, next.delayMillis)\n timers.add(nextTimer)\n }\n })\n }\n refresh()\n }\n return () => {\n cancelled = true\n for (const controller of abortControllers) controller.abort()\n for (const timer of timers) window.clearTimeout(timer)\n }\n }, [auth, board, diagnostics, env])\n\n return { signals, updateHealth, factSignals, schedules }\n}\n\nfunction failedObservation(envelope: Extract<Envelope, { state: 'error' }>, response: Response) {\n const supportReference = response.headers.get('x-dashboard-request-id')\n return {\n reason: envelope.error.message,\n ...(supportReference ? { supportReference } : {}),\n }\n}\n\nfunction isCandidates(\n value: unknown,\n): value is { type: 'pull-request-candidates'; pullRequests: Array<{ branch: string }> } {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { type?: unknown }).type === 'pull-request-candidates' &&\n Array.isArray((value as { pullRequests?: unknown }).pullRequests)\n )\n}\n\nfunction errorMessage(error: unknown) {\n return error instanceof Error ? error.message : String(error)\n}\n\nclass DiagnosticParseFailure extends Error {\n constructor(error: unknown) {\n super(errorMessage(error))\n }\n}\n\nfunction parseEnvelope(value: unknown): Envelope | undefined {\n const result = envelopeSchema.safeParse(value)\n return result.success ? result.data : undefined\n}\n","import {\n analyzeBoardLayout,\n type Board,\n type ClientEnv,\n isZeroPosition,\n} from '@ze-great-dashboard/shared'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport styles from './App.module.css'\nimport { projectAttention } from './attention.ts'\nimport { Diagnostics } from './Diagnostics.tsx'\nimport type { DashboardAuth } from './dashboard-fetch.ts'\nimport { dashboardFetch } from './dashboard-fetch.ts'\nimport { BrowserDiagnosticStore, cacheMetadata } from './diagnostics.ts'\nimport { OidcGate } from './OidcGate.tsx'\nimport { PanelPlaceholder } from './PanelPlaceholder.tsx'\nimport { PanelRenderer } from './panel-registry.tsx'\nimport { SecurityNotice } from './SecurityNotice.tsx'\nimport { UpdateActivity } from './UpdateActivity.tsx'\nimport { projectUpdateActivity } from './update-activity.ts'\nimport { useClientUpdate } from './useClientUpdate.ts'\nimport { usePanelSignals } from './usePanelSignals.ts'\n\n/**\n * The board shell.\n *\n * Stage 1 has no data: there is no proxy endpoint to poll yet. What this proves is the plumbing —\n * that the client was handed its configuration by the server and knows which version of itself it\n * is. The version readout is what makes two published versions visibly different, which is the\n * whole point of the Stage 1 exit criterion.\n */\nexport function App({ env }: { env: ClientEnv }) {\n if (env.security === 'blocked') return <SecurityNotice mode=\"blocked\" />\n return env.auth ? (\n <OidcGate env={env} auth={env.auth}>\n {(accessToken, denied) => <Dashboard env={env} accessToken={accessToken} onDenied={denied} />}\n </OidcGate>\n ) : (\n <Dashboard env={env} />\n )\n}\n\nfunction Dashboard({\n env,\n accessToken,\n onDenied,\n}: {\n env: ClientEnv\n accessToken?: string\n onDenied?: () => void\n}) {\n const [board, setBoard] = useState<Board>()\n const [loadedBoardName, setLoadedBoardName] = useState<string>()\n const diagnosticsRef = useRef<BrowserDiagnosticStore | null>(null)\n if (!diagnosticsRef.current) diagnosticsRef.current = new BrowserDiagnosticStore(env)\n const diagnostics = diagnosticsRef.current\n const auth = useMemo<DashboardAuth | undefined>(\n () =>\n accessToken\n ? { accessToken, onAuthenticationFailure: (status) => status === 403 && onDenied?.() }\n : undefined,\n [accessToken, onDenied],\n )\n useClientUpdate({ env, diagnostics, auth })\n const { signals, updateHealth, factSignals, schedules } = usePanelSignals({\n board: loadedBoardName === env.board ? board : undefined,\n env,\n diagnostics,\n auth,\n })\n const layout = useMemo(() => (board ? analyzeBoardLayout(board.panels) : undefined), [board])\n const attentionDrivers = useMemo(\n () => projectAttention({ board, signals, updateHealth, factSignals }),\n [board, factSignals, signals, updateHealth],\n )\n const attentionTreatment = attentionDrivers.length ? board?.attention?.treatment : undefined\n const activeAttentionPanels = new Set(attentionDrivers.map((driver) => driver.panelId))\n\n useEffect(() => {\n if (!layout || layout.issues.length === 0) return\n diagnostics.record({\n kind: 'layout-analyzed',\n issueCount: layout.issues.length,\n affectedPanelIds: layout.issues.map((issue) => issue.panelId),\n })\n }, [diagnostics, layout])\n\n useEffect(() => {\n let cancelled = false\n setBoard(undefined)\n setLoadedBoardName(undefined)\n const path = `${env.proxyPath}/boards/${encodeURIComponent(env.board)}`\n diagnostics.record({ kind: 'board-fetch-start', path })\n dashboardFetch(env, path, undefined, globalThis.fetch, auth)\n .then(async (response) => {\n diagnostics.record({\n kind: 'board-fetch-response',\n path,\n status: response.status,\n cache: cacheMetadata(response.headers),\n })\n if (!response.ok) throw new Error(`Board configuration returned ${response.status}`)\n try {\n return await response.json()\n } catch (error) {\n diagnostics.record({\n kind: 'board-fetch-parse-failure',\n path,\n message: errorMessage(error),\n })\n throw new DiagnosticParseFailure(error)\n }\n })\n .then((value: unknown) => {\n if (!cancelled) {\n setBoard(value as Board)\n setLoadedBoardName(env.board)\n const panels = Array.isArray((value as { panels?: unknown }).panels)\n ? (value as { panels: Array<{ id?: unknown }> }).panels\n : []\n diagnostics.record({\n kind: 'board-fetch-response',\n path,\n boardSummary: {\n panelCount: panels.length,\n panelIds: panels.flatMap((panel) => (typeof panel.id === 'string' ? [panel.id] : [])),\n },\n })\n }\n })\n .catch((error) => {\n if (!(error instanceof DiagnosticParseFailure)) {\n diagnostics.record({ kind: 'board-fetch-failure', path, message: errorMessage(error) })\n }\n if (!cancelled) {\n setBoard({ panels: [] })\n setLoadedBoardName(env.board)\n }\n })\n return () => {\n cancelled = true\n }\n }, [auth, diagnostics, env])\n\n return (\n <div\n className={`${styles.board} ${attentionTreatment ? styles[`attention-${attentionTreatment}`] : ''}`}\n data-attention-treatment={attentionTreatment}\n data-attention-active={attentionDrivers.length || undefined}\n >\n <header className={styles.header}>\n <h1 className={styles.title}>{env.board}</h1>\n {env.security === 'warning' && <SecurityNotice mode=\"warning\" />}\n {attentionDrivers.length > 0 && (\n <aside\n className={styles.attentionRail}\n role=\"alert\"\n aria-label=\"Important panel attention\"\n >\n <span className={styles.attentionGlyph} aria-hidden=\"true\">\n ⚠\n </span>\n <ul>\n {attentionDrivers.map((driver) => (\n <li key={`${driver.panelId}-${driver.factId ?? 'panel'}-${driver.reason}`}>\n <a href={`#panel-${driver.panelId}`}>\n <strong>{driver.label}</strong>: {driver.reason}\n </a>\n </li>\n ))}\n </ul>\n </aside>\n )}\n </header>\n <main className={styles.grid}>\n {!board && <PanelPlaceholder label=\"board\" hint=\"Loading configuration…\" wide />}\n {board?.panels\n .filter((panel) => !isZeroPosition(panel.position))\n .map((panel) => (\n <PanelRenderer\n key={panel.id}\n panel={panel}\n envelope={signals[panel.id]}\n attentionActive={activeAttentionPanels.has(panel.id)}\n updateHealth={updateHealth[panel.id]}\n facts={factSignals[panel.id]}\n />\n ))}\n </main>\n\n <footer className={styles.footer} data-board-footer>\n <span>Signals are read live from their configured authorities.</span>\n <div className={styles.footerTools}>\n {layout && layout.issues.length > 0 && (\n <LayoutWarning board={env.board} layout={layout} env={env} auth={auth} />\n )}\n <Diagnostics\n log={diagnostics}\n updateActivity={() => {\n const evidence = diagnostics.retainedEvidence()\n const projected = projectUpdateActivity({\n schedules,\n ...evidence,\n })\n return {\n capturedAt: projected.capturedAt,\n window: projected.window,\n schedules: projected.schedules,\n }\n }}\n />\n <UpdateActivity board={board} schedules={schedules} log={diagnostics} />\n </div>\n </footer>\n </div>\n )\n}\n\nfunction LayoutWarning({\n board,\n layout,\n env,\n auth,\n}: {\n board: string\n layout: ReturnType<typeof analyzeBoardLayout>\n env: ClientEnv\n auth?: DashboardAuth\n}) {\n const [open, setOpen] = useState(false)\n const dialogId = `layout-warning-${board}`\n\n useEffect(() => {\n if (!open) return\n const closeOnEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') setOpen(false)\n }\n window.addEventListener('keydown', closeOnEscape)\n return () => window.removeEventListener('keydown', closeOnEscape)\n }, [open])\n\n const boardPath = `${env.proxyPath}/boards/${encodeURIComponent(board)}`\n return (\n <div className={styles.layoutWarning} data-layout-warning>\n <button\n className={styles.layoutWarningButton}\n type=\"button\"\n aria-label={`Layout warnings (${layout.issues.length})`}\n aria-expanded={open}\n aria-controls={dialogId}\n onClick={() => setOpen(!open)}\n >\n <span aria-hidden=\"true\">⚠</span>\n <span>{layout.issues.length}</span>\n </button>\n {open && (\n <aside\n className={styles.layoutWarningDialog}\n id={dialogId}\n role=\"dialog\"\n aria-labelledby={`${dialogId}-title`}\n aria-modal=\"false\"\n >\n <div className={styles.layoutWarningHeading}>\n <strong id={`${dialogId}-title`}>Layout warnings</strong>\n <button\n className={styles.layoutWarningClose}\n type=\"button\"\n aria-label=\"Close layout warnings\"\n onClick={() => setOpen(false)}\n >\n ×\n </button>\n </div>\n <p>\n {layout.issues.length} layout issue{layout.issues.length === 1 ? '' : 's'} detected\n against the intended 12×12 space. The live board is unchanged: explicit overlaps remain\n overlapped and overflow continues in implicit rows.\n </p>\n <ul>\n {layout.issues.map((issue) => (\n <li key={`${issue.panelId}-${issue.kind}`}>\n <strong>{issue.panelId}</strong>: {issue.kind} at ({issue.position.x},{' '}\n {issue.position.y}), {issue.position.w}×{issue.position.h}\n {issue.conflictsWith.length ? `; overlaps ${issue.conflictsWith.join(', ')}` : ''}\n </li>\n ))}\n </ul>\n <div className={styles.layoutWarningDownloads}>\n <button\n type=\"button\"\n onClick={() => void downloadLayout(env, `${boardPath}/rendered`, auth)}\n >\n Download legal rendered layout\n </button>\n <button\n type=\"button\"\n onClick={() => void downloadLayout(env, `${boardPath}/authored`, auth)}\n >\n Download authored layout\n </button>\n </div>\n <p className={styles.layoutWarningNote}>\n The legal rendered layout normalizes the currently visible explicit area into 12×12 and\n makes the smallest deterministic adjustments needed to avoid collisions. The authored\n layout preserves the original coordinates exactly.\n </p>\n </aside>\n )}\n </div>\n )\n}\n\nasync function downloadLayout(env: ClientEnv, path: string, auth?: DashboardAuth) {\n const response = await dashboardFetch(env, path, undefined, globalThis.fetch, auth)\n if (!response.ok) throw new Error(`Layout download returned ${response.status}`)\n const link = document.createElement('a')\n link.href = URL.createObjectURL(await response.blob())\n link.download =\n response.headers.get('content-disposition')?.match(/filename=\"([^\"]+)\"/)?.[1] ?? 'layout.yaml'\n link.click()\n URL.revokeObjectURL(link.href)\n}\n\nfunction errorMessage(error: unknown) {\n return error instanceof Error ? error.message : String(error)\n}\n\nclass DiagnosticParseFailure extends Error {\n constructor(error: unknown) {\n super(errorMessage(error))\n }\n}\n",".error {\n margin: 0 auto;\n max-width: 60ch;\n padding: 2rem;\n color: var(--ink-primary);\n}\n.error pre {\n padding: 1rem;\n border-radius: var(--radius);\n border: 1px solid var(--status-critical);\n background: var(--surface-raised);\n color: var(--ink-secondary);\n font-size: 0.75em;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n","import styles from './ConfigError.module.css'\n\nexport function ConfigError({ message }: { message: string }) {\n return (\n <div className={styles.error} role=\"alert\">\n <h1>⚠️ Dashboard misconfigured</h1>\n <p>The page loaded, but the server did not hand it usable configuration.</p>\n <pre>{message}</pre>\n </div>\n )\n}\n","import { readClientEnv } from '@ze-great-dashboard/shared'\nimport { StrictMode } from 'react'\nimport { createRoot } from 'react-dom/client'\nimport { App } from './App.tsx'\nimport { ConfigError } from './ConfigError.tsx'\nimport './styles.css'\n\nconst container = document.getElementById('root')\nif (!container) {\n throw new Error('No #root element in the document — the template is not the one we expect.')\n}\n\nconst root = createRoot(container)\n\ntry {\n root.render(\n <StrictMode>\n <App env={readClientEnv()} />\n </StrictMode>,\n )\n} catch (error) {\n // A radiator that fails silently is worse than one that says what's wrong. If configuration\n // never arrived, say so on screen rather than rendering an empty board.\n root.render(<ConfigError message={error instanceof Error ? error.message : String(error)} />)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index-CMoIpVra.js","names":[],"sources":["../../../shared/dist/index.js","../../src/App.module.css","../../src/attention.ts","../../src/Diagnostics.module.css","../../src/Diagnostics.tsx","../../src/release-version.ts","../../src/dashboard-fetch.ts","../../src/browser-storage.ts","../../src/diagnostics-summary.ts","../../src/diagnostics.ts","../../src/AuthBoundary.module.css","../../src/oidc-manager.ts","../../src/OidcGate.tsx","../../src/PanelFrame.module.css","../../src/PanelPlaceholder.tsx","../../src/error-presentation.ts","../../src/HttpValuePanel.module.css","../../src/panel-layout.ts","../../src/panel-symbols.ts","../../src/PanelFrame.tsx","../../src/TimeAge.tsx","../../src/HttpValuePanel.tsx","../../src/PipelineAnimationDemoPanel.module.css","../../src/FallingShapesField.module.css","../../src/falling-shapes.ts","../../src/FallingShapesField.tsx","../../src/ReleaseTransitField.module.css","../../src/ReleaseTransitField.tsx","../../src/RunningField.module.css","../../src/SnowmanField.module.css","../../src/snowman-timing.ts","../../src/snowman.ts","../../src/snowman-canvas.ts","../../src/SnowmanField.tsx","../../src/StatusWeatherField.module.css","../../src/StatusWeatherField.tsx","../../src/PhasedProgressMarker.module.css","../../src/PhasedProgressMarker.tsx","../../src/TelemetryBloomField.module.css","../../src/TelemetryBloomField.tsx","../../src/RunningField.tsx","../../src/running-timing.ts","../../src/RunningFieldTiming.tsx","../../src/RunningProgress.module.css","../../src/RunningProgress.tsx","../../src/visual-seed.ts","../../src/PipelineAnimationDemoPanel.tsx","../../src/PipelinePanel.module.css","../../src/panel-status.ts","../../src/pipeline-activity.ts","../../src/PipelinePanel.tsx","../../src/PullRequestHealthPanel.module.css","../../src/panel-formatting.ts","../../src/pull-request-health.ts","../../src/PullRequestHealthPanel.tsx","../../src/panel-registry.tsx","../../src/SecurityNotice.module.css","../../src/SecurityNotice.tsx","../../src/UpdateActivity.module.css","../../src/update-activity.ts","../../src/update-activity-presentation.ts","../../src/UpdateActivity.tsx","../../src/useClientUpdate.ts","../../src/panel-diagnostics.ts","../../src/panel-memory.ts","../../src/panel-observation.ts","../../src/pipeline-reconciliation.ts","../../src/polling-panels.ts","../../src/polling-schedule.ts","../../src/pull-request-rollup.ts","../../src/usePanelSignals.ts","../../src/App.tsx","../../src/ConfigError.module.css","../../src/ConfigError.tsx","../../src/main.tsx"],"sourcesContent":["// packages/shared/src/board-config.ts\nimport { z as z2 } from \"zod\";\n\n// packages/shared/src/duration.ts\nimport { z } from \"zod\";\nvar DURATION_PATTERN = /^([1-9][0-9]*)(ms|s|m|h)$/;\nvar UNIT_MILLIS = {\n ms: 1,\n s: 1e3,\n m: 6e4,\n h: 36e5\n};\nfunction parseDuration(value) {\n const match = DURATION_PATTERN.exec(value);\n if (!match) return null;\n const [, rawAmount, rawUnit] = match;\n if (rawAmount === void 0 || rawUnit === void 0) return null;\n const amount = Number(rawAmount);\n if (amount <= 0) return null;\n return amount * UNIT_MILLIS[rawUnit];\n}\nvar durationSchema = z.string().regex(/^[1-9][0-9]*(?:ms|s|m|h)$/, {\n message: 'must be a positive duration like \"30s\", \"5m\", or \"1h\"'\n}).brand();\n\n// packages/shared/src/board-config.ts\nvar positionSchema = z2.union([\n z2.object({\n x: z2.number().int().min(0),\n y: z2.number().int().min(0),\n w: z2.number().int().min(1).max(12),\n h: z2.number().int().min(1)\n }),\n z2.object({ x: z2.literal(0), y: z2.literal(0), w: z2.literal(0), h: z2.literal(0) })\n]);\nvar panelDensities = [\"auto\", \"comfortable\", \"compact\"];\nvar panelDensitySchema = z2.enum(panelDensities);\nvar attentionTreatments = [\"beacon\", \"alarm\", \"steady\"];\nvar attentionTreatmentSchema = z2.enum(attentionTreatments);\nvar httpValueJsonPathSchema = z2.string().regex(/^\\$(?:\\.[A-Za-z_][A-Za-z0-9_]*|\\[\\d+\\])*$/, \"must be a simple JSON path\");\nvar httpValueFactSchema = z2.object({\n /** Stable address below the panel; labels and ordering may change without repointing it. */\n id: z2.string().min(1),\n label: z2.string().min(1),\n /** Public destination; the proxy continues to read only `url`. */\n link: z2.url().optional(),\n url: z2.url(),\n json_path: httpValueJsonPathSchema.optional()\n});\nvar httpValuePanelIdentitySchema = z2.object({\n id: z2.string().min(1),\n type: z2.literal(\"http-value\")\n});\nvar httpValueScalarPanelSchema = httpValuePanelIdentitySchema.extend({\n url: z2.url(),\n json_path: httpValueJsonPathSchema.optional(),\n link: z2.url().optional()\n});\nvar httpValueGroupedPanelSchema = httpValuePanelIdentitySchema.extend({\n facts: z2.array(httpValueFactSchema).min(1).max(4)\n});\nvar visibleRunningAnimations = [\n \"radial\",\n \"runway\",\n \"orbit\",\n \"signal-field\",\n \"telemetry-bloom\",\n \"release-transit\",\n \"status-weather\",\n \"falling-shapes\",\n \"snowman\"\n];\nvar runningAnimationSchema = z2.enum([...visibleRunningAnimations, \"off\"]);\nvar panelSchema = z2.looseObject({\n /** Presentation-only wall label. `id` remains the stable proxy and allowlist address. */\n label: z2.string().min(1).optional(),\n id: z2.string().min(1),\n type: z2.string().min(1),\n source: z2.string().min(1).optional(),\n pipeline: z2.union([z2.string(), z2.number()]).optional(),\n /** Resolved public source branch, supplied by the board endpoint for client memory scoping. */\n branch: z2.string().min(1).optional(),\n /** Content-density bias; position still controls the panel's explicit grid placement. */\n density: panelDensitySchema.optional(),\n /** Opt in to the board's presentation-only attention cue when this reading is unhealthy. */\n attention: z2.literal(true).optional(),\n /** Advisory in v1 — a panel without a position renders in config order rather than not at all. */\n position: positionSchema.optional(),\n refresh: durationSchema.optional(),\n /** Active pipeline runs are checked more often than normal panels. */\n running_refresh: durationSchema.optional(),\n /** Polling cadence around the estimated completion boundary. */\n running_completion_refresh: durationSchema.optional(),\n /** Maximum length of the tighter completion polling burst. */\n running_completion_window: durationSchema.optional(),\n /** Optional active-run treatment. Omitted selects a visible treatment at random. */\n running_animation: runningAnimationSchema.optional(),\n /** Local animation-demo cycle duration; ignored by other panel types. */\n demo_run_duration: durationSchema.optional(),\n /** Local animation-demo focused-review duration; ignored by other panel types. */\n demo_review_duration: durationSchema.optional(),\n /** A deliberate override only. Adapters derive links; hand-written ones drift. */\n link: z2.url().optional(),\n /** Source-agnostic endpoint used by the http-value signal. */\n url: z2.url().optional(),\n /** Small, deliberate JSON path subset: $.version, $.deployment.version, or $.response.docs[0].latestVersion. */\n json_path: httpValueJsonPathSchema.optional(),\n /** Up to four independently fetched source-agnostic readings in one visual panel. */\n facts: httpValueGroupedPanelSchema.shape.facts.optional()\n}).superRefine((panel, ctx) => {\n if (\"display\" in panel) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"display\"],\n message: \"display was removed; use density\",\n params: { constraint: \"display was removed; use density\" }\n });\n }\n if (panel.type !== \"http-value\") return;\n if (panel.facts) {\n if (panel.url !== void 0)\n ctx.addIssue({\n code: \"custom\",\n path: [\"url\"],\n message: \"use facts URLs for grouped panels\",\n params: { constraint: \"use facts URLs for grouped panels\" }\n });\n if (panel.json_path !== void 0)\n ctx.addIssue({\n code: \"custom\",\n path: [\"json_path\"],\n message: \"use facts json_path values for grouped panels\",\n params: { constraint: \"use facts json_path values for grouped panels\" }\n });\n const seen = /* @__PURE__ */ new Map();\n panel.facts.forEach((fact, index) => {\n const first = seen.get(fact.id);\n if (first === void 0) seen.set(fact.id, index);\n else\n ctx.addIssue({\n code: \"custom\",\n path: [\"facts\", index, \"id\"],\n message: `duplicate fact id \"${fact.id}\" (already used by fact at index ${first})`,\n params: { constraint: \"Use a unique fact id within this panel.\" }\n });\n });\n }\n});\nvar githubAppSchema = z2.object({\n app_id_env: z2.string().min(1),\n private_key_env: z2.string().min(1),\n installation_id_env: z2.string().min(1)\n});\nvar sourceAuthenticationSchema = {\n /** Credentials are never in the config — only the name of the env var holding one. */\n token_env: z2.string().min(1).optional(),\n github_app: githubAppSchema.optional()\n};\nfunction exactlyOneGithubAuthenticationMode(source, ctx) {\n if (source.token_env && source.github_app)\n ctx.addIssue({\n code: \"custom\",\n message: \"configure token_env or github_app, not both\",\n params: { constraint: \"configure token_env or github_app, not both\" }\n });\n}\nvar githubActionsSourceSchema = z2.looseObject({\n type: z2.literal(\"github-actions\"),\n repo: z2.string().regex(/^[^/\\s]+\\/[^/\\s]+$/, \"must be an owner/repository pair\"),\n /** The branch whose workflow health the dashboard represents. */\n branch: z2.string().min(1).optional(),\n ...sourceAuthenticationSchema\n}).superRefine(exactlyOneGithubAuthenticationMode);\nvar azureDevOpsSourceSchema = z2.looseObject({\n type: z2.literal(\"azure-devops\"),\n /** Azure DevOps organization name, used as one URL path segment. */\n organization: z2.string().regex(/^[^/\\s]+$/, \"must be an organization name\"),\n project: z2.string().min(1),\n /** The branch whose build health the dashboard represents. */\n branch: z2.string().min(1).optional(),\n /** A PAT environment variable. The adapter sends it with Basic authentication. */\n token_env: z2.string().min(1).optional(),\n /** An environment variable naming a local, short-lived delegated-token file. */\n entra_token_file_env: z2.string().min(1).optional()\n}).superRefine((source, ctx) => {\n if (source.token_env && source.entra_token_file_env) {\n ctx.addIssue({\n code: \"custom\",\n message: \"configure token_env or entra_token_file_env, not both\",\n params: { constraint: \"configure token_env or entra_token_file_env, not both\" }\n });\n }\n if (!source.token_env && !source.entra_token_file_env) {\n ctx.addIssue({\n code: \"custom\",\n message: \"configure token_env or entra_token_file_env\",\n params: { constraint: \"configure token_env or entra_token_file_env\" }\n });\n }\n});\nvar gitlabInstanceUrlSchema = z2.url().superRefine((value, ctx) => {\n const url = new URL(value);\n if (url.protocol !== \"https:\")\n ctx.addIssue({\n code: \"custom\",\n message: \"must be an HTTPS GitLab instance URL\",\n params: { constraint: \"must be an HTTPS GitLab instance URL\" }\n });\n if (url.username || url.password)\n ctx.addIssue({\n code: \"custom\",\n message: \"must not include credentials\",\n params: { constraint: \"must not include credentials\" }\n });\n if (url.search)\n ctx.addIssue({\n code: \"custom\",\n message: \"must not include a query string\",\n params: { constraint: \"must not include a query string\" }\n });\n if (url.hash)\n ctx.addIssue({\n code: \"custom\",\n message: \"must not include a fragment\",\n params: { constraint: \"must not include a fragment\" }\n });\n});\nvar gitlabCiSourceSchema = z2.looseObject({\n type: z2.literal(\"gitlab-ci\"),\n /** GitLab project path, including any nested groups. */\n project: z2.string().regex(/^[^/\\s]+(?:\\/[^/\\s]+)+$/, \"must be a namespace/project path\"),\n /** A GitLab personal, project, or group access-token environment variable. */\n token_env: z2.string().min(1),\n /** The branch or tag whose newest pipeline the dashboard represents. */\n branch: z2.string().min(1).optional(),\n /** HTTPS GitLab.com or a self-managed instance, optionally below a path prefix. */\n url: gitlabInstanceUrlSchema.optional().default(\"https://gitlab.com\")\n});\nvar sourceSchema = z2.looseObject({ type: z2.string().min(1), ...sourceAuthenticationSchema }).superRefine(exactlyOneGithubAuthenticationMode);\nfunction credentialEnvironmentNames(source) {\n const githubApp = githubAppSchema.safeParse(source.github_app);\n return [\n ...source.token_env ? [source.token_env] : [],\n ...githubApp.success ? [\n githubApp.data.app_id_env,\n githubApp.data.private_key_env,\n githubApp.data.installation_id_env\n ] : []\n ];\n}\nvar boardSchema = z2.object({\n refresh: durationSchema.optional(),\n running_refresh: durationSchema.optional(),\n running_completion_refresh: durationSchema.optional(),\n running_completion_window: durationSchema.optional(),\n /** One board-wide treatment keeps simultaneous important failures unambiguous. */\n attention: z2.object({ treatment: attentionTreatmentSchema }).optional(),\n panels: z2.array(panelSchema).min(1).superRefine((panels, ctx) => {\n const seen = /* @__PURE__ */ new Map();\n panels.forEach((panel, index) => {\n const firstIndex = seen.get(panel.id);\n if (firstIndex === void 0) {\n seen.set(panel.id, index);\n return;\n }\n ctx.addIssue({\n code: \"custom\",\n path: [index, \"id\"],\n message: `duplicate panel id \"${panel.id}\" (already used by panel at index ${firstIndex})`,\n params: { constraint: \"Use a unique panel id within this board.\" }\n });\n });\n })\n}).superRefine((board, ctx) => {\n if (board.panels.some((panel) => panel.attention) && !board.attention)\n ctx.addIssue({\n code: \"custom\",\n path: [\"attention\"],\n message: \"configure attention.treatment when one or more panels opt into attention\",\n params: { constraint: \"Important panels require one board attention treatment.\" }\n });\n});\nvar authSchema = z2.strictObject({\n issuer: z2.url(),\n /** Browser SPA client id. It is public, unlike every source credential. */\n client_id: z2.string().min(1),\n /** The separately registered API resource accepted by the dashboard proxy. */\n audience: z2.string().min(1),\n /** A deliberately portable, explicit identity boundary for the first direct-OIDC release. */\n allow: z2.strictObject({ subjects: z2.array(z2.string().min(1)).min(1) })\n});\nvar securityPolicies = [\"warn\", \"required\", \"unsecured\"];\nvar securityPolicySchema = z2.enum(securityPolicies);\nvar boardConfigSchema = z2.object({\n sources: z2.record(z2.string().min(1), sourceSchema).default({}),\n boards: z2.record(z2.string().min(1), boardSchema),\n auth: authSchema.optional(),\n security: securityPolicySchema.optional()\n}).superRefine((config, ctx) => {\n if (config.security === \"unsecured\" && config.auth) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"security\"],\n message: \"security: unsecured cannot be combined with auth\",\n params: { constraint: \"Remove auth or select warn or required.\" }\n });\n }\n for (const [sourceName, source] of Object.entries(config.sources)) {\n const sourceSchema2 = source.type === \"azure-devops\" ? azureDevOpsSourceSchema : source.type === \"gitlab-ci\" ? gitlabCiSourceSchema : void 0;\n if (!sourceSchema2) continue;\n const parsedSource = sourceSchema2.safeParse(source);\n if (!parsedSource.success) {\n for (const issue of parsedSource.error.issues) {\n ctx.addIssue({\n ...issue,\n path: [\"sources\", sourceName, ...issue.path]\n });\n }\n }\n }\n for (const [boardName, board] of Object.entries(config.boards)) {\n board.panels.forEach((panel, panelIndex) => {\n const source = panel.source ? config.sources[panel.source] : void 0;\n if (panel.type !== \"pipeline-status\" || source?.type !== \"azure-devops\") return;\n if (typeof panel.pipeline !== \"number\" || !Number.isInteger(panel.pipeline) || panel.pipeline <= 0) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"boards\", boardName, \"panels\", panelIndex, \"pipeline\"],\n message: \"Azure DevOps pipeline-status panels require a positive numeric pipeline definition id\",\n params: {\n constraint: \"Provide a positive numeric Azure DevOps pipeline definition id.\"\n }\n });\n }\n });\n }\n});\nvar boardConfigRuntimeRules = [\n {\n category: \"yaml-modeline-and-schema-version\",\n description: \"YAML parsing and a first-line modeline that names the selected release schema.\"\n },\n {\n category: \"unique-panel-and-fact-ids\",\n description: \"Panel IDs are unique within a board and fact IDs are unique within a panel.\"\n },\n {\n category: \"cross-field-configuration\",\n description: \"Mutually exclusive and paired fields, including grouped HTTP value fields and credential modes.\"\n },\n {\n category: \"panel-source-relationships\",\n description: \"Panel/source compatibility and source-specific requirements.\"\n },\n {\n category: \"panel-admission-and-bounded-adapter-operations\",\n description: \"Supported panel admission and the proxy operations each adapter is permitted to perform.\"\n },\n {\n category: \"environment-and-external-availability\",\n description: \"Environment-selected boards, credential resolution, and availability of external services.\"\n }\n];\nfunction boardConfigJsonSchema() {\n return {\n ...z2.toJSONSchema(boardConfigSchema, { target: \"draft-2020-12\" }),\n $id: \"board-config.schema.json\",\n title: \"Ze Great Dashboard board configuration\",\n \"x-dashboard-runtime-rules\": boardConfigRuntimeRules.map((rule) => ({ ...rule }))\n };\n}\nfunction serializeBoardConfigJsonSchema() {\n return `${JSON.stringify(boardConfigJsonSchema(), null, 2)}\n`;\n}\nfunction resolveRefreshMillis(args) {\n const requested = args.panelOverrideMillis ?? args.boardDefaultMillis;\n return Math.max(requested, args.adapterFloorMillis);\n}\n\n// packages/shared/src/board-config-modeline.ts\nvar MODEL_LINE = /^# yaml-language-server:\\s*\\$schema=(\\S+)\\s*$/;\nvar SCHEMA_FILE = \"board-config.schema.json\";\nfunction schemaUrlForAssetPath(assetPath) {\n return `${assetPath.replace(/\\/+$/, \"\")}/${SCHEMA_FILE}`;\n}\nfunction readBoardSchemaModeline(source, expectedSchemaUrl) {\n const line = source.split(/\\r?\\n/)[0];\n if (!line?.includes(\"yaml-language-server\"))\n throw new Error(\n `Board configuration must include a ${SCHEMA_FILE} modeline. Add this as the first line:\n# yaml-language-server: $schema=${expectedSchemaUrl ?? `https://<asset-host>/dashboard/<release-version>/${SCHEMA_FILE}`}`\n );\n const match = MODEL_LINE.exec(line);\n if (!match?.[1]) {\n throw new Error(\n `Malformed board schema modeline; expected \"# yaml-language-server: $schema=<URL>/${SCHEMA_FILE}\"`\n );\n }\n let url;\n try {\n url = new URL(match[1]);\n } catch {\n throw new Error(`Malformed board schema modeline; schema URL is not a valid URL: ${match[1]}`);\n }\n if (![\"http:\", \"https:\"].includes(url.protocol) || !url.pathname.endsWith(`/${SCHEMA_FILE}`)) {\n throw new Error(`Malformed board schema modeline; URL must end in /${SCHEMA_FILE}: ${match[1]}`);\n }\n return match[1];\n}\nfunction boardSchemaModeline(url) {\n return `# yaml-language-server: $schema=${url}`;\n}\nvar boardSchemaFileName = SCHEMA_FILE;\n\n// packages/shared/src/client-env.ts\nimport { z as z3 } from \"zod\";\nvar clientSecurityStates = [\"warning\", \"blocked\"];\nvar clientSecurityStateSchema = z3.enum(clientSecurityStates);\nvar clientEnvSchema = z3.object({\n /** Where the immutable client assets live. The one variable that repoints the whole client. */\n assetPath: z3.string().min(1),\n /** Opaque SHA-256 fingerprint of the canonical asset path, for diagnostic correlation only. */\n assetPathId: z3.string().regex(/^sha256:[a-f0-9]{64}$/),\n /** Same-origin path the proxy is mounted at, so there is no CORS and no cookie problem. */\n proxyPath: z3.string().min(1),\n /** Which board this is, resolved server-side so the client parses no URLs. */\n board: z3.string().min(1),\n /** Omitted entirely when unauthenticated — presence is what turns auth on. */\n auth: z3.object({\n issuer: z3.string().min(1),\n clientId: z3.string().min(1),\n audience: z3.string().min(1)\n }).optional(),\n /** Public deployment posture; it contains no board, source, or credential details. */\n security: clientSecurityStateSchema.optional()\n});\nvar clientIdentityResponseSchema = clientEnvSchema.pick({ assetPath: true, assetPathId: true }).extend({ serverVersion: z3.string().min(1) });\nfunction readClientEnv(source = globalThis.window?.env) {\n const result = clientEnvSchema.safeParse(source);\n if (!result.success) {\n throw new Error(\n `window.env is missing or invalid \\u2014 the server did not inject usable configuration.\n${z3.prettifyError(result.error)}`\n );\n }\n return result.data;\n}\n\n// packages/shared/src/envelope.ts\nimport { z as z4 } from \"zod\";\nvar errorKindSchema = z4.enum([\n \"unreachable\",\n \"unauthorized\",\n \"not-found\",\n \"no-runs\",\n \"upstream-error\"\n]);\nvar envelopeErrorSchema = z4.object({\n kind: errorKindSchema,\n message: z4.string()\n});\nvar envelopeSchema = z4.discriminatedUnion(\"state\", [\n z4.object({\n panelId: z4.string().min(1),\n state: z4.literal(\"ok\"),\n /** From the upstream response `Date`. A cached value must never be shown without its age. */\n observedAt: z4.iso.datetime(),\n /** Adapter-derived. The authority for this panel; the dashboard itself asserts nothing. */\n link: z4.url().nullable(),\n signal: z4.unknown()\n }),\n z4.object({\n panelId: z4.string().min(1),\n state: z4.literal(\"error\"),\n /**\n * Populated even on error: knowing *when* a failure was observed is the difference between\n * \"broken just now\" and \"broken all morning\", and a panel that can't reach its source is\n * exactly when a viewer most wants to click through.\n */\n observedAt: z4.iso.datetime(),\n link: z4.url().nullable(),\n error: envelopeErrorSchema\n })\n]);\nvar pipelineActivitySchema = z4.object({\n kind: z4.enum([\"job\", \"stage\", \"step\"]),\n name: z4.string().min(1),\n parent: z4.string().min(1).optional()\n});\nvar pipelineStatusSchema = z4.object({\n type: z4.literal(\"pipeline-status\"),\n status: z4.enum([\"passed\", \"failed\", \"warning\", \"running\", \"cancelled\", \"unknown\"]),\n /** The source's unmodified status/result vocabulary, for an honest display. */\n rawStatus: z4.string(),\n name: z4.string().min(1),\n /** The branch represented by this status, when the upstream supplies or filters by one. */\n branch: z4.string().min(1).optional(),\n /** Elapsed execution time, supplied only after the upstream run has completed. */\n durationMs: z4.number().int().nonnegative().optional(),\n /** When an active run began, so the client can advance its elapsed display between polls. */\n runStartedAt: z4.iso.datetime().optional(),\n /** Stable source-run identity, when the adapter provides one. */\n sourceRunId: z4.string().min(1).optional(),\n /** Best-effort live work detail; adapters may describe a job, stage, or step. */\n activity: pipelineActivitySchema.optional(),\n /** Advisory duration from recent completed runs remembered by this browser. */\n estimatedDurationMs: z4.number().int().positive().optional(),\n /** When this workflow run was last updated by its source, distinct from our observation time. */\n sourceUpdatedAt: z4.iso.datetime().optional()\n});\nvar pipelineStatusPriorities = {\n passed: 0,\n cancelled: 1,\n unknown: 2,\n running: 3,\n warning: 4,\n failed: 5\n};\nfunction pipelineStatusPriority(status) {\n return pipelineStatusPriorities[status];\n}\nvar pullRequestHealthItemSchema = z4.object({\n label: z4.string().min(1),\n status: pipelineStatusSchema.shape.status,\n detail: z4.string().min(1),\n link: z4.url().nullable()\n});\nvar pullRequestHealthSchema = z4.object({\n type: z4.literal(\"pull-request-health\"),\n status: pipelineStatusSchema.shape.status,\n summary: z4.string().min(1),\n workflows: z4.array(pullRequestHealthItemSchema),\n pullRequests: z4.array(pullRequestHealthItemSchema),\n /** Missing component reads remain visible even when the evidence we did get is reassuring. */\n incompleteObservations: z4.array(z4.object({ label: z4.string().min(1), message: z4.string().min(1) })).optional(),\n /** The latest component reading, disclosed beside the oldest aggregate evidence. */\n newestObservedAt: z4.iso.datetime().optional()\n});\nvar pullRequestCandidateSchema = z4.object({\n number: z4.number().int().positive(),\n branch: z4.string().min(1),\n link: z4.url()\n});\nvar pullRequestCandidatesSchema = z4.object({\n type: z4.literal(\"pull-request-candidates\"),\n pullRequests: z4.array(pullRequestCandidateSchema),\n /** GitHub's first page is a deliberate bounded observation, not proof that no later PR exists. */\n truncated: z4.boolean().optional()\n});\nvar pullRequestWorkflowObservationSchema = z4.object({\n type: z4.literal(\"pull-request-workflow\"),\n workflow: z4.string().min(1),\n item: pullRequestHealthItemSchema\n});\nvar pullRequestBuildObservationSchema = z4.object({\n type: z4.literal(\"pull-request-build\"),\n branch: z4.string().min(1),\n item: pullRequestHealthItemSchema\n});\nvar httpValueSchema = z4.object({\n type: z4.literal(\"http-value\"),\n value: z4.union([z4.string(), z4.number(), z4.boolean()])\n});\n\n// packages/shared/src/layout.ts\nvar columnCount = 12;\nvar rowCount = 12;\nfunction analyzeBoardLayout(panels) {\n const issues = panels.flatMap((panel) => {\n if (!panel.position || isZeroPosition(panel.position) || isPositionInCanvas(panel.position))\n return [];\n return [\n {\n panelId: panel.id,\n kind: \"out-of-bounds\",\n position: panel.position,\n conflictsWith: []\n }\n ];\n });\n const overlapIssues = /* @__PURE__ */ new Map();\n for (let leftIndex = 0; leftIndex < panels.length; leftIndex++) {\n const left = panels[leftIndex];\n if (!left?.position || isZeroPosition(left.position)) continue;\n for (let rightIndex = leftIndex + 1; rightIndex < panels.length; rightIndex++) {\n const right = panels[rightIndex];\n if (!right?.position || isZeroPosition(right.position)) continue;\n if (!overlaps(left.position, right.position)) continue;\n const key = `${right.id}\\0overlap`;\n const issue = overlapIssues.get(key);\n if (issue) issue.conflictsWith.push(left.id);\n else {\n const nextIssue = {\n panelId: right.id,\n kind: \"overlap\",\n position: right.position,\n conflictsWith: [left.id]\n };\n overlapIssues.set(key, nextIssue);\n issues.push(nextIssue);\n }\n }\n }\n return { issues };\n}\nfunction normalizeBoardLayout(panels) {\n const positioned = panels.flatMap((panel) => {\n if (!panel.position || isZeroPosition(panel.position)) return [];\n return [{ ...panel.position, panelId: panel.id }];\n });\n if (positioned.length === 0) return panels.map((panel) => ({ ...panel }));\n const minX = Math.min(...positioned.map((rectangle) => rectangle.x));\n const minY = Math.min(...positioned.map((rectangle) => rectangle.y));\n const maxX = Math.max(...positioned.map((rectangle) => rectangle.x + rectangle.w));\n const maxY = Math.max(...positioned.map((rectangle) => rectangle.y + rectangle.h));\n const scaleX = maxX - minX > columnCount ? columnCount / (maxX - minX) : 1;\n const scaleY = maxY - minY > rowCount ? rowCount / (maxY - minY) : 1;\n const accepted = [];\n return panels.map((panel) => {\n const position = panel.position;\n if (!position || isZeroPosition(position)) return { ...panel };\n const desired = scaleRectangle(position, minX, minY, scaleX, scaleY);\n const legal = nearestLegalRectangle(desired, accepted);\n if (!legal) return { ...panel, position: zeroPosition };\n accepted.push({ ...legal, panelId: panel.id });\n return { ...panel, position: legal };\n });\n}\nfunction isZeroPosition(position) {\n return position?.x === 0 && position.y === 0 && position.w === 0 && position.h === 0;\n}\nvar zeroPosition = { x: 0, y: 0, w: 0, h: 0 };\nfunction isPositionInCanvas(position) {\n return !isZeroPosition(position) && position.x + position.w <= columnCount && position.y + position.h <= rowCount;\n}\nfunction overlaps(left, right) {\n return left.x < right.x + right.w && left.x + left.w > right.x && left.y < right.y + right.h && left.y + left.h > right.y;\n}\nfunction scaleRectangle(position, minX, minY, scaleX, scaleY) {\n const x = scaleCoordinate(position.x, minX, scaleX);\n const y = scaleCoordinate(position.y, minY, scaleY);\n const right = scaleCoordinate(position.x + position.w, minX, scaleX);\n const bottom = scaleCoordinate(position.y + position.h, minY, scaleY);\n return {\n x,\n y,\n w: Math.max(1, right - x),\n h: Math.max(1, bottom - y)\n };\n}\nfunction scaleCoordinate(value, origin, scale) {\n return Math.round((value - origin) * scale);\n}\nfunction nearestLegalRectangle(desired, accepted) {\n const candidates = [];\n for (let width = desired.w; width >= 1; width--) {\n for (let height = desired.h; height >= 1; height--) {\n const shrink = desired.w - width + (desired.h - height);\n for (let y = 0; y <= rowCount - height; y++) {\n for (let x = 0; x <= columnCount - width; x++) {\n const candidate2 = { x, y, w: width, h: height };\n if (accepted.some((rectangle) => overlaps(candidate2, rectangle))) continue;\n candidates.push({\n ...candidate2,\n shrink,\n distance: Math.abs(x - desired.x) + Math.abs(y - desired.y)\n });\n }\n }\n }\n }\n candidates.sort(\n (left, right) => left.shrink - right.shrink || left.distance - right.distance || left.y - right.y || left.x - right.x\n );\n const [candidate] = candidates;\n if (!candidate) return void 0;\n return { x: candidate.x, y: candidate.y, w: candidate.w, h: candidate.h };\n}\n\n// packages/shared/src/polling-policy.ts\nvar pollingDefaults = {\n refreshMillis: 6e4,\n runningRefreshMillis: 15e3,\n runningCompletionRefreshMillis: 5e3,\n runningCompletionWindowMillis: 12e4\n};\nfunction resolvePollingSettings(board, panel) {\n const duration = (value, fallback) => parseDuration(value ?? \"\") ?? fallback;\n const panelValue = (key, boardValue, fallback) => duration(panel[key], duration(board[boardValue], fallback));\n return {\n refreshMillis: panelValue(\"refresh\", \"refresh\", pollingDefaults.refreshMillis),\n runningRefreshMillis: panelValue(\n \"running_refresh\",\n \"running_refresh\",\n pollingDefaults.runningRefreshMillis\n ),\n runningCompletionRefreshMillis: panelValue(\n \"running_completion_refresh\",\n \"running_completion_refresh\",\n pollingDefaults.runningCompletionRefreshMillis\n ),\n runningCompletionWindowMillis: panelValue(\n \"running_completion_window\",\n \"running_completion_window\",\n pollingDefaults.runningCompletionWindowMillis\n )\n };\n}\nexport {\n analyzeBoardLayout,\n attentionTreatmentSchema,\n attentionTreatments,\n authSchema,\n azureDevOpsSourceSchema,\n boardConfigJsonSchema,\n boardConfigRuntimeRules,\n boardConfigSchema,\n boardSchema,\n boardSchemaFileName,\n boardSchemaModeline,\n clientEnvSchema,\n clientIdentityResponseSchema,\n clientSecurityStateSchema,\n clientSecurityStates,\n credentialEnvironmentNames,\n durationSchema,\n envelopeSchema,\n errorKindSchema,\n githubActionsSourceSchema,\n githubAppSchema,\n gitlabCiSourceSchema,\n httpValueFactSchema,\n httpValueGroupedPanelSchema,\n httpValueScalarPanelSchema,\n httpValueSchema,\n isZeroPosition,\n normalizeBoardLayout,\n panelDensities,\n panelDensitySchema,\n panelSchema,\n parseDuration,\n pipelineActivitySchema,\n pipelineStatusPriority,\n pipelineStatusSchema,\n pollingDefaults,\n positionSchema,\n pullRequestBuildObservationSchema,\n pullRequestCandidateSchema,\n pullRequestCandidatesSchema,\n pullRequestHealthSchema,\n pullRequestWorkflowObservationSchema,\n readBoardSchemaModeline,\n readClientEnv,\n resolvePollingSettings,\n resolveRefreshMillis,\n runningAnimationSchema,\n schemaUrlForAssetPath,\n securityPolicies,\n securityPolicySchema,\n serializeBoardConfigJsonSchema,\n sourceSchema,\n visibleRunningAnimations\n};\n",".board {\n display: flex;\n flex-direction: column;\n gap: var(--gap);\n height: 100dvh;\n min-height: 0;\n padding: var(--gap);\n overflow-x: hidden;\n overflow-y: auto;\n}\n.header {\n display: flex;\n align-items: baseline;\n border-bottom: 1px solid var(--edge);\n padding-bottom: var(--gap);\n flex: 0 0 auto;\n}\n.attentionRail {\n display: flex;\n align-items: flex-start;\n gap: 0.45em;\n margin-inline-start: auto;\n padding: 0.35em 0.55em;\n border: 0.14rem solid var(--status-critical);\n border-radius: var(--radius);\n color: var(--ink-primary);\n background: var(--surface-raised);\n font-size: 0.7em;\n line-height: 1.3;\n}\n.attentionRail ul {\n margin: 0;\n padding-left: 1.1em;\n}\n.attentionRail a {\n color: inherit;\n text-decoration-color: var(--status-critical);\n}\n.attentionRail a:focus-visible {\n outline: 0.14rem solid var(--ink-primary);\n outline-offset: 0.12rem;\n}\n.attentionGlyph {\n color: var(--status-critical);\n}\n.attention-beacon {\n outline: 0.16rem solid var(--status-critical);\n outline-offset: -0.16rem;\n animation: attention-beacon 1.8s ease-in-out infinite;\n}\n.attention-alarm {\n outline: 0.22rem solid var(--status-critical);\n outline-offset: -0.22rem;\n animation: attention-alarm 0.75s steps(2, jump-none) infinite;\n}\n.attention-alarm .attentionRail {\n background: color-mix(in srgb, var(--status-critical) 18%, var(--surface-raised));\n}\n.attention-steady {\n outline: 0.22rem solid var(--status-critical);\n outline-offset: -0.22rem;\n}\n@keyframes attention-beacon {\n 50% {\n outline-color: var(--status-serious);\n }\n}\n@keyframes attention-alarm {\n 50% {\n outline-color: var(--ink-primary);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .attention-beacon,\n .attention-alarm {\n animation: none;\n outline: 0.22rem solid var(--status-critical);\n outline-offset: -0.22rem;\n }\n}\n.title {\n margin: 0;\n font-size: 1.75em;\n font-weight: 650;\n letter-spacing: -0.01em;\n}\n.grid {\n display: grid;\n grid-template-columns: repeat(12, minmax(0, 1fr));\n grid-template-rows: repeat(12, minmax(0, 1fr));\n grid-auto-rows: minmax(0, 1fr);\n gap: var(--gap);\n flex: 1;\n min-height: 0;\n align-content: stretch;\n}\n.footerTools {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n.layoutWarning {\n position: relative;\n}\n.layoutWarningButton {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.2em;\n min-width: 2em;\n min-height: 2em;\n border: 1px solid var(--status-warning);\n border-radius: 50%;\n color: var(--status-warning);\n background: var(--surface-raised);\n font: inherit;\n cursor: pointer;\n}\n.layoutWarningButton:hover,\n.layoutWarningButton:focus-visible {\n background: var(--surface);\n}\n.layoutWarningDialog {\n position: absolute;\n z-index: 10;\n right: 0;\n bottom: calc(100% + 0.75rem);\n width: min(32rem, calc(100vw - 2 * var(--gap)));\n padding: 0.8rem;\n border: 1px solid var(--status-warning);\n border-radius: var(--radius);\n color: var(--ink-secondary);\n background: var(--surface-raised);\n box-shadow: 0 0.5rem 1.5rem rgb(0 0 0 / 35%);\n}\n.layoutWarningHeading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 1rem;\n}\n.layoutWarningHeading strong {\n color: var(--status-warning);\n}\n.layoutWarningDialog p {\n margin: 0.6rem 0;\n}\n.layoutWarningDialog ul {\n margin: 0.35rem 0 0.75rem;\n padding-left: 1.25rem;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 0.85em;\n}\n.layoutWarningClose {\n border: 0;\n color: var(--ink-muted);\n background: transparent;\n font-size: 1.25em;\n line-height: 1;\n cursor: pointer;\n}\n.layoutWarningDownloads {\n display: grid;\n gap: 0.35rem;\n}\n.layoutWarningDownloads button {\n border: 1px solid var(--edge);\n border-radius: 0.25rem;\n background: var(--surface-raised);\n color: var(--ink-secondary);\n font: inherit;\n padding: 0.3em 0.55em;\n text-align: center;\n text-decoration: none;\n}\n.layoutWarningDownloads button:hover,\n.layoutWarningDownloads button:focus-visible {\n border-color: var(--ink-secondary);\n color: var(--ink-primary);\n}\n.layoutWarningNote {\n color: var(--ink-muted);\n font-size: 0.85em;\n}\n.footer {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: center;\n justify-content: space-between;\n gap: 0.5rem;\n color: var(--ink-muted);\n font-size: 0.75em;\n flex: 0 0 auto;\n}\n@media (max-width: 64rem) {\n .board {\n height: auto;\n min-height: 100dvh;\n overflow: visible;\n }\n .grid {\n grid-template-columns: 1fr;\n grid-template-rows: none;\n grid-auto-rows: auto;\n flex: 0 0 auto;\n min-height: auto;\n }\n .header {\n align-items: flex-start;\n flex-direction: column;\n }\n .attentionRail {\n margin-inline-start: 0;\n }\n .layoutWarningDialog {\n position: fixed;\n right: var(--gap);\n bottom: calc(var(--gap) + 3rem);\n }\n}\n","import {\n type Board,\n type Envelope,\n httpValueSchema,\n pipelineStatusSchema,\n pullRequestHealthSchema,\n} from '@ze-great-dashboard/shared'\nimport type { HttpValueFactObservation, PanelUpdateHealth } from './panel-props.ts'\n\nexport type AttentionDriver = {\n panelId: string\n label: string\n reason: string\n factId?: string\n}\n\n/**\n * Projects only public, already-rendered evidence into the board's opt-in attention rail.\n * It intentionally never infers a source condition from loading, warning, or unknown states.\n */\nexport function projectAttention(args: {\n board: Board | undefined\n signals: Record<string, Envelope | undefined>\n updateHealth: Record<string, PanelUpdateHealth | undefined>\n factSignals: Record<string, Record<string, HttpValueFactObservation | undefined> | undefined>\n}): AttentionDriver[] {\n if (!args.board?.attention) return []\n return args.board.panels.flatMap((panel) => {\n if (!panel.attention) return []\n const label = panel.label ?? panel.id\n if (panel.type === 'http-value' && panel.facts)\n return panel.facts.flatMap((fact) => {\n const observation = args.factSignals[panel.id]?.[fact.id]\n const reason = unreadableFactReason(observation)\n return reason\n ? [{ panelId: panel.id, label, reason: `${fact.label}: ${reason}`, factId: fact.id }]\n : []\n })\n const reason = unreadablePanelReason(\n panel.type,\n args.signals[panel.id],\n args.updateHealth[panel.id],\n )\n return reason ? [{ panelId: panel.id, label, reason }] : []\n })\n}\n\nfunction unreadableFactReason(observation: HttpValueFactObservation | undefined) {\n if (observation?.failure) return `Updates unavailable — ${observation.failure}`\n if (observation?.updateHealth) return `Updates unavailable — ${observation.updateHealth.message}`\n if (!observation?.envelope) return undefined\n if (observation.envelope.state === 'error') return observation.envelope.error.message\n return httpValueSchema.safeParse(observation.envelope.signal).success\n ? undefined\n : 'Invalid value'\n}\n\nfunction unreadablePanelReason(\n type: string,\n envelope: Envelope | undefined,\n updateHealth: PanelUpdateHealth | undefined,\n) {\n if (updateHealth) return `Updates unavailable — ${updateHealth.message}`\n if (!envelope) return undefined\n if (envelope.state === 'error') return envelope.error.message\n if (type === 'pipeline-status') {\n const signal = pipelineStatusSchema.safeParse(envelope.signal)\n if (!signal.success) return 'Invalid signal'\n return signal.data.status === 'failed' ? 'Pipeline failed' : undefined\n }\n if (type === 'pull-request-health') {\n const signal = pullRequestHealthSchema.safeParse(envelope.signal)\n if (!signal.success) return 'Invalid signal'\n if (signal.data.status === 'failed') return signal.data.summary\n const missing = signal.data.incompleteObservations?.[0]\n return missing ? `${missing.label}: ${missing.message}` : undefined\n }\n if (type === 'http-value')\n return httpValueSchema.safeParse(envelope.signal).success ? undefined : 'Invalid value'\n return undefined\n}\n",".diagnostics {\n position: relative;\n}\n\n.button {\n border: 1px solid var(--edge);\n border-radius: 0.25rem;\n background: var(--surface-raised);\n color: var(--ink-secondary);\n font: inherit;\n padding: 0.3em 0.55em;\n}\n\n.area {\n position: absolute;\n z-index: 1;\n right: 0;\n bottom: calc(100% + 0.5rem);\n width: min(24rem, 90vw);\n padding: 0.75rem;\n border: 1px solid var(--edge);\n border-radius: var(--radius);\n background: var(--surface-raised);\n box-shadow: 0 0.5rem 1.5rem #0008;\n}\n\n.area p {\n margin: 0 0 0.5rem;\n}\n\n.warning {\n color: var(--status-warning);\n}\n\n.panels {\n max-height: 12rem;\n overflow-y: auto;\n border-top: 1px solid var(--edge);\n margin: 0.5rem 0;\n padding-top: 0.5rem;\n}\n\n.actions {\n display: flex;\n gap: 0.5rem;\n}\n","import { useState, useSyncExternalStore } from 'react'\nimport styles from './Diagnostics.module.css'\nimport type { BrowserDiagnosticStore } from './diagnostics.ts'\nimport type { UpdateActivitySnapshot } from './update-activity.ts'\n\nexport function Diagnostics({\n log,\n updateActivity,\n}: {\n log: BrowserDiagnosticStore\n updateActivity?: () => UpdateActivitySnapshot\n}) {\n const [open, setOpen] = useState(false)\n useSyncExternalStore(log.subscribe, log.snapshot, log.snapshot)\n const count = log.count()\n const githubConsistencyIncidents = log.githubConsistencyIncidentCount()\n const summary = log.summary()\n const download = () => {\n const blob = new Blob(\n [\n JSON.stringify(\n log.export(updateActivity ? { updateActivity: updateActivity() } : {}),\n null,\n 2,\n ),\n ],\n { type: 'application/json' },\n )\n const url = URL.createObjectURL(blob)\n const link = document.createElement('a')\n link.href = url\n link.download = `dashboard-diagnostics-${new Date().toISOString().replaceAll(':', '-')}.json`\n link.click()\n URL.revokeObjectURL(url)\n }\n const clear = () => {\n if (!window.confirm('Clear this browser’s retained dashboard diagnostics?')) return\n log.clear()\n }\n\n return (\n <section className={styles.diagnostics}>\n <button\n className={styles.button}\n type=\"button\"\n aria-expanded={open}\n onClick={() => setOpen(!open)}\n >\n Diagnostics ({count})\n {githubConsistencyIncidents > 0 && ` · GitHub consistency ${githubConsistencyIncidents}`}\n </button>\n {open && (\n <div className={styles.area}>\n <p>\n Client {log.clientVersion()} · assets {log.assetPath()}\n </p>\n <p>\n {summary.retained.eventCount} retained browser-local events across{' '}\n {summary.retained.sessionCount} session{summary.retained.sessionCount === 1 ? '' : 's'}\n {summary.retained.firstEventAt && summary.retained.lastEventAt\n ? ` (${formatWindow(summary.retained.firstEventAt, summary.retained.lastEventAt)})`\n : ''}\n . They are never uploaded.\n </p>\n {summary.retained.evidenceMayBeIncomplete && (\n <p className={styles.warning} role=\"alert\">\n Earlier evidence was pruned: {summary.retained.retention.eventsPrunedByCount} at the\n 2,000-event cap and {summary.retained.retention.eventsPrunedByAge} by the 7-day age\n limit. “No failures” applies only to the retained window.\n </p>\n )}\n <p>\n Update failures: {summary.failures.clientUpdate}; board fetch failures:{' '}\n {summary.failures.boardFetch}.\n </p>\n {log.githubConsistencyIncidentCount() > 0 && (\n <p className={styles.warning} role=\"alert\">\n GitHub API consistency incidents: {log.githubConsistencyIncidentCount()}. A response\n older than the last accepted run was rejected; download diagnostics to report it.\n </p>\n )}\n {summary.panels.length > 0 && (\n <div className={styles.panels}>\n {summary.panels.map((panel) => (\n <p key={panel.panelId}>\n <strong>{panel.panelId}</strong> — {panel.requests} requests\n {Object.keys(panel.httpStatuses).length\n ? `; HTTP ${Object.entries(panel.httpStatuses)\n .map(([status, count]) => `${status}×${count}`)\n .join(', ')}`\n : ''}\n ; parse/network failures {panel.parseFailures}/{panel.networkFailures}; visible\n changes {panel.visibleStateChanges}; latest{' '}\n {panel.latestRendered\n ? `${panel.latestRendered.state}${panel.latestRendered.status ? `/${panel.latestRendered.status}` : ''}`\n : 'not rendered'}\n .\n {panel.latestFailedObservation && (\n <>\n {' '}\n Failure: {panel.latestFailedObservation.reason}. Support reference:{' '}\n <code>\n {panel.latestFailedObservation.supportReference ?? 'not provided'}\n </code>\n .\n </>\n )}\n </p>\n ))}\n </div>\n )}\n <div className={styles.actions}>\n <button className={styles.button} type=\"button\" onClick={download}>\n Download\n </button>\n <button className={styles.button} type=\"button\" onClick={clear}>\n Clear\n </button>\n </div>\n </div>\n )}\n </section>\n )\n}\n\nfunction formatWindow(first: string, last: string) {\n return first === last ? first : `${first} to ${last}`\n}\n","/** Embedded in the immutable client artifact; never supplied by the server at runtime. */\nexport const clientReleaseVersion = import.meta.env.RELEASE_VERSION ?? 'dev'\n","import type { ClientEnv } from '@ze-great-dashboard/shared'\nimport { clientReleaseVersion } from './release-version.ts'\n\nexport type DashboardAuth = {\n accessToken?: string\n onAuthenticationFailure?: (status: 401 | 403) => void\n}\n\n/**\n * Adds browser-supplied diagnostic claims to same-origin dashboard API requests. These headers\n * are deliberately not credentials or authorization inputs: the server treats them as untrusted\n * evidence and normalizes only safe values before logging.\n */\nexport function dashboardFetch(\n env: ClientEnv,\n input: RequestInfo | URL,\n init?: RequestInit,\n fetcher: typeof fetch = globalThis.fetch,\n auth: DashboardAuth = {},\n): Promise<Response> {\n const headers = new Headers(init?.headers)\n headers.set('X-Dashboard-Client-Version', clientReleaseVersion)\n headers.set('X-Dashboard-Client-Origin', globalThis.window.location.origin)\n headers.set('X-Dashboard-Client-Asset-Id', env.assetPathId)\n if (auth.accessToken) headers.set('authorization', `Bearer ${auth.accessToken}`)\n return fetcher(input, { ...init, headers }).then((response) => {\n if (response.status === 401 || response.status === 403)\n auth.onAuthenticationFailure?.(response.status)\n return response\n })\n}\n","export type BrowserStorageLike = Pick<Storage, 'getItem' | 'setItem'>\n\nexport function browserLocalStorage(): BrowserStorageLike | undefined {\n try {\n return window.localStorage\n } catch {\n return undefined\n }\n}\n\nexport function readBrowserJson<T>(\n storage: BrowserStorageLike | undefined,\n key: string,\n): T | undefined {\n try {\n const raw = storage?.getItem(key)\n return raw ? (JSON.parse(raw) as T) : undefined\n } catch {\n return undefined\n }\n}\n\nexport function writeBrowserJson(\n storage: BrowserStorageLike | undefined,\n key: string,\n value: unknown,\n) {\n try {\n storage?.setItem(key, JSON.stringify(value))\n } catch {\n // Browser storage is an optimization; callers retain their in-memory state.\n }\n}\n\nexport function removeBrowserValue(storage: Pick<Storage, 'removeItem'> | undefined, key: string) {\n try {\n storage?.removeItem(key)\n } catch {\n // Storage can be unavailable in private browsing or restricted frames.\n }\n}\n","import type {\n DiagnosticEvent,\n DiagnosticRetention,\n FailedObservation,\n RenderedPanelDiagnostic,\n} from './diagnostics.ts'\n\nexport type PanelDiagnosticsSummary = {\n panelId: string\n requests: number\n httpStatuses: Record<string, number>\n parseFailures: number\n networkFailures: number\n visibleStateChanges: number\n latestRendered?: RenderedPanelDiagnostic\n latestFailedObservation?: FailedObservation\n}\n\nexport type DiagnosticsSummary = {\n githubConsistencyIncidents: number\n retained: {\n eventCount: number\n firstEventAt?: string\n lastEventAt?: string\n sessionCount: number\n retention: DiagnosticRetention\n evidenceMayBeIncomplete: boolean\n }\n failures: {\n clientUpdate: number\n boardFetch: number\n }\n panels: PanelDiagnosticsSummary[]\n}\n\n/** Summarizes retained browser evidence only; omitted history is disclosed through retention. */\nexport function summarizeDiagnostics(\n events: readonly DiagnosticEvent[],\n retention: DiagnosticRetention,\n githubConsistencyIncidents = 0,\n): DiagnosticsSummary {\n const panels = new Map<string, PanelDiagnosticsSummary>()\n const sessions = new Set<string>()\n let clientUpdate = 0\n let boardFetch = 0\n\n for (const event of events) {\n sessions.add(event.sessionId)\n if (event.kind === 'client-update-failure') clientUpdate++\n if (event.kind === 'board-fetch-failure' || event.kind === 'board-fetch-parse-failure')\n boardFetch++\n if (!('panelId' in event)) continue\n\n const panel = panels.get(event.panelId) ?? {\n panelId: event.panelId,\n requests: 0,\n httpStatuses: {},\n parseFailures: 0,\n networkFailures: 0,\n visibleStateChanges: 0,\n }\n if (event.kind === 'panel-fetch-start') panel.requests++\n if (event.kind === 'panel-fetch-response') {\n if (event.status !== undefined) {\n const status = String(event.status)\n panel.httpStatuses[status] = (panel.httpStatuses[status] ?? 0) + 1\n }\n if (event.failure) panel.latestFailedObservation = event.failure\n }\n if (event.kind === 'panel-fetch-parse-failure') panel.parseFailures++\n if (event.kind === 'panel-fetch-failure') panel.networkFailures++\n if (event.kind === 'panel-rendered') {\n panel.visibleStateChanges++\n panel.latestRendered = event.rendered\n }\n panels.set(event.panelId, panel)\n }\n\n const timestamps = events.map((event) => event.at).sort()\n const discarded = retention.eventsPrunedByAge + retention.eventsPrunedByCount\n return {\n githubConsistencyIncidents,\n retained: {\n eventCount: events.length,\n firstEventAt: timestamps[0],\n lastEventAt: timestamps.at(-1),\n sessionCount: sessions.size,\n retention,\n evidenceMayBeIncomplete: discarded > 0,\n },\n failures: { clientUpdate, boardFetch },\n panels: [...panels.values()].sort((left, right) => left.panelId.localeCompare(right.panelId)),\n }\n}\n","import type { ClientEnv, Envelope } from '@ze-great-dashboard/shared'\nimport {\n type BrowserStorageLike,\n browserLocalStorage,\n readBrowserJson,\n removeBrowserValue,\n writeBrowserJson,\n} from './browser-storage.ts'\nimport { type DiagnosticsSummary, summarizeDiagnostics } from './diagnostics-summary.ts'\nimport { clientReleaseVersion } from './release-version.ts'\n\nconst storageKey = 'ze-great-dashboard.diagnostics.v2'\nconst legacyStorageKey = 'ze-great-dashboard.diagnostics.v1'\nexport const diagnosticsSchemaVersion = 2\nconst maximumEvents = 2_000\nconst maximumAgeMillis = 7 * 24 * 60 * 60 * 1_000\nconst diagnosticKinds = [\n 'session-start',\n 'client-update-check',\n 'client-update-response',\n 'client-update-failure',\n 'client-update-detected',\n 'board-fetch-start',\n 'board-fetch-response',\n 'board-fetch-parse-failure',\n 'board-fetch-failure',\n 'layout-analyzed',\n 'panel-fetch-start',\n 'panel-fetch-response',\n 'panel-fetch-parse-failure',\n 'panel-fetch-failure',\n 'panel-rendered',\n] as const\n\nexport type CacheMetadata = Partial<\n Record<'cacheControl' | 'etag' | 'lastModified' | 'date' | 'age', string>\n>\n\nexport type GithubConsistencyIncident = {\n at: string\n board: string\n panelId: string\n endpoint: string\n identity: { source: string; workflow: string; branch: string }\n accepted: { sourceUpdatedAt: string; status: string; link: string | null }\n regressed: { sourceUpdatedAt: string; status: string; link: string | null }\n response: { httpStatus?: number; date?: string; etag?: string; cacheControl?: string }\n}\n\ntype EventMetadata = {\n schemaVersion: typeof diagnosticsSchemaVersion\n at: string\n sessionId: string\n board: string\n clientVersion: string\n clientAssetPath: string\n clientAssetPathId: string\n}\n\nexport type RenderedPanelDiagnostic = {\n state: Envelope['state']\n status?: string\n link: string | null\n facts?: Array<{ id: string; state: 'ok' | 'error' | 'unavailable'; link: string | null }>\n}\n\nexport type FailedObservation = {\n reason: string\n supportReference?: string\n}\n\nexport type DiagnosticEventInput =\n | { kind: 'session-start' }\n | { kind: 'client-update-check'; path: string }\n | {\n kind: 'client-update-response'\n path: string\n serverVersion: string\n assetPathIdMatches: boolean\n }\n | { kind: 'client-update-failure'; path: string; message: string }\n | {\n kind: 'client-update-detected'\n path: string\n current: { assetPath: string }\n next: { assetPath: string }\n }\n | { kind: 'board-fetch-start'; path: string }\n | {\n kind: 'board-fetch-response'\n path: string\n status?: number\n cache?: CacheMetadata\n boardSummary?: { panelCount: number; panelIds: string[] }\n }\n | { kind: 'board-fetch-parse-failure'; path: string; message: string }\n | { kind: 'board-fetch-failure'; path: string; message: string }\n | { kind: 'layout-analyzed'; issueCount: number; affectedPanelIds: string[] }\n | { kind: 'panel-fetch-start'; panelId: string; path: string }\n | {\n kind: 'panel-fetch-response'\n panelId: string\n path: string\n status?: number\n cache?: CacheMetadata\n envelope?: Envelope\n failure?: FailedObservation\n }\n | { kind: 'panel-fetch-parse-failure'; panelId: string; path: string; message: string }\n | { kind: 'panel-fetch-failure'; panelId: string; path: string; message: string }\n | {\n kind: 'panel-rendered'\n panelId: string\n path: string\n rendered: RenderedPanelDiagnostic\n }\n\nexport type DiagnosticEvent = DiagnosticEventInput extends infer Event\n ? Event extends DiagnosticEventInput\n ? Event & EventMetadata\n : never\n : never\n\n/** The only interface client features need in order to emit browser diagnostics. */\nexport interface DiagnosticSink {\n record(event: DiagnosticEventInput): void\n recordGithubConsistencyIncident(incident: Omit<GithubConsistencyIncident, 'at' | 'board'>): void\n}\n\ntype PersistedDiagnosticEvent = Omit<DiagnosticEvent, 'schemaVersion'> & { schemaVersion?: number }\nexport type DiagnosticRetention = {\n eventsPrunedByAge: number\n eventsPrunedByCount: number\n}\nexport type RetainedDiagnosticEvidence = {\n events: DiagnosticEvent[]\n retention: DiagnosticRetention\n}\n\ntype StoredDiagnostics = {\n schemaVersion: number\n events: PersistedDiagnosticEvent[]\n retention?: Partial<DiagnosticRetention>\n githubConsistencyIncidents?: GithubConsistencyIncident[]\n}\n\ntype StorageLike = BrowserStorageLike & Pick<Storage, 'removeItem'>\n\n/** Browser-local diagnostic evidence. It deliberately has no server or shared-contract counterpart. */\nexport class BrowserDiagnosticStore implements DiagnosticSink {\n private events: DiagnosticEvent[] = []\n private retention: DiagnosticRetention = emptyRetention()\n private revision = 0\n private incidents: GithubConsistencyIncident[] = []\n private readonly listeners = new Set<() => void>()\n private readonly sessionId = crypto.randomUUID?.() ?? `${Date.now()}-${Math.random()}`\n\n constructor(\n private readonly env: ClientEnv,\n private readonly storage: StorageLike | undefined = browserLocalStorage() as\n | StorageLike\n | undefined,\n private readonly now: () => Date = () => new Date(),\n ) {\n // v1 could retain upstream-provided error text. It is intentionally not migrated.\n removeBrowserValue(this.storage, legacyStorageKey)\n this.events = this.read()\n this.record({ kind: 'session-start' })\n }\n\n recordGithubConsistencyIncident(incident: Omit<GithubConsistencyIncident, 'at' | 'board'>) {\n this.incidents.push({ ...incident, at: this.now().toISOString(), board: this.env.board })\n this.persist()\n this.revision++\n this.notify()\n }\n\n githubConsistencyIncidentCount = () => this.incidents.length\n\n record(event: DiagnosticEventInput) {\n const pruned = prune(\n [\n ...this.events,\n {\n ...event,\n schemaVersion: diagnosticsSchemaVersion,\n at: this.now().toISOString(),\n sessionId: this.sessionId,\n board: this.env.board,\n clientVersion: clientReleaseVersion,\n clientAssetPath: this.env.assetPath,\n clientAssetPathId: this.env.assetPathId,\n },\n ],\n this.now(),\n this.retention,\n )\n this.events = pruned.events\n this.retention = pruned.retention\n this.persist()\n this.revision++\n this.notify()\n }\n\n count = () => {\n return this.events.length\n }\n\n clientVersion = () => clientReleaseVersion\n\n assetPath = () => this.env.assetPath\n\n snapshot = () => this.revision\n\n summary = (): DiagnosticsSummary =>\n summarizeDiagnostics(this.events, this.retention, this.incidents.length)\n\n retainedEvidence = (): RetainedDiagnosticEvidence => ({\n events: [...this.events],\n retention: { ...this.retention },\n })\n\n clear() {\n this.events = []\n this.incidents = []\n this.retention = emptyRetention()\n removeBrowserValue(this.storage, storageKey)\n this.revision++\n this.notify()\n }\n\n subscribe = (listener: () => void) => {\n this.listeners.add(listener)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n export = <TSupplement extends object = object>(supplement?: TSupplement) => {\n return {\n schemaVersion: diagnosticsSchemaVersion,\n exportedAt: this.now().toISOString(),\n client: {\n version: clientReleaseVersion,\n assetPath: this.env.assetPath,\n assetPathId: this.env.assetPathId,\n board: this.env.board,\n sessionId: this.sessionId,\n },\n events: this.events,\n githubConsistencyIncidents: this.incidents,\n summary: this.summary(),\n ...supplement,\n }\n }\n\n private read(): DiagnosticEvent[] {\n const parsed = readBrowserJson<Partial<StoredDiagnostics>>(this.storage, storageKey)\n if (\n !parsed ||\n parsed.schemaVersion !== diagnosticsSchemaVersion ||\n !Array.isArray(parsed.events)\n ) {\n removeBrowserValue(this.storage, storageKey)\n return []\n }\n if (!parsed.events.every(isDiagnosticEvent)) {\n removeBrowserValue(this.storage, storageKey)\n return []\n }\n // v1 retained events predate per-event versions. Their containing store was already v1, so\n // retain them and normalize on the next write rather than discarding viewer evidence.\n const pruned = prune(\n parsed.events.map(\n (event) => ({ ...event, schemaVersion: diagnosticsSchemaVersion }) as DiagnosticEvent,\n ),\n this.now(),\n validRetention(parsed.retention),\n )\n this.retention = pruned.retention\n this.incidents = validIncidents(parsed.githubConsistencyIncidents)\n return pruned.events\n }\n\n private persist() {\n writeBrowserJson(this.storage, storageKey, {\n schemaVersion: diagnosticsSchemaVersion,\n events: this.events,\n retention: this.retention,\n githubConsistencyIncidents: this.incidents,\n })\n }\n\n private notify() {\n for (const listener of this.listeners) listener()\n }\n}\n\nfunction validIncidents(value: unknown): GithubConsistencyIncident[] {\n if (!Array.isArray(value)) return []\n return value.filter((incident): incident is GithubConsistencyIncident => {\n if (!incident || typeof incident !== 'object') return false\n const item = incident as Partial<GithubConsistencyIncident>\n return (\n typeof item.at === 'string' &&\n typeof item.board === 'string' &&\n typeof item.panelId === 'string' &&\n typeof item.endpoint === 'string' &&\n !!item.accepted &&\n !!item.regressed &&\n !!item.response\n )\n })\n}\n\nexport function cacheMetadata(headers: Headers): CacheMetadata | undefined {\n const entries = [\n ['cacheControl', 'cache-control'],\n ['etag', 'etag'],\n ['lastModified', 'last-modified'],\n ['date', 'date'],\n ['age', 'age'],\n ] as const\n const metadata = Object.fromEntries(\n entries.flatMap(([key, header]) => {\n const value = headers.get(header)\n return value ? [[key, value]] : []\n }),\n ) as CacheMetadata\n return Object.keys(metadata).length ? metadata : undefined\n}\n\nfunction emptyRetention(): DiagnosticRetention {\n return { eventsPrunedByAge: 0, eventsPrunedByCount: 0 }\n}\n\nfunction validRetention(value: unknown): DiagnosticRetention {\n if (!value || typeof value !== 'object') return emptyRetention()\n const retention = value as Partial<DiagnosticRetention>\n return {\n eventsPrunedByAge:\n typeof retention.eventsPrunedByAge === 'number' && retention.eventsPrunedByAge >= 0\n ? retention.eventsPrunedByAge\n : 0,\n eventsPrunedByCount:\n typeof retention.eventsPrunedByCount === 'number' && retention.eventsPrunedByCount >= 0\n ? retention.eventsPrunedByCount\n : 0,\n }\n}\n\nfunction prune(events: DiagnosticEvent[], now: Date, priorRetention: DiagnosticRetention) {\n const cutoff = now.valueOf() - maximumAgeMillis\n const current = events.filter(\n (event) =>\n Number.isFinite(new Date(event.at).valueOf()) && new Date(event.at).valueOf() >= cutoff,\n )\n const discardedByAge = events.length - current.length\n const discardedByCount = Math.max(0, current.length - maximumEvents)\n return {\n events: current.slice(-maximumEvents),\n retention: {\n eventsPrunedByAge: priorRetention.eventsPrunedByAge + discardedByAge,\n eventsPrunedByCount: priorRetention.eventsPrunedByCount + discardedByCount,\n },\n }\n}\n\nfunction isDiagnosticEvent(value: unknown): value is PersistedDiagnosticEvent {\n if (!value || typeof value !== 'object') return false\n const event = value as Partial<DiagnosticEvent>\n return (\n (event.schemaVersion === undefined || event.schemaVersion === diagnosticsSchemaVersion) &&\n typeof event.at === 'string' &&\n Number.isFinite(new Date(event.at).valueOf()) &&\n typeof event.sessionId === 'string' &&\n typeof event.board === 'string' &&\n diagnosticKinds.includes(event.kind as (typeof diagnosticKinds)[number])\n )\n}\n",".auth {\n display: grid;\n place-content: center;\n min-height: 100dvh;\n gap: 0.75rem;\n padding: 2rem;\n color: var(--ink-primary);\n background: var(--surface);\n}\n.auth h1,\n.auth p {\n margin: 0;\n}\n.auth button {\n justify-self: start;\n border: 1px solid var(--edge);\n border-radius: var(--radius);\n padding: 0.5em 0.8em;\n color: var(--ink-primary);\n background: var(--surface-raised);\n font: inherit;\n cursor: pointer;\n}\n.signout {\n position: fixed;\n z-index: 20;\n top: var(--gap);\n right: var(--gap);\n border: 1px solid var(--edge);\n border-radius: var(--radius);\n padding: 0.35em 0.6em;\n color: var(--ink-secondary);\n background: var(--surface-raised);\n font: inherit;\n cursor: pointer;\n}\n","import type { ClientEnv } from '@ze-great-dashboard/shared'\nimport { type StateStore, UserManager, WebStorageStateStore } from 'oidc-client-ts'\n\nclass MemoryStore implements StateStore {\n private readonly values = new Map<string, string>()\n async set(key: string, value: string) {\n this.values.set(key, value)\n }\n async get(key: string) {\n return this.values.get(key) ?? null\n }\n async remove(key: string) {\n const value = this.values.get(key) ?? null\n this.values.delete(key)\n return value\n }\n async getAllKeys() {\n return [...this.values.keys()]\n }\n}\n\n/** Creates the standards client; tokens remain in this tab's memory rather than browser storage. */\nexport function createOidcManager(auth: NonNullable<ClientEnv['auth']>) {\n return new UserManager({\n authority: auth.issuer,\n client_id: auth.clientId,\n redirect_uri: `${window.location.origin}/`,\n post_logout_redirect_uri: `${window.location.origin}/`,\n response_type: 'code',\n scope: 'openid profile offline_access',\n resource: auth.audience,\n extraQueryParams: { audience: auth.audience },\n userStore: new MemoryStore(),\n // PKCE transaction data, not tokens, must survive the provider redirect.\n stateStore: new WebStorageStateStore({ store: window.sessionStorage }),\n automaticSilentRenew: true,\n })\n}\n","import type { ClientEnv } from '@ze-great-dashboard/shared'\nimport { type ReactNode, useCallback, useEffect, useMemo, useState } from 'react'\nimport { AuthProvider, useAuth } from 'react-oidc-context'\nimport styles from './AuthBoundary.module.css'\nimport { createOidcManager } from './oidc-manager.ts'\n\nexport function OidcGate({\n env,\n auth,\n children,\n}: {\n env: ClientEnv\n auth: NonNullable<ClientEnv['auth']>\n children: (token: string, denied: () => void) => ReactNode\n}) {\n const manager = useMemo(() => createOidcManager(auth), [auth])\n return (\n <AuthProvider\n userManager={manager}\n onSigninCallback={() =>\n window.history.replaceState({}, document.title, window.location.pathname)\n }\n >\n <AuthScreen env={env}>{children}</AuthScreen>\n </AuthProvider>\n )\n}\n\nfunction AuthScreen({\n env,\n children,\n}: {\n env: ClientEnv\n children: (token: string, denied: () => void) => ReactNode\n}) {\n const auth = useAuth()\n const [denied, setDenied] = useState(false)\n const deny = useCallback(() => setDenied(true), [])\n useEffect(() => {\n if (!auth.isAuthenticated) setDenied(false)\n }, [auth.isAuthenticated])\n if (auth.isLoading)\n return (\n <main className={styles.auth} aria-live=\"polite\">\n Signing in…\n </main>\n )\n if (denied)\n return (\n <main className={styles.auth}>\n <h1>Access denied</h1>\n <p>Your authenticated identity is not permitted to view this dashboard.</p>\n </main>\n )\n if (!auth.isAuthenticated || !auth.user?.access_token)\n return (\n <main className={styles.auth}>\n <h1>{env.board}</h1>\n <p>Sign in to view the dashboard.</p>\n <button type=\"button\" onClick={() => void auth.signinRedirect()}>\n Sign in\n </button>\n </main>\n )\n return (\n <>\n <button className={styles.signout} type=\"button\" onClick={() => void auth.signoutRedirect()}>\n Sign out\n </button>\n {children(auth.user.access_token, deny)}\n </>\n )\n}\n",".panel {\n grid-column: var(--panel-column, span 6);\n grid-row: var(--panel-row, auto);\n display: flex;\n flex-direction: column;\n /* A panel reads from its upper edge; the remaining lower area is deliberate breathing room. */\n justify-content: flex-start;\n gap: 0.15em;\n min-width: 0;\n min-height: 0;\n padding: clamp(0.5rem, 0.8vw, var(--gap));\n border: 1px solid var(--edge);\n border-radius: var(--radius);\n background: var(--surface-raised);\n position: relative;\n isolation: isolate;\n overflow: hidden;\n line-height: 1.2;\n container-name: panel;\n container-type: size;\n}\n.attentionActive {\n outline: 0.14rem solid var(--status-critical);\n outline-offset: 0.16rem;\n}\n.content {\n position: relative;\n z-index: 1;\n display: flex;\n flex: 0 1 auto;\n flex-direction: column;\n justify-content: flex-start;\n gap: 0.1em;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n}\n.evidence {\n display: contents;\n}\n/* The source link owns its corner, so the label and evidence never render beneath it. */\n.panel:has(.sourceAction) .content {\n padding-inline-end: 2.25em;\n}\n.content > *,\n.details > * {\n min-width: 0;\n max-width: 100%;\n}\n.content:has([data-running-progress=\"runway\"]),\n.content:has([data-running-progress=\"signal-field\"]) {\n flex: 1 1 0;\n}\n.statusBand {\n display: grid;\n flex: 1 1 0;\n grid-template-rows: 2.6em minmax(0, 1fr) auto;\n gap: 0;\n}\n.statusBand > [data-panel-anchor=\"status\"] {\n position: absolute;\n inset-inline: 0;\n top: 50%;\n grid-row: 2;\n align-self: center;\n transform: translateY(-50%);\n}\n.statusBand > [data-panel-anchor=\"evidence\"] {\n display: block;\n grid-row: 3;\n align-self: end;\n}\n.content:not(.statusBand) > [data-panel-anchor=\"status\"] {\n display: contents;\n}\n.statusBand > [data-panel-anchor=\"status\"],\n.statusBand > [data-panel-anchor=\"evidence\"] {\n min-width: 0;\n}\n.error {\n border-color: var(--status-serious);\n}\n.wide {\n grid-column: span 12;\n}\n.density-comfortable {\n padding: 0.65em;\n gap: 0.1em;\n}\n.density-comfortable .content {\n gap: 0.1em;\n}\n.density-compact {\n min-height: 3.5em;\n padding: 0.2em;\n gap: 0;\n line-height: 1.05;\n justify-content: flex-start;\n}\n.density-compact .content {\n gap: 0;\n}\n.label {\n margin: 0;\n overflow-wrap: anywhere;\n font-size: 1em;\n font-weight: 600;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n color: var(--ink-secondary);\n}\n.statusBand .label {\n grid-row: 1;\n}\n.typeGlyph {\n display: none;\n}\n.identityText {\n overflow-wrap: anywhere;\n}\n.density-compact .label {\n font-size: 0.8em;\n}\n.hint {\n margin: 0;\n font-size: 0.75em;\n color: var(--ink-muted);\n overflow-wrap: anywhere;\n}\n.branch {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n overflow-wrap: anywhere;\n}\n.observed {\n display: flex;\n flex-wrap: wrap;\n gap: 0.35em;\n align-items: center;\n}\n.meta {\n display: var(--panel-meta-display, block);\n}\n.metaValue {\n min-width: 0;\n overflow-wrap: anywhere;\n}\n.compactValue {\n display: none;\n}\n.warning {\n color: var(--status-warning);\n}\n.serious {\n color: var(--status-serious);\n}\n.status {\n margin: 0;\n font-size: 1.35em;\n font-weight: 650;\n}\n.statusGlyph {\n display: inline-block;\n}\n.compactOnlyStatus {\n display: none;\n}\n.density-compact .status {\n font-size: 1.1em;\n}\n.passed {\n color: var(--status-good);\n}\n.failed {\n color: var(--status-critical);\n}\n.warning,\n.running {\n color: var(--status-warning);\n}\n.cancelled,\n.unknown {\n color: var(--ink-secondary);\n}\n.sourceAction {\n position: absolute;\n z-index: 2;\n top: 0.35em;\n right: 0.35em;\n display: inline-grid;\n width: 2em;\n height: 2em;\n place-items: center;\n border-radius: 0.3em;\n color: var(--ink-secondary);\n font-size: 0.85em;\n font-weight: 600;\n line-height: 1;\n text-decoration: none;\n}\n.sourceAction:hover {\n color: var(--ink-primary);\n background: color-mix(in srgb, var(--ink-primary) 8%, transparent);\n}\n.sourceAction:focus-visible {\n outline: 2px solid var(--ink-primary);\n outline-offset: 2px;\n}\n\n.density-comfortable :is(.hint, .observed),\n.density-compact :is(.hint, .observed) {\n font-size: 0.65em;\n}\n@container panel (min-width: 48rem) {\n .density-comfortable.shallow,\n .density-auto.shallow {\n padding: 0.45em 0.65em;\n }\n .density-comfortable.shallow .content,\n .density-auto.shallow .content {\n flex-direction: row;\n flex-wrap: wrap;\n align-items: baseline;\n column-gap: 0.7em;\n row-gap: 0.15em;\n }\n .density-comfortable.shallow .status,\n .density-auto.shallow .status {\n flex: 0 0 auto;\n font-size: 1em;\n }\n .density-comfortable.shallow :is(.label, .observed),\n .density-auto.shallow :is(.label, .observed) {\n flex: 0 0 auto;\n }\n}\n@container panel (min-width: 12rem) {\n .density-compact.shallow .content,\n .density-auto.shallow .content {\n flex-direction: row;\n flex-wrap: wrap;\n align-items: baseline;\n column-gap: 0.7em;\n row-gap: 0.15em;\n }\n .density-compact.shallow :is(.label, .observed),\n .density-auto.shallow :is(.label, .observed) {\n flex: 0 0 auto;\n }\n}\n/* Width and height use the same scale steps, so a narrow or tall cell gets the same text budget. */\n@container panel (max-width: 22rem) {\n .content,\n .sourceAction {\n font-size: 0.8em;\n }\n}\n@container panel (max-width: 15rem) {\n .content,\n .sourceAction {\n font-size: 0.9em;\n }\n}\n@container panel (max-height: 10rem) {\n .content,\n .sourceAction {\n font-size: 0.8em;\n }\n}\n@container panel (max-height: 7rem) {\n .content,\n .sourceAction {\n font-size: 0.9em;\n }\n}\n/* Responsive layout may flow authored cells into one column; content never escapes its cell. */\n@media (max-width: 64rem) {\n .panel {\n grid-column: 1 / -1;\n grid-row: auto;\n min-height: 6em;\n --stacked-card-reading-line-height: 1.25;\n /* Desktop cells need size containment to honor their assigned grid height. Stacked cards\n instead need their readable evidence to contribute to height; retain inline queries for\n width-responsive treatments without containing the block axis. */\n container-type: inline-size;\n }\n /* Stacked cards grow for their evidence; the panel still clips only its decorative field. */\n .content {\n flex-shrink: 0;\n min-height: auto;\n overflow: visible;\n line-height: var(--stacked-card-reading-line-height);\n }\n .density-comfortable .content,\n .density-compact .content,\n .density-auto .content {\n flex-direction: column;\n align-items: stretch;\n }\n}\n\n@container panel (max-width: 11rem) and (max-height: 9rem) {\n .content {\n --panel-meta-display: flex;\n }\n .label {\n font-size: 0.85em;\n }\n .status {\n font-size: 1.05em;\n }\n}\n@container panel (max-height: 5rem) {\n .content {\n --panel-meta-display: flex;\n }\n .label {\n font-size: 0.85em;\n }\n .status {\n font-size: 1.05em;\n }\n}\n\n@container panel (max-width: 13rem) {\n .density-compact .content {\n --panel-meta-display: flex;\n }\n .density-compact .content > .meta {\n font-size: 0.6em;\n }\n}\n@container panel (max-width: 13rem) {\n /* Compact evidence keeps its full wording for assistive technology and the hover title. */\n .meta:has(.compactValue) .fullValue {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n .meta:has(.compactValue) .compactValue {\n display: inline;\n }\n}\n@container panel (max-width: 8rem) {\n /* Text-light is an internal sub-mode: secondary text remains in the accessibility tree. */\n .content {\n --panel-meta-display: flex;\n gap: 0.05em;\n }\n}\n@container panel (min-height: 24rem) and (max-width: 13rem) {\n .content {\n --panel-meta-display: flex;\n gap: 0.05em;\n }\n\n .statusBand {\n grid-template-rows: 2.6em minmax(0, 1fr) 5em;\n }\n}\n@container panel (max-height: 4rem) {\n .content {\n --panel-meta-display: flex;\n gap: 0.05em;\n }\n}\n\n@container panel (max-width: 13rem) and (max-height: 10rem) {\n .density-comfortable .content > .meta {\n font-size: 0.68em;\n }\n}\n\n@container panel (max-width: 18rem) and (max-height: 10rem) {\n .density-compact .content > .meta {\n font-size: 0.6em;\n }\n}\n\n.meta {\n align-items: center;\n gap: 0.2em;\n min-width: 0;\n}\n.metaValue {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Portrait cells retain their authored footprint but become a symbol-led scan surface. */\n@container panel (max-width: 13rem) and (min-height: 10rem) and (max-aspect-ratio: 3 / 4) {\n .content {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, max-content));\n grid-template-rows: min-content;\n align-content: start;\n justify-content: center;\n gap: 0.45em;\n }\n .label {\n grid-column: 1;\n grid-row: 1;\n margin: 0;\n }\n .typeGlyph {\n display: inline-block;\n color: var(--ink-secondary);\n font-size: 1.8em;\n line-height: 1;\n }\n .status {\n grid-column: 2;\n grid-row: 1;\n margin: 0;\n font-size: 1.8em;\n line-height: 1;\n }\n .compactOnlyStatus {\n display: block;\n }\n /* Text-light portrait treatments retain their full wording for assistive technology. */\n .identityText,\n .statusText,\n .content > [data-panel-evidence-priority=\"secondary\"] > :not([data-panel-status]),\n .content > [data-panel-anchor=\"evidence\"][data-panel-evidence-priority=\"secondary\"] {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n .content > [data-panel-anchor=\"status\"] {\n grid-column: 2;\n grid-row: 1;\n align-self: start;\n }\n /* Health tiles keep their upright identity while preserving the shared scan bands. */\n .statusBand {\n display: grid;\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: 2.8em minmax(0, 1fr) 5em;\n align-content: stretch;\n justify-content: stretch;\n gap: 0;\n }\n .statusBand .label {\n display: flex;\n flex-direction: column;\n grid-column: 1;\n grid-row: 1;\n width: 100%;\n align-items: start;\n justify-content: center;\n gap: 0.1em;\n font-size: 0.78em;\n line-height: 1.15;\n text-align: center;\n }\n .statusBand .identityText {\n /* The title gets its own line, so the large type glyph cannot reduce it to one character. */\n flex: none;\n width: 100%;\n min-width: 0;\n position: static;\n height: auto;\n padding: 0;\n margin: 0;\n overflow: visible;\n clip: auto;\n white-space: normal;\n }\n .statusBand > [data-panel-anchor=\"status\"] {\n position: static;\n inset-inline: auto;\n top: auto;\n grid-column: 1;\n grid-row: 2;\n align-self: center;\n justify-self: center;\n transform: none;\n }\n .statusBand > [data-panel-anchor=\"evidence\"] {\n position: static;\n display: block;\n grid-column: 1;\n grid-row: 3;\n width: auto;\n height: auto;\n padding: 0;\n margin: 0;\n overflow: hidden;\n clip: auto;\n white-space: normal;\n }\n .statusBand .status {\n font-size: 2.1em;\n }\n}\n","/**\n * A panel-shaped hole, so the grid can be looked at and argued with before any signal exists.\n * Replaced by real panels in Stage 2 — nothing here is meant to survive.\n */\nexport function PanelPlaceholder({\n label,\n hint,\n wide = false,\n}: {\n label: string\n hint: string\n wide?: boolean\n}) {\n return (\n <section\n className={`${styles.panel} ${wide ? styles.wide : ''}`}\n data-panel\n data-panel-id=\"placeholder\"\n >\n <h2 className={styles.label}>{label}</h2>\n <p className={styles.hint}>{hint}</p>\n </section>\n )\n}\n\nimport styles from './PanelFrame.module.css'\n","import type { ErrorKind } from '@ze-great-dashboard/shared'\n\nexport function errorPresentation(kind: ErrorKind) {\n switch (kind) {\n case 'unauthorized':\n return { label: 'Access denied', emphasis: 'serious' as const }\n case 'not-found':\n return { label: 'Source not found', emphasis: 'serious' as const }\n case 'unreachable':\n case 'upstream-error':\n return { label: 'Source unavailable', emphasis: 'serious' as const }\n case 'no-runs':\n return { label: 'No workflow runs', emphasis: 'warning' as const }\n }\n}\n",".fact {\n display: contents;\n}\n\n.facts {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 0.35em 0.6em;\n min-width: 0;\n}\n\n.factCell {\n position: relative;\n min-width: 0;\n padding: 0.1em 1.8em 0.1em 0;\n}\n\n.factCell h3 {\n margin: 0;\n color: var(--ink-secondary);\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 0.65em;\n font-weight: 600;\n overflow-wrap: anywhere;\n}\n\n.factCell :global([data-panel-meta]) {\n font-size: 0.55em;\n}\n\n.factSource {\n position: absolute;\n top: 0.1em;\n right: 0.15em;\n display: grid;\n width: 1.5em;\n height: 1.5em;\n place-items: center;\n border-radius: 0.25em;\n color: var(--ink-secondary);\n font-size: 0.7em;\n text-decoration: none;\n}\n\n.factSource:hover,\n.factSource:focus-visible {\n color: var(--ink-primary);\n background: color-mix(in srgb, var(--ink-primary) 8%, transparent);\n}\n\n@container panel (max-width: 13rem) {\n .facts {\n grid-template-columns: 1fr;\n }\n}\n@container panel (min-width: 48rem) {\n :global([data-density=\"compact\"][data-shallow=\"true\"]) .fact > *,\n :global([data-density=\"auto\"][data-shallow=\"true\"]) .fact > * {\n margin: 0;\n }\n}\n@container panel (min-width: 12rem) {\n :global([data-density=\"compact\"][data-shallow=\"true\"]) .fact > *,\n :global([data-density=\"auto\"][data-shallow=\"true\"]) .fact > * {\n margin: 0;\n }\n}\n","import type { Panel } from '@ze-great-dashboard/shared'\nimport type { CSSProperties } from 'react'\n\n/** Convert the advisory board position into CSS grid placement. */\nexport function panelLayout(panel: Panel): CSSProperties | undefined {\n const position = panel.position\n if (!position) return undefined\n\n return {\n '--panel-column': `${position.x + 1} / span ${position.w}`,\n '--panel-row': `${position.y + 1} / span ${position.h}`,\n } as CSSProperties\n}\n","import type { PipelineStatus } from '@ze-great-dashboard/shared'\n\n/**\n * The compact tile contract. These are primary scan symbols, so a glyph has one meaning here.\n * Secondary metadata may reuse familiar symbols only when it retains that same meaning.\n */\nexport const panelTypeSymbols = {\n 'pipeline-status': { glyph: '▣', label: 'Pipeline status' },\n 'pull-request-health': { glyph: '⌘', label: 'Pull request health' },\n 'http-value': { glyph: '◌', label: 'HTTP value' },\n 'pipeline-animation-demo': { glyph: '✦', label: 'Pipeline animation demo' },\n} as const\n\n/** Renderable client panel types are defined by the compact identity contract. */\nexport type RenderablePanelType = keyof typeof panelTypeSymbols\n\nexport const statusSymbols: Record<PipelineStatus['status'], { glyph: string; label: string }> = {\n passed: { glyph: '✓', label: 'Passed' },\n failed: { glyph: '✕', label: 'Failed' },\n warning: { glyph: '⚠', label: 'Warning' },\n running: { glyph: '↻', label: 'Running' },\n cancelled: { glyph: '⊘', label: 'Cancelled' },\n unknown: { glyph: '?', label: 'Unknown' },\n}\n\nexport function panelTypeSymbol(type: string) {\n return panelTypeSymbols[type as keyof typeof panelTypeSymbols]\n}\n\n/** Every primary glyph and its single semantic meaning, useful for keeping the registry auditable. */\nexport const primarySymbolMeanings = [\n ...Object.entries(panelTypeSymbols).map(([type, symbol]) => ({\n glyph: symbol.glyph,\n meaning: `panel type: ${type}`,\n })),\n ...Object.entries(statusSymbols).map(([status, symbol]) => ({\n glyph: symbol.glyph,\n meaning: `status: ${status}`,\n })),\n]\n","import type { Envelope, Panel, PipelineStatus } from '@ze-great-dashboard/shared'\nimport type { ReactNode } from 'react'\nimport styles from './PanelFrame.module.css'\nimport { panelLayout } from './panel-layout.ts'\nimport { panelTypeSymbol } from './panel-symbols.ts'\n\ntype PanelStatusKind = PipelineStatus['status']\ntype CompactEvidence = { kind: 'short-value'; value: ReactNode } | { kind: 'glyph-only' }\n\nexport function PanelHint({\n children,\n className,\n title,\n}: {\n children: ReactNode\n className?: string\n title?: string\n}) {\n return (\n <p className={`${styles.hint} ${className ?? ''}`} title={title}>\n {children}\n </p>\n )\n}\n\n/** A concise metadata row with one visible glyph and the full value retained in the DOM. */\nexport function PanelMetadata({\n glyph,\n label,\n value,\n compact,\n title,\n observed = false,\n emphasis,\n className,\n}: {\n glyph: string\n label: string\n value: ReactNode\n /** A text-light visual alternative; the full value remains available to assistive technology. */\n compact?: CompactEvidence\n title?: string\n observed?: boolean\n emphasis?: 'warning' | 'serious'\n className?: string\n}) {\n return (\n <p\n className={`${styles.hint} ${observed ? styles.observed : ''} ${emphasis ? styles[emphasis] : ''} ${styles.meta} ${className ?? ''}`}\n data-panel-meta\n >\n <span aria-hidden=\"true\">{glyph}</span> <span className=\"screen-reader-only\">{label}: </span>\n <span className={styles.metaValue} title={title}>\n <span className={styles.fullValue}>{value}</span>\n {compact && (\n <span className={styles.compactValue} aria-hidden=\"true\">\n {compact.kind === 'short-value' ? compact.value : null}\n </span>\n )}\n </span>\n </p>\n )\n}\n\n/** Stable layout slot for a panel's ordinary readable evidence. */\nexport function PanelEvidence({\n children,\n className,\n priority = 'secondary',\n anchor,\n}: {\n children: ReactNode\n className?: string\n /** Evidence can be intentionally suppressed by a symbol-led compact composition. */\n priority?: 'primary' | 'secondary'\n /** Place this evidence in an opt-in PanelFrame layout slot. */\n anchor?: 'evidence'\n}) {\n return (\n <div\n className={`${styles.evidence} ${className ?? ''}`}\n data-panel-evidence\n data-panel-evidence-priority={priority}\n data-panel-anchor={anchor}\n >\n {children}\n </div>\n )\n}\n\nexport function PanelStatus({\n status,\n emphasis,\n glyph,\n label,\n compactOnly = false,\n}: {\n status?: PanelStatusKind\n emphasis?: 'warning' | 'serious'\n glyph: string\n label: string\n /** Render a compact state only in a portrait tile without changing ordinary cards. */\n compactOnly?: boolean\n}) {\n return (\n <p\n className={`${styles.status} ${status ? styles[status] : ''} ${emphasis ? styles[emphasis] : ''} ${compactOnly ? styles.compactOnlyStatus : ''}`}\n data-panel-status\n >\n {glyph && (\n <span className={styles.statusGlyph} aria-hidden=\"true\">\n {glyph}\n </span>\n )}\n {glyph && label && ' '}\n <span className={styles.statusText}>{label}</span>\n </p>\n )\n}\n\n/** A prominent fact or loading message; unlike PanelStatus, this carries no state semantics. */\nexport function PanelValue({\n children,\n emphasis,\n}: {\n children: ReactNode\n emphasis?: 'warning' | 'serious'\n}) {\n return <p className={`${styles.status} ${emphasis ? styles[emphasis] : ''}`}>{children}</p>\n}\n\nexport function PanelFrame({\n panel,\n envelope,\n attentionActive = false,\n error = false,\n field,\n layout,\n children,\n}: {\n panel: Panel\n envelope?: Envelope\n attentionActive?: boolean\n error?: boolean\n /** Decorative active-run layer. It is intentionally a sibling of readable panel content. */\n field?: ReactNode\n /** Opt-in slots for health panels with a shared identity, state, and evidence band. */\n layout?: 'status-band'\n children: ReactNode\n}) {\n const density = panel.density ?? 'auto'\n const position = panel.position\n const typeSymbol = panelTypeSymbol(panel.type)\n const shallow = position !== undefined && position.h <= 2\n const short = position !== undefined && position.h <= 3\n return (\n <section\n className={`${styles.panel} ${styles[`density-${density}`]} ${shallow ? styles.shallow : ''} ${short ? styles.short : ''} ${error ? styles.error : ''} ${attentionActive ? styles.attentionActive : ''}`}\n id={`panel-${panel.id}`}\n style={panelLayout(panel)}\n aria-busy={envelope ? undefined : true}\n data-panel\n data-panel-id={panel.id}\n data-panel-position={\n position ? `${position.x},${position.y},${position.w},${position.h}` : undefined\n }\n data-density={density}\n data-shallow={shallow}\n data-short={short}\n data-error={error || undefined}\n data-panel-type={panel.type}\n data-attention-active={attentionActive || undefined}\n >\n {field}\n <PanelSourceLink panelId={panel.id} link={envelope?.link} />\n <div\n className={`${styles.content} ${layout === 'status-band' ? styles.statusBand : ''}`}\n data-panel-content\n data-panel-layout={layout}\n >\n <h2 className={styles.label} data-panel-anchor=\"identity\">\n {typeSymbol && (\n <span\n className={styles.typeGlyph}\n aria-hidden=\"true\"\n title={typeSymbol.label}\n data-panel-type-glyph\n >\n {typeSymbol.glyph}\n </span>\n )}\n <span className={styles.identityText} data-panel-identity-text>\n {panel.label ?? panel.id}\n </span>\n </h2>\n {children}\n </div>\n </section>\n )\n}\n\nfunction PanelSourceLink({ panelId, link }: { panelId: string; link?: string | null }) {\n if (!link) return null\n\n return (\n <a\n className={styles.sourceAction}\n href={link}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={`View source for ${panelId} (opens in a new tab)`}\n title={`View source for ${panelId} (opens in a new tab)`}\n data-panel-action=\"source\"\n data-panel-link\n >\n <span aria-hidden=\"true\">↗</span>\n <span className=\"screen-reader-only\">View source</span>\n </a>\n )\n}\n","import { PanelMetadata } from './PanelFrame.tsx'\nimport type { PanelUpdateHealth } from './panel-props.ts'\n\nexport function ObservedAt({ value, label = 'Observed' }: { value: string; label?: string }) {\n return <TimeAge value={value} label={label} />\n}\n\nexport function PipelineAge({\n sourceUpdatedAt,\n observedAt,\n running,\n runStartedAt,\n}: {\n sourceUpdatedAt?: string\n observedAt: string\n running: boolean\n runStartedAt?: string\n}) {\n if (running && runStartedAt) return <TimeAge value={runStartedAt} label=\"Started\" />\n return (\n <TimeAge\n value={sourceUpdatedAt ?? observedAt}\n label={sourceUpdatedAt ? 'Last update' : 'Observed'}\n />\n )\n}\n\nexport function UpdateHealth({ health }: { health: PanelUpdateHealth }) {\n const unavailable = health.consecutiveFailures >= 3\n const label = unavailable ? 'Updates unavailable' : 'Updates delayed'\n return (\n <>\n <PanelMetadata\n glyph=\"⚠\"\n label={label}\n value={`${label} · ${health.message}`}\n title={health.message}\n emphasis={unavailable ? 'serious' : 'warning'}\n />\n <TimeAge value={health.lastConfirmedAt} label=\"Last confirmed\" />\n </>\n )\n}\n\nfunction TimeAge({ value, label }: { value: string; label: string }) {\n const observed = new Date(value)\n const formatted = observed.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n const age = Date.now() - observed.getTime()\n const content = `${label} ${formatAge(age)}`\n return (\n <PanelMetadata\n glyph=\"◷\"\n label={label}\n value={content}\n compact={{ kind: 'short-value', value: formatCompactAge(age) }}\n title={`${label} at ${formatted}`}\n observed\n />\n )\n}\n\nexport function formatAge(milliseconds: number) {\n if (milliseconds < 60_000) return 'just now'\n const minutes = Math.floor(milliseconds / 60_000)\n if (minutes < 60) return `${minutes}m ago`\n const hours = Math.floor(minutes / 60)\n return `${hours}h ${minutes % 60}m ago`\n}\n\nfunction formatCompactAge(milliseconds: number) {\n if (milliseconds < 60_000) return 'now'\n const minutes = Math.floor(milliseconds / 60_000)\n if (minutes < 60) return `${minutes}m`\n const hours = Math.floor(minutes / 60)\n return `${hours}h ${minutes % 60}m`\n}\n","import { httpValueSchema } from '@ze-great-dashboard/shared'\nimport { errorPresentation } from './error-presentation.ts'\nimport styles from './HttpValuePanel.module.css'\nimport { PanelEvidence, PanelFrame, PanelHint, PanelStatus, PanelValue } from './PanelFrame.tsx'\nimport type { HttpValueFactObservation, PanelProps } from './panel-props.ts'\nimport { ObservedAt, UpdateHealth } from './TimeAge.tsx'\n\nexport function HttpValuePanel({\n panel,\n envelope,\n attentionActive,\n updateHealth,\n facts,\n}: PanelProps) {\n if (panel.facts)\n return <GroupedHttpValuePanel panel={panel} attentionActive={attentionActive} facts={facts} />\n if (!envelope)\n return (\n <PanelFrame panel={panel} attentionActive={attentionActive}>\n <PanelEvidence>\n <PanelHint>Loading…</PanelHint>\n </PanelEvidence>\n </PanelFrame>\n )\n if (envelope.state === 'error') {\n const presentation = errorPresentation(envelope.error.kind)\n return (\n <PanelFrame panel={panel} envelope={envelope} attentionActive={attentionActive} error>\n <PanelEvidence>\n <PanelStatus glyph=\"⚠\" label={presentation.label} emphasis={presentation.emphasis} />\n <PanelHint>{envelope.error.message}</PanelHint>\n </PanelEvidence>\n </PanelFrame>\n )\n }\n const signal = httpValueSchema.safeParse(envelope.signal)\n if (!signal.success)\n return (\n <PanelFrame panel={panel} envelope={envelope} attentionActive={attentionActive} error>\n <PanelEvidence>\n <PanelStatus glyph=\"⚠\" label=\"Invalid value\" />\n </PanelEvidence>\n </PanelFrame>\n )\n return (\n <PanelFrame panel={panel} envelope={envelope} attentionActive={attentionActive}>\n <PanelEvidence className={styles.fact}>\n <PanelStatus glyph=\"✓\" label=\"Value read\" compactOnly />\n <PanelValue>{String(signal.data.value)}</PanelValue>\n <ObservedAt value={envelope.observedAt} />\n {updateHealth && <UpdateHealth health={updateHealth} />}\n </PanelEvidence>\n </PanelFrame>\n )\n}\n\nfunction GroupedHttpValuePanel({\n panel,\n attentionActive,\n facts,\n}: Pick<PanelProps, 'panel' | 'attentionActive' | 'facts'>) {\n if (!panel.facts) return null\n return (\n <PanelFrame panel={panel} attentionActive={attentionActive}>\n <PanelEvidence>\n <div className={styles.facts} data-http-value-facts>\n {panel.facts.map((fact) => (\n <HttpValueFactCell key={fact.id} label={fact.label} observation={facts?.[fact.id]} />\n ))}\n </div>\n </PanelEvidence>\n </PanelFrame>\n )\n}\n\nfunction HttpValueFactCell({\n label,\n observation,\n}: {\n label: string\n observation: HttpValueFactObservation | undefined\n}) {\n const envelope = observation?.envelope\n if (!envelope)\n return (\n <section className={styles.factCell} data-http-value-fact>\n <h3>{label}</h3>\n <PanelValue emphasis={observation?.failure ? 'serious' : undefined}>\n {observation?.failure ? '⚠ Updates unavailable' : 'Loading…'}\n </PanelValue>\n {observation?.updateHealth && <UpdateHealth health={observation.updateHealth} />}\n </section>\n )\n if (envelope.state === 'error') {\n const presentation = errorPresentation(envelope.error.kind)\n return (\n <section className={styles.factCell} data-http-value-fact data-error>\n <FactSourceLink label={label} link={envelope.link} />\n <h3>{label}</h3>\n <PanelStatus glyph=\"⚠\" label={presentation.label} emphasis={presentation.emphasis} />\n <PanelHint>{envelope.error.message}</PanelHint>\n <ObservedAt value={envelope.observedAt} />\n </section>\n )\n }\n const signal = httpValueSchema.safeParse(envelope.signal)\n if (!signal.success)\n return (\n <section className={styles.factCell} data-http-value-fact data-error>\n <FactSourceLink label={label} link={envelope.link} />\n <h3>{label}</h3>\n <PanelStatus glyph=\"⚠\" label=\"Invalid value\" emphasis=\"serious\" />\n <ObservedAt value={envelope.observedAt} />\n </section>\n )\n return (\n <section className={styles.factCell} data-http-value-fact>\n <FactSourceLink label={label} link={envelope.link} />\n <h3>{label}</h3>\n <PanelValue>{String(signal.data.value)}</PanelValue>\n <ObservedAt value={envelope.observedAt} />\n </section>\n )\n}\n\nfunction FactSourceLink({ label, link }: { label: string; link: string | null }) {\n if (!link) return null\n return (\n <a\n className={styles.factSource}\n href={link}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={`View source for ${label} (opens in a new tab)`}\n title={`View source for ${label} (opens in a new tab)`}\n >\n <span aria-hidden=\"true\">↗</span>\n <span className=\"screen-reader-only\">View source</span>\n </a>\n )\n}\n",".variant {\n margin: 0;\n color: var(--ink-muted);\n font-size: 0.72em;\n text-transform: capitalize;\n transition: color 180ms ease;\n}\n@container panel (max-width: 13rem) {\n .variantPrefix {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .variant {\n transition: none;\n }\n}\n",".field {\n position: absolute;\n z-index: 0;\n inset: 0;\n overflow: hidden;\n pointer-events: none;\n contain: layout paint;\n color: var(--status-warning);\n}\n.grid {\n position: absolute;\n inset: 10%;\n}\n.piece {\n position: absolute;\n left: calc((var(--piece-x) / var(--shape-columns)) * 100%);\n top: calc((var(--piece-y) / var(--shape-rows)) * 100%);\n width: calc((var(--piece-width) / var(--shape-columns)) * 100%);\n height: calc((var(--piece-height) / var(--shape-rows)) * 100%);\n transition:\n left 120ms linear,\n top 120ms linear;\n}\n.field[data-recycling=\"true\"] .piece {\n transition:\n left 500ms cubic-bezier(0.22, 1, 0.36, 1),\n top 500ms cubic-bezier(0.22, 1, 0.36, 1),\n opacity 180ms ease;\n}\n.field[data-overdue=\"true\"] .piece[data-piece-phase=\"settled\"] {\n opacity: 0.72;\n border-color: currentColor;\n}\n.field[data-overdue=\"true\"] .cell {\n background: color-mix(in srgb, currentColor 38%, transparent);\n box-shadow: 0 0 0.6em color-mix(in srgb, currentColor 48%, transparent);\n}\n.field[data-overdue=\"true\"] .clearingCell {\n animation-duration: 900ms;\n}\n/* biome-ignore lint/style/noDescendingSpecificity: base cell rules follow the overdue override intentionally. */\n.cell {\n position: absolute;\n left: calc((var(--cell-x) / var(--piece-width)) * 100% + 0.12em);\n top: calc((var(--cell-y) / var(--piece-height)) * 100% + 0.12em);\n width: calc(100% / var(--piece-width) - 0.24em);\n height: calc(100% / var(--piece-height) - 0.24em);\n border: 1px solid color-mix(in srgb, currentColor 55%, transparent);\n border-radius: 0.12em;\n background: color-mix(in srgb, currentColor 28%, transparent);\n box-shadow: 0 0 0.45em color-mix(in srgb, currentColor 35%, transparent);\n}\n/* biome-ignore lint/style/noDescendingSpecificity: base clearing rules follow the overdue override intentionally. */\n.clearingCell {\n position: absolute;\n left: calc((var(--clear-x) / var(--shape-columns)) * 100% + 0.12em);\n top: calc((var(--clear-y) / var(--shape-rows)) * 100% + 0.12em);\n width: calc(100% / var(--shape-columns) - 0.24em);\n height: calc(100% / var(--shape-rows) - 0.24em);\n border: 1px solid color-mix(in srgb, currentColor 55%, transparent);\n border-radius: 0.12em;\n background: color-mix(in srgb, currentColor 28%, transparent);\n animation: clear-cell 500ms ease-out forwards;\n}\n.piece[data-piece-phase=\"entry\"] {\n opacity: 0.35;\n}\n.piece[data-piece-phase=\"align\"] {\n opacity: 0.65;\n}\n.piece[data-piece-phase=\"travel\"] {\n opacity: 0.9;\n}\n/* biome-ignore lint/style/noDescendingSpecificity: settled phase is the base state for the overdue override. */\n.piece[data-piece-phase=\"settled\"] {\n opacity: 0.5;\n}\n@media (prefers-reduced-motion: reduce) {\n .piece,\n .field[data-recycling=\"true\"] .piece {\n transition: none;\n }\n .field[data-overdue=\"true\"] .clearingCell {\n animation: none;\n opacity: 0;\n }\n /* biome-ignore lint/style/noDescendingSpecificity: reduced-motion base rule follows the overdue override. */\n .clearingCell {\n animation: none;\n opacity: 0;\n }\n}\n\n@keyframes clear-cell {\n to {\n opacity: 0;\n transform: scale(0.35);\n }\n}\n","export type FallingDirection = 'horizontal' | 'vertical'\nexport type FallingCell = { x: number; y: number }\nexport type FallingShape = {\n id: number\n bornAt: number\n cells: FallingCell[]\n x: number\n y: number\n targetX?: number\n targetY?: number\n phase: 'entry' | 'align' | 'travel' | 'settled'\n}\n\nexport const FALLING_TARGET_FILL = 0.85\n\nconst shapes: FallingCell[][] = [\n [\n { x: 0, y: 0 },\n { x: 1, y: 0 },\n ],\n [\n { x: 0, y: 0 },\n { x: 0, y: 1 },\n ],\n [\n { x: 0, y: 0 },\n { x: 1, y: 0 },\n { x: 0, y: 1 },\n ],\n [\n { x: 0, y: 0 },\n { x: 1, y: 0 },\n { x: 2, y: 0 },\n ],\n [\n { x: 0, y: 0 },\n { x: 0, y: 1 },\n { x: 1, y: 1 },\n ],\n]\n\nexport function fallingDirection(width: number, height: number): FallingDirection {\n return width > height ? 'horizontal' : 'vertical'\n}\n\nexport function fallingGrid(\n direction: FallingDirection,\n width = direction === 'horizontal' ? 12 : 3,\n height = direction === 'horizontal' ? 3 : 12,\n): { columns: number; rows: number } {\n const fieldWidth = Math.max(1, width * 0.8)\n const fieldHeight = Math.max(1, height * 0.8)\n const cellSize = Math.max(24, Math.min(42, Math.min(fieldWidth, fieldHeight) / 4))\n const columns = Math.max(3, Math.min(24, Math.round(fieldWidth / cellSize)))\n const rows = Math.max(3, Math.min(16, Math.round(fieldHeight / cellSize)))\n return direction === 'horizontal'\n ? { columns: Math.max(columns, rows), rows }\n : { columns, rows: Math.max(rows, columns) }\n}\n\nexport function shapeFits(shape: FallingCell[], columns: number, rows: number): boolean {\n const maxX = Math.max(...shape.map((cell) => cell.x))\n const maxY = Math.max(...shape.map((cell) => cell.y))\n return maxX < columns && maxY < rows\n}\n\nexport function overlaps(left: FallingShape, right: FallingShape): boolean {\n return left.cells.some((leftCell) =>\n right.cells.some(\n (rightCell) =>\n left.x + leftCell.x === right.x + rightCell.x &&\n left.y + leftCell.y === right.y + rightCell.y,\n ),\n )\n}\n\nexport function chooseShape(seed: number, columns: number, rows: number): FallingCell[] {\n const candidates = shapes.filter((shape) => shapeFits(shape, columns, rows))\n return candidates[randomIndex(seed, candidates.length)] ?? [{ x: 0, y: 0 }]\n}\n\nexport function findDestination(\n shape: FallingCell[],\n direction: FallingDirection,\n columns: number,\n rows: number,\n settled: readonly FallingShape[],\n seed = 0,\n requireSupported = false,\n): { x: number; y: number } | undefined {\n const width = Math.max(...shape.map((cell) => cell.x)) + 1\n const height = Math.max(...shape.map((cell) => cell.y)) + 1\n const candidates: Array<{ x: number; y: number; support: number }> = []\n for (let y = 0; y <= rows - height; y++) {\n for (let x = 0; x <= columns - width; x++) {\n const candidate = { id: -1, bornAt: 0, cells: shape, x, y, phase: 'settled' as const }\n if (settled.some((item) => overlaps(candidate, item))) continue\n if (!clearPath(shape, direction, columns, rows, candidate, settled)) continue\n const support =\n direction === 'vertical'\n ? shape.filter(\n (cell) =>\n y + cell.y === rows - 1 ||\n settled.some((item) =>\n item.cells.some(\n (other) =>\n item.x + other.x === x + cell.x && item.y + other.y === y + cell.y + 1,\n ),\n ),\n ).length\n : shape.filter(\n (cell) =>\n x + cell.x === 0 ||\n settled.some((item) =>\n item.cells.some(\n (other) =>\n item.x + other.x === x + cell.x - 1 && item.y + other.y === y + cell.y,\n ),\n ),\n ).length\n if (requireSupported && support < leadingEdgeCount(shape, direction)) continue\n candidates.push({ x, y, support })\n }\n }\n candidates.sort(\n (left, right) =>\n right.support - left.support ||\n (direction === 'vertical'\n ? right.y - left.y || left.x - right.x\n : left.x - right.x || left.y - right.y),\n )\n const bestSupport = candidates[0]?.support\n const best = candidates.filter((candidate) => candidate.support === bestSupport)\n const destination = best[randomIndex(seed, best.length)]\n return destination ? { x: destination.x, y: destination.y } : undefined\n}\n\nexport function findPlacement(\n direction: FallingDirection,\n columns: number,\n rows: number,\n settled: readonly FallingShape[],\n seed: number,\n requireSupported: boolean,\n): { shape: FallingCell[]; destination: { x: number; y: number } } | undefined {\n const candidates = shapes.flatMap((shape, index) => {\n if (!shapeFits(shape, columns, rows)) return []\n const destination = findDestination(\n shape,\n direction,\n columns,\n rows,\n settled,\n seed + index * 31,\n requireSupported,\n )\n return destination ? [{ shape, destination }] : []\n })\n if (candidates.length === 0) return undefined\n return candidates[randomIndex(seed, candidates.length)]\n}\n\nexport function targetCellCount(columns: number, rows: number, progress: number): number {\n return Math.ceil(columns * rows * FALLING_TARGET_FILL * Math.min(1, Math.max(0, progress)))\n}\n\nexport function occupiedCellCount(shapes: readonly FallingShape[]): number {\n return shapes.reduce((count, shape) => count + shape.cells.length, 0)\n}\n\nexport type LineClear = {\n shapes: FallingShape[]\n cleared: FallingCell[]\n complete: boolean\n}\n\n/** Clears only cells in the trailing edge line and slides the surviving field into it. */\nexport function clearTrailingLine(\n direction: FallingDirection,\n columns: number,\n rows: number,\n settled: readonly FallingShape[],\n allowPartial: boolean,\n): LineClear | undefined {\n const edgeLine = direction === 'vertical' ? rows - 1 : 0\n const occupied = new Set(\n settled.flatMap((item) =>\n item.cells\n .filter((cell) =>\n direction === 'vertical' ? item.y + cell.y === edgeLine : item.x + cell.x === edgeLine,\n )\n .map((cell) => (direction === 'vertical' ? item.x + cell.x : item.y + cell.y)),\n ),\n )\n const lineWidth = direction === 'vertical' ? columns : rows\n const complete = occupied.size === lineWidth\n if (!complete && !allowPartial) return undefined\n if (occupied.size === 0) return undefined\n\n const cleared: FallingCell[] = []\n const shapes = settled.flatMap((item) => {\n const remaining = item.cells.filter((cell) => {\n const onLine =\n direction === 'vertical' ? item.y + cell.y === edgeLine : item.x + cell.x === edgeLine\n if (onLine) {\n cleared.push({ x: item.x + cell.x, y: item.y + cell.y })\n }\n return !onLine\n })\n if (remaining.length === 0) return []\n return [\n {\n ...item,\n cells: remaining,\n y: direction === 'vertical' ? item.y + 1 : item.y,\n x: direction === 'horizontal' ? item.x - 1 : item.x,\n },\n ]\n })\n return { shapes, cleared, complete }\n}\n\nexport function buildStaticField(\n direction: FallingDirection,\n columns: number,\n rows: number,\n seed: number,\n count: number,\n): FallingShape[] {\n const settled: FallingShape[] = []\n for (let id = 0; id < count; id += 1) {\n const pieceSeed = seed + id * 17\n const shape = chooseShape(pieceSeed, columns, rows)\n const destination = findDestination(shape, direction, columns, rows, settled, pieceSeed + 1)\n if (!destination) break\n settled.push({\n id,\n bornAt: 0,\n cells: shape,\n x: destination.x,\n y: destination.y,\n phase: 'settled',\n })\n }\n return settled\n}\n\nfunction leadingEdgeCount(shape: FallingCell[], direction: FallingDirection): number {\n if (direction === 'vertical') {\n return new Set(shape.map((cell) => cell.x)).size\n }\n return new Set(shape.map((cell) => cell.y)).size\n}\n\nfunction clearPath(\n shape: FallingCell[],\n direction: FallingDirection,\n columns: number,\n rows: number,\n destination: FallingShape,\n settled: readonly FallingShape[],\n): boolean {\n const width = Math.max(...shape.map((cell) => cell.x)) + 1\n const height = Math.max(...shape.map((cell) => cell.y)) + 1\n if (direction === 'vertical') {\n for (let y = 0; y <= destination.y; y += 1) {\n if (settled.some((item) => overlaps({ ...destination, y }, item))) return false\n }\n return destination.y + height <= rows\n }\n for (let x = columns - width; x >= destination.x; x -= 1) {\n if (settled.some((item) => overlaps({ ...destination, x }, item))) return false\n }\n return destination.x + width <= columns\n}\n\nfunction randomIndex(seed: number, length: number): number {\n if (length <= 1) return 0\n const value = Math.sin(seed * 12.9898 + 78.233) * 43_758.5453\n return Math.floor((value - Math.floor(value)) * length)\n}\n","import type { CSSProperties } from 'react'\nimport { useEffect, useRef, useState } from 'react'\nimport styles from './FallingShapesField.module.css'\nimport {\n buildStaticField,\n clearTrailingLine,\n type FallingDirection,\n type FallingShape,\n fallingDirection,\n fallingGrid,\n findPlacement,\n occupiedCellCount,\n targetCellCount,\n} from './falling-shapes.ts'\n\nconst TICK_MS = 50\nconst PIECE_INTERVAL_MS = 1_250\nconst ENTRY_MS = 250\nconst TRAVEL_MS = 850\nconst RECYCLE_MS = 500\n\nexport function FallingShapesField({\n progress,\n estimatedDurationMs,\n overdue,\n seed = 0,\n}: {\n progress: number\n estimatedDurationMs?: number\n overdue: boolean\n seed?: number\n}) {\n const rootRef = useRef<HTMLDivElement>(null)\n const [geometry, setGeometry] = useState<{\n columns: number\n rows: number\n direction: FallingDirection\n }>({\n ...fallingGrid('vertical'),\n direction: 'vertical' as const,\n })\n const [pieces, setPieces] = useState<FallingShape[]>([])\n const [recycling, setRecycling] = useState(false)\n const [clearingCells, setClearingCells] = useState<{ x: number; y: number }[]>([])\n const [reducedMotion, setReducedMotion] = useState(false)\n const geometryRef = useRef(geometry)\n const previousGeometryRef = useRef(geometry)\n const progressRef = useRef(progress)\n const seedRef = useRef(seed)\n const directionRef = useRef<FallingDirection | undefined>(undefined)\n const piecesRef = useRef<FallingShape[]>([])\n const recyclingRef = useRef(false)\n const simulation = useRef({\n startedAt: Date.now(),\n nextPieceAt: PIECE_INTERVAL_MS,\n recycleUntil: 0,\n id: 0,\n settled: [] as FallingShape[],\n })\n\n useEffect(() => {\n progressRef.current = progress\n }, [progress])\n\n useEffect(() => {\n seedRef.current = seed\n }, [seed])\n\n useEffect(() => {\n const root = rootRef.current\n if (!root) return\n const update = () => {\n const rect = root.getBoundingClientRect()\n if (rect.width === 0 || rect.height === 0) return\n setGeometry((_current) => {\n const direction = directionRef.current ?? fallingDirection(rect.width, rect.height)\n directionRef.current = direction\n const next = { ...fallingGrid(direction, rect.width, rect.height), direction }\n geometryRef.current = next\n return next\n })\n }\n update()\n if (typeof ResizeObserver === 'undefined') return\n const observer = new ResizeObserver(update)\n observer.observe(root)\n return () => observer.disconnect()\n }, [])\n\n useEffect(() => {\n const media = window.matchMedia('(prefers-reduced-motion: reduce)')\n const update = () => setReducedMotion(media.matches)\n update()\n media.addEventListener?.('change', update)\n return () => media.removeEventListener?.('change', update)\n }, [])\n\n useEffect(() => {\n const previous = previousGeometryRef.current\n const changed =\n previous.direction !== geometry.direction ||\n previous.columns !== geometry.columns ||\n previous.rows !== geometry.rows\n previousGeometryRef.current = geometry\n if (!changed || reducedMotion) return\n simulation.current = {\n startedAt: Date.now(),\n nextPieceAt: PIECE_INTERVAL_MS,\n id: 0,\n recycleUntil: 0,\n settled: [],\n }\n piecesRef.current = []\n setPieces([])\n setRecycling(false)\n setClearingCells([])\n recyclingRef.current = false\n }, [geometry, reducedMotion])\n\n useEffect(() => {\n if (!reducedMotion) return\n const staticPieces = buildStaticField(\n geometry.direction,\n geometry.columns,\n geometry.rows,\n seedRef.current,\n Math.max(1, Math.floor(progressRef.current * 6)),\n )\n piecesRef.current = staticPieces\n simulation.current.settled = staticPieces\n setPieces(staticPieces)\n }, [geometry, reducedMotion])\n\n useEffect(() => {\n if (reducedMotion) return\n const timer = window.setInterval(() => {\n const state = simulation.current\n const elapsed = Date.now() - state.startedAt\n const currentGeometry = geometryRef.current\n const currentProgress = progressRef.current\n const target = targetCellCount(currentGeometry.columns, currentGeometry.rows, currentProgress)\n let next = [...state.settled]\n let active = piecesRef.current.filter((piece) => piece.phase !== 'settled')\n if (elapsed < state.recycleUntil) return\n if (recyclingRef.current) {\n recyclingRef.current = false\n setRecycling(false)\n setClearingCells([])\n }\n if (elapsed >= state.nextPieceAt && active.length === 0) {\n if (currentProgress < 1 && occupiedCellCount(next) >= target) {\n return\n }\n const id = state.id\n const pieceSeed = seedRef.current + id * 17\n const placement = findPlacement(\n currentGeometry.direction,\n currentGeometry.columns,\n currentGeometry.rows,\n next,\n pieceSeed + 1,\n !overdue,\n )\n if (!placement && (currentProgress >= 1 || estimatedDurationMs === undefined)) {\n const cleared = clearTrailingLine(\n currentGeometry.direction,\n currentGeometry.columns,\n currentGeometry.rows,\n next,\n true,\n )\n if (cleared) {\n next = cleared.shapes\n state.settled = next\n state.recycleUntil = elapsed + RECYCLE_MS\n state.nextPieceAt = state.recycleUntil\n piecesRef.current = next\n recyclingRef.current = true\n setClearingCells(cleared.cleared)\n setPieces(next)\n setRecycling(true)\n return\n }\n }\n if (placement) {\n state.id += 1\n const { shape, destination } = placement\n const height = Math.max(...shape.map((cell) => cell.y)) + 1\n active = [\n ...active,\n {\n id,\n bornAt: elapsed,\n cells: shape,\n x:\n currentGeometry.direction === 'horizontal'\n ? currentGeometry.columns - Math.max(...shape.map((cell) => cell.x)) - 0.5\n : destination.x,\n y: currentGeometry.direction === 'vertical' ? -height + 0.5 : destination.y,\n targetX: destination.x,\n targetY: destination.y,\n phase: 'entry',\n },\n ]\n }\n state.nextPieceAt += pieceInterval(estimatedDurationMs, currentGeometry)\n }\n active = active.map((piece) => {\n const age = elapsed - piece.bornAt\n const destination =\n piece.targetX === undefined || piece.targetY === undefined\n ? undefined\n : { x: piece.targetX, y: piece.targetY }\n if (!destination) return piece\n const amount = Math.min(1, Math.max(0, (age - ENTRY_MS) / TRAVEL_MS))\n if (amount >= 1) {\n next = [\n ...next,\n { ...piece, x: destination.x, y: destination.y, phase: 'settled' as const },\n ]\n return { ...piece, x: destination.x, y: destination.y, phase: 'settled' as const }\n }\n const startX =\n currentGeometry.direction === 'horizontal'\n ? currentGeometry.columns - Math.max(...piece.cells.map((cell) => cell.x)) - 1\n : destination.x\n const startY = currentGeometry.direction === 'vertical' ? 0 : destination.y\n const lifecycleAmount = Math.min(1, Math.max(0, age / (ENTRY_MS + TRAVEL_MS)))\n return {\n ...piece,\n x:\n currentGeometry.direction === 'horizontal'\n ? startX + (destination.x - startX) * amount\n : startX,\n y:\n currentGeometry.direction === 'vertical'\n ? startY + (destination.y - startY) * amount\n : startY,\n phase: age < ENTRY_MS ? 'entry' : lifecycleAmount < 0.35 ? 'align' : 'travel',\n }\n })\n state.settled = next\n const visible = [...next, ...active.filter((piece) => piece.phase !== 'settled')]\n piecesRef.current = visible\n setPieces(visible)\n }, TICK_MS)\n return () => window.clearInterval(timer)\n }, [estimatedDurationMs, overdue, reducedMotion])\n\n return (\n <div\n ref={rootRef}\n className={styles.field}\n data-running-part=\"falling-shapes-field\"\n data-overdue={overdue || undefined}\n data-direction={geometry.direction}\n data-recycling={recycling || undefined}\n style={\n { '--shape-columns': geometry.columns, '--shape-rows': geometry.rows } as CSSProperties\n }\n >\n <div className={styles.grid}>\n {clearingCells.map((cell) => (\n <span\n key={`${cell.x}-${cell.y}`}\n className={styles.clearingCell}\n style={{ '--clear-x': cell.x, '--clear-y': cell.y } as CSSProperties}\n />\n ))}\n {pieces.map((piece) => (\n <div\n key={piece.id}\n className={styles.piece}\n data-piece={piece.id}\n data-piece-phase={piece.phase}\n style={\n {\n '--piece-x': piece.x,\n '--piece-y': piece.y,\n '--piece-width': Math.max(...piece.cells.map((cell) => cell.x)) + 1,\n '--piece-height': Math.max(...piece.cells.map((cell) => cell.y)) + 1,\n } as CSSProperties\n }\n >\n {piece.cells.map((cell) => (\n <span\n key={`${cell.x}-${cell.y}`}\n className={styles.cell}\n style={{ '--cell-x': cell.x, '--cell-y': cell.y } as CSSProperties}\n />\n ))}\n </div>\n ))}\n </div>\n </div>\n )\n}\n\nfunction pieceInterval(\n estimatedDurationMs: number | undefined,\n geometry: { columns: number; rows: number },\n) {\n const target = Math.ceil(geometry.columns * geometry.rows * 0.85)\n if (estimatedDurationMs === undefined || target <= 0) return PIECE_INTERVAL_MS\n return Math.max(400, estimatedDurationMs / Math.max(1, Math.ceil(target / 3)))\n}\n",".frontier {\n position: absolute;\n inset: 0 auto 0 0;\n width: var(--running-progress);\n background: linear-gradient(\n 90deg,\n color-mix(in srgb, currentColor 16%, transparent),\n transparent\n );\n border-right: 1px solid color-mix(in srgb, currentColor 75%, transparent);\n}\n.now {\n position: absolute;\n top: 10%;\n bottom: 10%;\n left: 70%;\n width: 1px;\n background: color-mix(in srgb, var(--ink-primary) 45%, transparent);\n}\n.routes {\n position: absolute;\n inset: 18% 8%;\n display: grid;\n align-content: space-between;\n}\n.route {\n height: 1px;\n background: linear-gradient(\n 90deg,\n transparent,\n color-mix(in srgb, var(--ink-muted) 45%, transparent),\n transparent\n );\n}\n.route:nth-child(2) {\n transform: translateX(8%);\n}\n.route:nth-child(3) {\n transform: translateX(-6%);\n}\n.trail,\n.packet {\n position: absolute;\n top: 50%;\n left: -10%;\n border-radius: 999px;\n animation: packet 4.8s ease-in-out infinite alternate;\n}\n.trail {\n width: 18%;\n height: 2px;\n background: linear-gradient(90deg, transparent, currentColor);\n opacity: 0.65;\n}\n.packet {\n width: 0.48em;\n height: 0.48em;\n background: currentColor;\n box-shadow: 0 0 0.65em currentColor;\n}\n@container running-field (max-width: 40rem) {\n .routes,\n .trail,\n .packet,\n .now {\n display: none;\n }\n .frontier {\n width: 0.28em;\n border-right: 0;\n background: currentColor;\n }\n}\n[data-overdue=\"true\"] .frontier {\n width: 70%;\n background: linear-gradient(\n 90deg,\n color-mix(in srgb, currentColor 28%, transparent),\n transparent\n );\n}\n[data-overdue=\"true\"] .packet {\n left: 70%;\n animation: packet-stall 1.8s ease-in-out infinite alternate;\n}\n[data-overdue=\"true\"] .trail {\n left: 43%;\n width: 27%;\n animation: trail-backup 1.8s ease-in-out infinite alternate;\n}\n@keyframes packet {\n from {\n transform: translate(-10cqw, -50%);\n }\n to {\n transform: translate(120cqw, -50%);\n }\n}\n@keyframes packet-stall {\n from {\n transform: translate(-50%, -50%) scale(0.82);\n opacity: 0.72;\n }\n to {\n transform: translate(-50%, -50%) scale(1.12);\n opacity: 1;\n }\n}\n@keyframes trail-backup {\n from {\n transform: translate(-8%, -50%);\n opacity: 0.5;\n }\n to {\n transform: translate(8%, -50%);\n opacity: 0.95;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n [data-overdue=\"true\"] .trail,\n [data-overdue=\"true\"] .packet,\n .trail,\n .packet {\n animation: none;\n }\n .frontier {\n transition: none;\n }\n}\n","import styles from './ReleaseTransitField.module.css'\n\nexport function ReleaseTransitField() {\n return (\n <>\n <span className={styles.frontier} data-running-part=\"frontier\" />\n <span className={styles.now} data-running-part=\"transit-now\" />\n <span className={styles.routes} data-running-part=\"transit-routes\">\n {[0, 1, 2].map((route) => (\n <span className={styles.route} key={route} />\n ))}\n </span>\n <span className={styles.trail} data-running-part=\"transit-trail\" />\n <span className={styles.packet} data-running-part=\"transit-packet\" />\n </>\n )\n}\n",".field {\n position: absolute;\n z-index: 0;\n inset: 0;\n overflow: hidden;\n pointer-events: none;\n container-type: size;\n container-name: running-field;\n color: var(--status-warning);\n}\n.overdue {\n color: var(--status-serious);\n}\n.timing {\n width: min(12ch, 100%);\n max-width: 100%;\n min-width: 0;\n flex: 0 1 12ch;\n margin: 0;\n color: var(--ink-secondary);\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 0.72em;\n font-variant-numeric: tabular-nums;\n text-align: end;\n white-space: nowrap;\n overflow: hidden;\n}\n.timingOverdue {\n color: var(--status-serious);\n}\n",".field {\n position: absolute;\n inset: 0;\n overflow: hidden;\n contain: layout paint;\n}\n.canvas {\n display: block;\n width: 100%;\n height: 100%;\n}\n","export type SnowmanScheduleMode = 'snowfall' | 'arrival' | 'hop' | 'full'\n\nexport type SnowmanSchedule = {\n mode: SnowmanScheduleMode\n bodyStart: number\n bodyEnd: number\n headStart: number\n hopStart: number\n land: number\n settleEnd: number\n end: number\n}\n\n/** Derive one deterministic choreography from the complete expected run duration. */\nexport function snowmanSchedule(duration: number): SnowmanSchedule {\n const bodyWindow = duration * 0.25\n const headWindow = duration * 0.2\n const mode: SnowmanScheduleMode =\n bodyWindow < 700 || headWindow < 350\n ? 'snowfall'\n : headWindow < 530\n ? 'arrival'\n : headWindow < 1030\n ? 'hop'\n : 'full'\n const scale = clamp(\n (headWindow - (mode === 'full' ? 1030 : 530)) / (mode === 'full' ? 1620 : 620),\n 0,\n 1,\n )\n const roll = mode === 'full' ? 500 + 1000 * scale : 0\n const tail = mode === 'arrival' ? 0 : 180 + 70 * scale\n const hop = mode === 'arrival' ? Math.min(900, headWindow) : 350 + 550 * scale\n const end = duration * 0.95\n const land = end - tail\n return {\n mode,\n bodyStart: duration * 0.75 - Math.min(2500, bodyWindow),\n bodyEnd: duration * 0.75,\n headStart: land - hop - roll,\n hopStart: land - hop,\n land,\n settleEnd: land + (tail ? 120 + 60 * scale : 0),\n end,\n }\n}\n\nexport function scheduleAmount(time: number, start: number, end: number) {\n return end === start ? Number(time >= end) : clamp((time - start) / (end - start), 0, 1)\n}\n\nexport function smoothScheduleAmount(value: number) {\n return value * value * (3 - 2 * value)\n}\n\nfunction clamp(value: number, low: number, high: number) {\n return Math.max(low, Math.min(high, value))\n}\n","export type SnowmanPhase = 'drift' | 'snowing' | 'assembling' | 'complete' | 'overdue'\nexport type SnowCellOwner = 'ground' | 'body' | 'head' | 'snowman'\nexport type SnowmanDimensions = { width: number; height: number }\n\nexport type SnowCell = {\n id: number\n x: number\n y: number\n owner: SnowCellOwner\n /** Coordinates relative to a rolling ball. Ground and accumulated snow omit these. */\n localX?: number\n localY?: number\n targetLocalX?: number\n targetLocalY?: number\n packed?: boolean\n}\nexport type AirborneFlake = { id: number; x: number; y: number; bornAt: number }\nexport type Snowball = {\n kind: 'body' | 'head'\n x: number\n y: number\n radius: number\n angle: number\n /** A placed ball no longer follows the relaxing terrain beneath it. */\n locked: boolean\n /** The final support position captured when the body locks. */\n supportY?: number\n launch?: { x: number; y: number }\n}\nexport type SnowmanSimulation = {\n nextAt: number\n id: number\n lastElapsed: number\n grid: { columns: number; rows: number }\n flakes: AirborneFlake[]\n cells: SnowCell[]\n body?: Snowball\n head?: Snowball\n toppling?: { startedAt: number; angle: number; pivotX: number; pivotY: number }\n toppled: boolean\n hat?: { x: number; y: number; angle: number }\n}\n\nexport { snowmanSchedule } from './snowman-timing.ts'\n\nimport {\n scheduleAmount as amount,\n smoothScheduleAmount as ease,\n snowmanSchedule,\n} from './snowman-timing.ts'\n\nconst STEP_MS = 25\nconst ASSEMBLY_START = 0.5\nconst HAT_AT = 0.95\n/** Attached snowfall at which the completed decorative figure falls and stays down. */\nexport const SNOWMAN_TOPPLE_LOAD = 60\n\nexport function createSnowmanSimulation(\n dimensions: SnowmanDimensions = { width: 360, height: 180 },\n): SnowmanSimulation {\n return {\n nextAt: 0,\n id: 0,\n lastElapsed: 0,\n grid: snowmanGrid(dimensions),\n flakes: [],\n cells: [],\n toppled: false,\n }\n}\n\nexport function snowmanGrid(dimensions: SnowmanDimensions) {\n // Four device-independent pixels gives fine grain without making a compact field expensive.\n const columns = clamp(Math.round(dimensions.width / 4), 48, 180)\n const rows = clamp(Math.round(dimensions.height / 4), 28, 100)\n return { columns, rows }\n}\n\nexport function snowmanScenePhase(\n progress: number,\n estimatedDurationMs: number | undefined,\n overdue: boolean,\n): SnowmanPhase {\n if (overdue) return 'overdue'\n if (estimatedDurationMs === undefined) return 'snowing'\n if (snowmanSchedule(estimatedDurationMs).mode === 'snowfall') return 'snowing'\n if (progress >= HAT_AT) return 'complete'\n if (progress >= ASSEMBLY_START) return 'assembling'\n return 'drift'\n}\n\n/** A permanent slight breeze plus seed-stable, visibly stronger intermittent gusts. */\nexport function snowmanWind(seed: number, elapsed: number) {\n const direction = random(seed + 41) < 0.5 ? -1 : 1\n const breeze = direction * (0.72 + random(seed + 43) * 0.45)\n const smallVariation = Math.sin(elapsed / 1_600 + random(seed + 47) * Math.PI * 2) * 0.4\n const gustWave = Math.max(0, Math.sin(elapsed / 3_100 + random(seed + 53) * Math.PI * 2))\n const gust = direction * gustWave ** 7 * (3.2 + random(seed + 59) * 1.8)\n return breeze + smallVariation + gust\n}\n\nexport function snowmanMaterialCount(dimensions: SnowmanDimensions) {\n const grid = snowmanGrid(dimensions)\n return Math.round(grid.columns * grid.rows * 0.18)\n}\n\nexport function snowmanSpawnInterval(\n estimatedDurationMs: number | undefined,\n dimensions: SnowmanDimensions,\n overdue = false,\n elapsed = 0,\n) {\n if (estimatedDurationMs === undefined) return overdue ? 30 : 60\n const ordinary = (estimatedDurationMs * HAT_AT) / snowmanMaterialCount(dimensions)\n if (overdue) return ordinary / 2\n const schedule = snowmanSchedule(estimatedDurationMs)\n if (schedule.mode !== 'snowfall' && elapsed >= Math.max(0, schedule.bodyStart - 500)) {\n return ordinary * 4\n }\n return ordinary\n}\n\n/** Advances a fixed-step cellular snow simulation without reading the DOM or a browser clock. */\nexport function advanceSnowmanSimulation(\n previous: SnowmanSimulation,\n {\n elapsed,\n progress,\n estimatedDurationMs,\n overdue,\n seed,\n dimensions,\n }: {\n elapsed: number\n progress: number\n estimatedDurationMs?: number\n overdue: boolean\n seed: number\n dimensions: SnowmanDimensions\n },\n): SnowmanSimulation {\n const grid = snowmanGrid(dimensions)\n let simulation =\n previous.grid.columns === grid.columns && previous.grid.rows === grid.rows\n ? clone(previous)\n : createSnowmanSimulation(dimensions)\n const targetElapsed = Math.max(simulation.lastElapsed, elapsed)\n for (let time = simulation.lastElapsed + STEP_MS; time <= targetElapsed; time += STEP_MS) {\n simulation = step(\n simulation,\n time,\n estimatedDurationMs === undefined ? progress : time / estimatedDurationMs,\n estimatedDurationMs,\n overdue && (estimatedDurationMs === undefined || time >= estimatedDurationMs),\n seed,\n dimensions,\n )\n simulation.lastElapsed = time\n }\n return simulation\n}\n\nexport function snowmanLoad(cells: readonly SnowCell[]) {\n return cells.filter((cell) => cell.owner === 'snowman').length\n}\n\nexport function resolvedCells(simulation: SnowmanSimulation) {\n return simulation.cells.map((cell) => {\n const ball =\n cell.owner === 'body' ? simulation.body : cell.owner === 'head' ? simulation.head : undefined\n const resolved =\n ball && cell.localX !== undefined && cell.localY !== undefined\n ? {\n ...cell,\n x: ball.x + cell.localX * Math.cos(ball.angle) - cell.localY * Math.sin(ball.angle),\n y: ball.y + cell.localX * Math.sin(ball.angle) + cell.localY * Math.cos(ball.angle),\n }\n : cell\n return simulation.toppling && resolved.owner !== 'ground'\n ? rotateAround(resolved, simulation.toppling)\n : resolved\n })\n}\n\nexport function resolvedBallCenter(simulation: SnowmanSimulation, ball: Snowball) {\n return simulation.toppling ? rotateAround(ball, simulation.toppling) : ball\n}\n\nfunction step(\n simulation: SnowmanSimulation,\n elapsed: number,\n progress: number,\n estimatedDurationMs: number | undefined,\n overdue: boolean,\n seed: number,\n dimensions: SnowmanDimensions,\n) {\n const phase = snowmanScenePhase(progress, estimatedDurationMs, overdue)\n const interval = snowmanSpawnInterval(estimatedDurationMs, dimensions, overdue, elapsed)\n while (elapsed >= simulation.nextAt) {\n simulation.flakes.push({\n id: simulation.id++,\n x: random(seed + simulation.id * 17) * simulation.grid.columns,\n y: -1 - random(seed + simulation.id * 23) * 6,\n bornAt: simulation.nextAt,\n })\n simulation.nextAt += interval\n }\n\n updateBalls(simulation, progress, estimatedDurationMs, overdue)\n const occupied = occupiedCells(simulation)\n const wind = snowmanWind(seed, elapsed) * (STEP_MS / 1_000)\n const fall =\n estimatedDurationMs === undefined\n ? 0.52\n : Math.max(0.52, ((simulation.grid.rows + 7) * STEP_MS) / (estimatedDurationMs * 0.25))\n const nextFlakes: AirborneFlake[] = []\n for (const flake of simulation.flakes) {\n const moved = { ...flake, x: flake.x + wind, y: flake.y + fall }\n const ball = hitBall(simulation, moved)\n if (ball) {\n joinBall(simulation, ball, flake.id, moved.x - ball.x, moved.y - ball.y)\n continue\n }\n const resting = findRestingCell(moved, occupied, simulation.grid, wind, seed)\n if (!resting) {\n nextFlakes.push({ ...moved, x: clamp(moved.x, 0, simulation.grid.columns - 1) })\n continue\n }\n const belowOwner = occupied.get(key(resting.x, resting.y + 1))\n simulation.cells.push({\n id: flake.id,\n x: resting.x,\n y: resting.y,\n owner:\n belowOwner === 'body' || belowOwner === 'head' || belowOwner === 'snowman'\n ? 'snowman'\n : 'ground',\n })\n occupied.set(key(resting.x, resting.y), simulation.cells.at(-1)?.owner ?? 'ground')\n }\n simulation.flakes = nextFlakes\n if (estimatedDurationMs !== undefined && phase !== 'drift' && phase !== 'snowing')\n collectTouchedGround(simulation)\n compactBallCells(simulation)\n // A small cascade closes a swept gap promptly without making the whole bank flow at once.\n relaxSettledSnow(simulation, seed, elapsed)\n relaxSettledSnow(simulation, seed, elapsed + STEP_MS / 2)\n const body = simulation.body\n if (body?.locked) {\n body.supportY ??= restingBallY(simulation, body.x, body.radius, body.y + body.radius)\n body.y = body.supportY\n }\n if (\n overdue &&\n !simulation.toppling &&\n !simulation.toppled &&\n snowmanLoad(simulation.cells) >= SNOWMAN_TOPPLE_LOAD\n )\n beginTopple(simulation, elapsed)\n advanceTopple(simulation, elapsed)\n return simulation\n}\n\nfunction updateBalls(\n simulation: SnowmanSimulation,\n progress: number,\n estimatedDurationMs: number | undefined,\n _overdue: boolean,\n) {\n if (estimatedDurationMs === undefined) return\n const schedule = snowmanSchedule(estimatedDurationMs)\n if (schedule.mode === 'snowfall') return\n const time = progress * estimatedDurationMs\n const { columns, rows } = simulation.grid\n const bodyAmount = ease(amount(time, schedule.bodyStart, schedule.bodyEnd))\n if (time >= schedule.bodyStart && !simulation.body) {\n const x = columns * 0.14\n simulation.body = {\n kind: 'body',\n x,\n y: restingBallY(simulation, x, 2, rows - 1),\n radius: 2,\n angle: 0,\n locked: false,\n }\n }\n const body = simulation.body\n if (body && !body.locked) {\n body.radius = Math.max(body.radius, ballRadius(simulation, 'body', 2))\n const x = columns * (0.14 + 0.38 * bodyAmount)\n rollBallTo(body, x, restingBallY(simulation, x, body.radius, rows - 1))\n body.locked = time >= schedule.bodyEnd\n }\n if (time >= schedule.headStart && !simulation.head) {\n const x = columns * (schedule.mode === 'full' ? 0.88 : 0.66)\n simulation.head = {\n kind: 'head',\n x,\n y: restingBallY(simulation, x, 1.7, rows - 1),\n radius: 1.7,\n angle: 0,\n locked: false,\n }\n collectTouchedGround(simulation)\n }\n const head = simulation.head\n if (head && body && !head.locked) {\n head.radius = Math.max(head.radius, ballRadius(simulation, 'head', 1.7))\n if (time < schedule.hopStart) {\n const rolling = ease(amount(time, schedule.headStart, schedule.hopStart))\n const x = columns * (0.88 - 0.22 * rolling)\n rollBallTo(head, x, restingBallY(simulation, x, head.radius, rows - 1))\n } else {\n head.launch ??= { x: head.x, y: head.y }\n const hop = amount(time, schedule.hopStart, schedule.land)\n const seatY = body.y - body.radius - head.radius + 0.5\n head.x = head.launch.x + (body.x - head.launch.x) * ease(hop)\n head.y =\n head.launch.y +\n (seatY - head.launch.y) * ease(hop) -\n Math.sin(Math.PI * hop) * Math.max(5, body.radius * 1.5)\n if (time >= schedule.land) {\n const settle = amount(time, schedule.land, schedule.settleEnd)\n head.y += Math.sin(Math.PI * settle) * 0.45\n }\n head.locked = time >= schedule.settleEnd\n }\n }\n if (head && time >= schedule.land) {\n const drop = amount(time, schedule.land, schedule.end)\n simulation.hat = {\n x: head.x,\n y: head.y - head.radius - 1 - 5 * (1 - drop * drop),\n angle: (1 - ease(drop)) * -0.22,\n }\n }\n}\n\nfunction rollBallTo(ball: Snowball, x: number, y: number) {\n const nextY = moveToward(ball.y, y, 0.16)\n const dx = x - ball.x\n ball.angle += (Math.sign(dx) * Math.hypot(dx, nextY - ball.y)) / Math.max(ball.radius, 1)\n ball.x = x\n ball.y = nextY\n}\n\nfunction collectTouchedGround(simulation: SnowmanSimulation) {\n const resolved = resolvedCells(simulation)\n const originals = new Map(simulation.cells.map((cell) => [cell.id, cell]))\n const groundCoordinates = new Set(\n resolved\n .filter((cell) => cell.owner === 'ground')\n .map((cell) => key(Math.round(cell.x), Math.round(cell.y))),\n )\n const exposedGround = new Set(\n resolved\n .filter((cell) => cell.owner === 'ground')\n .filter((cell) => !groundCoordinates.has(key(Math.round(cell.x), Math.round(cell.y) - 1)))\n .map((cell) => cell.id),\n )\n for (const ball of [simulation.body, simulation.head]) {\n if (!ball || ball.locked) continue\n const owner = ball.kind\n const captureRadius = ball.radius + 0.75\n for (const cell of resolved) {\n if (!canCollect(simulation, ball)) break\n if (cell.owner !== 'ground') continue\n const dx = cell.x - ball.x\n const dy = cell.y - ball.y\n const distance = Math.hypot(dx, dy)\n // The roller takes only exposed grains on its lower, leading contact arc. Capturing buried\n // cells makes the ball appear to hook loose snow into the air behind it.\n if (!exposedGround.has(cell.id) || distance > captureRadius || dy < -ball.radius * 0.2)\n continue\n const original = originals.get(cell.id)\n if (!original) continue\n joinBall(simulation, ball, original.id, dx, dy)\n }\n ball.radius = Math.max(\n ball.radius,\n ballRadius(simulation, owner, ball.kind === 'body' ? 2 : 1.7),\n )\n }\n}\n\nfunction canCollect(simulation: SnowmanSimulation, ball: Snowball) {\n if (ball.kind === 'body' || !simulation.body) return true\n const bodyRadius = simulation.body.radius\n const targetHeadRadius = bodyRadius * 0.72\n const maxHeadCount = Math.max(\n 12,\n Math.round(Math.PI * (Math.max(0, targetHeadRadius - 1.7) / 0.6) ** 2),\n )\n return simulation.cells.filter((cell) => cell.owner === 'head').length < maxHeadCount\n}\n\nfunction hitBall(simulation: SnowmanSimulation, flake: AirborneFlake) {\n const candidates = [simulation.body, simulation.head].filter(\n (ball): ball is Snowball => ball !== undefined && !ball.locked,\n )\n return candidates.find(\n (ball) =>\n canCollect(simulation, ball) && Math.hypot(flake.x - ball.x, flake.y - ball.y) <= ball.radius,\n )\n}\n\nfunction joinBall(\n simulation: SnowmanSimulation,\n ball: Snowball,\n id: number,\n localX: number,\n localY: number,\n) {\n const cosine = Math.cos(-ball.angle)\n const sine = Math.sin(-ball.angle)\n const rotatedX = localX * cosine - localY * sine\n localY = localX * sine + localY * cosine\n localX = rotatedX\n const cell = simulation.cells.find((candidate) => candidate.id === id)\n const target = ballInteriorSlot(simulation, ball, id)\n const start = openBallPosition(simulation, ball, localX, localY, id)\n const next = {\n id,\n x: ball.x + start.x,\n y: ball.y + start.y,\n owner: ball.kind,\n localX: start.x,\n localY: start.y,\n targetLocalX: target.x,\n targetLocalY: target.y,\n }\n if (cell) Object.assign(cell, next)\n else simulation.cells.push(next)\n ball.radius = Math.max(\n ball.radius,\n ballRadius(simulation, ball.kind, ball.kind === 'body' ? 2 : 1.7),\n )\n rebalanceBallTargets(simulation, ball)\n}\n\nfunction openBallPosition(\n simulation: SnowmanSimulation,\n ball: Snowball,\n localX: number,\n localY: number,\n id: number,\n) {\n const cells = simulation.cells.filter((cell) => cell.id !== id && cell.owner === ball.kind)\n const free = (x: number, y: number) =>\n cells.every((cell) => Math.hypot((cell.localX ?? 0) - x, (cell.localY ?? 0) - y) >= 0.75)\n if (free(localX, localY)) return { x: localX, y: localY }\n // Search outward from the contact, retaining already packed grains in their material frame.\n for (let radius = 0.75; ; radius += 0.75) {\n for (let i = 0; i < 32; i++) {\n const angle = (i * Math.PI) / 16\n const x = localX + Math.cos(angle) * radius\n const y = localY + Math.sin(angle) * radius\n if ((Math.hypot(x, y) <= ball.radius + 0.75 || radius > ball.radius * 2) && free(x, y)) {\n ball.radius = Math.max(ball.radius, Math.hypot(x, y) - 0.5)\n return { x, y }\n }\n }\n }\n}\n\nfunction ballInteriorSlot(simulation: SnowmanSimulation, ball: Snowball, id: number) {\n const existing = simulation.cells.filter(\n (cell) =>\n cell.owner === ball.kind &&\n cell.targetLocalX !== undefined &&\n cell.targetLocalY !== undefined,\n )\n const free = (x: number, y: number, minDistance = 0.72) =>\n existing.every(\n (cell) =>\n Math.hypot((cell.targetLocalX ?? 0) - x, (cell.targetLocalY ?? 0) - y) >= minDistance,\n )\n for (let attempt = 0; attempt < 64; attempt += 1) {\n const angle = random(id * 31 + attempt * 17) * Math.PI * 2\n const distance = Math.sqrt(random(id * 37 + attempt * 19)) * Math.max(0.4, ball.radius - 0.35)\n const x = Math.cos(angle) * distance\n const y = Math.sin(angle) * distance\n if (free(x, y)) return { x, y }\n }\n for (let radius = 0.4; radius <= ball.radius - 0.35; radius += 0.5) {\n const steps = Math.max(6, Math.round((2 * Math.PI * radius) / 0.72))\n for (let i = 0; i < steps; i++) {\n const angle = (i * Math.PI * 2) / steps + random(id * 13)\n const x = Math.cos(angle) * radius\n const y = Math.sin(angle) * radius\n if (free(x, y, 0.6)) return { x, y }\n }\n }\n return { x: 0, y: 0 }\n}\n\nfunction compactBallCells(simulation: SnowmanSimulation) {\n for (const cell of simulation.cells) {\n if (\n cell.packed ||\n cell.localX === undefined ||\n cell.localY === undefined ||\n cell.targetLocalX === undefined ||\n cell.targetLocalY === undefined\n )\n continue\n const x = moveToward(cell.localX, cell.targetLocalX, 0.25)\n const y = moveToward(cell.localY, cell.targetLocalY, 0.25)\n cell.localX = x\n cell.localY = y\n cell.packed = x === cell.targetLocalX && y === cell.targetLocalY\n }\n}\n\n/** Reassigns the material to a dense lattice so newly collected snow compresses older grains. */\nfunction rebalanceBallTargets(simulation: SnowmanSimulation, ball: Snowball) {\n const cells = simulation.cells.filter(\n (cell) => cell.owner === ball.kind && cell.localX !== undefined && cell.localY !== undefined,\n )\n const slots = denseBallSlots(ball.radius, cells.length)\n cells.sort((first, second) => first.id - second.id)\n for (const [index, cell] of cells.entries()) {\n const slot = slots[index]\n if (!slot) break\n cell.targetLocalX = slot.x\n cell.targetLocalY = slot.y\n cell.packed = false\n }\n}\n\nfunction denseBallSlots(radius: number, count: number) {\n const boundary = Math.max(0.2, radius - 0.1)\n const candidates: Array<{ x: number; y: number }> = []\n const spacing = 0.9\n const vertical = (spacing * Math.sqrt(3)) / 2\n for (let row = -Math.ceil(boundary / vertical); row <= Math.ceil(boundary / vertical); row += 1) {\n const y = row * vertical\n const offset = (row & 1) === 0 ? 0 : spacing / 2\n for (\n let column = -Math.ceil(boundary / spacing);\n column <= Math.ceil(boundary / spacing);\n column += 1\n ) {\n const x = column * spacing + offset\n if (Math.hypot(x, y) <= boundary) candidates.push({ x, y })\n }\n }\n candidates.sort((first, second) => Math.hypot(first.x, first.y) - Math.hypot(second.x, second.y))\n const slots: Array<{ x: number; y: number }> = []\n for (const candidate of candidates) {\n if (slots.every((slot) => Math.hypot(slot.x - candidate.x, slot.y - candidate.y) >= 0.82))\n slots.push(candidate)\n if (slots.length === count) break\n }\n return slots\n}\n\nexport function resolvedHat(simulation: SnowmanSimulation) {\n if (!simulation.hat) return undefined\n return simulation.toppling\n ? {\n ...rotateAround(simulation.hat, simulation.toppling),\n angle: simulation.hat.angle + simulation.toppling.angle,\n }\n : simulation.hat\n}\n\n/** Interpolate presentation only; particle identities and physics remain on the fixed clock. */\nexport function interpolateSnowman(\n previous: SnowmanSimulation,\n next: SnowmanSimulation,\n fraction: number,\n) {\n const scene = clone(next)\n const mix = (a: number, b: number) => a + (b - a) * clamp(fraction, 0, 1)\n for (const kind of ['body', 'head'] as const) {\n const a = previous[kind],\n b = scene[kind]\n if (a && b) {\n b.x = mix(a.x, b.x)\n b.y = mix(a.y, b.y)\n b.angle = mix(a.angle, b.angle)\n }\n }\n const oldFlakes = new Map(previous.flakes.map((flake) => [flake.id, flake]))\n for (const flake of scene.flakes) {\n const old = oldFlakes.get(flake.id)\n if (old) {\n flake.x = mix(old.x, flake.x)\n flake.y = mix(old.y, flake.y)\n }\n }\n if (scene.toppling && previous.toppling)\n scene.toppling.angle = mix(previous.toppling.angle, scene.toppling.angle)\n if (scene.hat && previous.hat)\n scene.hat = {\n x: mix(previous.hat.x, scene.hat.x),\n y: mix(previous.hat.y, scene.hat.y),\n angle: mix(previous.hat.angle, scene.hat.angle),\n }\n return scene\n}\n\nfunction occupiedCells(simulation: SnowmanSimulation) {\n const occupied = new Map<string, SnowCellOwner>()\n for (const cell of resolvedCells(simulation))\n occupied.set(key(Math.round(cell.x), Math.round(cell.y)), cell.owner)\n return occupied\n}\n\n/** Lets a settled bank creep into a newly cleared trench instead of preserving impossible voids. */\nfunction relaxSettledSnow(simulation: SnowmanSimulation, seed: number, elapsed: number) {\n const occupied = occupiedCells(simulation)\n const ground = simulation.cells\n .filter((cell) => cell.owner === 'ground')\n .sort((first, second) => second.y - first.y || first.x - second.x)\n for (const cell of ground) {\n const below = key(cell.x, cell.y + 1)\n if (cell.y < simulation.grid.rows - 1 && !occupied.has(below)) {\n occupied.delete(key(cell.x, cell.y))\n cell.y += 1\n occupied.set(key(cell.x, cell.y), cell.owner)\n continue\n }\n const preferred = random(seed + cell.id * 29 + elapsed) < 0.5 ? -1 : 1\n for (const direction of [preferred, -preferred]) {\n const x = cell.x + direction\n if (\n x < 0 ||\n x >= simulation.grid.columns ||\n cell.y >= simulation.grid.rows - 1 ||\n occupied.has(key(x, cell.y)) ||\n occupied.has(key(x, cell.y + 1))\n )\n continue\n occupied.delete(key(cell.x, cell.y))\n cell.x = x\n cell.y += 1\n occupied.set(key(cell.x, cell.y), cell.owner)\n break\n }\n }\n}\n\nfunction findRestingCell(\n flake: AirborneFlake,\n occupied: Map<string, SnowCellOwner>,\n grid: SnowmanSimulation['grid'],\n wind: number,\n seed: number,\n) {\n const x = Math.round(flake.x)\n const y = Math.round(flake.y)\n if (y < 0) return undefined\n if (y >= grid.rows - 1) return { x, y: grid.rows - 1 }\n if (!occupied.has(key(x, y + 1))) return undefined\n const preferred = wind >= 0 ? 1 : -1\n const alternate = random(seed + flake.id * 71 + y) > 0.5 ? preferred : -preferred\n for (const offset of [alternate, -alternate]) {\n const side = x + offset\n if (\n side >= 0 &&\n side < grid.columns &&\n !occupied.has(key(side, y + 1)) &&\n !occupied.has(key(side, y))\n )\n return { x: side, y: y + 1 }\n }\n return occupied.has(key(x, y)) ? { x, y: Math.max(0, y - 1) } : { x, y }\n}\n\nfunction restingBallY(simulation: SnowmanSimulation, x: number, radius: number, fallback: number) {\n const cells = resolvedCells(simulation).filter(\n (cell) => cell.owner === 'ground' && Math.abs(cell.x - x) <= radius,\n )\n const surface = cells.length ? Math.min(...cells.map((cell) => cell.y)) : fallback\n return surface - radius\n}\nfunction ballRadius(simulation: SnowmanSimulation, owner: 'body' | 'head', minimum: number) {\n const count = simulation.cells.filter((cell) => cell.owner === owner).length\n return minimum + Math.sqrt(count / Math.PI) * 0.5\n}\nfunction beginTopple(simulation: SnowmanSimulation, elapsed: number) {\n const body = simulation.body\n if (!body) return\n simulation.toppling = {\n startedAt: elapsed,\n angle: 0,\n pivotX: body.x,\n pivotY: body.y + body.radius * 0.72,\n }\n}\n\nfunction advanceTopple(simulation: SnowmanSimulation, elapsed: number) {\n const toppling = simulation.toppling\n if (!toppling) return\n const progress = clamp((elapsed - toppling.startedAt) / 750, 0, 1)\n // Ease-in keeps the initial loss of balance readable; ease-out lets the body settle rather than snap.\n toppling.angle = (1 - (1 - progress) ** 3) * (Math.PI / 2)\n if (progress === 1) simulation.toppled = true\n}\n\nfunction rotateAround<T extends { x: number; y: number }>(\n point: T,\n toppling: NonNullable<SnowmanSimulation['toppling']>,\n) {\n const cosine = Math.cos(toppling.angle)\n const sine = Math.sin(toppling.angle)\n const x = point.x - toppling.pivotX\n const y = point.y - toppling.pivotY\n return {\n ...point,\n x: toppling.pivotX + x * cosine - y * sine,\n y: toppling.pivotY + x * sine + y * cosine,\n }\n}\nfunction clone(simulation: SnowmanSimulation): SnowmanSimulation {\n return {\n ...simulation,\n grid: { ...simulation.grid },\n hat: simulation.hat && { ...simulation.hat },\n flakes: simulation.flakes.map((flake) => ({ ...flake })),\n cells: simulation.cells.map((cell) => ({ ...cell })),\n body: simulation.body && { ...simulation.body },\n head: simulation.head && { ...simulation.head },\n toppling: simulation.toppling && { ...simulation.toppling },\n }\n}\nfunction key(x: number, y: number) {\n return `${x}:${y}`\n}\nfunction clamp(value: number, low: number, high: number) {\n return Math.max(low, Math.min(high, value))\n}\nfunction moveToward(current: number, target: number, maximumStep: number) {\n if (Math.abs(target - current) <= maximumStep) return target\n return current + Math.sign(target - current) * maximumStep\n}\nfunction random(value: number) {\n const sine = Math.sin(value * 12.9898) * 43758.5453\n return sine - Math.floor(sine)\n}\n","import { resolvedCells, resolvedHat, type SnowmanSimulation } from './snowman.ts'\n\nexport function drawSnowmanCanvas(\n canvas: HTMLCanvasElement | null,\n simulation: SnowmanSimulation,\n dimensions: { width: number; height: number },\n) {\n if (!canvas) return\n const context = canvas.getContext('2d')\n if (!context) return\n const scale = window.devicePixelRatio || 1\n const width = Math.max(1, Math.round(dimensions.width))\n const height = Math.max(1, Math.round(dimensions.height))\n if (canvas.width !== width * scale || canvas.height !== height * scale) {\n canvas.width = width * scale\n canvas.height = height * scale\n canvas.style.width = `${width}px`\n canvas.style.height = `${height}px`\n }\n context.setTransform(scale, 0, 0, scale, 0, 0)\n context.clearRect(0, 0, width, height)\n const cellWidth = width / simulation.grid.columns\n const cellHeight = height / simulation.grid.rows\n context.fillStyle = 'rgba(244, 241, 223, 0.52)'\n for (const cell of resolvedCells(simulation))\n drawDot(context, (cell.x + 0.5) * cellWidth, (cell.y + 0.5) * cellHeight, cellWidth, cellHeight)\n context.fillStyle = 'rgba(244, 241, 223, 0.76)'\n for (const flake of simulation.flakes)\n drawDot(\n context,\n (flake.x + 0.5) * cellWidth,\n (flake.y + 0.5) * cellHeight,\n cellWidth * 0.72,\n cellHeight * 0.72,\n )\n const hat = resolvedHat(simulation)\n if (hat && simulation.head) {\n const radius = simulation.head.radius\n context.save()\n context.translate(hat.x * cellWidth, hat.y * cellHeight)\n context.scale(cellWidth, cellHeight)\n context.rotate(hat.angle)\n context.fillStyle = 'rgba(27, 31, 24, 0.78)'\n context.fillRect(-radius * 0.65, -2, radius * 1.3, 2)\n context.fillRect(-radius, -0.3, radius * 2, 0.45)\n context.restore()\n }\n}\n\nfunction drawDot(\n context: CanvasRenderingContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n) {\n context.beginPath()\n context.arc(x, y, Math.max(0.8, Math.min(width, height) * 0.42), 0, Math.PI * 2)\n context.fill()\n}\n","import { useEffect, useRef, useState } from 'react'\nimport styles from './SnowmanField.module.css'\nimport {\n advanceSnowmanSimulation,\n createSnowmanSimulation,\n interpolateSnowman,\n snowmanScenePhase,\n} from './snowman.ts'\nimport { drawSnowmanCanvas } from './snowman-canvas.ts'\n\n/** A dense, seeded canvas snow scene. It remains decorative and never holds panel data. */\nexport function SnowmanField({\n progress,\n estimatedDurationMs,\n overdue,\n seed = 0,\n}: {\n progress: number\n estimatedDurationMs?: number\n overdue: boolean\n seed?: number\n}) {\n const rootRef = useRef<HTMLDivElement>(null)\n const canvasRef = useRef<HTMLCanvasElement>(null)\n const [dimensions, setDimensions] = useState({ width: 360, height: 180 })\n const [reducedMotion, setReducedMotion] = useState(\n () => window.matchMedia('(prefers-reduced-motion: reduce)').matches,\n )\n\n const progressRef = useRef(progress)\n const overdueRef = useRef(overdue)\n const state = useRef({\n startedAt: Date.now(),\n progressAt: Date.now(),\n progress,\n simulation: createSnowmanSimulation(),\n })\n\n useEffect(() => {\n progressRef.current = progress\n state.current.progressAt = Date.now()\n state.current.progress = progress\n }, [progress])\n useEffect(() => {\n overdueRef.current = overdue\n }, [overdue])\n useEffect(() => {\n const media = window.matchMedia('(prefers-reduced-motion: reduce)')\n const update = () => setReducedMotion(media.matches)\n update()\n media.addEventListener?.('change', update)\n return () => media.removeEventListener?.('change', update)\n }, [])\n useEffect(() => {\n const root = rootRef.current\n if (!root) return\n const update = () => {\n const rect = root.getBoundingClientRect()\n if (rect.width > 0 && rect.height > 0)\n setDimensions({ width: rect.width, height: rect.height })\n }\n update()\n if (typeof ResizeObserver === 'undefined') return\n const observer = new ResizeObserver(update)\n observer.observe(root)\n return () => observer.disconnect()\n }, [])\n useEffect(() => {\n if (reducedMotion) return\n state.current.simulation = createSnowmanSimulation(dimensions)\n let frame = 0\n const paint = () => {\n const current = state.current\n const elapsed =\n estimatedDurationMs === undefined\n ? Date.now() - current.startedAt\n : current.progress * estimatedDurationMs + (Date.now() - current.progressAt)\n const options = {\n progress: progressRef.current,\n estimatedDurationMs,\n overdue: overdueRef.current,\n seed,\n dimensions,\n }\n const next = advanceSnowmanSimulation(current.simulation, { ...options, elapsed })\n current.simulation = next\n const future = advanceSnowmanSimulation(next, { ...options, elapsed: next.lastElapsed + 25 })\n const scene = interpolateSnowman(next, future, (elapsed - next.lastElapsed) / 25)\n drawSnowmanCanvas(canvasRef.current, scene, dimensions)\n const root = rootRef.current\n if (root) {\n root.dataset.snowCellCount = String(next.cells.length)\n root.dataset.snowDensity = next.grid.columns < 65 ? 'compact' : 'full'\n if (next.toppled) root.dataset.snowmanToppled = 'true'\n else delete root.dataset.snowmanToppled\n }\n if (!reducedMotion) frame = window.requestAnimationFrame(paint)\n }\n frame = window.requestAnimationFrame(paint)\n return () => window.cancelAnimationFrame(frame)\n }, [dimensions, estimatedDurationMs, reducedMotion, seed])\n useEffect(() => {\n if (!reducedMotion) return\n const scene = advanceSnowmanSimulation(createSnowmanSimulation(dimensions), {\n elapsed: estimatedDurationMs === undefined ? 4800 : progress * estimatedDurationMs,\n progress,\n estimatedDurationMs,\n overdue,\n seed,\n dimensions,\n })\n drawSnowmanCanvas(canvasRef.current, scene, dimensions)\n if (rootRef.current) {\n rootRef.current.dataset.snowCellCount = String(scene.cells.length)\n if (scene.toppled) rootRef.current.dataset.snowmanToppled = 'true'\n else delete rootRef.current.dataset.snowmanToppled\n }\n }, [dimensions, estimatedDurationMs, overdue, progress, reducedMotion, seed])\n const phase = snowmanScenePhase(progress, estimatedDurationMs, overdue)\n return (\n <div\n ref={rootRef}\n className={styles.field}\n data-running-part=\"snowman-field\"\n data-snowman-phase={phase}\n data-reduced-motion={reducedMotion || undefined}\n >\n <canvas ref={canvasRef} className={styles.canvas} data-running-part=\"snowman-canvas\" />\n </div>\n )\n}\n",".haze {\n position: absolute;\n inset: -15%;\n background:\n radial-gradient(\n ellipse at 18% 44%,\n color-mix(in srgb, currentColor 19%, transparent),\n transparent 42%\n ),\n radial-gradient(\n ellipse at 74% 63%,\n color-mix(in srgb, currentColor 12%, transparent),\n transparent 38%\n );\n animation: haze 15s ease-in-out infinite alternate;\n}\n.pressure {\n display: none;\n}\n.band {\n position: absolute;\n right: -15%;\n left: -15%;\n height: 1px;\n background: linear-gradient(\n 90deg,\n transparent,\n color-mix(in srgb, currentColor 32%, transparent),\n transparent\n );\n animation: band 10s ease-in-out infinite alternate;\n}\n.bandOne {\n top: 32%;\n}\n.bandTwo {\n top: 67%;\n animation-delay: -4s;\n}\n.bandThree {\n top: 49%;\n animation-delay: -7s;\n opacity: 0.55;\n}\n.drift {\n position: absolute;\n width: clamp(0.34em, 0.9cqw, 0.7em);\n height: clamp(0.34em, 0.9cqw, 0.7em);\n border: 1px solid color-mix(in srgb, currentColor 78%, transparent);\n border-radius: 50%;\n box-shadow: 0 0 0.55em color-mix(in srgb, currentColor 55%, transparent);\n animation: drift 11s ease-in-out infinite alternate;\n}\n.driftOne {\n top: 25%;\n left: 12%;\n}\n.driftTwo {\n top: 72%;\n left: 58%;\n width: 0.34em;\n height: 0.34em;\n animation-duration: 14s;\n animation-delay: -4s;\n opacity: 0.6;\n}\n.driftThree {\n top: 18%;\n left: 74%;\n width: 0.7em;\n height: 0.7em;\n animation-duration: 17s;\n animation-delay: -9s;\n opacity: 0.55;\n}\n.driftFour {\n top: 58%;\n left: 31%;\n width: 0.42em;\n height: 0.42em;\n animation-duration: 9s;\n animation-delay: -2s;\n opacity: 0.75;\n}\n.driftFive {\n top: 84%;\n left: 83%;\n width: 0.58em;\n height: 0.58em;\n animation-duration: 13s;\n animation-delay: -6s;\n opacity: 0.45;\n}\n@container running-field (max-width: 40rem) or (max-height: 6rem) {\n .drift,\n .band {\n display: none;\n }\n .haze {\n inset: auto 0 0 auto;\n width: 2.5em;\n height: 2.5em;\n opacity: 0.65;\n }\n}\n[data-overdue=\"true\"] .haze {\n inset: -30%;\n background:\n radial-gradient(\n ellipse at 22% 48%,\n color-mix(in srgb, currentColor 34%, transparent),\n transparent 42%\n ),\n radial-gradient(\n ellipse at 78% 58%,\n color-mix(in srgb, currentColor 25%, transparent),\n transparent 36%\n );\n}\n[data-overdue=\"true\"] .pressure {\n display: block;\n position: absolute;\n inset: 20% 0;\n border-top: 1px solid color-mix(in srgb, currentColor 65%, transparent);\n border-bottom: 1px solid color-mix(in srgb, currentColor 65%, transparent);\n background: repeating-linear-gradient(\n 180deg,\n transparent 0 0.55em,\n color-mix(in srgb, currentColor 14%, transparent) 0.55em 0.62em\n );\n opacity: 0.75;\n animation: pressure 3.4s ease-in-out infinite alternate;\n}\n[data-overdue=\"true\"] .band {\n background: linear-gradient(90deg, transparent, currentColor, transparent);\n animation-name: storm-band;\n}\n[data-overdue=\"true\"] .drift {\n transform: translate(12cqw, -2cqh) scale(0.82);\n}\n@keyframes haze {\n to {\n transform: translate(9%, -4%);\n }\n}\n@keyframes band {\n to {\n transform: translateX(8%);\n opacity: 0.45;\n }\n}\n@keyframes drift {\n to {\n transform: translate(10cqw, -2cqh);\n }\n}\n@keyframes pressure {\n from {\n transform: scaleY(0.72);\n opacity: 0.45;\n }\n to {\n transform: scaleY(1.12);\n opacity: 0.9;\n }\n}\n@keyframes storm-band {\n to {\n transform: translateX(-14%);\n opacity: 0.9;\n }\n}\n@media (prefers-reduced-motion: reduce) {\n [data-overdue=\"true\"] .pressure,\n .haze,\n .band,\n .drift {\n animation: none;\n }\n .pressure {\n animation: none;\n }\n}\n","import styles from './StatusWeatherField.module.css'\n\nexport function StatusWeatherField() {\n return (\n <>\n <span className={styles.haze} data-running-part=\"weather-haze\" />\n <span className={styles.pressure} data-running-part=\"weather-pressure\" />\n <span className={`${styles.band} ${styles.bandOne}`} />\n <span className={`${styles.band} ${styles.bandTwo}`} />\n <span className={`${styles.band} ${styles.bandThree}`} />\n <span className={`${styles.drift} ${styles.driftOne}`} />\n <span className={`${styles.drift} ${styles.driftTwo}`} />\n <span className={`${styles.drift} ${styles.driftThree}`} />\n <span className={`${styles.drift} ${styles.driftFour}`} />\n <span className={`${styles.drift} ${styles.driftFive}`} />\n </>\n )\n}\n",".anchor {\n position: absolute;\n top: 50%;\n left: var(--running-progress);\n}\n.body {\n position: absolute;\n inset: 0;\n animation: phased-marker 3.2s ease-in-out infinite alternate;\n animation-delay: var(--phased-marker-delay, 0s);\n will-change: transform;\n}\n@keyframes phased-marker {\n from {\n transform: translate(var(--phased-marker-travel, -10em), -50%);\n }\n to {\n transform: translate(-50%, -50%);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .body {\n animation: none;\n }\n}\n","import type { CSSProperties } from 'react'\nimport styles from './PhasedProgressMarker.module.css'\n\n/**\n * A progress-anchored decorative marker. The anchor owns live progress geometry; the body owns\n * its independent phase animation, so a timing render cannot replace its transform.\n */\nexport function PhasedProgressMarker({\n anchorClassName,\n bodyClassName,\n delay,\n anchorPart,\n bodyPart,\n}: {\n anchorClassName: string | undefined\n bodyClassName: string | undefined\n delay?: string\n anchorPart?: string\n bodyPart: string\n}) {\n const style = delay ? ({ '--phased-marker-delay': delay } as CSSProperties) : undefined\n return (\n <span className={`${styles.anchor} ${anchorClassName ?? ''}`} data-running-part={anchorPart}>\n <span\n className={`${styles.body} ${bodyClassName ?? ''}`}\n data-running-part={bodyPart}\n style={style}\n />\n </span>\n )\n}\n",".frontier {\n position: absolute;\n inset: 0 auto 0 0;\n width: var(--running-progress);\n background: linear-gradient(\n 90deg,\n color-mix(in srgb, currentColor 16%, transparent),\n transparent\n );\n border-right: 1px solid color-mix(in srgb, currentColor 75%, transparent);\n}\n.flare {\n display: none;\n}\n.lanes {\n position: absolute;\n inset: 13% 7%;\n display: grid;\n align-content: space-between;\n}\n.lane {\n position: relative;\n height: 1px;\n background: linear-gradient(\n 90deg,\n transparent,\n color-mix(in srgb, var(--edge) 90%, transparent),\n transparent\n );\n}\n.markerAnchor {\n width: 0.42em;\n height: 0.25em;\n}\n.markerBody {\n --phased-marker-travel: -10cqw;\n border-radius: 999px;\n background: currentColor;\n box-shadow: 0 0 0.6em currentColor;\n}\n.lane:nth-child(2) .markerBody {\n opacity: 0.7;\n}\n.lane:nth-child(3) .markerBody {\n opacity: 0.5;\n}\n.lane:nth-child(4) .markerBody {\n opacity: 0.8;\n}\n@container running-field (max-width: 40rem) or (max-height: 6rem) {\n .lanes {\n display: none;\n }\n .frontier {\n width: 0.28em;\n border-right: 0;\n background: currentColor;\n }\n}\n[data-overdue=\"true\"] .frontier {\n width: 100%;\n background: linear-gradient(\n 90deg,\n color-mix(in srgb, currentColor 34%, transparent),\n transparent\n );\n border-right-color: currentColor;\n}\n[data-overdue=\"true\"] .flare {\n display: block;\n position: absolute;\n top: 0;\n left: 100%;\n width: 2.4em;\n height: 100%;\n background: radial-gradient(ellipse, currentColor 0, transparent 68%);\n transform: translateX(-50%);\n animation: bloom-flare 1.6s ease-in-out infinite alternate;\n}\n[data-overdue=\"true\"] .markerBody {\n --phased-marker-travel: -22.5cqw;\n animation-duration: 0.72s;\n animation-timing-function: ease-in-out;\n}\n@media (prefers-reduced-motion: reduce) {\n .frontier {\n transition: none;\n }\n [data-overdue=\"true\"] .flare,\n [data-overdue=\"true\"] .markerBody {\n animation: none;\n }\n}\n@keyframes bloom-flare {\n from {\n opacity: 0.42;\n transform: translateX(-50%) scale(0.8);\n }\n to {\n opacity: 0.95;\n transform: translateX(-50%) scale(1.15);\n }\n}\n","import { PhasedProgressMarker } from './PhasedProgressMarker.tsx'\nimport styles from './TelemetryBloomField.module.css'\n\nexport function TelemetryBloomField() {\n return (\n <>\n <span className={styles.frontier} data-running-part=\"frontier\" />\n <span className={styles.flare} data-running-part=\"bloom-flare\" />\n <span className={styles.lanes} data-running-part=\"bloom-lanes\">\n {[0, 1, 2, 3].map((lane) => (\n <span className={styles.lane} key={lane} data-running-part=\"bloom-lane\">\n <PhasedProgressMarker\n anchorClassName={styles.markerAnchor}\n bodyClassName={styles.markerBody}\n delay={[undefined, '-0.8s', '-1.7s', '-2.4s'][lane]}\n anchorPart=\"bloom-marker-anchor\"\n bodyPart=\"bloom-marker\"\n />\n </span>\n ))}\n </span>\n </>\n )\n}\n","import type { RunningAnimation } from '@ze-great-dashboard/shared'\nimport type { CSSProperties } from 'react'\nimport { FallingShapesField } from './FallingShapesField.tsx'\nimport { ReleaseTransitField } from './ReleaseTransitField.tsx'\nimport styles from './RunningField.module.css'\nimport { SnowmanField } from './SnowmanField.tsx'\nimport { StatusWeatherField } from './StatusWeatherField.tsx'\nimport { TelemetryBloomField } from './TelemetryBloomField.tsx'\n\nexport type RunningFieldAnimation = Extract<\n RunningAnimation,\n 'telemetry-bloom' | 'release-transit' | 'status-weather' | 'falling-shapes' | 'snowman'\n>\n\nexport function isRunningFieldAnimation(\n animation: Exclude<RunningAnimation, 'off'>,\n): animation is RunningFieldAnimation {\n return [\n 'telemetry-bloom',\n 'release-transit',\n 'status-weather',\n 'falling-shapes',\n 'snowman',\n ].includes(animation)\n}\n\nexport function RunningField({\n animation,\n progress,\n estimatedDurationMs,\n overdue,\n indeterminate,\n seed,\n}: {\n animation: RunningFieldAnimation\n progress: number\n estimatedDurationMs?: number\n overdue: boolean\n indeterminate: boolean\n seed?: number\n}) {\n const style = {\n '--running-progress': `${progress * 100}%`,\n } as CSSProperties\n return (\n <div\n className={`${styles.field} ${overdue ? styles.overdue : ''}`}\n data-animation={animation}\n data-running-field\n data-overdue={overdue || undefined}\n data-indeterminate={indeterminate || undefined}\n aria-hidden=\"true\"\n style={style}\n >\n {animation === 'telemetry-bloom' && <TelemetryBloomField />}\n {animation === 'release-transit' && <ReleaseTransitField />}\n {animation === 'status-weather' && <StatusWeatherField />}\n {animation === 'falling-shapes' && (\n <FallingShapesField\n progress={progress}\n estimatedDurationMs={estimatedDurationMs}\n overdue={overdue}\n seed={seed}\n />\n )}\n {animation === 'snowman' && (\n <SnowmanField\n progress={progress}\n estimatedDurationMs={estimatedDurationMs}\n overdue={overdue}\n seed={seed}\n />\n )}\n </div>\n )\n}\n","import { useEffect, useState } from 'react'\n\nconst VISUAL_TICK_MS = 20\n\nexport type RunningTiming = {\n elapsedMs: number | undefined\n estimatedDurationMs: number | undefined\n hasEstimate: boolean\n overdue: boolean\n progress: number\n}\n\nexport function useRunningTiming(\n runStartedAt?: string,\n estimatedDurationMs?: number,\n): RunningTiming {\n const now = useClock(Boolean(runStartedAt))\n const startedAt = runStartedAt ? new Date(runStartedAt).valueOf() : Number.NaN\n const elapsedMs = Number.isFinite(startedAt) ? Math.max(0, now - startedAt) : undefined\n const hasEstimate = elapsedMs !== undefined && estimatedDurationMs !== undefined\n const overdue = hasEstimate && elapsedMs > estimatedDurationMs\n const progress = hasEstimate ? Math.min(elapsedMs / estimatedDurationMs, 1) : 0\n return { elapsedMs, estimatedDurationMs, hasEstimate, overdue, progress }\n}\n\nfunction useClock(enabled: boolean) {\n const [now, setNow] = useState(() => Date.now())\n useEffect(() => {\n if (!enabled) return\n setNow(Date.now())\n // The timing text rounds to seconds, but progress gets display-cadence intermediate positions.\n // This avoids the visible sawtooth created by a coarse timer and CSS transition.\n const interval = window.setInterval(() => setNow(Date.now()), VISUAL_TICK_MS)\n return () => window.clearInterval(interval)\n }, [enabled])\n return now\n}\n\nexport function timingDescription(\n elapsedMs: number | undefined,\n estimatedDurationMs: number | undefined,\n overdue: boolean,\n) {\n const elapsed =\n elapsedMs === undefined ? 'Run in progress' : `Elapsed ${formatDuration(elapsedMs)}`\n const expected =\n estimatedDurationMs === undefined\n ? 'Expected duration unavailable'\n : `Expected ≈ ${formatDuration(estimatedDurationMs)}`\n return `${elapsed} · ${expected}${overdue ? ' · Over estimate' : ''}`\n}\n\nexport function compactTiming(\n elapsedMs: number | undefined,\n estimatedDurationMs: number | undefined,\n overdue: boolean,\n) {\n const elapsed = elapsedMs === undefined ? '—' : formatClockDuration(elapsedMs)\n const expected =\n estimatedDurationMs === undefined ? '?' : `~${formatClockDuration(estimatedDurationMs)}`\n return `${overdue ? '⚠' : '\\u00a0'}${elapsed}/${expected}`\n}\n\nfunction formatDuration(durationMs: number) {\n const totalSeconds = Math.floor(durationMs / 1_000)\n const hours = Math.floor(totalSeconds / 3_600)\n const minutes = Math.floor((totalSeconds % 3_600) / 60)\n const seconds = totalSeconds % 60\n if (hours > 0) return `${hours}h ${minutes}m`\n if (minutes > 0) return `${minutes}m ${seconds}s`\n return `${seconds}s`\n}\n\nfunction formatClockDuration(durationMs: number) {\n const totalSeconds = Math.floor(durationMs / 1_000)\n const hours = Math.floor(totalSeconds / 3_600)\n const minutes = Math.floor((totalSeconds % 3_600) / 60)\n const seconds = totalSeconds % 60\n const clock = `${minutes}:${String(seconds).padStart(2, '0')}`\n return hours > 0 ? `${hours}:${clock.padStart(5, '0')}` : clock\n}\n","import styles from './RunningField.module.css'\nimport { compactTiming, timingDescription } from './running-timing.ts'\n\n/** The sole readable timing projection for panel-scale decorative fields. */\nexport function RunningFieldTiming({\n elapsedMs,\n estimatedDurationMs,\n overdue,\n}: {\n elapsedMs: number | undefined\n estimatedDurationMs: number | undefined\n overdue: boolean\n}) {\n return (\n <p className={`${styles.timing} ${overdue ? styles.timingOverdue : ''}`}>\n <span className=\"screen-reader-only\">\n {timingDescription(elapsedMs, estimatedDurationMs, overdue)}\n </span>\n <span aria-hidden=\"true\">{compactTiming(elapsedMs, estimatedDurationMs, overdue)}</span>\n </p>\n )\n}\n",".progress {\n display: flex;\n align-items: center;\n gap: 0.6em;\n min-width: 0;\n color: var(--status-warning);\n}\n.visual {\n position: relative;\n flex: 0 0 auto;\n}\n.timing {\n margin: 0;\n color: var(--ink-secondary);\n font-size: 0.72em;\n}\n.overdue {\n color: var(--status-serious);\n}\n.overdue .timing {\n color: var(--status-serious);\n}\n.readout {\n width: 12ch;\n flex: 0 0 12ch;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-variant-numeric: tabular-nums;\n text-align: end;\n white-space: nowrap;\n}\n.radial .visual {\n width: 2.35em;\n height: 2.35em;\n border: 0.14em solid var(--edge);\n border-radius: 50%;\n background: conic-gradient(var(--status-warning) var(--running-progress), var(--edge) 0);\n box-shadow:\n inset 0 0 0 0.22em var(--surface-raised),\n 0 0 0.55em color-mix(in srgb, var(--status-warning) 45%, transparent);\n}\n.radial .visual::after {\n content: \"\";\n position: absolute;\n inset: -0.14em;\n border-radius: 50%;\n border-top: 0.14em solid var(--status-warning);\n animation: sweep 1.7s linear infinite;\n}\n.overdue.radial .visual::before {\n content: \"\";\n position: absolute;\n inset: -0.42em;\n border: 0.1em solid var(--status-serious);\n border-radius: 50%;\n box-shadow: 0 0 0.55em color-mix(in srgb, var(--status-serious) 65%, transparent);\n animation: alarm-ring 1.8s ease-in-out infinite;\n}\n.radialCore {\n position: absolute;\n inset: 0.68em;\n border-radius: 50%;\n background: var(--status-warning);\n box-shadow: 0 0 0.45em var(--status-warning);\n}\n.overdue .radialCore {\n background: var(--status-serious);\n box-shadow: 0 0 0.55em var(--status-serious);\n animation: reactor-breathe 1.8s ease-in-out infinite alternate;\n}\n.runway {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-self: stretch;\n container-type: inline-size;\n}\n.runway .visual {\n width: min(12em, 100%);\n max-width: 100%;\n height: 0.8em;\n overflow: hidden;\n border: 1px solid var(--edge);\n border-radius: 999px;\n background: linear-gradient(90deg, var(--status-warning) var(--running-progress), var(--edge) 0);\n}\n.runway .visual::after {\n content: \"\";\n position: absolute;\n top: -0.25em;\n bottom: -0.25em;\n left: calc(var(--running-progress) - 0.06em);\n width: 0.12em;\n background: var(--ink-primary);\n box-shadow: 0 0 0.45em var(--ink-primary);\n}\n.overdue.runway .visual::before {\n content: \"\";\n position: absolute;\n inset: -0.2em 0;\n left: calc(100% - 0.55em);\n width: 0.55em;\n background: repeating-linear-gradient(\n -45deg,\n var(--status-serious) 0 0.12em,\n var(--surface) 0.12em 0.24em\n );\n box-shadow: 0 0 0.5em color-mix(in srgb, var(--status-serious) 70%, transparent);\n animation: barrier-pulse 1.4s ease-in-out infinite alternate;\n}\n.overdue.runway .visual::after {\n background: var(--status-serious);\n box-shadow: 0 0 0.55em var(--status-serious);\n animation: barrier-pulse 1.4s ease-in-out infinite alternate;\n}\n.spark {\n position: absolute;\n top: 50%;\n left: -0.5em;\n width: 0.35em;\n height: 0.35em;\n border-radius: 50%;\n background: var(--ink-primary);\n box-shadow: 0 0 0.4em var(--status-warning);\n animation: spark 1.5s linear infinite;\n}\n.overdue.runway .spark {\n animation-duration: 1s;\n}\n.sparkTwo {\n display: none;\n animation-delay: -0.5s;\n}\n.overdue.runway .sparkTwo {\n display: block;\n}\n.orbit .visual {\n width: 2.4em;\n height: 2.4em;\n border: 1px solid var(--edge);\n border-radius: 50%;\n}\n/* biome-ignore lint/style/noDescendingSpecificity: the radial overdue ring precedes this separate legacy treatment. */\n.orbit .visual::before {\n content: \"\";\n position: absolute;\n inset: 0.18em;\n border: 0.12em solid transparent;\n border-top-color: var(--status-warning);\n border-radius: 50%;\n transform: rotate(var(--running-degrees));\n}\n.orbitCore {\n position: absolute;\n inset: 0.75em;\n border-radius: 50%;\n background: var(--status-warning);\n box-shadow: 0 0 0.45em var(--status-warning);\n}\n.overdue .orbitCore {\n background: var(--status-serious);\n box-shadow: 0 0 0.55em var(--status-serious);\n animation: reactor-breathe 1.15s ease-in-out infinite alternate;\n}\n.particle {\n position: absolute;\n top: 0.25em;\n left: calc(50% - 0.16em);\n width: 0.32em;\n height: 0.32em;\n border-radius: 50%;\n background: var(--ink-primary);\n transform-origin: 0.16em 0.95em;\n animation: orbit 1.8s linear infinite;\n}\n.particleTwo {\n animation-delay: -0.9s;\n background: var(--status-warning);\n}\n.overdue.orbit .visual::after {\n content: \"\";\n position: absolute;\n inset: 0.42em;\n border: 0.08em solid color-mix(in srgb, var(--status-serious) 75%, transparent);\n border-radius: 50%;\n box-shadow: 0 0 0.6em color-mix(in srgb, var(--status-serious) 55%, transparent);\n animation: gravity-well 1.15s ease-in-out infinite alternate;\n}\n.overdue.orbit .particle {\n transform-origin: 0.16em 0.7em;\n animation-duration: 0.95s;\n}\n.indeterminate .visual {\n background-image: repeating-linear-gradient(\n 135deg,\n color-mix(in srgb, var(--status-warning) 70%, transparent) 0 0.25em,\n var(--edge) 0.25em 0.5em\n );\n animation: shift 1s linear infinite;\n}\n.signalField {\n container-type: size;\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-self: stretch;\n flex: 1 1 auto;\n min-height: 0;\n max-height: 100%;\n}\n.signalField .visual {\n width: auto;\n height: 1em;\n max-height: 100%;\n overflow: hidden;\n border: 1px solid var(--edge);\n border-radius: 999px;\n background: var(--surface);\n}\n.rail {\n position: absolute;\n inset: 0;\n background: linear-gradient(90deg, var(--status-warning) var(--running-progress), var(--edge) 0);\n opacity: 0.75;\n}\n.lead {\n position: absolute;\n top: -0.2em;\n bottom: -0.2em;\n left: calc(var(--running-progress) - 0.08em);\n width: 0.16em;\n border-radius: 999px;\n background: var(--ink-primary);\n box-shadow: 0 0 0.5em var(--status-warning);\n}\n.pulse {\n position: absolute;\n top: 50%;\n left: -0.5em;\n width: 0.3em;\n height: 0.3em;\n border-radius: 50%;\n background: var(--ink-primary);\n box-shadow: 0 0 0.4em var(--status-warning);\n animation: pulse 2.4s ease-in-out infinite alternate;\n}\n.pulseTwo {\n animation-delay: -1.2s;\n}\n.tracks {\n display: none;\n}\n@container panel (min-width: 26rem) {\n .runway .visual {\n flex: 1 1 auto;\n width: auto;\n height: clamp(1.1em, 7cqw, 2.7em);\n box-shadow: inset 0 0 1em color-mix(in srgb, var(--status-warning) 16%, transparent);\n }\n .runway .visual::after {\n left: calc(var(--running-progress) - 0.08em);\n width: 0.16em;\n }\n .spark {\n animation-name: sparkWide;\n }\n}\n@container panel (max-width: 18rem) {\n .signalField {\n flex: 0 1 auto;\n min-height: 0;\n }\n .signalField .visual {\n width: 2.65em;\n height: 1.15em;\n }\n .signalField .rail {\n background: var(--edge);\n }\n .signalField .lead {\n top: 0.2em;\n bottom: 0.2em;\n width: 0.38em;\n border-radius: 50%;\n }\n .pulse {\n display: none;\n }\n}\n@container panel (max-height: 5rem) {\n .signalField {\n flex: 0 1 auto;\n min-height: 0;\n }\n .signalField .visual {\n width: 2.65em;\n height: 1.15em;\n }\n .signalField .rail {\n background: var(--edge);\n }\n .signalField .lead {\n top: 0.2em;\n bottom: 0.2em;\n width: 0.38em;\n border-radius: 50%;\n }\n .pulse {\n display: none;\n }\n}\n/* A size-contained signal field cannot use its own intrinsic height as a query input: its\n auto-sized content would always satisfy the compact branch. Width is the stable panel-scale\n discriminator; the field's parent already controls its available height. */\n@container panel (min-width: 26rem) {\n .signalField .visual {\n height: 100%;\n min-height: 0;\n border-radius: 0.25em;\n background: linear-gradient(\n 180deg,\n color-mix(in srgb, var(--edge) 60%, transparent),\n transparent\n );\n }\n .signalField .visual::before {\n content: \"\";\n position: absolute;\n inset: 0 auto 0 0;\n width: var(--running-progress);\n background:\n repeating-linear-gradient(\n 0deg,\n transparent 0 0.55em,\n color-mix(in srgb, var(--status-warning) 16%, transparent) 0.55em 0.6em\n ),\n linear-gradient(\n 90deg,\n color-mix(in srgb, var(--status-warning) 19%, transparent),\n color-mix(in srgb, var(--status-warning) 7%, transparent)\n );\n box-shadow: inset -0.8em 0 1em color-mix(in srgb, var(--status-warning) 22%, transparent);\n }\n .signalField .rail {\n top: 50%;\n bottom: auto;\n height: 1px;\n }\n .signalField .lead {\n top: calc(50% - 0.45em);\n bottom: auto;\n height: 0.9em;\n }\n .pulse {\n display: none;\n }\n .tracks {\n position: absolute;\n inset: 0.8em 0;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n }\n .track {\n position: relative;\n height: 1px;\n background: linear-gradient(\n 90deg,\n transparent,\n color-mix(in srgb, var(--edge) 85%, transparent),\n transparent\n );\n }\n .markerAnchor {\n width: 0.38em;\n height: 0.22em;\n }\n .markerBody {\n border-radius: 0.06em;\n background: var(--status-warning);\n box-shadow: 0 0 0.4em var(--status-warning);\n }\n .track:nth-child(2) .markerBody {\n animation-delay: -0.8s;\n opacity: 0.7;\n }\n .track:nth-child(3) .markerBody {\n animation-delay: -1.7s;\n opacity: 0.45;\n }\n .track:nth-child(4) .markerBody {\n animation-delay: -2.4s;\n opacity: 0.7;\n }\n .track:nth-child(5) .markerBody {\n animation-delay: -0.35s;\n opacity: 0.55;\n }\n}\n.overdue.signalField .rail {\n background: linear-gradient(90deg, var(--status-serious) 0 100%);\n opacity: 0.42;\n}\n.overdue.signalField .lead {\n background: var(--status-serious);\n box-shadow: 0 0 0.7em var(--status-serious);\n animation: endpoint-pulse 1.2s ease-in-out infinite alternate;\n}\n.overdue.signalField .markerBody {\n --phased-marker-travel: -10em;\n background: var(--status-serious);\n box-shadow: 0 0 0.55em var(--status-serious);\n animation-duration: 0.68s;\n animation-timing-function: ease-in-out;\n}\n.short .signalField .visual {\n height: 1em;\n}\n@keyframes sweep {\n to {\n transform: rotate(360deg);\n }\n}\n@keyframes alarm-ring {\n from {\n transform: scale(0.92);\n opacity: 0.45;\n }\n to {\n transform: scale(1.08);\n opacity: 1;\n }\n}\n@keyframes reactor-breathe {\n from {\n transform: scale(0.84);\n opacity: 0.7;\n }\n to {\n transform: scale(1.12);\n opacity: 1;\n }\n}\n@keyframes barrier-pulse {\n from {\n opacity: 0.55;\n }\n to {\n opacity: 1;\n }\n}\n@keyframes gravity-well {\n from {\n transform: scale(0.82);\n opacity: 0.45;\n }\n to {\n transform: scale(1.08);\n opacity: 0.95;\n }\n}\n@keyframes endpoint-pulse {\n from {\n transform: scaleY(0.75);\n opacity: 0.65;\n }\n to {\n transform: scaleY(1.15);\n opacity: 1;\n }\n}\n@keyframes spark {\n to {\n transform: translateX(13em);\n }\n}\n@keyframes sparkWide {\n to {\n transform: translateX(100cqw);\n }\n}\n@keyframes orbit {\n to {\n transform: rotate(360deg);\n }\n}\n@keyframes shift {\n to {\n background-position: 1em 0;\n }\n}\n@keyframes pulse {\n from {\n transform: translate(-0.5em, -50%);\n }\n to {\n transform: translate(calc(var(--running-progress) + 0.5em), -50%);\n }\n}\n@media (prefers-reduced-motion: reduce) {\n .radial .visual::after,\n .overdue.radial .visual::before,\n .overdue .radialCore,\n .spark,\n .runway .visual::after,\n .overdue.runway .visual::before,\n .overdue.runway .visual::after,\n .particle,\n .overdue.orbit .visual::after,\n .pulse,\n .lead,\n .overdue.signalField .lead,\n .overdue.signalField .markerBody,\n /* biome-ignore lint/style/noDescendingSpecificity: the shared reduced-motion list intentionally follows themed overrides. */\n .signalField .visual::before,\n .indeterminate .visual {\n animation: none;\n }\n}\n","import type { RunningAnimation } from '@ze-great-dashboard/shared'\nimport type { CSSProperties } from 'react'\nimport { PhasedProgressMarker } from './PhasedProgressMarker.tsx'\nimport styles from './RunningProgress.module.css'\nimport { compactTiming, type RunningTiming, timingDescription } from './running-timing.ts'\n\nexport function RunningProgress({\n animation,\n timing,\n}: {\n animation: LegacyRunningAnimation\n timing: RunningTiming\n}) {\n const { elapsedMs, estimatedDurationMs, hasEstimate, overdue, progress } = timing\n const usesReadout = animation === 'runway' || animation === 'signal-field'\n const timingText = timingDescription(elapsedMs, estimatedDurationMs, overdue)\n const style = {\n '--running-progress': `${progress * 100}%`,\n '--running-degrees': `${progress * 360}deg`,\n } as CSSProperties\n const animationStyle = animation === 'signal-field' ? styles.signalField : styles[animation]\n\n return (\n <div\n className={`${styles.progress} ${animationStyle} ${overdue ? styles.overdue : ''} ${hasEstimate ? '' : styles.indeterminate}`}\n style={style}\n data-running-progress={animation}\n data-overdue={overdue || undefined}\n data-indeterminate={!hasEstimate || undefined}\n >\n <div className={styles.visual} aria-hidden=\"true\" data-running-visual>\n {animation === 'radial' && <span className={styles.radialCore} />}\n {animation === 'runway' && (\n <>\n <span className={styles.spark} data-running-part=\"runway-spark\" />\n <span\n className={`${styles.spark} ${styles.sparkTwo}`}\n data-running-part=\"runway-spark-two\"\n />\n </>\n )}\n {animation === 'orbit' && (\n <>\n <span className={styles.orbitCore} />\n <span className={styles.particle} />\n <span className={`${styles.particle} ${styles.particleTwo}`} />\n </>\n )}\n {animation === 'signal-field' && (\n <>\n <span className={styles.rail} />\n <span className={styles.lead} />\n <span className={styles.pulse} />\n <span className={`${styles.pulse} ${styles.pulseTwo}`} />\n <span className={styles.tracks} data-running-part=\"signal-tracks\">\n {[0, 1, 2, 3, 4].map((track) => (\n <span className={styles.track} key={track} data-running-part=\"signal-track\">\n <PhasedProgressMarker\n anchorClassName={styles.markerAnchor}\n bodyClassName={styles.markerBody}\n delay={[undefined, '-0.8s', '-1.7s', '-2.4s', '-0.35s'][track]}\n anchorPart=\"signal-marker-anchor\"\n bodyPart=\"signal-marker\"\n />\n </span>\n ))}\n </span>\n </>\n )}\n </div>\n <p className={`${styles.timing} ${usesReadout ? styles.readout : ''}`}>\n {usesReadout ? (\n <>\n <span className=\"screen-reader-only\">{timingText}</span>\n <span aria-hidden=\"true\">{compactTiming(elapsedMs, estimatedDurationMs, overdue)}</span>\n </>\n ) : (\n timingText\n )}\n </p>\n </div>\n )\n}\n\n/** The compact, inline treatments retained for existing boards. */\nexport type LegacyRunningAnimation = Extract<\n RunningAnimation,\n 'radial' | 'runway' | 'orbit' | 'signal-field'\n>\n\nexport function isLegacyRunningAnimation(\n animation: RunningAnimation,\n): animation is LegacyRunningAnimation {\n return ['radial', 'runway', 'orbit', 'signal-field'].includes(animation)\n}\n","/** A stable numeric variation seed for decorative fields keyed by a panel's public id. */\nexport function visualSeed(value: string): number {\n return Array.from(value).reduce(\n (hash, character) => (hash * 31 + character.charCodeAt(0)) >>> 0,\n 7,\n )\n}\n","import { type Panel, parseDuration } from '@ze-great-dashboard/shared'\nimport { useEffect, useState } from 'react'\nimport { PanelEvidence, PanelFrame, PanelStatus } from './PanelFrame.tsx'\nimport styles from './PipelineAnimationDemoPanel.module.css'\nimport { isRunningFieldAnimation, RunningField } from './RunningField.tsx'\nimport { RunningFieldTiming } from './RunningFieldTiming.tsx'\nimport { RunningProgress } from './RunningProgress.tsx'\nimport { useRunningTiming } from './running-timing.ts'\nimport { visualSeed } from './visual-seed.ts'\n\nconst DEFAULT_RUN_DURATION_MS = 20_000\nconst ESTIMATED_DURATION_MS = 15_000\nconst DEFAULT_REVIEW_DURATION_MS = 300_000\nconst REVIEW_CYCLE_MULTIPLIER = 1.25\nconst variants = [\n 'radial',\n 'runway',\n 'orbit',\n 'signal-field',\n 'telemetry-bloom',\n 'release-transit',\n 'status-weather',\n 'falling-shapes',\n 'snowman',\n] as const\n\n/**\n * A local comparison aid for the active-run treatments. It deliberately creates no signal or\n * diagnostic evidence: its state is derived only from the wall clock and repeats forever.\n */\nexport function PipelineAnimationDemoPanel({ panel }: { panel: Panel }) {\n const now = useClock()\n // A configured visible treatment turns the local comparison aid into a stable review panel.\n // `off` retains the rotating default: the demo exists to render a treatment.\n const fixedAnimation =\n panel.running_animation === undefined || panel.running_animation === 'off'\n ? undefined\n : panel.running_animation\n const runDurationMs = durationMillis(panel.demo_run_duration, DEFAULT_RUN_DURATION_MS)\n const reviewDurationMs = durationMillis(panel.demo_review_duration, DEFAULT_REVIEW_DURATION_MS)\n const durationMs = fixedAnimation\n ? Math.ceil(reviewDurationMs * REVIEW_CYCLE_MULTIPLIER)\n : runDurationMs\n const runNumber = Math.floor(now / durationMs)\n const animation = fixedAnimation ?? variants[runNumber % variants.length] ?? 'radial'\n const runStartedAt = runNumber * durationMs\n\n return (\n <DemoRun\n panel={panel}\n animation={animation}\n runStartedAt={runStartedAt}\n estimatedDurationMs={fixedAnimation ? reviewDurationMs : ESTIMATED_DURATION_MS}\n />\n )\n}\n\nfunction durationMillis(value: Panel['demo_run_duration'], fallback: number): number {\n if (!value) return fallback\n return parseDuration(value) ?? fallback\n}\n\nfunction DemoRun({\n panel,\n animation,\n runStartedAt,\n estimatedDurationMs,\n}: {\n panel: Panel\n animation: (typeof variants)[number]\n runStartedAt: number\n estimatedDurationMs: number\n}) {\n const startedAt = new Date(runStartedAt).toISOString()\n const timing = useRunningTiming(startedAt, estimatedDurationMs)\n const usesField = isRunningFieldAnimation(animation)\n return (\n <PanelFrame\n panel={panel}\n field={\n usesField ? (\n <RunningField\n key={`${animation}-${runStartedAt}`}\n animation={animation}\n progress={timing.progress}\n estimatedDurationMs={timing.estimatedDurationMs}\n overdue={timing.overdue}\n indeterminate={!timing.hasEstimate}\n seed={visualSeed(panel.id)}\n />\n ) : undefined\n }\n >\n <PanelEvidence>\n <PanelStatus status=\"running\" glyph=\"↻\" label=\"Running\" />\n <p className={styles.variant}>\n <span className={styles.variantPrefix}>Demo treatment · </span>\n {animation}\n </p>\n {usesField ? (\n <RunningFieldTiming\n elapsedMs={timing.elapsedMs}\n estimatedDurationMs={estimatedDurationMs}\n overdue={timing.overdue}\n />\n ) : (\n <RunningProgress animation={animation} timing={timing} />\n )}\n </PanelEvidence>\n </PanelFrame>\n )\n}\n\nfunction useClock() {\n const [now, setNow] = useState(() => Date.now())\n useEffect(() => {\n const interval = window.setInterval(() => setNow(Date.now()), 1_000)\n return () => window.clearInterval(interval)\n }, [])\n return now\n}\n",".details {\n display: contents;\n}\n.details > :global(.hint) {\n line-height: 1.1;\n}\n.activity,\n.duration {\n overflow-wrap: anywhere;\n}\n@container panel (min-width: 48rem) {\n :global([data-density=\"comfortable\"][data-shallow=\"true\"]) .details > *,\n :global([data-density=\"auto\"][data-shallow=\"true\"]) .details > * {\n margin: 0;\n }\n}\n","import type { PipelineStatus } from '@ze-great-dashboard/shared'\nimport { statusSymbols } from './panel-symbols.ts'\n\nexport type PanelStatusKind = PipelineStatus['status']\n\nexport function statusPresentation(status: PanelStatusKind, passedLabel = 'Passed') {\n const presentation = statusSymbols[status]\n return status === 'passed' ? { ...presentation, label: passedLabel } : presentation\n}\n","import type { PipelineActivity } from '@ze-great-dashboard/shared'\n\nexport function formatPipelineActivity(activity: PipelineActivity | undefined) {\n if (!activity) return 'Activity unavailable'\n return activity.parent ? `${activity.parent} › ${activity.name}` : activity.name\n}\n","import {\n type Envelope,\n type Panel,\n type PipelineStatus,\n pipelineStatusSchema,\n type RunningAnimation,\n visibleRunningAnimations,\n} from '@ze-great-dashboard/shared'\nimport { useRef, useState } from 'react'\nimport { errorPresentation } from './error-presentation.ts'\nimport { PanelEvidence, PanelFrame, PanelHint, PanelMetadata, PanelStatus } from './PanelFrame.tsx'\nimport styles from './PipelinePanel.module.css'\nimport type { PanelProps } from './panel-props.ts'\nimport { statusPresentation } from './panel-status.ts'\nimport { formatPipelineActivity } from './pipeline-activity.ts'\nimport { isRunningFieldAnimation, RunningField } from './RunningField.tsx'\nimport { RunningFieldTiming } from './RunningFieldTiming.tsx'\nimport { isLegacyRunningAnimation, RunningProgress } from './RunningProgress.tsx'\nimport { useRunningTiming } from './running-timing.ts'\nimport { PipelineAge, UpdateHealth } from './TimeAge.tsx'\nimport { visualSeed } from './visual-seed.ts'\n\nexport function PipelinePanel({ panel, envelope, attentionActive, updateHealth }: PanelProps) {\n if (!envelope)\n return (\n <PanelFrame panel={panel} attentionActive={attentionActive}>\n <PanelEvidence>\n <PanelHint>Loading…</PanelHint>\n </PanelEvidence>\n </PanelFrame>\n )\n if (envelope.state === 'error') {\n const presentation = errorPresentation(envelope.error.kind)\n return (\n <PanelFrame\n panel={panel}\n envelope={envelope}\n attentionActive={attentionActive}\n error\n layout=\"status-band\"\n >\n <div data-panel-anchor=\"status\">\n <PanelStatus glyph=\"⚠\" label={presentation.label} emphasis={presentation.emphasis} />\n </div>\n <PanelEvidence anchor=\"evidence\">\n <PanelHint>{envelope.error.message}</PanelHint>\n </PanelEvidence>\n </PanelFrame>\n )\n }\n\n const signal = pipelineStatusSchema.safeParse(envelope.signal)\n if (!signal.success)\n return (\n <PanelFrame\n panel={panel}\n envelope={envelope}\n attentionActive={attentionActive}\n error\n layout=\"status-band\"\n >\n <div data-panel-anchor=\"status\">\n <PanelStatus glyph=\"⚠\" label=\"Invalid signal\" />\n </div>\n <PanelEvidence anchor=\"evidence\">\n <PanelHint>The received pipeline status could not be read.</PanelHint>\n </PanelEvidence>\n </PanelFrame>\n )\n return (\n <PipelineSignalPanel\n panel={panel}\n envelope={envelope}\n signal={signal.data}\n updateHealth={updateHealth}\n attentionActive={attentionActive}\n />\n )\n}\n\nfunction PipelineSignalPanel({\n panel,\n envelope,\n signal,\n updateHealth,\n attentionActive,\n}: {\n panel: Panel\n envelope: Envelope\n signal: PipelineStatus\n updateHealth?: PanelProps['updateHealth']\n attentionActive?: boolean\n}) {\n const presentation = statusPresentation(signal.status)\n const [defaultAnimation, setDefaultAnimation] = useState<RunningAnimation | undefined>(() =>\n signal.status === 'running' ? selectDefaultRunningAnimation() : undefined,\n )\n const previousStatusRef = useRef(signal.status)\n if (signal.status !== previousStatusRef.current) {\n const wasRunning = previousStatusRef.current === 'running'\n previousStatusRef.current = signal.status\n if (panel.running_animation === undefined && !wasRunning && signal.status === 'running') {\n setDefaultAnimation((previousAnimation) => selectDefaultRunningAnimation(previousAnimation))\n }\n }\n const animation = panel.running_animation ?? defaultAnimation ?? 'off'\n const activeRun = signal.status === 'running' && animation !== 'off'\n const timing = useRunningTiming(signal.runStartedAt, signal.estimatedDurationMs)\n const usesField = activeRun && isRunningFieldAnimation(animation)\n const usesLegacyProgress = activeRun && isLegacyRunningAnimation(animation)\n return (\n <PanelFrame\n panel={panel}\n envelope={envelope}\n attentionActive={attentionActive}\n layout={usesField || usesLegacyProgress ? undefined : 'status-band'}\n field={\n usesField ? (\n <RunningField\n animation={animation}\n progress={timing.progress}\n estimatedDurationMs={timing.estimatedDurationMs}\n overdue={timing.overdue}\n indeterminate={!timing.hasEstimate}\n seed={visualSeed(panel.id)}\n />\n ) : undefined\n }\n >\n <div data-panel-anchor=\"status\">\n <PanelStatus status={signal.status} glyph={presentation.glyph} label={presentation.label} />\n </div>\n <PanelEvidence className={styles.details} anchor=\"evidence\">\n {signal.status === 'running' && (\n <PanelMetadata\n glyph=\"⚙\"\n label=\"Activity\"\n value={formatPipelineActivity(signal.activity)}\n compact={{ kind: 'glyph-only' }}\n title={`Activity: ${formatPipelineActivity(signal.activity)}`}\n className={styles.activity}\n />\n )}\n {signal.branch && (\n <PanelMetadata\n glyph=\"⎇\"\n label=\"Branch\"\n value={<span className={styles.branch}>{signal.branch}</span>}\n compact={{\n kind: 'short-value',\n value: <span className={styles.branch}>{signal.branch}</span>,\n }}\n title={`Branch: ${signal.branch}`}\n />\n )}\n {usesField && (\n <RunningFieldTiming\n elapsedMs={timing.elapsedMs}\n estimatedDurationMs={signal.estimatedDurationMs}\n overdue={timing.overdue}\n />\n )}\n {usesLegacyProgress && <RunningProgress animation={animation} timing={timing} />}\n {signal.status !== 'running' && signal.durationMs !== undefined && (\n <PanelMetadata\n glyph=\"◷\"\n label=\"Duration\"\n value={`Took ${formatDuration(signal.durationMs)}`}\n compact={{ kind: 'short-value', value: formatDuration(signal.durationMs) }}\n title={`Duration: Took ${formatDuration(signal.durationMs)}`}\n className={styles.duration}\n />\n )}\n <PipelineAge\n sourceUpdatedAt={signal.sourceUpdatedAt}\n observedAt={envelope.observedAt}\n running={signal.status === 'running'}\n runStartedAt={signal.runStartedAt}\n />\n {updateHealth && <UpdateHealth health={updateHealth} />}\n </PanelEvidence>\n </PanelFrame>\n )\n}\n\nfunction selectDefaultRunningAnimation(previousAnimation?: RunningAnimation) {\n const candidates = visibleRunningAnimations.filter((animation) => animation !== previousAnimation)\n return candidates[Math.floor(Math.random() * candidates.length)] ?? 'telemetry-bloom'\n}\n\nfunction formatDuration(durationMs: number) {\n const totalSeconds = Math.floor(durationMs / 1_000)\n const hours = Math.floor(totalSeconds / 3_600)\n const minutes = Math.floor((totalSeconds % 3_600) / 60)\n const seconds = totalSeconds % 60\n\n if (hours > 0) return `${hours}h ${minutes}m`\n if (minutes > 0) return `${minutes}m ${seconds}s`\n return `${seconds}s`\n}\n",".compactFacts {\n display: none;\n min-width: 0;\n flex-direction: column;\n gap: 0.1em;\n}\n\n.incomplete {\n color: var(--warning-text);\n}\n\n.compactFact {\n min-width: 0;\n margin: 0;\n font-size: 0.7em;\n color: var(--ink-muted);\n}\n\n.failedItem {\n min-width: 0;\n margin: 0;\n color: var(--ink-primary);\n font-size: 0.85em;\n font-weight: 600;\n}\n\n.evidence,\n.freshness {\n display: flex;\n min-width: 0;\n flex-direction: column;\n gap: 0.1em;\n}\n\n@container panel (max-width: 13rem) and (min-height: 24rem) {\n .statusAnchor :global([class*=\"status\"]) {\n font-size: 1.7em;\n }\n\n .compactFacts {\n display: flex;\n }\n\n .fullSummary {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n}\n\n@container panel (max-width: 13rem) and (max-height: 10rem) {\n :global([data-density=\"compact\"]) .compactFacts ~ :global([data-panel-meta]) {\n display: none;\n }\n}\n","export function formatCount(count: number, singular: string, plural = `${singular}s`) {\n return `${count} ${count === 1 ? singular : plural}`\n}\n","import type { PullRequestHealth } from '@ze-great-dashboard/shared'\nimport { formatCount } from './panel-formatting.ts'\n\nexport type PullRequestHealthCompactFacts = {\n workflow: string\n pullRequests: string\n primary: string\n secondary: string\n primaryDetail?: string\n primaryKind?: 'failed' | 'warning'\n title: string\n}\n\n/**\n * Keep the wall-facing version of this aggregate signal short without making the\n * server's prose summary part of the client contract.\n */\nexport function compactPullRequestHealthFacts(\n signal: PullRequestHealth,\n): PullRequestHealthCompactFacts {\n const attentionItem = [...signal.workflows, ...signal.pullRequests].find(\n (item) => item.status === 'failed' || item.status === 'warning',\n )\n\n if (attentionItem) {\n return {\n workflow: formatCount(signal.workflows.length, 'workflow'),\n pullRequests: formatCount(signal.pullRequests.length, 'open PR'),\n primary: `${attentionItem.label} ${attentionItem.status}`,\n secondary: `${formatCount(signal.workflows.length, 'workflow')} · ${formatCount(signal.pullRequests.length, 'open PR')}`,\n primaryDetail: attentionItem.detail,\n primaryKind: attentionItem.status === 'warning' ? 'warning' : 'failed',\n title: `${signal.summary} — ${attentionItem.label}: ${attentionItem.detail}`,\n }\n }\n\n return {\n workflow: formatCount(signal.workflows.length, 'workflow'),\n pullRequests: formatCount(signal.pullRequests.length, 'open PR'),\n primary: formatCount(signal.workflows.length, 'workflow'),\n secondary: formatCount(signal.pullRequests.length, 'open PR'),\n title: signal.summary,\n }\n}\n","import { pullRequestHealthSchema } from '@ze-great-dashboard/shared'\nimport { errorPresentation } from './error-presentation.ts'\nimport { PanelEvidence, PanelFrame, PanelHint, PanelMetadata, PanelStatus } from './PanelFrame.tsx'\nimport styles from './PullRequestHealthPanel.module.css'\nimport type { PanelProps } from './panel-props.ts'\nimport { statusPresentation } from './panel-status.ts'\nimport { compactPullRequestHealthFacts } from './pull-request-health.ts'\nimport { ObservedAt, UpdateHealth } from './TimeAge.tsx'\n\nexport function PullRequestHealthPanel({\n panel,\n envelope,\n attentionActive,\n updateHealth,\n}: PanelProps) {\n if (!envelope)\n return (\n <PanelFrame panel={panel} attentionActive={attentionActive}>\n <PanelEvidence>\n <PanelHint>Loading…</PanelHint>\n </PanelEvidence>\n </PanelFrame>\n )\n if (envelope.state === 'error') {\n const presentation = errorPresentation(envelope.error.kind)\n return (\n <PanelFrame\n panel={panel}\n envelope={envelope}\n attentionActive={attentionActive}\n error\n layout=\"status-band\"\n >\n <div data-panel-anchor=\"status\">\n <PanelStatus glyph=\"⚠\" label={presentation.label} emphasis={presentation.emphasis} />\n </div>\n <PanelEvidence anchor=\"evidence\">\n <PanelHint>{envelope.error.message}</PanelHint>\n </PanelEvidence>\n </PanelFrame>\n )\n }\n const signal = pullRequestHealthSchema.safeParse(envelope.signal)\n if (!signal.success)\n return (\n <PanelFrame\n panel={panel}\n envelope={envelope}\n attentionActive={attentionActive}\n error\n layout=\"status-band\"\n >\n <div data-panel-anchor=\"status\">\n <PanelStatus glyph=\"⚠\" label=\"Invalid signal\" />\n </div>\n <PanelEvidence anchor=\"evidence\">\n <PanelHint>The received pull-request health status could not be read.</PanelHint>\n </PanelEvidence>\n </PanelFrame>\n )\n const presentation = statusPresentation(signal.data.status, 'Healthy')\n const compactFacts = compactPullRequestHealthFacts(signal.data)\n return (\n <PanelFrame\n panel={panel}\n envelope={envelope}\n attentionActive={attentionActive}\n layout=\"status-band\"\n >\n <div className={styles.statusAnchor} data-panel-anchor=\"status\">\n <PanelStatus\n status={signal.data.status}\n glyph={presentation.glyph}\n label={presentation.label}\n />\n </div>\n <div\n className={styles.evidence}\n data-panel-anchor=\"evidence\"\n data-panel-evidence-priority=\"secondary\"\n >\n <PanelHint className={styles.fullSummary} title={signal.data.summary}>\n {signal.data.summary}\n </PanelHint>\n <div className={styles.compactFacts} title={compactFacts.title} data-compact-facts>\n {compactFacts.primaryDetail && (\n <p className={styles.failedItem} title={compactFacts.primaryDetail}>\n <span aria-hidden=\"true\">⚠</span>{' '}\n <span className=\"screen-reader-only\">\n {compactFacts.primaryKind === 'warning' ? 'Warning' : 'Failed'} item:{' '}\n </span>\n {compactFacts.primary}\n <span className=\"screen-reader-only\">. Detail: {compactFacts.primaryDetail}</span>\n </p>\n )}\n <PanelMetadata\n glyph=\"⚙\"\n label=\"Update workflows\"\n value={compactFacts.workflow}\n compact={{ kind: 'short-value', value: signal.data.workflows.length }}\n title={`Update workflows: ${compactFacts.workflow}`}\n className={styles.compactFact}\n />\n <PanelMetadata\n glyph=\"⎇\"\n label=\"Open update pull requests\"\n value={compactFacts.pullRequests}\n compact={{ kind: 'short-value', value: signal.data.pullRequests.length }}\n title={`Open update pull requests: ${compactFacts.pullRequests}`}\n className={styles.compactFact}\n />\n </div>\n <div className={styles.freshness}>\n <ObservedAt value={envelope.observedAt} label=\"Observed (oldest evidence)\" />\n {signal.data.newestObservedAt && (\n <span className=\"screen-reader-only\">\n Newest evidence observed {signal.data.newestObservedAt}.\n </span>\n )}\n {updateHealth && <UpdateHealth health={updateHealth} />}\n </div>\n {signal.data.incompleteObservations && (\n <div role=\"status\">\n <PanelHint className={styles.incomplete}>\n ⚠ Incomplete observations:{' '}\n {signal.data.incompleteObservations\n .map(({ label, message }) => `${label}: ${message}`)\n .join(' · ')}\n </PanelHint>\n </div>\n )}\n </div>\n </PanelFrame>\n )\n}\n","import type { ComponentType } from 'react'\nimport { HttpValuePanel } from './HttpValuePanel.tsx'\nimport { PanelPlaceholder } from './PanelPlaceholder.tsx'\nimport { PipelineAnimationDemoPanel } from './PipelineAnimationDemoPanel.tsx'\nimport { PipelinePanel } from './PipelinePanel.tsx'\nimport { PullRequestHealthPanel } from './PullRequestHealthPanel.tsx'\nimport type { PanelProps } from './panel-props.ts'\nimport type { RenderablePanelType } from './panel-symbols.ts'\n\ntype PanelRendererProps = PanelProps\n\n/** The one client-side dispatch point for panel types. */\nexport const panelRenderers: Record<RenderablePanelType, ComponentType<PanelRendererProps>> = {\n 'pipeline-status': PipelinePanel,\n 'pull-request-health': PullRequestHealthPanel,\n 'http-value': HttpValuePanel,\n 'pipeline-animation-demo': PipelineAnimationDemoPanel,\n}\n\nexport function PanelRenderer({\n panel,\n envelope,\n attentionActive,\n updateHealth,\n facts,\n}: PanelRendererProps) {\n const Renderer = panelRenderers[panel.type as RenderablePanelType]\n return Renderer ? (\n <Renderer\n panel={panel}\n envelope={envelope}\n attentionActive={attentionActive}\n updateHealth={updateHealth}\n facts={facts}\n />\n ) : (\n <PanelPlaceholder label={panel.type} hint=\"Not wired yet\" wide />\n )\n}\n",".notice {\n display: flex;\n align-items: flex-start;\n gap: 0.45em;\n margin-inline-start: auto;\n padding: 0.35em 0.55em;\n border: 0.14rem solid var(--status-critical);\n border-radius: var(--radius);\n color: var(--ink-primary);\n background: var(--surface-raised);\n font-size: 0.7em;\n line-height: 1.3;\n}\n.notice > span:first-child {\n color: var(--status-critical);\n}\n.notice a,\n.blocked a {\n color: inherit;\n text-decoration-color: var(--status-critical);\n}\n.blocked {\n max-width: 42rem;\n margin: 12vh auto;\n padding: 2rem;\n border: 0.25rem solid var(--status-critical);\n border-radius: var(--radius);\n background: var(--surface-raised);\n}\n.blocked h1 {\n color: var(--status-critical);\n}\n@media (max-width: 64rem) {\n .notice {\n margin-inline-start: 0;\n }\n}\n","import type { ClientSecurityState } from '@ze-great-dashboard/shared'\nimport styles from './SecurityNotice.module.css'\n\nconst authenticationGuide =\n 'https://github.com/robertfmurdock/ze-great-dashboard/blob/main/docs/oidc-authentication.md'\n\n/** Deployment-level posture, intentionally separate from panel health and diagnostics. */\nexport function SecurityNotice({ mode }: { mode: ClientSecurityState }) {\n if (mode === 'blocked')\n return (\n <main className={styles.blocked} role=\"alert\">\n <h1>⚠ Authentication configuration required</h1>\n <p>\n This dashboard is blocked because authentication is required but has not been configured.\n </p>\n <p>No dashboard data was loaded.</p>\n <p>\n <a href={authenticationGuide}>Read the authentication setup guide</a>.\n </p>\n </main>\n )\n return (\n <aside className={styles.notice} role=\"alert\" aria-label=\"Unauthenticated deployment warning\">\n <span aria-hidden=\"true\">⚠</span>\n <span>\n <strong>This deployment has no authentication.</strong> If this is reachable on a public\n network and reveals important information, take it down now. Configure the board’s{' '}\n <code>auth</code> block and <code>security: required</code>, or set{' '}\n <code>security: unsecured</code> to explicitly acknowledge intentional public access.{' '}\n <a href={authenticationGuide}>Read the authentication setup guide</a>.\n </span>\n </aside>\n )\n}\n",".trigger,\n.close {\n border: 1px solid var(--edge);\n border-radius: 0.25rem;\n background: var(--surface-raised);\n color: var(--ink-secondary);\n font: inherit;\n padding: 0.3em 0.55em;\n cursor: pointer;\n}\n.dialog {\n position: fixed;\n z-index: 20;\n inset: 0;\n display: grid;\n grid-template-rows: auto minmax(0, 1fr);\n padding: var(--gap);\n background: var(--surface);\n color: var(--ink-secondary);\n font-size: clamp(0.8rem, 1vw, 1.15rem);\n}\n.dialogHeader {\n display: flex;\n align-items: start;\n justify-content: space-between;\n gap: 1rem;\n border-bottom: 1px solid var(--edge);\n padding-bottom: var(--gap);\n}\n.dialogHeader h2,\n.dialogHeader p,\n.note,\n.empty {\n margin: 0;\n}\n.dialogHeader h2 {\n color: var(--ink-primary);\n font-size: 1.35em;\n}\n.dialogHeader p {\n margin-top: 0.2rem;\n}\n.body {\n min-height: 0;\n overflow: auto;\n padding-top: var(--gap);\n}\n.legend,\n.note,\n.empty {\n color: var(--ink-muted);\n}\n.legend {\n display: block;\n font-size: 0.9em;\n}\n.axis {\n display: flex;\n justify-content: space-between;\n margin: 0.45rem 0 0.15rem max(10rem, 28%);\n color: var(--ink-muted);\n font-size: 0.85em;\n}\n.lanes {\n display: grid;\n gap: 0.2rem;\n}\n.lane {\n display: grid;\n grid-template-columns: minmax(9rem, 28%) minmax(0, 1fr);\n gap: 0.55rem;\n align-items: center;\n min-width: 0;\n}\n.laneLabel {\n overflow-wrap: anywhere;\n}\n.track {\n position: relative;\n display: block;\n min-width: 0;\n height: 0.8rem;\n border-bottom: 1px solid var(--edge);\n}\n.observed,\n.expected {\n position: absolute;\n top: 0.1rem;\n width: 0.55rem;\n height: 0.55rem;\n transform: translateX(-50%);\n}\n.observed {\n border-radius: 50%;\n background: var(--ink-primary);\n}\n.expected {\n border: 1px solid var(--ink-secondary);\n transform: translateX(-50%) rotate(45deg);\n}\n.note {\n margin-top: 0.8rem;\n font-size: 0.9em;\n}\n@media (max-width: 40rem) {\n .axis {\n margin-left: 0;\n }\n .lane {\n grid-template-columns: 1fr;\n }\n .legend {\n justify-self: start;\n }\n}\n","import type { DiagnosticEvent, DiagnosticRetention } from './diagnostics.ts'\nimport type { PollingScheduleSnapshot } from './polling-schedule.ts'\n\nexport const updateActivityWindowMillis = 10 * 60 * 1_000\n\nexport type UpdateActivitySnapshot = {\n capturedAt: string\n window: { from: string; to: string }\n schedules: PollingScheduleSnapshot[]\n}\n\nexport type UpdateActivityLane = PollingScheduleSnapshot & {\n observed: Array<{ path: string; starts: string[] }>\n hasRetainedEvidence: boolean\n}\n\nexport function projectUpdateActivity({\n schedules,\n events,\n retention,\n now = new Date(),\n}: {\n schedules: PollingScheduleSnapshot[]\n events: DiagnosticEvent[]\n retention: DiagnosticRetention\n now?: Date\n}): UpdateActivitySnapshot & {\n lanes: UpdateActivityLane[]\n evidenceMayBeIncomplete: boolean\n} {\n const toMillis = now.valueOf()\n const fromMillis = toMillis - updateActivityWindowMillis\n const starts = events.filter(\n (event): event is Extract<DiagnosticEvent, { kind: 'panel-fetch-start' }> =>\n event.kind === 'panel-fetch-start' &&\n Number.isFinite(Date.parse(event.at)) &&\n Date.parse(event.at) >= fromMillis &&\n Date.parse(event.at) <= toMillis,\n )\n const lanes = schedules.map((schedule) => {\n const paths = new Map<string, string[]>()\n for (const event of starts) {\n if (event.panelId !== schedule.panelId) continue\n const observed = paths.get(event.path) ?? []\n observed.push(event.at)\n paths.set(event.path, observed)\n }\n return {\n ...schedule,\n observed: [...paths.entries()].map(([path, requestStarts]) => ({\n path,\n starts: requestStarts,\n })),\n hasRetainedEvidence: paths.size > 0,\n }\n })\n return {\n capturedAt: now.toISOString(),\n window: { from: new Date(fromMillis).toISOString(), to: now.toISOString() },\n schedules,\n lanes,\n evidenceMayBeIncomplete: retention.eventsPrunedByAge > 0 || retention.eventsPrunedByCount > 0,\n }\n}\n","import type { PollingScheduleSnapshot } from './polling-schedule.ts'\nimport { type UpdateActivityLane, updateActivityWindowMillis } from './update-activity.ts'\n\nexport function activityMarkerPosition(at: string, now: Date) {\n return Math.max(\n 0,\n Math.min(\n 100,\n ((Date.parse(at) - (now.valueOf() - updateActivityWindowMillis)) /\n updateActivityWindowMillis) *\n 100,\n ),\n )\n}\n\nexport function activityLaneLabel(lane: UpdateActivityLane, now: Date) {\n return `${lane.label}, panel ${lane.panelId}; ${cadenceLabel(lane.cadence)} cadence; ${lane.inFlight ? 'request in flight' : lane.nextDueAt ? relativeDue(lane.nextDueAt, now) : 'awaiting first request'}; ${lane.observed.length ? `${lane.observed.length} observed proxy path${lane.observed.length === 1 ? '' : 's'}` : 'no retained requests in the last 10 minutes'}`\n}\n\nfunction cadenceLabel(cadence: PollingScheduleSnapshot['cadence']) {\n return cadence === 'completion-window'\n ? 'Completion-window'\n : cadence === 'running'\n ? 'Running'\n : 'Normal'\n}\n\nfunction relativeDue(at: string, now: Date) {\n const millis = Date.parse(at) - now.valueOf()\n return millis < 0 ? `Overdue by ${formatMillis(-millis)}` : `Next poll in ${formatMillis(millis)}`\n}\n\nfunction formatMillis(millis: number) {\n return millis % 60_000 === 0\n ? `${Math.round(millis / 60_000)}m`\n : `${Math.max(1, Math.round(millis / 1_000))}s`\n}\n","import type { Board } from '@ze-great-dashboard/shared'\nimport { useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'\nimport type { BrowserDiagnosticStore } from './diagnostics.ts'\nimport type { PollingScheduleSnapshot } from './polling-schedule.ts'\nimport styles from './UpdateActivity.module.css'\nimport { projectUpdateActivity } from './update-activity.ts'\nimport { activityLaneLabel, activityMarkerPosition } from './update-activity-presentation.ts'\n\n/** A browser-local polling timeline, available on demand. Diagnostics retains the exportable detail. */\nexport function UpdateActivity({\n board,\n schedules,\n log,\n}: {\n board: Board | undefined\n schedules: PollingScheduleSnapshot[]\n log: BrowserDiagnosticStore\n}) {\n const [now, setNow] = useState(() => new Date())\n const [open, setOpen] = useState(false)\n const triggerRef = useRef<HTMLButtonElement>(null)\n const dialogRef = useRef<HTMLElement>(null)\n const closeRef = useRef<HTMLButtonElement>(null)\n const wasOpenRef = useRef(false)\n useSyncExternalStore(log.subscribe, log.snapshot, log.snapshot)\n useEffect(() => {\n if (!open) return\n const interval = window.setInterval(() => setNow(new Date()), 1_000)\n return () => window.clearInterval(interval)\n }, [open])\n const activity = useMemo(\n () => projectUpdateActivity({ schedules, ...log.retainedEvidence(), now }),\n [log, now, schedules],\n )\n\n useEffect(() => {\n if (!open) {\n if (wasOpenRef.current) triggerRef.current?.focus()\n wasOpenRef.current = false\n return\n }\n\n wasOpenRef.current = true\n const dismiss = () => setOpen(false)\n let timeout = window.setTimeout(dismiss, 60_000)\n const resetDismissal = () => {\n window.clearTimeout(timeout)\n timeout = window.setTimeout(dismiss, 60_000)\n }\n const closeOnEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') dismiss()\n }\n const containFocus = (event: KeyboardEvent) => {\n if (event.key !== 'Tab') return\n const focusable = [\n ...(dialogRef.current?.querySelectorAll<HTMLElement>(\n 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])',\n ) ?? []),\n ]\n const first = focusable.at(0)\n const last = focusable.at(-1)\n if (!first || !last) return\n if (event.shiftKey && document.activeElement === first) {\n event.preventDefault()\n last?.focus()\n } else if (!event.shiftKey && document.activeElement === last) {\n event.preventDefault()\n first.focus()\n }\n }\n const dialog = dialogRef.current\n dialog?.addEventListener('pointerdown', resetDismissal)\n dialog?.addEventListener('keydown', resetDismissal)\n dialog?.addEventListener('focusin', resetDismissal)\n dialog?.addEventListener('keydown', containFocus)\n window.addEventListener('keydown', closeOnEscape)\n closeRef.current?.focus()\n return () => {\n window.clearTimeout(timeout)\n dialog?.removeEventListener('pointerdown', resetDismissal)\n dialog?.removeEventListener('keydown', resetDismissal)\n dialog?.removeEventListener('focusin', resetDismissal)\n dialog?.removeEventListener('keydown', containFocus)\n window.removeEventListener('keydown', closeOnEscape)\n }\n }, [open])\n\n return (\n <>\n <button\n ref={triggerRef}\n className={styles.trigger}\n type=\"button\"\n aria-expanded={open}\n aria-controls=\"update-activity-dialog\"\n onClick={() => {\n setNow(new Date())\n setOpen(true)\n }}\n >\n Update activity\n </button>\n {open && (\n <section\n ref={dialogRef}\n className={styles.dialog}\n data-update-activity\n id=\"update-activity-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"update-activity-title\"\n >\n <div className={styles.dialogHeader}>\n <div>\n <h2 id=\"update-activity-title\">Update activity</h2>\n <p>\n Browser-local proxy reads from the last 10 minutes. Panels schedule independently.\n </p>\n </div>\n <button\n ref={closeRef}\n className={styles.close}\n type=\"button\"\n onClick={() => setOpen(false)}\n >\n Close\n </button>\n </div>\n <div className={styles.body}>\n <span className={styles.legend}>● observed · ◇ expected</span>\n {board && activity.lanes.length === 0 && (\n <p className={styles.empty}>No visible polling panels are configured.</p>\n )}\n {activity.lanes.length > 0 && (\n <>\n <div className={styles.axis} aria-hidden=\"true\">\n <span>10m ago</span>\n <span>now</span>\n </div>\n <div className={styles.lanes}>\n {activity.lanes.map((lane) => (\n <div className={styles.lane} data-update-activity-lane key={lane.panelId}>\n <span className={styles.laneLabel}>{lane.label}</span>\n <span\n className={styles.track}\n role=\"img\"\n aria-label={activityLaneLabel(lane, now)}\n >\n {lane.observed.flatMap(({ path, starts }) =>\n starts.map((start) => (\n <i\n className={styles.observed}\n key={`${path}-${start}`}\n style={{ left: `${activityMarkerPosition(start, now)}%` }}\n title={`Observed request: ${path}`}\n />\n )),\n )}\n {lane.nextDueAt && (\n <i\n className={styles.expected}\n style={{ left: `${activityMarkerPosition(lane.nextDueAt, now)}%` }}\n title=\"Expected next poll\"\n />\n )}\n </span>\n </div>\n ))}\n </div>\n </>\n )}\n {activity.evidenceMayBeIncomplete && (\n <p className={styles.note}>\n Older browser evidence was pruned, so an empty lane only means no retained request\n in this window.\n </p>\n )}\n <p className={styles.note}>\n Observed markers are requests this browser started; the outlined marker is the current\n expected next poll, not an observed request.\n </p>\n </div>\n </section>\n )}\n </>\n )\n}\n","import { type ClientEnv, clientIdentityResponseSchema } from '@ze-great-dashboard/shared'\nimport { useEffect } from 'react'\nimport type { DashboardAuth } from './dashboard-fetch.ts'\nimport { dashboardFetch } from './dashboard-fetch.ts'\nimport type { DiagnosticSink } from './diagnostics.ts'\n\nconst clientUpdateIntervalMillis = 60_000\nconst clientUpdateTimeoutMillis = 10_000\nconst defaultReload = () => globalThis.window.location.reload()\n\nexport function useClientUpdate({\n env,\n diagnostics,\n fetcher,\n reload = defaultReload,\n auth,\n}: {\n env: ClientEnv\n diagnostics: DiagnosticSink\n fetcher?: typeof fetch\n reload?: () => void\n auth?: DashboardAuth\n}) {\n useEffect(() => {\n let cancelled = false\n let inFlight = false\n let activeController: AbortController | undefined\n const path = `${env.proxyPath}/client`\n\n const check = async () => {\n if (cancelled || inFlight) return\n inFlight = true\n const controller = new AbortController()\n activeController = controller\n const timeout = globalThis.setTimeout(() => controller.abort(), clientUpdateTimeoutMillis)\n diagnostics.record({ kind: 'client-update-check', path })\n try {\n const response = await dashboardFetch(\n env,\n path,\n {\n cache: 'no-store',\n signal: controller.signal,\n },\n fetcher ?? globalThis.fetch,\n auth,\n )\n if (!response.ok) throw new Error(`Client identity returned ${response.status}`)\n const parsed = clientIdentityResponseSchema.safeParse(await response.json())\n if (!parsed.success) throw new Error('Client identity response was invalid')\n if (cancelled) return\n diagnostics.record({\n kind: 'client-update-response',\n path,\n serverVersion: parsed.data.serverVersion,\n assetPathIdMatches: parsed.data.assetPathId === env.assetPathId,\n })\n if (parsed.data.assetPath !== env.assetPath) {\n diagnostics.record({\n kind: 'client-update-detected',\n path,\n current: { assetPath: env.assetPath },\n next: parsed.data,\n })\n reload()\n }\n } catch (error) {\n if (!cancelled && !(error instanceof DOMException && error.name === 'AbortError')) {\n diagnostics.record({\n kind: 'client-update-failure',\n path,\n message: error instanceof Error ? error.message : String(error),\n })\n }\n } finally {\n globalThis.clearTimeout(timeout)\n inFlight = false\n if (activeController === controller) activeController = undefined\n if (!cancelled) globalThis.setTimeout(() => void check(), clientUpdateIntervalMillis)\n }\n }\n\n void check()\n return () => {\n cancelled = true\n activeController?.abort()\n }\n }, [auth, diagnostics, env, fetcher, reload])\n}\n","import {\n type Envelope,\n type Panel,\n pipelineStatusSchema,\n pullRequestHealthSchema,\n} from '@ze-great-dashboard/shared'\nimport type { RenderedPanelDiagnostic } from './diagnostics.ts'\nimport type { HttpValueFactObservation } from './panel-props.ts'\n\n/**\n * The compact public fact a viewer saw. Keep new panel projections here beside their\n * presentation boundary; this is intentionally not a source or server event contract.\n */\nexport function projectPanelDiagnostic(panel: Panel, envelope: Envelope): RenderedPanelDiagnostic {\n if (envelope.state === 'error') return { state: envelope.state, link: envelope.link }\n\n if (panel.type === 'pipeline-status') {\n const signal = pipelineStatusSchema.safeParse(envelope.signal)\n return {\n state: envelope.state,\n status: signal.success ? signal.data.status : undefined,\n link: envelope.link,\n }\n }\n\n if (panel.type === 'pull-request-health') {\n const signal = pullRequestHealthSchema.safeParse(envelope.signal)\n return {\n state: envelope.state,\n status: signal.success ? signal.data.status : undefined,\n link: envelope.link,\n }\n }\n\n return { state: envelope.state, link: envelope.link }\n}\n\nexport function panelDiagnosticChanged(\n previous: Envelope | undefined,\n panel: Panel,\n next: Envelope,\n) {\n if (!previous) return true\n const before = projectPanelDiagnostic(panel, previous)\n const after = projectPanelDiagnostic(panel, next)\n return (\n before.state !== after.state || before.status !== after.status || before.link !== after.link\n )\n}\n\n/** Public evidence for a visual group whose sources were observed independently. */\nexport function projectHttpValueFactsDiagnostic(\n facts: Record<string, HttpValueFactObservation | undefined>,\n): RenderedPanelDiagnostic {\n const projected = Object.entries(facts).map(([id, observation]) => {\n if (!observation?.envelope) return { id, state: 'unavailable' as const, link: null }\n return { id, state: observation.envelope.state, link: observation.envelope.link }\n })\n return {\n state: projected.some((fact) => fact.state === 'ok') ? 'ok' : 'error',\n link: null,\n facts: projected,\n }\n}\n\nexport function httpValueFactsDiagnosticChanged(\n previous: Record<string, HttpValueFactObservation | undefined> | undefined,\n next: Record<string, HttpValueFactObservation | undefined>,\n) {\n return (\n JSON.stringify(previous && projectHttpValueFactsDiagnostic(previous)) !==\n JSON.stringify(projectHttpValueFactsDiagnostic(next))\n )\n}\n","import type { Panel, PipelineStatus } from '@ze-great-dashboard/shared'\nimport { browserLocalStorage, readBrowserJson, writeBrowserJson } from './browser-storage.ts'\n\nconst storageKey = 'ze-great-dashboard.panel-memory.v1'\nconst schemaVersion = 1\nconst historyWindowMillis = 14 * 24 * 60 * 60 * 1_000\n\nexport type PanelMemoryIdentity = {\n board: string\n panelId: string\n source: string\n workflow: string\n branch: string\n}\n\nexport type AcceptedPipeline = {\n sourceUpdatedAt: string\n status: PipelineStatus['status']\n link: string | null\n}\n\nexport type DurationSample = {\n link: string | null\n sourceRunId?: string\n durationMs: number\n sourceUpdatedAt: string\n}\ntype History = {\n latest?: AcceptedPipeline\n durations: Record<string, DurationSample>\n latestCompleted?: DurationSample\n}\ntype StoredMemory = { schemaVersion: number; histories: Record<string, History> }\ntype StorageLike = Pick<Storage, 'getItem' | 'setItem'>\n\nexport class BrowserPanelMemory {\n private histories: Record<string, History>\n private readonly storage: StorageLike | undefined\n\n constructor(\n storage: StorageLike | undefined = browserLocalStorage(),\n private readonly now: () => Date = () => new Date(),\n ) {\n this.storage = storage\n this.histories = this.read()\n this.pruneAll()\n }\n\n latest(identity: PanelMemoryIdentity): AcceptedPipeline | undefined {\n return this.history(identity).latest\n }\n\n rememberLatest(identity: PanelMemoryIdentity, latest: AcceptedPipeline) {\n this.history(identity).latest = latest\n this.persist()\n }\n\n recordRun(identity: PanelMemoryIdentity, sample: DurationSample, successful = false) {\n const history = this.history(identity)\n if (successful) history.durations[sampleKey(sample)] = sample\n const previous = history.latestCompleted\n if (!previous || isAtLeastAsRecent(sample.sourceUpdatedAt, previous.sourceUpdatedAt)) {\n history.latestCompleted = sample\n }\n this.pruneHistory(history)\n this.persist()\n }\n\n recordSuccessfulRun(identity: PanelMemoryIdentity, sample: DurationSample) {\n this.recordRun(identity, sample, true)\n }\n\n recordCompletedRun(identity: PanelMemoryIdentity, sample: DurationSample) {\n this.recordRun(identity, sample)\n }\n\n medianDuration(identity: PanelMemoryIdentity): number | undefined {\n const history = this.history(identity)\n this.pruneHistory(history)\n const durations = Object.values(history.durations)\n .map(({ durationMs }) => durationMs)\n .sort((left, right) => left - right)\n if (durations.length === 0) return undefined\n const middle = Math.floor(durations.length / 2)\n if (durations.length % 2 === 1) return durations[middle]\n const lower = durations[middle - 1]\n const upper = durations[middle]\n return lower === undefined || upper === undefined ? undefined : Math.floor((lower + upper) / 2)\n }\n\n resolveEstimatedDuration(identity: PanelMemoryIdentity): number | undefined {\n const successful = this.medianDuration(identity)\n if (successful !== undefined) return successful\n\n const history = this.history(identity)\n this.pruneHistory(history)\n return history.latestCompleted?.durationMs\n }\n\n private history(identity: PanelMemoryIdentity) {\n const key = identityKey(identity)\n const existing = this.histories[key]\n if (existing) return existing\n const created: History = { durations: {} }\n this.histories[key] = created\n return created\n }\n\n private pruneAll() {\n for (const history of Object.values(this.histories)) this.pruneHistory(history)\n this.persist()\n }\n\n private pruneHistory(history: History) {\n const cutoff = this.now().valueOf() - historyWindowMillis\n for (const [link, sample] of Object.entries(history.durations)) {\n const at = sourceTimestamp(sample.sourceUpdatedAt)\n if (at === undefined || at < cutoff) delete history.durations[link]\n }\n const latestCompletedAt = history.latestCompleted\n ? sourceTimestamp(history.latestCompleted.sourceUpdatedAt)\n : undefined\n if (\n history.latestCompleted &&\n (latestCompletedAt === undefined || latestCompletedAt < cutoff)\n ) {\n delete history.latestCompleted\n }\n }\n\n private read(): Record<string, History> {\n const parsed = readBrowserJson<Partial<StoredMemory>>(this.storage, storageKey)\n if (parsed?.schemaVersion !== schemaVersion || !parsed.histories) return {}\n return isHistories(parsed.histories) ? parsed.histories : {}\n }\n\n private persist() {\n writeBrowserJson(this.storage, storageKey, { schemaVersion, histories: this.histories })\n }\n}\n\nfunction sampleKey(sample: DurationSample) {\n return sample.sourceRunId ?? sample.link ?? sample.sourceUpdatedAt\n}\n\nfunction isAtLeastAsRecent(left: string, right: string) {\n const leftAt = sourceTimestamp(left)\n const rightAt = sourceTimestamp(right)\n return leftAt !== undefined && (rightAt === undefined || leftAt >= rightAt)\n}\n\nfunction sourceTimestamp(value: string) {\n const timestamp = Date.parse(value)\n return Number.isFinite(timestamp) ? timestamp : undefined\n}\n\nexport function resolvePanelMemoryIdentity(board: string, panel: Panel): PanelMemoryIdentity {\n return {\n board,\n panelId: panel.id,\n source: panel.source ?? '',\n workflow:\n typeof panel.pipeline === 'string' || typeof panel.pipeline === 'number'\n ? String(panel.pipeline)\n : '',\n branch: panel.branch ?? '',\n }\n}\n\nfunction identityKey(identity: PanelMemoryIdentity) {\n return JSON.stringify([\n identity.board,\n identity.panelId,\n identity.source,\n identity.workflow,\n identity.branch,\n ])\n}\n\nfunction isHistories(value: unknown): value is Record<string, History> {\n if (!isRecord(value)) return false\n return Object.values(value).every(isHistory)\n}\n\nfunction isHistory(value: unknown): value is History {\n if (!isRecord(value) || !isRecord(value.durations)) return false\n if (!Object.values(value.durations).every(isDurationSample)) return false\n return value.latestCompleted === undefined || isDurationSample(value.latestCompleted)\n}\n\nfunction isDurationSample(value: unknown): value is DurationSample {\n if (!isRecord(value)) return false\n return (\n (typeof value.link === 'string' || value.link === null) &&\n (value.sourceRunId === undefined || typeof value.sourceRunId === 'string') &&\n typeof value.durationMs === 'number' &&\n Number.isInteger(value.durationMs) &&\n value.durationMs >= 0 &&\n typeof value.sourceUpdatedAt === 'string' &&\n sourceTimestamp(value.sourceUpdatedAt) !== undefined\n )\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n","import { type Envelope, envelopeSchema } from '@ze-great-dashboard/shared'\nimport { cacheMetadata, type DiagnosticSink } from './diagnostics.ts'\n\nexport type ComponentObservation = { envelope?: Envelope; error?: string }\n\n/**\n * Reads one bounded panel component while retaining its browser cache conversation and public\n * diagnostics. Composite panels use this instead of inventing an aggregate source response.\n */\nexport async function readPanelObservation(args: {\n diagnostics: DiagnosticSink\n panelId: string\n path: string\n signal?: AbortSignal\n cache: Map<string, Envelope>\n fetcher: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>\n}): Promise<ComponentObservation> {\n args.diagnostics.record({ kind: 'panel-fetch-start', panelId: args.panelId, path: args.path })\n try {\n const response = await args.fetcher(args.path, { signal: args.signal })\n const transport = {\n kind: 'panel-fetch-response' as const,\n panelId: args.panelId,\n path: args.path,\n status: response.status,\n cache: cacheMetadata(response.headers),\n }\n if (response.status === 304) {\n args.diagnostics.record(transport)\n const cached = args.cache.get(args.path)\n return cached\n ? { envelope: cached }\n : { error: 'Source returned not modified before an initial observation.' }\n }\n const parsed = envelopeSchema.safeParse(await response.json())\n if (!parsed.success) {\n args.diagnostics.record(transport)\n args.diagnostics.record({\n kind: 'panel-fetch-parse-failure',\n panelId: args.panelId,\n path: args.path,\n message: 'Response was not a valid signal envelope.',\n })\n return { error: 'Response was not a valid signal envelope.' }\n }\n const envelope = parsed.data\n args.diagnostics.record({\n ...transport,\n envelope,\n ...(envelope.state === 'error' ? { failure: failedObservation(envelope, response) } : {}),\n })\n if (envelope.state === 'ok') args.cache.set(args.path, envelope)\n return { envelope }\n } catch (error) {\n if (!args.signal?.aborted)\n args.diagnostics.record({\n kind: 'panel-fetch-failure',\n panelId: args.panelId,\n path: args.path,\n message: errorMessage(error),\n })\n return { error: errorMessage(error) }\n }\n}\n\nfunction failedObservation(envelope: Extract<Envelope, { state: 'error' }>, response: Response) {\n const supportReference = response.headers.get('x-dashboard-request-id')\n return {\n reason: envelope.error.message,\n ...(supportReference ? { supportReference } : {}),\n }\n}\n\nfunction errorMessage(error: unknown) {\n return error instanceof Error ? error.message : String(error)\n}\n","import type { Envelope, PipelineStatus } from '@ze-great-dashboard/shared'\nimport { pipelineStatusSchema } from '@ze-great-dashboard/shared'\nimport type { AcceptedPipeline } from './panel-memory.ts'\n\nexport type PipelineDurationSample = {\n link: string | null\n sourceRunId?: string\n durationMs: number\n sourceUpdatedAt: string\n}\n\nexport type PipelineReconciliation =\n | { kind: 'not-pipeline'; envelope: Envelope }\n | {\n kind: 'rejected'\n envelope: Extract<Envelope, { state: 'ok' }>\n signal: PipelineStatus & { sourceUpdatedAt: string }\n }\n | {\n kind: 'accepted'\n envelope: Envelope\n signal: PipelineStatus\n accepted?: AcceptedPipeline\n durationSample?: PipelineDurationSample\n }\n\nexport function reconcilePipelineResponse(args: {\n envelope: Envelope\n accepted?: AcceptedPipeline\n estimatedDurationMs?: number\n}): PipelineReconciliation {\n const signal = pipelineStatus(args.envelope)\n if (!signal) return { kind: 'not-pipeline', envelope: args.envelope }\n if (\n args.accepted &&\n signal.sourceUpdatedAt &&\n Date.parse(signal.sourceUpdatedAt) < Date.parse(args.accepted.sourceUpdatedAt)\n ) {\n if (args.envelope.state !== 'ok' || !signal.sourceUpdatedAt)\n return { kind: 'not-pipeline', envelope: args.envelope }\n return {\n kind: 'rejected',\n envelope: args.envelope,\n signal: { ...signal, sourceUpdatedAt: signal.sourceUpdatedAt },\n }\n }\n\n const accepted = signal.sourceUpdatedAt\n ? { sourceUpdatedAt: signal.sourceUpdatedAt, status: signal.status, link: args.envelope.link }\n : undefined\n const durationSample =\n signal.status !== 'running' &&\n signal.durationMs !== undefined &&\n signal.sourceUpdatedAt &&\n Number.isFinite(Date.parse(signal.sourceUpdatedAt))\n ? {\n link: args.envelope.link,\n ...(signal.sourceRunId ? { sourceRunId: signal.sourceRunId } : {}),\n durationMs: signal.durationMs,\n sourceUpdatedAt: signal.sourceUpdatedAt,\n }\n : undefined\n const envelope =\n signal.status === 'running' &&\n args.estimatedDurationMs !== undefined &&\n args.envelope.state === 'ok'\n ? { ...args.envelope, signal: { ...signal, estimatedDurationMs: args.estimatedDurationMs } }\n : args.envelope\n return { kind: 'accepted', envelope, signal, accepted, durationSample }\n}\n\nexport function pipelineStatus(envelope: Envelope): PipelineStatus | undefined {\n if (envelope.state !== 'ok') return undefined\n const result = pipelineStatusSchema.safeParse(envelope.signal)\n return result.success ? result.data : undefined\n}\n","import {\n type Board,\n type ClientEnv,\n isZeroPosition,\n resolvePollingSettings,\n} from '@ze-great-dashboard/shared'\nimport type { PollingScheduleSnapshot } from './polling-schedule.ts'\n\ntype PollingPanel = Board['panels'][number] & {\n type: 'pipeline-status' | 'pull-request-health' | 'http-value'\n}\n\n/** The exact visible panel types that originate proxy polling in this client. */\nexport function pollingPanels(board: Board): PollingPanel[] {\n return board.panels.filter(\n (panel): panel is PollingPanel =>\n !isZeroPosition(panel.position) &&\n (panel.type === 'pipeline-status' ||\n panel.type === 'pull-request-health' ||\n panel.type === 'http-value'),\n )\n}\n\nexport function panelProxyPath(env: ClientEnv, panelId: string) {\n return `${env.proxyPath}/panel/${encodeURIComponent(env.board)}/${encodeURIComponent(panelId)}`\n}\n\n/** Build the initial schedule without claiming branch-dependent fan-out before it is observed. */\nexport function initialPollingSchedule(\n board: Board,\n env: ClientEnv,\n panel: PollingPanel,\n): PollingScheduleSnapshot {\n const path = panelProxyPath(env, panel.id)\n const knownPaths =\n panel.type === 'http-value' && panel.facts\n ? panel.facts.map((fact) => `${path}/facts/${encodeURIComponent(fact.id)}`)\n : panel.type === 'pull-request-health'\n ? [\n `${path}/pull-requests`,\n ...readUpdateWorkflows(panel).map(\n ({ workflow }) => `${path}/update-workflow/${encodeURIComponent(workflow)}`,\n ),\n ]\n : [path]\n return {\n panelId: panel.id,\n label: panel.label ?? panel.id,\n settings: resolvePollingSettings(board, panel),\n cadence: 'normal',\n inFlight: false,\n knownPaths,\n }\n}\n\nexport function readUpdateWorkflows(panel: unknown) {\n const value =\n typeof panel === 'object' && panel !== null\n ? (panel as { update_workflows?: unknown }).update_workflows\n : undefined\n if (!Array.isArray(value)) return []\n return value.flatMap((entry) =>\n typeof entry === 'object' &&\n entry !== null &&\n typeof (entry as { workflow?: unknown }).workflow === 'string'\n ? [{ workflow: (entry as { workflow: string }).workflow }]\n : [],\n )\n}\n","import {\n type Envelope,\n type PipelineStatus,\n type PollingSettings,\n pipelineStatusSchema,\n} from '@ze-great-dashboard/shared'\n\n/** Ephemeral scheduling state; polling owns it and views may project it. */\nexport type PollingScheduleSnapshot = {\n panelId: string\n label: string\n settings: PollingSettings\n cadence: PollingCadence\n inFlight: boolean\n lastRequestStartedAt?: string\n nextDueAt?: string\n /** Paths known before this cycle; dynamic fan-out is disclosed only once observed. */\n knownPaths: string[]\n}\n\n/** Return the next delay for a panel, keeping active runs responsive without polling forever at burst speed. */\nexport function nextPollDelayMillis(\n envelope: Envelope | undefined,\n nowMillis: number,\n settings: PollingSettings,\n): number {\n return resolveNextPoll(envelope, nowMillis, settings).delayMillis\n}\n\nexport type PollingCadence = 'normal' | 'running' | 'completion-window'\n\n/** The scheduler and activity view share this resolved cadence; neither infers it from history. */\nexport function resolveNextPoll(\n envelope: Envelope | undefined,\n nowMillis: number,\n settings: PollingSettings,\n): { delayMillis: number; cadence: PollingCadence } {\n const pipeline = runningPipeline(envelope)\n if (!pipeline) return { delayMillis: settings.refreshMillis, cadence: 'normal' }\n\n const completionAt = estimatedCompletionAt(pipeline)\n if (completionAt === undefined)\n return { delayMillis: settings.runningRefreshMillis, cadence: 'running' }\n\n if (nowMillis < completionAt) {\n return {\n delayMillis: Math.min(settings.runningRefreshMillis, completionAt - nowMillis),\n cadence: 'running',\n }\n }\n if (nowMillis < completionAt + settings.runningCompletionWindowMillis) {\n return { delayMillis: settings.runningCompletionRefreshMillis, cadence: 'completion-window' }\n }\n return { delayMillis: settings.runningRefreshMillis, cadence: 'running' }\n}\n\nfunction runningPipeline(envelope: Envelope | undefined): PipelineStatus | undefined {\n if (envelope?.state !== 'ok') return undefined\n const result = pipelineStatusSchema.safeParse(envelope.signal)\n return result.success && result.data.status === 'running' ? result.data : undefined\n}\n\nfunction estimatedCompletionAt(signal: PipelineStatus): number | undefined {\n if (!signal.runStartedAt || signal.estimatedDurationMs === undefined) return undefined\n const startedAt = Date.parse(signal.runStartedAt)\n return Number.isFinite(startedAt) ? startedAt + signal.estimatedDurationMs : undefined\n}\n","import type {\n Envelope,\n PipelineStatus,\n PullRequestCandidate,\n PullRequestHealth,\n} from '@ze-great-dashboard/shared'\nimport {\n pipelineStatusPriority,\n pullRequestBuildObservationSchema,\n pullRequestCandidatesSchema,\n pullRequestWorkflowObservationSchema,\n} from '@ze-great-dashboard/shared'\n\ntype Observation = { envelope?: Envelope; error?: string }\n\n/** Purely combines normalized, public component observations; it never constructs source URLs. */\nexport function rollupPullRequestHealth(args: {\n panelId: string\n link: string | null\n workflows: Array<{ workflow: string; observation: Observation }>\n candidates: Observation\n builds: Map<string, Observation>\n}): Envelope | undefined {\n const incomplete: Array<{ label: string; message: string }> = []\n const workflows = args.workflows.map(({ workflow, observation }) => {\n const signal = observationItem(observation.envelope, 'pull-request-workflow')\n if (signal) return signal.item as PullRequestHealth['workflows'][number]\n const message = observation.error ?? 'No usable observation is available.'\n incomplete.push({ label: `Update workflow ${workflow}`, message })\n return {\n label: workflow,\n status: 'unknown' as const,\n detail: `Update workflow ${workflow} · Unavailable: ${message}`,\n link: null,\n }\n })\n const candidatesSignal = candidateSignal(args.candidates.envelope)\n if (!candidatesSignal) {\n const message = args.candidates.error ?? 'No usable observation is available.'\n incomplete.push({ label: 'Open update PR candidates', message })\n if (workflows.every((item) => item.status === 'unknown')) return undefined\n return buildEnvelope(\n args,\n workflows,\n [],\n incomplete,\n observationDates(args.workflows.map(({ observation }) => observation)),\n )\n }\n if (candidatesSignal.truncated)\n incomplete.push({\n label: 'Open update PR candidates',\n message: 'The first 100 candidates were observed; additional open update PRs may exist.',\n })\n const pullRequests = candidatesSignal.pullRequests.map((candidate: PullRequestCandidate) => {\n const observation = args.builds.get(candidate.branch)\n const signal = observationItem(observation?.envelope, 'pull-request-build')\n if (signal)\n return {\n ...signal.item,\n label: `PR #${candidate.number}`,\n detail: signal.item.detail,\n link: candidate.link,\n }\n const message = observation?.error ?? 'No usable observation is available.'\n incomplete.push({ label: `PR #${candidate.number}`, message })\n return {\n label: `PR #${candidate.number}`,\n status: 'unknown' as const,\n detail: `${candidate.branch} · Unavailable: ${message}`,\n link: candidate.link,\n }\n })\n return buildEnvelope(\n args,\n workflows,\n pullRequests,\n incomplete,\n observationDates([\n ...args.workflows.map(({ observation }) => observation),\n args.candidates,\n ...args.builds.values(),\n ]),\n )\n}\n\nfunction buildEnvelope(\n args: Parameters<typeof rollupPullRequestHealth>[0],\n workflows: PullRequestHealth['workflows'],\n pullRequests: PullRequestHealth['pullRequests'],\n incomplete: Array<{ label: string; message: string }>,\n dates: string[],\n) {\n const status = aggregateStatus([...workflows, ...pullRequests].map((item) => item.status))\n const attentionItem = [...workflows, ...pullRequests].find((item) => item.status === status)\n const summary =\n status !== 'passed' && attentionItem\n ? `${attentionItem.label}: ${attentionItem.detail}`\n : pullRequests.length === 0\n ? `${workflows.length} update workflow${workflows.length === 1 ? '' : 's'} · No open update PRs`\n : `${workflows.length} update workflow${workflows.length === 1 ? '' : 's'} · ${pullRequests.length} open update PR${pullRequests.length === 1 ? '' : 's'}`\n const sorted = dates.sort()\n return {\n panelId: args.panelId,\n state: 'ok' as const,\n observedAt: sorted[0] ?? new Date().toISOString(),\n link: args.link,\n signal: {\n type: 'pull-request-health' as const,\n status,\n summary,\n workflows,\n pullRequests,\n ...(incomplete.length ? { incompleteObservations: incomplete } : {}),\n ...(sorted.length > 1 ? { newestObservedAt: sorted.at(-1) } : {}),\n } satisfies PullRequestHealth,\n }\n}\n\nfunction observationItem(\n envelope: Envelope | undefined,\n type: 'pull-request-workflow' | 'pull-request-build',\n): { item: PullRequestHealth['workflows'][number] } | undefined {\n if (envelope?.state !== 'ok') return undefined\n const schema =\n type === 'pull-request-workflow'\n ? pullRequestWorkflowObservationSchema\n : pullRequestBuildObservationSchema\n const result = schema.safeParse(envelope.signal)\n return result.success ? { item: result.data.item } : undefined\n}\nfunction candidateSignal(\n envelope: Envelope | undefined,\n): { pullRequests: PullRequestCandidate[]; truncated?: boolean } | undefined {\n if (envelope?.state !== 'ok') return undefined\n const result = pullRequestCandidatesSchema.safeParse(envelope.signal)\n return result.success ? result.data : undefined\n}\nfunction observationDates(observations: Observation[]) {\n return observations.flatMap(({ envelope }) =>\n envelope?.state === 'ok' ? [envelope.observedAt] : [],\n )\n}\nfunction aggregateStatus(statuses: PipelineStatus['status'][]): PipelineStatus['status'] {\n return statuses.reduce(\n (mostUrgent, status) =>\n pipelineStatusPriority(status) > pipelineStatusPriority(mostUrgent) ? status : mostUrgent,\n 'passed' as const,\n )\n}\n","import {\n type Board,\n type ClientEnv,\n type Envelope,\n envelopeSchema,\n} from '@ze-great-dashboard/shared'\nimport { useEffect, useRef, useState } from 'react'\nimport type { DashboardAuth } from './dashboard-fetch.ts'\nimport { dashboardFetch } from './dashboard-fetch.ts'\nimport { cacheMetadata, type DiagnosticSink } from './diagnostics.ts'\nimport {\n httpValueFactsDiagnosticChanged,\n panelDiagnosticChanged,\n projectHttpValueFactsDiagnostic,\n projectPanelDiagnostic,\n} from './panel-diagnostics.ts'\nimport { BrowserPanelMemory, resolvePanelMemoryIdentity } from './panel-memory.ts'\nimport { readPanelObservation } from './panel-observation.ts'\nimport type { HttpValueFactObservation, PanelUpdateHealth } from './panel-props.ts'\nimport { reconcilePipelineResponse } from './pipeline-reconciliation.ts'\nimport {\n initialPollingSchedule,\n panelProxyPath,\n pollingPanels,\n readUpdateWorkflows,\n} from './polling-panels.ts'\nimport { type PollingScheduleSnapshot, resolveNextPoll } from './polling-schedule.ts'\nimport { rollupPullRequestHealth } from './pull-request-rollup.ts'\n\nexport function usePanelSignals({\n board,\n env,\n diagnostics,\n memory,\n auth,\n}: {\n board: Board | undefined\n env: ClientEnv\n diagnostics: DiagnosticSink\n memory?: BrowserPanelMemory\n auth?: DashboardAuth\n}) {\n const [signals, setSignals] = useState<Record<string, Envelope | undefined>>({})\n const [updateHealth, setUpdateHealth] = useState<Record<string, PanelUpdateHealth | undefined>>(\n {},\n )\n const [factSignals, setFactSignals] = useState<\n Record<string, Record<string, HttpValueFactObservation | undefined> | undefined>\n >({})\n const [schedules, setSchedules] = useState<PollingScheduleSnapshot[]>([])\n const signalsRef = useRef<Record<string, Envelope | undefined>>({})\n const factSignalsRef = useRef<\n Record<string, Record<string, HttpValueFactObservation | undefined> | undefined>\n >({})\n const memoryRef = useRef<BrowserPanelMemory | null>(null)\n if (!memoryRef.current) memoryRef.current = memory ?? new BrowserPanelMemory()\n\n useEffect(() => {\n signalsRef.current = {}\n factSignalsRef.current = {}\n setSignals({})\n setUpdateHealth({})\n setFactSignals({})\n setSchedules([])\n if (!board) return\n\n let cancelled = false\n const timers = new Set<number>()\n const abortControllers = new Set<AbortController>()\n const panels = pollingPanels(board)\n const initialSchedules = panels.map((panel) => initialPollingSchedule(board, env, panel))\n const schedulesByPanelId = new Map(\n initialSchedules.map((schedule) => [schedule.panelId, schedule]),\n )\n setSchedules(initialSchedules)\n const updateSchedule = (panelId: string, update: Partial<PollingScheduleSnapshot>) => {\n if (cancelled) return\n setSchedules((current) =>\n current.map((schedule) =>\n schedule.panelId === panelId ? { ...schedule, ...update } : schedule,\n ),\n )\n }\n for (const panel of panels) {\n let inFlight = false\n const memory = memoryRef.current\n if (!memory) return\n const schedule = schedulesByPanelId.get(panel.id)\n if (!schedule) continue\n const { settings } = schedule\n const path = panelProxyPath(env, panel.id)\n let lastEnvelope: Envelope | undefined\n let lastConfirmedAt: string | undefined\n const recordConfirmedUpdate = () => {\n lastConfirmedAt = new Date().toISOString()\n if (!cancelled)\n setUpdateHealth((current) => {\n if (!current[panel.id]) return current\n const next = { ...current }\n delete next[panel.id]\n return next\n })\n }\n const recordUpdateFailure = (error: unknown) => {\n const confirmedAt = lastConfirmedAt\n if (cancelled || !confirmedAt) return\n const message = errorMessage(error)\n setUpdateHealth((current) => {\n const previous = current[panel.id]\n return {\n ...current,\n [panel.id]: {\n consecutiveFailures: (previous?.consecutiveFailures ?? 0) + 1,\n message,\n lastConfirmedAt: confirmedAt,\n },\n }\n })\n }\n if (panel.type === 'http-value' && panel.facts) {\n const facts = panel.facts\n const components = new Map<string, Envelope>()\n let activeController: AbortController | undefined\n const refreshFacts = async () => {\n if (cancelled || inFlight) return\n inFlight = true\n updateSchedule(panel.id, {\n inFlight: true,\n lastRequestStartedAt: new Date().toISOString(),\n nextDueAt: undefined,\n })\n activeController = new AbortController()\n abortControllers.add(activeController)\n const root = `${path}/facts`\n const observations = await Promise.all(\n facts.map(async (fact) => {\n const factPath = `${root}/${encodeURIComponent(fact.id)}`\n const result = await readPanelObservation({\n diagnostics,\n panelId: panel.id,\n path: factPath,\n signal: activeController?.signal,\n cache: components,\n fetcher: (input, init) => dashboardFetch(env, input, init, globalThis.fetch, auth),\n })\n return [fact.id, result.error ? { failure: result.error } : result] as const\n }),\n )\n if (!cancelled && !activeController.signal.aborted) {\n const next = Object.fromEntries(observations)\n const previous = factSignalsRef.current[panel.id]\n if (httpValueFactsDiagnosticChanged(previous, next))\n diagnostics.record({\n kind: 'panel-rendered',\n panelId: panel.id,\n path,\n rendered: projectHttpValueFactsDiagnostic(next),\n })\n factSignalsRef.current = { ...factSignalsRef.current, [panel.id]: next }\n setFactSignals(factSignalsRef.current)\n }\n inFlight = false\n abortControllers.delete(activeController)\n if (!cancelled) {\n const due = Date.now() + settings.refreshMillis\n updateSchedule(panel.id, {\n inFlight: false,\n cadence: 'normal',\n nextDueAt: new Date(due).toISOString(),\n })\n const timer = window.setTimeout(() => {\n timers.delete(timer)\n void refreshFacts()\n }, settings.refreshMillis)\n timers.add(timer)\n }\n }\n void refreshFacts()\n continue\n }\n if (panel.type === 'pull-request-health') {\n const workflows = readUpdateWorkflows(panel)\n const components = new Map<string, Envelope>()\n let activeController: AbortController | undefined\n const request = async (componentPath: string) => {\n const result = await readPanelObservation({\n diagnostics,\n panelId: panel.id,\n path: componentPath,\n signal: activeController?.signal,\n cache: components,\n fetcher: (input, init) => dashboardFetch(env, input, init, globalThis.fetch, auth),\n })\n if (result.envelope?.state === 'error') return { error: result.envelope.error.message }\n return result\n }\n const refreshPullRequestHealth = async () => {\n if (cancelled || inFlight) return\n inFlight = true\n updateSchedule(panel.id, {\n inFlight: true,\n lastRequestStartedAt: new Date().toISOString(),\n nextDueAt: undefined,\n })\n activeController = new AbortController()\n abortControllers.add(activeController)\n const root = path\n const [candidateResult, ...workflowResults] = await Promise.all([\n request(`${root}/pull-requests`),\n ...workflows.map(({ workflow }) =>\n request(`${root}/update-workflow/${encodeURIComponent(workflow)}`),\n ),\n ])\n const candidates =\n candidateResult.envelope?.state === 'ok' &&\n isCandidates(candidateResult.envelope.signal)\n ? candidateResult.envelope.signal.pullRequests\n : []\n if (cancelled || activeController.signal.aborted) {\n abortControllers.delete(activeController)\n return\n }\n const buildResults = await Promise.all(\n candidates.map(\n async (candidate) =>\n [\n candidate.branch,\n await request(\n `${root}/pull-request-build?branch=${encodeURIComponent(candidate.branch)}`,\n ),\n ] as const,\n ),\n )\n const rolled = rollupPullRequestHealth({\n panelId: panel.id,\n link: candidateResult.envelope?.link ?? null,\n workflows: workflows.map(({ workflow }, index) => ({\n workflow,\n observation: workflowResults[index] ?? { error: 'Missing workflow result.' },\n })),\n candidates: candidateResult,\n builds: new Map(buildResults),\n })\n if (cancelled || activeController.signal.aborted) {\n abortControllers.delete(activeController)\n return\n }\n if (rolled && !cancelled) {\n lastEnvelope = rolled\n recordConfirmedUpdate()\n const previous = signalsRef.current[panel.id]\n if (panelDiagnosticChanged(previous, panel, rolled))\n diagnostics.record({\n kind: 'panel-rendered',\n panelId: panel.id,\n path,\n rendered: projectPanelDiagnostic(panel, rolled),\n })\n signalsRef.current = { ...signalsRef.current, [panel.id]: rolled }\n setSignals(signalsRef.current)\n } else if (!cancelled) recordUpdateFailure('No usable pull-request observations.')\n inFlight = false\n abortControllers.delete(activeController)\n if (!cancelled) {\n const next = resolveNextPoll(lastEnvelope, Date.now(), settings)\n const due = Date.now() + next.delayMillis\n updateSchedule(panel.id, {\n inFlight: false,\n cadence: next.cadence,\n nextDueAt: new Date(due).toISOString(),\n })\n const nextTimer = window.setTimeout(() => {\n timers.delete(nextTimer)\n void refreshPullRequestHealth()\n }, next.delayMillis)\n timers.add(nextTimer)\n }\n }\n void refreshPullRequestHealth()\n continue\n }\n const refresh = () => {\n if (cancelled || inFlight) return\n inFlight = true\n updateSchedule(panel.id, {\n inFlight: true,\n lastRequestStartedAt: new Date().toISOString(),\n nextDueAt: undefined,\n })\n diagnostics.record({ kind: 'panel-fetch-start', panelId: panel.id, path })\n dashboardFetch(env, path, undefined, globalThis.fetch, auth)\n .then(async (response) => {\n const transport = {\n kind: 'panel-fetch-response' as const,\n panelId: panel.id,\n path,\n status: response.status,\n cache: cacheMetadata(response.headers),\n }\n if (response.status === 304) {\n diagnostics.record(transport)\n recordConfirmedUpdate()\n return undefined\n }\n try {\n const value: unknown = await response.json()\n const envelope = parseEnvelope(value)\n if (!envelope) {\n diagnostics.record(transport)\n diagnostics.record({\n kind: 'panel-fetch-parse-failure',\n panelId: panel.id,\n path,\n message: 'Response was not a valid signal envelope.',\n })\n recordUpdateFailure('Response was not a valid signal envelope.')\n return undefined\n }\n diagnostics.record({\n ...transport,\n envelope,\n ...(envelope.state === 'error'\n ? { failure: failedObservation(envelope, response) }\n : {}),\n })\n recordConfirmedUpdate()\n return { envelope, cache: transport.cache, status: response.status }\n } catch (error) {\n diagnostics.record(transport)\n diagnostics.record({\n kind: 'panel-fetch-parse-failure',\n panelId: panel.id,\n path,\n message: errorMessage(error),\n })\n throw new DiagnosticParseFailure(error)\n }\n })\n .then((result) => {\n if (!result) return\n let envelope = result.envelope\n if (panel.type === 'pipeline-status') {\n const identity = resolvePanelMemoryIdentity(env.board, panel)\n const accepted = memory.latest(identity)\n const reconciliation = reconcilePipelineResponse({\n envelope,\n accepted,\n estimatedDurationMs: memory.resolveEstimatedDuration(identity),\n })\n if (reconciliation.kind === 'rejected' && accepted) {\n const signal = reconciliation.signal\n diagnostics.recordGithubConsistencyIncident({\n panelId: panel.id,\n endpoint: path,\n identity: {\n source: identity.source,\n workflow: identity.workflow,\n branch: identity.branch,\n },\n accepted,\n regressed: {\n sourceUpdatedAt: signal.sourceUpdatedAt,\n status: signal.status,\n link: envelope.link,\n },\n response: {\n httpStatus: result.status,\n date: result.cache?.date,\n etag: result.cache?.etag,\n cacheControl: result.cache?.cacheControl,\n },\n })\n return\n }\n if (reconciliation.kind === 'accepted') {\n envelope = reconciliation.envelope\n if (reconciliation.accepted)\n memory.rememberLatest(identity, reconciliation.accepted)\n if (reconciliation.durationSample) {\n const sample = {\n link: reconciliation.durationSample.link,\n ...(reconciliation.durationSample.sourceRunId\n ? { sourceRunId: reconciliation.durationSample.sourceRunId }\n : {}),\n durationMs: reconciliation.durationSample.durationMs,\n sourceUpdatedAt: reconciliation.durationSample.sourceUpdatedAt,\n }\n memory.recordRun(identity, sample, reconciliation.signal.status === 'passed')\n }\n }\n }\n lastEnvelope = envelope\n if (!cancelled) {\n const previous = signalsRef.current[panel.id]\n if (panelDiagnosticChanged(previous, panel, envelope)) {\n diagnostics.record({\n kind: 'panel-rendered',\n panelId: panel.id,\n path,\n rendered: projectPanelDiagnostic(panel, envelope),\n })\n }\n signalsRef.current = { ...signalsRef.current, [panel.id]: envelope }\n setSignals(signalsRef.current)\n }\n })\n .catch((error) => {\n recordUpdateFailure(error)\n if (!(error instanceof DiagnosticParseFailure)) {\n diagnostics.record({\n kind: 'panel-fetch-failure',\n panelId: panel.id,\n path,\n message: errorMessage(error),\n })\n }\n })\n .finally(() => {\n inFlight = false\n if (!cancelled) {\n const next = resolveNextPoll(lastEnvelope, Date.now(), settings)\n const due = Date.now() + next.delayMillis\n updateSchedule(panel.id, {\n inFlight: false,\n cadence: next.cadence,\n nextDueAt: new Date(due).toISOString(),\n })\n const nextTimer = window.setTimeout(() => {\n timers.delete(nextTimer)\n refresh()\n }, next.delayMillis)\n timers.add(nextTimer)\n }\n })\n }\n refresh()\n }\n return () => {\n cancelled = true\n for (const controller of abortControllers) controller.abort()\n for (const timer of timers) window.clearTimeout(timer)\n }\n }, [auth, board, diagnostics, env])\n\n return { signals, updateHealth, factSignals, schedules }\n}\n\nfunction failedObservation(envelope: Extract<Envelope, { state: 'error' }>, response: Response) {\n const supportReference = response.headers.get('x-dashboard-request-id')\n return {\n reason: envelope.error.message,\n ...(supportReference ? { supportReference } : {}),\n }\n}\n\nfunction isCandidates(\n value: unknown,\n): value is { type: 'pull-request-candidates'; pullRequests: Array<{ branch: string }> } {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { type?: unknown }).type === 'pull-request-candidates' &&\n Array.isArray((value as { pullRequests?: unknown }).pullRequests)\n )\n}\n\nfunction errorMessage(error: unknown) {\n return error instanceof Error ? error.message : String(error)\n}\n\nclass DiagnosticParseFailure extends Error {\n constructor(error: unknown) {\n super(errorMessage(error))\n }\n}\n\nfunction parseEnvelope(value: unknown): Envelope | undefined {\n const result = envelopeSchema.safeParse(value)\n return result.success ? result.data : undefined\n}\n","import {\n analyzeBoardLayout,\n type Board,\n type ClientEnv,\n isZeroPosition,\n} from '@ze-great-dashboard/shared'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport styles from './App.module.css'\nimport { projectAttention } from './attention.ts'\nimport { Diagnostics } from './Diagnostics.tsx'\nimport type { DashboardAuth } from './dashboard-fetch.ts'\nimport { dashboardFetch } from './dashboard-fetch.ts'\nimport { BrowserDiagnosticStore, cacheMetadata } from './diagnostics.ts'\nimport { OidcGate } from './OidcGate.tsx'\nimport { PanelPlaceholder } from './PanelPlaceholder.tsx'\nimport { PanelRenderer } from './panel-registry.tsx'\nimport { SecurityNotice } from './SecurityNotice.tsx'\nimport { UpdateActivity } from './UpdateActivity.tsx'\nimport { projectUpdateActivity } from './update-activity.ts'\nimport { useClientUpdate } from './useClientUpdate.ts'\nimport { usePanelSignals } from './usePanelSignals.ts'\n\n/**\n * The board shell.\n *\n * Stage 1 has no data: there is no proxy endpoint to poll yet. What this proves is the plumbing —\n * that the client was handed its configuration by the server and knows which version of itself it\n * is. The version readout is what makes two published versions visibly different, which is the\n * whole point of the Stage 1 exit criterion.\n */\nexport function App({ env }: { env: ClientEnv }) {\n if (env.security === 'blocked') return <SecurityNotice mode=\"blocked\" />\n return env.auth ? (\n <OidcGate env={env} auth={env.auth}>\n {(accessToken, denied) => <Dashboard env={env} accessToken={accessToken} onDenied={denied} />}\n </OidcGate>\n ) : (\n <Dashboard env={env} />\n )\n}\n\nfunction Dashboard({\n env,\n accessToken,\n onDenied,\n}: {\n env: ClientEnv\n accessToken?: string\n onDenied?: () => void\n}) {\n const [board, setBoard] = useState<Board>()\n const [loadedBoardName, setLoadedBoardName] = useState<string>()\n const diagnosticsRef = useRef<BrowserDiagnosticStore | null>(null)\n if (!diagnosticsRef.current) diagnosticsRef.current = new BrowserDiagnosticStore(env)\n const diagnostics = diagnosticsRef.current\n const auth = useMemo<DashboardAuth | undefined>(\n () =>\n accessToken\n ? { accessToken, onAuthenticationFailure: (status) => status === 403 && onDenied?.() }\n : undefined,\n [accessToken, onDenied],\n )\n useClientUpdate({ env, diagnostics, auth })\n const { signals, updateHealth, factSignals, schedules } = usePanelSignals({\n board: loadedBoardName === env.board ? board : undefined,\n env,\n diagnostics,\n auth,\n })\n const layout = useMemo(() => (board ? analyzeBoardLayout(board.panels) : undefined), [board])\n const attentionDrivers = useMemo(\n () => projectAttention({ board, signals, updateHealth, factSignals }),\n [board, factSignals, signals, updateHealth],\n )\n const attentionTreatment = attentionDrivers.length ? board?.attention?.treatment : undefined\n const activeAttentionPanels = new Set(attentionDrivers.map((driver) => driver.panelId))\n\n useEffect(() => {\n if (!layout || layout.issues.length === 0) return\n diagnostics.record({\n kind: 'layout-analyzed',\n issueCount: layout.issues.length,\n affectedPanelIds: layout.issues.map((issue) => issue.panelId),\n })\n }, [diagnostics, layout])\n\n useEffect(() => {\n let cancelled = false\n setBoard(undefined)\n setLoadedBoardName(undefined)\n const path = `${env.proxyPath}/boards/${encodeURIComponent(env.board)}`\n diagnostics.record({ kind: 'board-fetch-start', path })\n dashboardFetch(env, path, undefined, globalThis.fetch, auth)\n .then(async (response) => {\n diagnostics.record({\n kind: 'board-fetch-response',\n path,\n status: response.status,\n cache: cacheMetadata(response.headers),\n })\n if (!response.ok) throw new Error(`Board configuration returned ${response.status}`)\n try {\n return await response.json()\n } catch (error) {\n diagnostics.record({\n kind: 'board-fetch-parse-failure',\n path,\n message: errorMessage(error),\n })\n throw new DiagnosticParseFailure(error)\n }\n })\n .then((value: unknown) => {\n if (!cancelled) {\n setBoard(value as Board)\n setLoadedBoardName(env.board)\n const panels = Array.isArray((value as { panels?: unknown }).panels)\n ? (value as { panels: Array<{ id?: unknown }> }).panels\n : []\n diagnostics.record({\n kind: 'board-fetch-response',\n path,\n boardSummary: {\n panelCount: panels.length,\n panelIds: panels.flatMap((panel) => (typeof panel.id === 'string' ? [panel.id] : [])),\n },\n })\n }\n })\n .catch((error) => {\n if (!(error instanceof DiagnosticParseFailure)) {\n diagnostics.record({ kind: 'board-fetch-failure', path, message: errorMessage(error) })\n }\n if (!cancelled) {\n setBoard({ panels: [] })\n setLoadedBoardName(env.board)\n }\n })\n return () => {\n cancelled = true\n }\n }, [auth, diagnostics, env])\n\n return (\n <div\n className={`${styles.board} ${attentionTreatment ? styles[`attention-${attentionTreatment}`] : ''}`}\n data-attention-treatment={attentionTreatment}\n data-attention-active={attentionDrivers.length || undefined}\n >\n <header className={styles.header}>\n <h1 className={styles.title}>{env.board}</h1>\n {env.security === 'warning' && <SecurityNotice mode=\"warning\" />}\n {attentionDrivers.length > 0 && (\n <aside\n className={styles.attentionRail}\n role=\"alert\"\n aria-label=\"Important panel attention\"\n >\n <span className={styles.attentionGlyph} aria-hidden=\"true\">\n ⚠\n </span>\n <ul>\n {attentionDrivers.map((driver) => (\n <li key={`${driver.panelId}-${driver.factId ?? 'panel'}-${driver.reason}`}>\n <a href={`#panel-${driver.panelId}`}>\n <strong>{driver.label}</strong>: {driver.reason}\n </a>\n </li>\n ))}\n </ul>\n </aside>\n )}\n </header>\n <main className={styles.grid}>\n {!board && <PanelPlaceholder label=\"board\" hint=\"Loading configuration…\" wide />}\n {board?.panels\n .filter((panel) => !isZeroPosition(panel.position))\n .map((panel) => (\n <PanelRenderer\n key={panel.id}\n panel={panel}\n envelope={signals[panel.id]}\n attentionActive={activeAttentionPanels.has(panel.id)}\n updateHealth={updateHealth[panel.id]}\n facts={factSignals[panel.id]}\n />\n ))}\n </main>\n\n <footer className={styles.footer} data-board-footer>\n <span>Signals are read live from their configured authorities.</span>\n <div className={styles.footerTools}>\n {layout && layout.issues.length > 0 && (\n <LayoutWarning board={env.board} layout={layout} env={env} auth={auth} />\n )}\n <Diagnostics\n log={diagnostics}\n updateActivity={() => {\n const evidence = diagnostics.retainedEvidence()\n const projected = projectUpdateActivity({\n schedules,\n ...evidence,\n })\n return {\n capturedAt: projected.capturedAt,\n window: projected.window,\n schedules: projected.schedules,\n }\n }}\n />\n <UpdateActivity board={board} schedules={schedules} log={diagnostics} />\n </div>\n </footer>\n </div>\n )\n}\n\nfunction LayoutWarning({\n board,\n layout,\n env,\n auth,\n}: {\n board: string\n layout: ReturnType<typeof analyzeBoardLayout>\n env: ClientEnv\n auth?: DashboardAuth\n}) {\n const [open, setOpen] = useState(false)\n const dialogId = `layout-warning-${board}`\n\n useEffect(() => {\n if (!open) return\n const closeOnEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') setOpen(false)\n }\n window.addEventListener('keydown', closeOnEscape)\n return () => window.removeEventListener('keydown', closeOnEscape)\n }, [open])\n\n const boardPath = `${env.proxyPath}/boards/${encodeURIComponent(board)}`\n return (\n <div className={styles.layoutWarning} data-layout-warning>\n <button\n className={styles.layoutWarningButton}\n type=\"button\"\n aria-label={`Layout warnings (${layout.issues.length})`}\n aria-expanded={open}\n aria-controls={dialogId}\n onClick={() => setOpen(!open)}\n >\n <span aria-hidden=\"true\">⚠</span>\n <span>{layout.issues.length}</span>\n </button>\n {open && (\n <aside\n className={styles.layoutWarningDialog}\n id={dialogId}\n role=\"dialog\"\n aria-labelledby={`${dialogId}-title`}\n aria-modal=\"false\"\n >\n <div className={styles.layoutWarningHeading}>\n <strong id={`${dialogId}-title`}>Layout warnings</strong>\n <button\n className={styles.layoutWarningClose}\n type=\"button\"\n aria-label=\"Close layout warnings\"\n onClick={() => setOpen(false)}\n >\n ×\n </button>\n </div>\n <p>\n {layout.issues.length} layout issue{layout.issues.length === 1 ? '' : 's'} detected\n against the intended 12×12 space. The live board is unchanged: explicit overlaps remain\n overlapped and overflow continues in implicit rows.\n </p>\n <ul>\n {layout.issues.map((issue) => (\n <li key={`${issue.panelId}-${issue.kind}`}>\n <strong>{issue.panelId}</strong>: {issue.kind} at ({issue.position.x},{' '}\n {issue.position.y}), {issue.position.w}×{issue.position.h}\n {issue.conflictsWith.length ? `; overlaps ${issue.conflictsWith.join(', ')}` : ''}\n </li>\n ))}\n </ul>\n <div className={styles.layoutWarningDownloads}>\n <button\n type=\"button\"\n onClick={() => void downloadLayout(env, `${boardPath}/rendered`, auth)}\n >\n Download legal rendered layout\n </button>\n <button\n type=\"button\"\n onClick={() => void downloadLayout(env, `${boardPath}/authored`, auth)}\n >\n Download authored layout\n </button>\n </div>\n <p className={styles.layoutWarningNote}>\n The legal rendered layout normalizes the currently visible explicit area into 12×12 and\n makes the smallest deterministic adjustments needed to avoid collisions. The authored\n layout preserves the original coordinates exactly.\n </p>\n </aside>\n )}\n </div>\n )\n}\n\nasync function downloadLayout(env: ClientEnv, path: string, auth?: DashboardAuth) {\n const response = await dashboardFetch(env, path, undefined, globalThis.fetch, auth)\n if (!response.ok) throw new Error(`Layout download returned ${response.status}`)\n const link = document.createElement('a')\n link.href = URL.createObjectURL(await response.blob())\n link.download =\n response.headers.get('content-disposition')?.match(/filename=\"([^\"]+)\"/)?.[1] ?? 'layout.yaml'\n link.click()\n URL.revokeObjectURL(link.href)\n}\n\nfunction errorMessage(error: unknown) {\n return error instanceof Error ? error.message : String(error)\n}\n\nclass DiagnosticParseFailure extends Error {\n constructor(error: unknown) {\n super(errorMessage(error))\n }\n}\n",".error {\n margin: 0 auto;\n max-width: 60ch;\n padding: 2rem;\n color: var(--ink-primary);\n}\n.error pre {\n padding: 1rem;\n border-radius: var(--radius);\n border: 1px solid var(--status-critical);\n background: var(--surface-raised);\n color: var(--ink-secondary);\n font-size: 0.75em;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n","import styles from './ConfigError.module.css'\n\nexport function ConfigError({ message }: { message: string }) {\n return (\n <div className={styles.error} role=\"alert\">\n <h1>⚠️ Dashboard misconfigured</h1>\n <p>The page loaded, but the server did not hand it usable configuration.</p>\n <pre>{message}</pre>\n </div>\n )\n}\n","import { readClientEnv } from '@ze-great-dashboard/shared'\nimport { StrictMode } from 'react'\nimport { createRoot } from 'react-dom/client'\nimport { App } from './App.tsx'\nimport { ConfigError } from './ConfigError.tsx'\nimport './styles.css'\n\nconst container = document.getElementById('root')\nif (!container) {\n throw new Error('No #root element in the document — the template is not the one we expect.')\n}\n\nconst root = createRoot(container)\n\ntry {\n root.render(\n <StrictMode>\n <App env={readClientEnv()} />\n </StrictMode>,\n )\n} catch (error) {\n // A radiator that fails silently is worse than one that says what's wrong. If configuration\n // never arrived, say so on screen rather than rendering an empty board.\n root.render(<ConfigError message={error instanceof Error ? error.message : String(error)} />)\n}\n"],"mappings":"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"}