@vitreajs/vitrea 0.1.0 → 0.2.0
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.
- package/README.md +226 -22
- package/dist/{dist-FGJI5LQM.js → dist-RQ4ZMA3D.js} +984 -98
- package/dist/dist-RQ4ZMA3D.js.map +1 -0
- package/dist/index.d.ts +555 -39
- package/dist/index.js +129 -18
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/dist/dist-FGJI5LQM.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../renderer-webgpu/src/wgsl/analysis.ts","../../policy/src/refraction.ts","../../renderer-webgpu/src/color.ts","../../renderer-webgpu/src/material.ts","../../renderer-webgpu/src/analysis.ts","../../renderer-webgpu/src/errors.ts","../../renderer-webgpu/src/backdrop.ts","../../renderer-webgpu/src/device.ts","../../renderer-webgpu/src/governor.ts","../../renderer-webgpu/src/pipeline-cache.ts","../../renderer-webgpu/src/texture-pool.ts","../../renderer-webgpu/src/gpu-context.ts","../../renderer-webgpu/src/render-model.ts","../../renderer-webgpu/src/instances.ts","../../renderer-webgpu/src/timing.ts","../../renderer-webgpu/src/wgsl/cross-check.ts","../../renderer-webgpu/src/wgsl/backdrop.ts","../../renderer-webgpu/src/wgsl/field.ts","../../renderer-webgpu/src/wgsl/highlight.ts","../../renderer-webgpu/src/wgsl/optics.ts","../../renderer-webgpu/src/wgsl/prelude.ts","../../renderer-webgpu/src/wgsl/index.ts","../../renderer-webgpu/src/passes.ts","../../renderer-webgpu/src/pyramid-plan.ts","../../renderer-webgpu/src/rebuild-ledger.ts","../../renderer-webgpu/src/pyramid.ts","../../renderer-webgpu/src/renderer.ts"],"names":["smoothstep","shape","outerShadowReachPx","level"],"mappings":"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","file":"dist-RQ4ZMA3D.js","sourcesContent":["/**\n * The analysis reduction: luminance, variance and edge density off the blur\n * pyramid, into a four-float stats buffer per backdrop source.\n *\n * This is what `analysis: \"exact\"` means in X2 — a real reduction over the real\n * pixels, not an estimate. It runs once per pyramid rebuild, which by the §Core\n * model invariant is at most once per dirty source per frame.\n *\n * ## Why one workgroup\n *\n * The reduction reads a fixed 64×64 grid of bilinear samples off a chosen chain\n * level, whatever that level's real size is. That makes the pass's cost constant\n * — 4096 samples, one workgroup, one dispatch — instead of proportional to the\n * backdrop's resolution, and it makes the result independent of the resolution\n * policy, so raising or lowering `scale` does not move the tint. A grid rather\n * than every texel is the right trade because the values feed a tint and a\n * light/dark decision, both of which are already low-passed in time.\n *\n * ## Edge density\n *\n * Central differences of luminance on the same grid, averaged. Read off a\n * mid-chain level rather than the coarsest: the coarsest level has had every edge\n * blurred out of it, so an edge measurement there would report the same small\n * number for a photograph and for a solid colour. The level choice lives on the\n * CPU (`pyramid-plan.ts`) where the sizes are known.\n *\n * ## Variance\n *\n * Accumulated as the mean of squares and folded at the end, which is the\n * numerically shakier of the two standard routes — but the inputs are luminances\n * in [0, ~1] over 4096 samples, so the cancellation is nowhere near f32's\n * resolution, and it costs one accumulator instead of two passes.\n */\n\nexport const ANALYSIS_WORKGROUP = 64;\nexport const ANALYSIS_GRID = 64;\n\n/** `stats` layout: mean luminance, variance, edge density, sample count. */\nexport const ANALYSIS_STATS_FLOATS = 4;\n\nexport const WGSL_ANALYSIS_PASS = `struct AnalysisUniforms {\n /// grid.xy = sample grid size, grid.z = source level, grid.w = 1/(grid-1)\n grid : vec4f,\n /// texel.xy = one texel of the sampled level, in uv\n texel : vec4f,\n};\n\n@group(0) @binding(0) var<uniform> au : AnalysisUniforms;\n@group(0) @binding(1) var analysisSampler : sampler;\n@group(0) @binding(2) var analysisTexture : texture_2d<f32>;\n@group(0) @binding(3) var<storage, read_write> stats : array<f32>;\n\nvar<workgroup> partialLum : array<f32, ${ANALYSIS_WORKGROUP}>;\nvar<workgroup> partialSq : array<f32, ${ANALYSIS_WORKGROUP}>;\nvar<workgroup> partialEdge : array<f32, ${ANALYSIS_WORKGROUP}>;\n\nfn lum_at(uv : vec2f) -> f32 {\n let s = textureSampleLevel(analysisTexture, analysisSampler, uv, au.grid.z);\n // Level 0 onwards is premultiplied linear; unpremultiplying keeps a\n // transparent backdrop region from reading as black rather than as absent.\n let colour = s.rgb / max(s.a, 1e-6);\n return luminance(colour);\n}\n\n@compute @workgroup_size(${ANALYSIS_WORKGROUP})\nfn cs_analysis(@builtin(local_invocation_index) lane : u32) {\n let total = u32(au.grid.x * au.grid.y);\n var sumLum = 0.0;\n var sumSq = 0.0;\n var sumEdge = 0.0;\n var n = 0.0;\n\n var i = lane;\n loop {\n if (i >= total) { break; }\n let gx = f32(i % u32(au.grid.x));\n let gy = f32(i / u32(au.grid.x));\n let uv = vec2f(gx, gy) * au.grid.w;\n\n let c = lum_at(uv);\n let dx = lum_at(uv + vec2f(au.texel.x, 0.0)) - lum_at(uv - vec2f(au.texel.x, 0.0));\n let dy = lum_at(uv + vec2f(0.0, au.texel.y)) - lum_at(uv - vec2f(0.0, au.texel.y));\n\n sumLum = sumLum + c;\n sumSq = sumSq + c * c;\n sumEdge = sumEdge + length(vec2f(dx, dy)) * 0.5;\n n = n + 1.0;\n\n i = i + ${ANALYSIS_WORKGROUP}u;\n }\n\n partialLum[lane] = sumLum;\n partialSq[lane] = sumSq;\n partialEdge[lane] = sumEdge;\n workgroupBarrier();\n\n // Tree reduction. ${ANALYSIS_WORKGROUP} is a power of two, so no tail case.\n var stride = ${ANALYSIS_WORKGROUP}u / 2u;\n loop {\n if (stride == 0u) { break; }\n if (lane < stride) {\n partialLum[lane] = partialLum[lane] + partialLum[lane + stride];\n partialSq[lane] = partialSq[lane] + partialSq[lane + stride];\n partialEdge[lane] = partialEdge[lane] + partialEdge[lane + stride];\n }\n workgroupBarrier();\n stride = stride / 2u;\n }\n\n if (lane == 0u) {\n let count = max(f32(total), 1.0);\n let mean = partialLum[0] / count;\n stats[0] = mean;\n stats[1] = max(partialSq[0] / count - mean * mean, 0.0);\n stats[2] = partialEdge[0] / count;\n stats[3] = count;\n }\n}`;\n","// The refraction ladder, and the dual-cap rule that only means something against\n// it (Decision Log #19). `index.ts` carries the account of why the ladder lives\n// in a package of its own rather than in core; this file is the ladder.\n//\n// Every declaration's doc comment below is inlined verbatim into the published\n// `vitrea` and `vitrea-web` type declarations, because tsup's `dts.resolve`\n// bundles this package into both. That is the reason the prose here stays on\n// what a consumer of `effectiveRefraction` needs and the workspace-internal\n// layering argument stays in `index.ts`, where nothing inlines it: a file\n// comment only detaches from the first declaration when imports sit between\n// them, and this file has no imports to sit there.\n\n/**\n * The refraction ladder, weakest rung first.\n *\n * Two independent things cap refraction: the accessibility policy's ceiling\n * (core's `ResolvedMaterialPolicy.refraction`, a regime — `nominal | reduced |\n * none`) and the group's resolved capability state (X2's `RefractionQuality` —\n * `true | approximate | none`, what the sampling backend can actually deliver).\n * **Renderers honour the lower of the two** (Decision Log #19), which is only a\n * meaningful sentence against an ordering — this one.\n *\n * Written out rather than derived from `RefractionQuality`, because that type's\n * own declaration order is not an ordering.\n */\nexport const REFRACTION_LADDER = [\"none\", \"approximate\", \"true\"] as const;\n\n/**\n * X2's capability-derived refraction level (`core/src/state.ts` re-exports this\n * name). Derived from the ladder so the rungs and the type cannot drift apart.\n */\nexport type RefractionQuality = (typeof REFRACTION_LADDER)[number];\n\n/**\n * The accessibility *ceiling* axis — core's `ResolvedMaterialPolicy.refraction`.\n * A different vocabulary from `RefractionQuality` on purpose: one says what the\n * backend can deliver, the other what the user's preferences permit.\n */\nexport type RefractionRegime = \"nominal\" | \"reduced\" | \"none\";\n\n/**\n * The slice of a resolved material policy the ladder reads: one axis.\n *\n * Typed as the minimum rather than as a whole policy so both tiers' fuller types\n * satisfy it structurally with no adapter — core's `ResolvedMaterialPolicy` above\n * the seam, the renderer's `MaterialPolicyView` below it.\n */\nexport interface RefractionPolicyView {\n readonly refraction: RefractionRegime;\n}\n\nexport function refractionRank(quality: RefractionQuality): number {\n return REFRACTION_LADDER.indexOf(quality);\n}\n\n/**\n * The accessibility regime as a rung on the same ladder.\n *\n * `reduced` maps to `approximate` rather than to something between: the ladder\n * has three rungs and \"less refraction than true lensing\" is exactly the\n * rim-lensing approximation. `nominal` maps to the top rung, which is a cap of\n * \"uncapped\" — it can never raise a state, only fail to lower it.\n */\nexport function accessibilityRefractionCap(policy: RefractionPolicyView): RefractionQuality {\n switch (policy.refraction) {\n case \"nominal\":\n return \"true\";\n case \"reduced\":\n return \"approximate\";\n case \"none\":\n return \"none\";\n }\n}\n\n/** The lower of the two caps. Symmetric — neither argument is privileged. */\nexport function effectiveRefraction(\n a: RefractionQuality,\n b: RefractionQuality,\n): RefractionQuality {\n return refractionRank(a) <= refractionRank(b) ? a : b;\n}\n\n/** How much of a depth simulation each rung allows, keyed by the ladder. */\nexport type RefractionScale = Readonly<Record<RefractionQuality, number>>;\n\n/**\n * The rung scales both tiers start from.\n *\n * `approximate` is not \"half of true\": it is the rim-lensing approximation, a\n * shallower bend confined nearer the edge, which is what a group sampling a CSS\n * proxy can honestly claim. Reduced transparency lands here too, which is the\n * point of the ladder having three rungs and not two.\n *\n * **Advisory and calibration-delegated (C7), like every other optical constant.**\n * This is the *default*, not the running value: `@vitrea/renderer-webgpu`'s\n * `MaterialProfile.refractionScale` is what the shaders read and what\n * `withMaterialOverrides` replaces, and the CSS tier's `sourceRefractionScale`\n * merges the same patch by the same rule. The literal lives here rather than in\n * either tier because it was previously authored three times over — once in the\n * profile and twice in `platform-web/src/optics.ts` — and three copies of one\n * measured number is three chances for a calibration round to move two of them.\n */\nexport const DEFAULT_REFRACTION_SCALE: RefractionScale = {\n none: 0,\n approximate: 0.45,\n true: 1,\n};\n","/**\n * X5 — the colour pipeline, CPU side.\n *\n * The contract in one line: **internal optical maths in linear light,\n * compositing premultiplied, output sRGB, v1 locked to the sRGB gamut.** Without\n * that lock golden images destabilise across GPUs and browsers and blur energy\n * drifts from the reference, which is the whole reason §Color pipeline exists.\n *\n * Three concrete consequences the rest of the renderer leans on:\n *\n * 1. **Every internal texture is `rgba16float` and holds linear light.** 8-bit\n * linear would band visibly in a blur pyramid; `rgba16float` is renderable and\n * filterable everywhere WebGPU is, so no adapter feature is required.\n * 2. **Alpha is normalised at import** (X3). `copyExternalImageToTexture`\n * delivers premultiplied; `importExternalTexture` delivers unpremultiplied.\n * Whichever arrives, level 0 of the pyramid is premultiplied linear — one\n * invariant, checked once at import, instead of an alpha mode threaded\n * through every downstream pass.\n * 3. **Output is encoded once, at the end of the last pass.** The optics and\n * highlight canvases are configured `alphaMode: \"premultiplied\"` in a plain\n * (non-`-srgb`) 8-bit format, and the browser composites those bytes as sRGB.\n * So the final step is `encode(linear)` and then `* alpha` — premultiplying in\n * the *encoded* space, which is what canvas compositing expects. Premultiplying\n * in linear and then encoding would darken every edge pixel.\n *\n * The transfer functions here are the exact piecewise sRGB curve, not the 2.2\n * approximation: the WGSL uses the same piecewise form, and a test asserts the\n * two agree, so a golden regenerated on one and asserted on the other cannot\n * drift by a code unit.\n */\n\n/**\n * The colour spaces v1 accepts on an imported backdrop.\n *\n * `display-p3` is *accepted and tagged*, never silently treated as sRGB — but v1\n * converts it into the sRGB working space rather than carrying a wide gamut\n * through the pipeline (§Color pipeline: \"Display-P3 and HDR/extended-range are\n * future profiles\"). Tagging it is what makes the future profile a data change.\n */\nexport const BACKDROP_COLOR_SPACES = [\"srgb\", \"display-p3\"] as const;\n\nexport type BackdropColorSpace = (typeof BACKDROP_COLOR_SPACES)[number];\n\n/** How a provider's pixels arrive. Normalised to `premultiplied` at import. */\nexport const BACKDROP_ALPHA_MODES = [\"premultiplied\", \"unpremultiplied\", \"opaque\"] as const;\n\nexport type BackdropAlphaMode = (typeof BACKDROP_ALPHA_MODES)[number];\n\n/** The one internal pixel format. See consequence 1 above. */\nexport const WORKING_TEXTURE_FORMAT: GPUTextureFormat = \"rgba16float\";\n\n/** The presentation format for the plane canvases and for golden readback. */\nexport const OUTPUT_TEXTURE_FORMAT: GPUTextureFormat = \"rgba8unorm\";\n\nconst SRGB_LINEAR_CUTOFF = 0.0031308;\nconst SRGB_ENCODED_CUTOFF = 0.04045;\nconst SRGB_SLOPE = 12.92;\nconst SRGB_ALPHA = 1.055;\nconst SRGB_OFFSET = 0.055;\nconst SRGB_GAMMA = 2.4;\n\n/** One channel, sRGB-encoded [0,1] → linear-light [0,1]. */\nexport function srgbToLinearChannel(c: number): number {\n if (c <= SRGB_ENCODED_CUTOFF) return c / SRGB_SLOPE;\n return Math.pow((c + SRGB_OFFSET) / SRGB_ALPHA, SRGB_GAMMA);\n}\n\n/** One channel, linear-light [0,1] → sRGB-encoded [0,1]. */\nexport function linearToSrgbChannel(c: number): number {\n if (c <= SRGB_LINEAR_CUTOFF) return c * SRGB_SLOPE;\n return SRGB_ALPHA * Math.pow(c, 1 / SRGB_GAMMA) - SRGB_OFFSET;\n}\n\nexport type Rgb = readonly [r: number, g: number, b: number];\n\nexport const srgbToLinear = (c: Rgb): Rgb => [\n srgbToLinearChannel(c[0]),\n srgbToLinearChannel(c[1]),\n srgbToLinearChannel(c[2]),\n];\n\nexport const linearToSrgb = (c: Rgb): Rgb => [\n linearToSrgbChannel(c[0]),\n linearToSrgbChannel(c[1]),\n linearToSrgbChannel(c[2]),\n];\n\n/**\n * Rec.709 luminance weights, applied to **linear** light.\n *\n * Stated explicitly because the common mistake is to weight sRGB-encoded values\n * — which gives a number that tracks perceived lightness loosely and blur energy\n * not at all. The analysis pass reduces linear luminance for the same reason the\n * blur runs in linear light: both are energy integrals.\n */\nexport const LUMINANCE_WEIGHTS: Rgb = [0.2126, 0.7152, 0.0722];\n\nexport function relativeLuminance(linear: Rgb): number {\n return (\n linear[0] * LUMINANCE_WEIGHTS[0] +\n linear[1] * LUMINANCE_WEIGHTS[1] +\n linear[2] * LUMINANCE_WEIGHTS[2]\n );\n}\n\n/**\n * Display-P3 → sRGB (linear light, both ends).\n *\n * The 3×3 is the product of P3-to-XYZ and XYZ-to-sRGB under D65. Out-of-gamut\n * results are clamped, which loses saturation on very saturated P3 content — the\n * honest v1 behaviour, and the reason the colour space is *tagged* rather than\n * assumed (a P3 profile can then convert differently without touching a shader).\n */\nconst P3_TO_SRGB: readonly Rgb[] = [\n [1.224940176280559, -0.224940176280559, 0],\n [-0.042056973821316, 1.042056973821316, 0],\n [-0.019637554590334, -0.078636046901105, 1.098273601491439],\n];\n\nexport function displayP3ToSrgbLinear(linearP3: Rgb): Rgb {\n const out: number[] = [];\n for (const row of P3_TO_SRGB) {\n out.push(\n Math.min(1, Math.max(0, row[0] * linearP3[0] + row[1] * linearP3[1] + row[2] * linearP3[2])),\n );\n }\n return [out[0] as number, out[1] as number, out[2] as number];\n}\n\n/**\n * The colour-space conversion the import pass must apply, as data.\n *\n * Returned as a matrix (row-major 3×3) so the shader takes one uniform and has\n * no branch on colour space. Identity for sRGB — the overwhelmingly common case\n * costs three dot products, which is cheaper than the branch would be.\n */\nexport function importColorMatrix(space: BackdropColorSpace): Float32Array {\n if (space === \"srgb\") {\n return new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);\n }\n const rows = P3_TO_SRGB;\n return new Float32Array([\n ...(rows[0] as Rgb),\n ...(rows[1] as Rgb),\n ...(rows[2] as Rgb),\n ]);\n}\n\n/**\n * The alpha normalisation the import pass must apply, as a scalar flag.\n *\n * `0` = already premultiplied, `1` = divide the colour by alpha first, `2` =\n * force alpha to 1. Three modes and one uniform, resolved on the CPU where the\n * provider's contract is known, so no shader ever guesses (X3).\n */\nexport function alphaNormalisationMode(mode: BackdropAlphaMode): number {\n switch (mode) {\n case \"premultiplied\":\n return 0;\n case \"unpremultiplied\":\n return 1;\n case \"opaque\":\n return 2;\n }\n}\n\n/**\n * Encode a linear-light colour and its alpha the way the output pass does, for\n * tests and for golden-image expectations computed on the CPU.\n */\nexport function encodeOutput(linear: Rgb, alpha: number): readonly [number, number, number, number] {\n const a = Math.min(1, Math.max(0, alpha));\n const encoded = linearToSrgb(linear);\n return [encoded[0] * a, encoded[1] * a, encoded[2] * a, a];\n}\n\n/** The same, quantised to the 8-bit bytes a golden PNG holds. */\nexport function encodeOutputBytes(linear: Rgb, alpha: number): readonly number[] {\n return encodeOutput(linear, alpha).map((c) => Math.round(Math.min(1, Math.max(0, c)) * 255));\n}\n","/**\n * The optical constants, and the two foldings that decide what the shader\n * actually gets: the dual cap, and the size-parameterised lens.\n *\n * **Every number here is advisory and calibration-delegated (C7).** They are\n * chosen so the material is coherent out of the box — a plausible glass, not a\n * measured one — and §Calibration names exactly this kind of value as a delegated\n * unknown. They live in one profile object (`MaterialProfile`) so replacing them\n * with fitted values is a data change (`withMaterialOverrides`), and no shader\n * carries a literal of its own. The named constants below are re-exports of that\n * profile's defaults, kept because a reader wants a name for σ = 8 more often\n * than a whole profile.\n *\n * ## The dual cap (Decision Log #19)\n *\n * Two independent things cap refraction: the accessibility policy's regime\n * (`nominal | reduced | none`) and the group's resolved capability state\n * (`true | approximate | none` — what the sampling backend can actually deliver).\n * **The lower of the two wins**, and this module folds them into one scalar before\n * anything reaches a uniform, so the shader has no way to honour the wrong one.\n *\n * The ordering is `@vitrea/policy`'s, and so is the fold. It used to be restated\n * here — this package sits *below* core in the dependency graph and platform-web\n * sits above it, so for most of v1 there was no module both tiers could see and\n * the CSS tier carried a second copy. Decision Log #23(d) closed that seam by\n * putting the ladder in a pure leaf underneath everything, which the renderer can\n * depend on directly (alongside `@vitrea/geometry`) with no cycle to close. The\n * two copies can no longer disagree because there is only one.\n */\n\nimport {\n accessibilityRefractionCap,\n DEFAULT_REFRACTION_SCALE,\n REFRACTION_LADDER,\n type RefractionQuality,\n} from \"@vitrea/policy\";\n\nimport type { Rgb } from \"./color\";\nimport { srgbToLinear } from \"./color\";\n\n// Re-exported under the names this package and its tests already know them by,\n// so nothing downstream has to learn where the ladder went.\nexport {\n accessibilityRefractionCap,\n effectiveRefraction,\n REFRACTION_LADDER,\n refractionRank,\n type RefractionQuality,\n} from \"@vitrea/policy\";\n\n/**\n * The slice of core's `ResolvedAccessibilityPolicy[\"material\"]` the renderer\n * reads. core's type is assignable to this; a test pins that.\n */\nexport interface MaterialPolicyView {\n readonly glass: \"material\" | \"none\";\n readonly frost: \"nominal\" | \"increased\" | \"none\";\n readonly refraction: \"nominal\" | \"reduced\" | \"none\";\n readonly occlusion: \"nominal\" | \"increased\" | \"opaque\";\n readonly border: \"nominal\" | \"strong\";\n readonly ambientTint: \"nominal\" | \"reduced\" | \"none\";\n readonly foreground: \"adaptive\" | \"near-monochrome\";\n}\n\n/** Nominal accessibility material policy — nothing capped. Mirrors core's. */\nexport const NOMINAL_MATERIAL_POLICY: MaterialPolicyView = {\n glass: \"material\",\n frost: \"nominal\",\n refraction: \"nominal\",\n occlusion: \"nominal\",\n border: \"nominal\",\n ambientTint: \"nominal\",\n foreground: \"adaptive\",\n};\n\n/** The two variants, declared as data so a profile merge can walk them. */\nexport const MATERIAL_VARIANTS = [\"regular\", \"clear\"] as const;\n\nexport type MaterialVariant = (typeof MATERIAL_VARIANTS)[number];\n\nexport interface MaterialOptics {\n /** Body blur σ in CSS px. Matches `platform-web`'s `MATERIAL_OPTICS.blurRadius`. */\n readonly blurSigma: number;\n /** Tint over the blurred backdrop, linear light. */\n readonly tint: Rgb;\n readonly tintAlpha: number;\n /** Rim band half-width in CSS px, and its ambient brightness. */\n readonly rimWidth: number;\n readonly rimAlpha: number;\n /** Specular exponent and gain on the rim. */\n readonly specularPower: number;\n readonly specularGain: number;\n /** Inner-shadow depth (0..1) and how much of it is applied. */\n readonly shadowDepth: number;\n readonly shadowAlpha: number;\n /** Highlight colour for the sweep and press glow, linear light. */\n readonly highlight: Rgb;\n}\n\n/** The rim a `border: \"strong\"` policy substitutes, whatever the variant asked for. */\nexport interface MaterialRim {\n readonly rimWidth: number;\n readonly rimAlpha: number;\n}\n\n/**\n * The outer shadow (W8) — the material's own occlusion of the backdrop *outside*\n * its contour, and the largest single facet the project has measured.\n *\n * Not the same quantity as `MaterialOptics.shadowDepth`/`shadowAlpha`, which are\n * the *inner* shadow: that one darkens the material's own body near its contour,\n * this one darkens what is behind and beside the surface. Profile-level rather\n * than per-variant, because the bed measures it per profile and never varied the\n * variant.\n *\n * ## The mechanism, as measured\n *\n * The reference's shadow is the component's OWN rounded silhouette, outset by\n * `spreadPx`, translated down by `offsetPx`, blurred by a Gaussian of standard\n * deviation `sigmaPx`, and applied MULTIPLICATIVELY: the backdrop keeps\n * `1 − occlusion·falloff` of its own light. Fitted in two dimensions against the\n * active bed, that model reproduces the reference to an RMS of 0.0021 in\n * occlusion over 142,550 pixels on the finest cell, and the same three lengths\n * describe every profile, backdrop, span and scale in the bed.\n *\n * **Multiplicative, and not additively.** Mirrored pixel pairs either side of a\n * capsule over the `photo` backdrop see the same shadow over different backdrop\n * luminances: the darkening's ratio tracks the backdrop's ratio to 4.5% while a\n * constant-subtraction model misses by 79% of the signal. So the shadow is\n * analytically INVISIBLE over black — `dark-solid` cells are byte-identical to\n * their background — and that property is what both tiers reproduce exactly,\n * because a fully transparent black composited over anything leaves it alone and\n * black times anything is black.\n *\n * ## Lengths, in points\n *\n * Every length below is in CSS px and the 2× bed proves it: `sigmaPx` measures\n * 15.5 at 1× and 31.0 at 2× device px, `offsetPx` 7.9 and 15.8. A shadow\n * specified in points is what doubles that way.\n *\n * They are also SPAN-INVARIANT, which is a positive measurement rather than an\n * absence: across spans of 32, 44, 96 and 160 px the fitted σ stays within\n * 15.4…15.9 and the offset within 6.9…8.1. The size law reaches the amplitude\n * (`sizeGain`) and nothing else.\n */\nexport interface MaterialOuterShadow {\n /** Downward translation of the shadow's silhouette, CSS px. */\n readonly offsetPx: number;\n /** Gaussian σ the silhouette is blurred by, CSS px. A `box-shadow` blur is 2σ. */\n readonly sigmaPx: number;\n /** Outward spread of the silhouette before the blur, CSS px. */\n readonly spreadPx: number;\n /**\n * Peak occlusion: the fraction of the backdrop's own LINEAR light removed deep\n * inside the shadow. Zero stands the whole facet down, pad and all.\n */\n readonly occlusion: number;\n /**\n * What reduced transparency does to `occlusion` — MEASURED, not assumed, which\n * is what the charter asked for before the fold was written.\n *\n * The reference's shadow under `reduce transparency` is the same shadow at\n * 0.566 of the amplitude: 0.1830/0.3259, 0.1884/0.3309 and 0.1882/0.3314 on the\n * three structured backdrops at a 44 px span, with σ, offset and spread\n * unmoved. It does not vanish and it does not intensify.\n *\n * The `increased contrast` reference reproduces the reduced-transparency\n * amplitude to four decimals (0.1830, 0.1884, 0.1882 — the same numbers), which\n * is Decision Log 8's finding again: macOS force-couples the two toggles, so the\n * contrast reference IS the reduced-transparency state and the bed cannot\n * separate them. The fold therefore keys on `frost`, the axis reduced\n * transparency alone sets, rather than on the contrast axes it would be\n * indistinguishable on here.\n */\n readonly reducedTransparencyOcclusion: number;\n /**\n * The size law's grip on the amplitude: the fraction of the REMAINING\n * transparency a full-thickness surface's shadow closes, on\n * `sizeOcclusionGain`'s relative form.\n *\n * Ships at 0 — the identity — and the reason is a measurement rather than an\n * absence of one. Fitted per scene at a frozen geometry, the amplitude's span\n * dependence points in OPPOSITE directions in the two colour schemes: light\n * standard falls from 0.326 to 0.196 between a 44 px and a 96 px span over\n * `photo` (and 0.331 → 0.285 over `checkerboard`, 0.331 → 0.245 over\n * `hc-text`), while dark standard RISES from 0.060 to 0.177 to 0.274 across 44,\n * 96 and 160 px. Under reduced transparency it is flat (0.183, 0.192, 0.165).\n * One monotone gain on one thickness curve cannot be all three, and any\n * non-zero value fitted to one scheme is wrong in the other — the same shape of\n * finding Decision Log 13 recorded for W7's curve (\"surface size is its own\n * axis\"). The seam ships so the cascade can fit it if a two-axis rework lands;\n * the value stays at the identity until something can identify it.\n */\n readonly sizeGain: number;\n}\n\n/**\n * Every number the material runs on, in one place.\n *\n * The same seam `@vitrea/motion`'s `MotionProfile` opens for the drivers, for the\n * optics: C7's harness measures these against `apple-macos-26.5-*` fixtures and\n * replaces what is here, so nothing downstream may hard-code an optical constant\n * of its own. A profile overrides every one of them (`withMaterialOverrides`),\n * which makes landing a calibrated set a data change rather than a code change.\n *\n * Units: CSS px for distance, linear light for colour, viewport coordinates with\n * y pointing down for direction.\n */\nexport interface MaterialProfile {\n /** Per-variant optics. `clear` is persistently more transparent than `regular`. */\n readonly optics: Readonly<Record<MaterialVariant, MaterialOptics>>;\n\n /** The two ends of adaptation: what the tint becomes over a dark and a light backdrop. */\n readonly adaptiveTintDark: Rgb;\n readonly adaptiveTintLight: Rgb;\n /** Luminance band the tint crosses over. Hysteresis in time is the driver's job. */\n readonly adaptiveLuminanceLow: number;\n readonly adaptiveLuminanceHigh: number;\n\n /**\n * How much of the lens the shader is allowed to apply, per rung.\n *\n * `approximate` is not \"half of true\": it is the rim-lensing approximation, a\n * shallower bend confined nearer the edge, which is what a group sampling a CSS\n * proxy can honestly claim. Reduced transparency lands here too, which is the\n * point of the ladder having three rungs and not two.\n */\n readonly refractionScale: Readonly<Record<RefractionQuality, number>>;\n\n /**\n * **The size law's one curve** — the span band over which the material stops\n * reading as a thin sheet and starts reading as a thick slab (W2).\n *\n * Apple states one mechanism and lists its consequences: as glass \"morphs to\n * larger sizes… its material characteristics change to simulate a thicker, more\n * substantial material. It casts deeper, richer shadows, has more pronounced\n * lensing and refraction effects, and a softer scattering of light\" (S219). One\n * mechanism means one curve: `sizeThickness(span)` is a smoothstep from\n * `sizeSpanMin` to `sizeSpanMax`, and **every** thickness-derived facet is a\n * gain on it — the lens (`lensSizeGainMax`), the scattering\n * (`sizeScatterGainMax`), the occlusion (`sizeOcclusionGain`) and the inner\n * shadow (`sizeShadowGainMax`). Two curves would be two mechanisms, and the\n * reference only has one.\n *\n * A smoothstep rather than a straight ratio, so two surfaces of nearly the same\n * size never read as differently thick, and so every gain saturates instead of\n * growing without bound on a full-width platter. Below `sizeSpanMin` the whole\n * law is **exactly inert**: a small control renders as it did before the law\n * existed, which is what makes the law additive rather than a global retune.\n *\n * MEASURED (W2, on the settled bed): the band is where the reference's own\n * size-dependence happens. Over a fixed checkerboard backdrop the light-standard\n * reference passes 0.244 of the backdrop's contrast at a 32 px span, 0.230 at\n * 44 px and 0.144 at 96 px, and its backdrop correlation falls 0.634 → 0.606 →\n * 0.475 across the same three — so the movement is essentially complete by 96 px\n * and has barely started at 32. See the claims doc's size-law section.\n */\n readonly sizeSpanMin: number;\n readonly sizeSpanMax: number;\n\n /**\n * The lens's gain on the size curve — \"more pronounced lensing and refraction\".\n *\n * `lensDepthPx` is `thickness × lensSizeGain(span)`, clamped to the shorter\n * *half* extent. The clamp is what keeps a small control from being all lens: a\n * 24 px-tall button cannot bend more than 12 px of backdrop however thick it is\n * authored.\n */\n readonly lensSizeGainMax: number;\n\n /**\n * The scattering gain — \"a softer scattering of light\". How many times wider\n * the material's body blur runs at full size.\n *\n * **The facet the settled bed identifies most directly.** Two backdrops\n * disagree in exactly the way a widening kernel predicts and an opacity change\n * does not. Over the checkerboard — all of whose structure sits at one 16 px\n * period, and whose surroundings carry the same mean as its interior — the\n * reference's retained contrast falls 41% from a 32 px span to a 96 px one while\n * its interior *level* stays put (0.607 → 0.641). Over the synthetic photo —\n * broadband, and with surroundings whose mean differs from the mask's — the\n * retained contrast barely moves between 44 px and 96 px (0.546 → 0.544) while\n * the level converges toward the neighbourhood (0.585 → 0.628). A larger alpha\n * would have moved both backdrops' contrast together and pulled both levels\n * toward the tint; a wider kernel moves exactly what moved.\n *\n * Both tiers carry it, from one function (`sizeScatterSigma`): the CSS tier\n * multiplies its `blur()` σ, and the GPU tier lerps its body sample toward the\n * chain level whose blur is that σ.\n */\n readonly sizeScatterGainMax: number;\n\n /**\n * The occlusion gain — \"a larger size is more opaque. A smaller size is\n * clearer\" (S284). The fraction of the *remaining* transparency the size law\n * closes at full size.\n *\n * Relative rather than absolute, for `increasedOcclusionLift`'s reason: a floor\n * dies silently the moment nominal passes it, and a fraction of the headroom\n * cannot. It also composes correctly with the accessibility lift — under reduced\n * transparency nominal is already near 1, so the size law has almost no headroom\n * left to close, which is exactly what the reference does there (its transmission\n * reads 0.011 at a 44 px span and 0.014 at 96 px — no size dependence, because\n * there is none left to have).\n */\n readonly sizeOcclusionGain: number;\n\n /**\n * The inner shadow's gain — \"casts deeper, richer shadows\". A multiplier on\n * `shadowDepth` at full size.\n *\n * **Coupled by construction, not fitted, and the difference is stated rather\n * than hidden.** The fixtures cannot identify it: the reference's peak darkening\n * outside its contour measures 0.0000–0.0001 on almost every calibration scene\n * and vitrea's measures the same order (C9a, `shadowFalloff`), so there is no\n * measured gap for a sweep to close, and what this renderer's `shadowDepth`\n * scales is an *inner* shadow whose contribution to the interior level is\n * degenerate with the tint's — two constants, one observable. So the direction\n * comes from Apple's sentence and the magnitude is held to what the objective is\n * flat over, with that flatness recorded. GPU tier only: the CSS tier's shadow is\n * an outer `box-shadow` the reference does not cast at all (Decision Log #32(c)).\n */\n readonly sizeShadowGainMax: number;\n\n /** Chain LOD per CSS px of lens depth, and how much sharper the rim samples. */\n readonly lensBodyLodPerPx: number;\n readonly lensRimLodBias: number;\n\n /**\n * What each accessibility regime does to the numbers above. The multipliers\n * match `platform-web`'s CSS tier so the two renderers degrade the same way\n * under the same preference.\n */\n readonly reducedTransparencyFrost: number;\n /**\n * How much of the *remaining* transparency reduced transparency closes.\n *\n * **Relative, not absolute (Decision Log #32(d)).** This was\n * `increasedOcclusionAlpha`, an absolute floor of 0.62 applied as\n * `Math.max(nominal, floor)` — a real lift while nominal was the advisory 0.28,\n * and a no-op from the moment C9a measured nominal at 0.62. The policy died\n * without being touched and nothing noticed for a whole child. A fraction of the\n * headroom cannot die that way: it lifts strictly for every nominal below 1,\n * whatever a later tuning pass moves nominal to.\n *\n * The fraction is the pre-C9a lift, restored rather than invented:\n * (0.62 − 0.28) / (1 − 0.28) = 0.4722, which reproduces the old floor exactly at\n * the old nominal. At today's nominal it reads 0.62 → 0.799.\n *\n * Mirrored by `@vitreajs/vitrea-web`'s `INCREASED_OCCLUSION_LIFT`, and pinned in\n * both directions by `packages/calibration/test/tier-coherence.test.ts`.\n */\n readonly increasedOcclusionLift: number;\n readonly strongBorderRim: MaterialRim;\n readonly reducedTintAdaptation: number;\n\n /**\n * The author tint's tone map — Apple's \"range of tones **mapped to content\n * brightness underneath**\" (S219), as four numbers.\n *\n * The seed the author gives is not the colour the material paints. It is the\n * middle of a range: over a dark backdrop the material shows a shade of the\n * seed (`tintToneFloor`, a multiple of it in linear light, so hue and\n * chromaticity survive); over a bright one it shows the seed washed toward\n * white (`tintToneCeilMix`), which is what Apple's \"changing its hue,\n * brightness and saturation… without deviating too much from the intended\n * color\" describes. `tintToneLow`/`tintToneHigh` are the backdrop luminances\n * the two ends are reached at, crossed with a smoothstep for the same reason\n * `lensSpanMin`/`lensSpanMax` are.\n *\n * **Advisory and calibration-delegated**, like every other number in this\n * profile: they are chosen so a tinted surface reads as coloured glass rather\n * than as paint, and the tinted-capture extension fits them. Nothing here is\n * measured yet, and no claim rests on these values.\n */\n readonly tintToneFloor: number;\n readonly tintToneCeilMix: number;\n readonly tintToneLow: number;\n readonly tintToneHigh: number;\n\n /**\n * **Backdrop tone adaptation (W7)** — the axis Apple's material has and this\n * one did not: over a dark enough backdrop the material stops being a lighter\n * thing in front of it and takes the backdrop's own tone.\n *\n * The mechanism is one mix, and it is deliberately the *tint colour* rather\n * than the tint alpha: `backdropToneMax` at full strength makes the tint equal\n * the sampled backdrop, so `mix(backdrop, tint, tintAlpha)` collapses to the\n * backdrop exactly and the surface is left with its rim, its inner shadow and\n * its lensing and nothing else. That is what the settled reference does —\n * `dark-solid__capsule-button__rest` is byte-identical to its own background\n * in every standard profile, at both scales, in both colour schemes.\n *\n * `backdropToneLow`/`backdropToneHigh` are the backdrop luminances (linear)\n * the two ends are reached at, crossed with a smoothstep for the same reason\n * `tintToneLow`/`High` are.\n *\n * `backdropToneSizeBias` is the size gate, and it is not decoration: the same\n * backdrop moves a small surface and a large one by very different amounts.\n * Over `dark-solid` the reference's 44 px capsule adapts completely while its\n * 96 px rrect keeps three quarters of its own appearance, measured on both\n * scales independently and agreeing to three decimals. The bias enters the\n * curve's *argument* rather than its amplitude — a thicker surface behaves as\n * though its backdrop were brighter, which is what more material between the\n * viewer and the backdrop means — because an amplitude gate cannot reproduce\n * the second dark backdrop (`impulse`) and this does.\n *\n * The axis is WITHIN a colour scheme. The scheme picks the neutral; this moves\n * the material away from that neutral toward what is actually behind it. So the\n * dark profile runs the same law with the same constants and does not\n * double-adapt: over `dark-solid` its capsule collapses onto the backdrop too,\n * and the light and dark references become the same pixels there.\n */\n readonly backdropToneMax: number;\n readonly backdropToneLow: number;\n readonly backdropToneHigh: number;\n readonly backdropToneSizeBias: number;\n\n /** The outer shadow (W8) — see `MaterialOuterShadow`. */\n readonly outerShadow: MaterialOuterShadow;\n\n /**\n * Advisory light direction, in viewport coordinates with y pointing down: a\n * little left of straight overhead, which is where Apple's material reads its\n * specular from.\n */\n readonly lightDirection: readonly [number, number];\n /** Specular sweep band width in radians, and the press glow's reach in CSS px. */\n readonly sweepBandRadians: number;\n readonly glowRadiusCss: number;\n readonly glowGain: number;\n readonly sweepGain: number;\n}\n\n/*\n * There is no longer a dark counterpart to this constant. The old\n * `SRGB_DARK_TINT` ([0.09, 0.09, 0.1]) existed only as the light-backdrop end of\n * the adaptive crossover, and C9a measured that the reference does not invert its\n * tint against the backdrop at all — see `adaptiveTintLight` below. The\n * dark-SCHEME tint is a different quantity and lives with the profile that\n * carries it: packages/calibration/profiles/apple-macos-26.5-1x-dark-standard.json.\n */\nconst SRGB_WHITE_TINT: Rgb = [1, 1, 1];\n\n/**\n * How much of the remaining transparency an `occlusion: \"increased\"` policy\n * closes. **FITTED (round two, 2026-08-31) — 0.4722 → 0.75.**\n *\n * The old number was never a measurement. It was the pre-C9a lift re-expressed as\n * a fraction, (0.62 − 0.28) / (1 − 0.28), chosen so the derivation reproduced the\n * old floor exactly at the old nominal — and no stage of the recalibration\n * cascade had refitted it, which is the gap claims §5.14 records against itself.\n * Against the active bed it under-occluded badly: the reference's interior sits\n * at 0.893 under reduced transparency and 0.957 under increased contrast where\n * vitrea reached 0.777 and 0.783.\n *\n * ## One constant, two references that want different things\n *\n * macOS force-couples the accessibility toggles (Decision Log 8), so BOTH\n * accessibility profiles resolve to `occlusion: \"increased\"` and both are served\n * by this one number. Fitted on each profile's own untinted calibration cells\n * against the declared objective, they disagree: increased contrast wants 0.80\n * (0.36045 → 0.23366 across the grid, a 1.54× spread) and reduced transparency\n * wants 0.70 (0.10940 → 0.04875, 2.76×). Their implied alphas differ too — 0.945\n * and 0.864 — which is a property of the two references, not of the fit.\n *\n * 0.75 is the minimiser of the two profiles' objectives summed at equal weight,\n * which is the honest tie-break when one constant serves two equally-gated\n * profiles: 0.70 → 0.31022, **0.75 → 0.29742**, 0.80 → 0.30347. Both checks agree\n * (ΔE 0.01087 and 0.00279 at the chosen point) and both profiles improve enormously\n * against the shipped 0.4722, which reads 0.46985 on the same sum.\n *\n * Mirrored by `@vitreajs/vitrea-web`'s `INCREASED_OCCLUSION_LIFT`, and pinned in\n * both directions by `packages/calibration/test/tier-coherence.test.ts`.\n */\nexport const INCREASED_OCCLUSION_LIFT = 0.75;\n\n/**\n * The occlusion alpha a resolved policy asks for, given whatever nominal the\n * material carries. Mirrors `@vitreajs/vitrea-web`'s `occlusionAlphaUnderPolicy`.\n */\nexport function occlusionAlphaUnderPolicy(\n nominal: number,\n occlusion: MaterialPolicyView[\"occlusion\"],\n lift: number = INCREASED_OCCLUSION_LIFT,\n): number {\n switch (occlusion) {\n case \"nominal\":\n return nominal;\n case \"increased\":\n return nominal + lift * (1 - nominal);\n case \"opaque\":\n return 1;\n }\n}\n\nexport const DEFAULT_MATERIAL_PROFILE: MaterialProfile = {\n optics: {\n // σ = 8 for the regular variant, which keeps this package's blur and\n // `platform-web`'s CSS-tier blur on the same number — and makes core's 24 px\n // `samplingPadding` advisory exactly the 3σ S1 measured.\n regular: {\n /*\n * REFITTED (recalibration cascade, 2026-08-31) against the ACTIVE-pose bed.\n * C9a's 0.62 and σ = 8 were fitted against the inactive material and are\n * kept in git history, not here.\n *\n * `blurSigma` 3 is the first value this constant has ever had that the\n * fixtures could identify. §6.1 called it unidentifiable because the\n * inactive reference passed almost no backdrop structure; the active one\n * passes a great deal (interior standard deviation 0.1358 over the\n * checkerboard against vitrea's 0.0176 at σ = 8), so the objective's spread\n * term now bites — it triples from σ = 3 to σ = 6 at a fixed alpha.\n *\n * `tintAlpha` 0.46 is the minimiser over the eight tone-inert untinted rest\n * calibration cells, a genuine interior optimum (0.38 → 0.16945, 0.46 →\n * 0.15704, 0.54 → 0.17248) with ΔE and SSIM agreeing. It remains true that\n * no single value is right for every scene: a lerp toward one tint colour\n * implies an alpha of 0.24 over the checkerboard and 0.47 over the photo at\n * the same 44 px span, which is the lerp-versus-multiply question C9a\n * recorded and nobody has acted on. Claims §5.13.\n */\n blurSigma: 3,\n tint: srgbToLinear(SRGB_WHITE_TINT),\n tintAlpha: 0.46,\n rimWidth: 1.5,\n rimAlpha: 0.18,\n specularPower: 6,\n specularGain: 0.55,\n shadowDepth: 0.35,\n /*\n * REFITTED 0.55 → 0.05 (2026-08-31), and it is the largest single\n * improvement in the cascade: the objective falls 0.14615 → 0.09333 with\n * ΔE and SSIM both improving.\n *\n * The active reference's contour is BRIGHTER than its own body — a rim peak\n * of 0.025…0.129 above baseline, always at one pixel deep. vitrea's read\n * 0.0000 with its peak 8-12 px in, meaning it had no edge feature at all:\n * the inner shadow at 0.55 was darkening the contour faster than the rim lit\n * it. The rim constants themselves did not move; the thing suppressing them\n * did. On the inactive bed the reference's rim was 0.0000…0.0041 and this\n * was invisible, which is what §6.2 recorded as \"below quantisation\".\n */\n shadowAlpha: 0.05,\n highlight: srgbToLinear(SRGB_WHITE_TINT),\n },\n // Persistently more transparent, so it frosts less and tints less.\n clear: {\n blurSigma: 4,\n tint: srgbToLinear(SRGB_WHITE_TINT),\n tintAlpha: 0.1,\n rimWidth: 1.25,\n rimAlpha: 0.14,\n specularPower: 8,\n specularGain: 0.45,\n shadowDepth: 0.22,\n shadowAlpha: 0.4,\n highlight: srgbToLinear(SRGB_WHITE_TINT),\n },\n },\n\n /*\n * MEASURED (C9a): both ends are the same tint, which makes the crossover inert\n * by default. That is a finding, not a shortcut.\n *\n * The two ends used to straddle the backdrop — white over a dark backdrop,\n * near-black over a light one — so the material always contrasted with what was\n * behind it. Apple's Regular material does not do that. Its interior rises\n * monotonically with the backdrop across the whole canonical range (0.680 at a\n * backdrop of 0.003, 0.932 at 0.891, light scheme), which is a fixed tint at\n * partial transmission. What it keys on instead is the COLOUR SCHEME: over the\n * same bright checkerboard the reference sits at 0.809 in light and 0.055 in\n * dark. Leaving the inversion on cost more than the whole tint tune was worth —\n * it drove the light-scheme error from 0.348 to 0.449 on the interior-level\n * term alone.\n *\n * So the scheme picks the tint, and the calibration profiles carry one set of\n * numbers per scheme (packages/calibration/profiles/). The crossover mechanism\n * is untouched and still available to a profile that wants it; the default\n * simply no longer claims a behaviour the reference does not have.\n *\n * Two limits worth naming. The ends are global rather than per-variant, so the\n * clear variant inherits this — and clear has no calibration scenes at all, so\n * it is uncalibrated either way. And nothing yet selects a profile from the\n * scheme; that is C9a's parent-impact item.\n */\n adaptiveTintDark: srgbToLinear(SRGB_WHITE_TINT),\n adaptiveTintLight: srgbToLinear(SRGB_WHITE_TINT),\n adaptiveLuminanceLow: 0.12,\n adaptiveLuminanceHigh: 0.42,\n\n // Authored in `@vitrea/policy` alongside the ladder it is keyed by, because the\n // CSS tier needs the same table and used to hold two more copies of it\n // (Decision Log #23(d)). The profile is still what the shaders read and still\n // what `withMaterialOverrides` replaces — only the *default* literal moved, and\n // it moved unchanged.\n refractionScale: DEFAULT_REFRACTION_SCALE,\n\n /*\n * MEASURED (W2), against the settled apple-macos-26.5 bed, and set from the\n * REFERENCE's own size-dependence rather than from the objective's minimum.\n *\n * The band was 28…420 while it served the lens alone and nothing had measured\n * it, which put the whole canonical range (32…160 px) inside the first 17% of\n * the curve. What the settled reference actually does, over a fixed checkerboard\n * backdrop: it passes 0.244 of the backdrop's contrast at a 32 px span, 0.230 at\n * 44 px and 0.144 at 96 px. So 6% of the movement happens between 32 and 44 and\n * the rest between 44 and 96, and it is finished by 96 — which is what these two\n * numbers are. `sizeSpanMin` is also the smallest canonical component's span, so\n * that component is the law's exact zero by construction.\n *\n * The tuning objective would rather have 64 (0.1568 against 0.1637 on the rest\n * cells, a 4% win inside a grid that spans 1.07×). Declined, and the reason is\n * recorded rather than the win taken: the gain comes entirely from the interior\n * *level* term, whose residual is the backdrop tone-adaptation gap that wave\n * child W7 is chartered to close — so a band fitted to 64 would be using the\n * size law as a proxy for a mechanism vitrea does not have yet, against the\n * reference's own measurement of where its size-dependence lives, and W7 would\n * have to unpick it. See the claims doc's size-law section.\n */\n sizeSpanMin: 32,\n sizeSpanMax: 96,\n lensSizeGainMax: 2.6,\n\n /*\n * MEASURED (W2), each with its own status — see the fields' notes.\n *\n * `sizeScatterGainMax` = 1: implemented on both tiers and inert, because the\n * canonical fixtures cannot resolve it. The objective is flat to 1.00× over\n * gains 1…6, and that is not the backdrop chain's depth talking: re-run with the\n * chain deepened (MIN_LEVEL_EXTENT 8 → 4, which lifts the reachable σ on the\n * 320×200 canvas from 1.2× to 2.4×) the grid is still flat to 1.00× and still\n * best at 1. A number the fixtures cannot see is a number that will be met by\n * accident, so this ships at the identity with the mechanism in place.\n *\n * `sizeOcclusionGain` = 0: fitted, and the fit is a boundary optimum with real\n * leverage against it — the objective rises monotonically, 0.168 → 0.224 across\n * 0…0.5, a 1.33× spread. The diagnosis is not a tuning failure: vitrea's\n * interior sits 0.16–0.19 above the reference's at every span because the\n * reference's level is set by backdrop tone adaptation toward roughly 0.63 while\n * vitrea lerps toward a white tint, so making a large surface *more* opaque can\n * only take it further from the reference. The facet is Apple's (\"a larger size\n * is more opaque\"); the axis that would let it fit is W7's.\n *\n * `sizeShadowGainMax` = 1.4: fitted on the calibration REST cells, where the\n * grid 1.0/1.2/1.4/1.6/1.8/2.2 reads 0.1577/0.1551/0.1533/0.1530/0.1529/0.1531.\n * 1.4 through 2.2 are one flat region (0.25% apart); 1.4 is the point inside it\n * that costs the checks least (ΔE 0.01282 against the baseline's 0.01290, SSIM\n * 0.9671 against 0.9689) and it is the per-cell minimum on both well-conditioned\n * span-96 rest cells. The pressed cells prefer 2.4 monotonically and are\n * excluded from the fit on §6.3's grounds — their native side carries no press\n * pose, so they compare two different states and cannot arbitrate a material\n * constant.\n *\n * ## Re-fitted against the ACTIVE bed (2026-08-31)\n *\n * `sizeScatterGainMax` stays 1 and is now POSITIVELY identified rather than\n * flat: with `blurSigma` refitted to 3 the objective rises 6-7% at gains 2 and\n * 4, so the identity is the optimum instead of a tie.\n *\n * `sizeOcclusionGain` stays 0, a boundary result for the fourth time and for a\n * fourth distinct reason. The reasoning above is retired: the per-cell residual\n * now points the gain's way in every backdrop (web − reference falls with span\n * — checkerboard +0.105/+0.112/+0.046 at 32/44/96 px, photo −0.004/−0.087,\n * light-solid −0.028/+0.001), so the facet finally has the right sign. What it\n * does not have is magnitude: over 0/0.05/0.10/0.15 × spans ending 96/128/160\n * the whole grid is flat to 1.04×, and a 0.2% preference is not evidence. It\n * ships at the identity because the bed cannot identify it, not because the\n * mechanism is wrong.\n *\n * ## Re-fitted against the FROZEN bed (2026-09-01)\n *\n * `sizeOcclusionGain` 0 → **0.05**, and this is the first time the bed could\n * see it. Every earlier fit was a boundary result because calibration held no\n * span above `sizeSpanMax`, so the curve this gain rides was saturated at every\n * cell that could vote. The frozen bed adds three span-128 `rrect-ml`\n * calibration cells, and with them the grid stops being flat: 0.05 is the\n * optimum at **both** backing scales independently — 1× 0.08288 against the\n * identity's 0.08374, 2× 0.09338 against 0.09557 — and ΔE and SSIM move the\n * same way at both.\n *\n * It is still a small number and it is reported as one: a 1.0% preference at\n * 1×, against the 0.2% this doc rightly refused a round ago. What changed is\n * not the margin's size but that it now reproduces on an independent profile\n * instead of resting on one flat grid.\n *\n * `sizeSpanMax` stays 96, and that is now a measurement rather than an\n * assumption. With a span-128 cell voting, the grid rises monotonically —\n * 96/112/128/144/160/192 reading 0.0837/0.0858/0.0943/0.1060/0.1171/0.1300 —\n * so the band's top is where it was, and the suspicion that the bed simply\n * could not see above it is answered rather than inherited.\n *\n * `sizeShadowGainMax` 1.4 → 1. Its evidence dissolved rather than reversing:\n * this is a gain on the INNER SHADOW, and the inner shadow was refitted from\n * `shadowAlpha` 0.55 to 0.05, so there is almost nothing left for it to gain\n * on. The grid 1.0/1.4/2.2 is flat to 0.2%. Carrying a fitted-looking 1.4 whose\n * measurement no longer exists would be the worse of the two errors.\n */\n sizeScatterGainMax: 1,\n sizeOcclusionGain: 0.05,\n sizeShadowGainMax: 1,\n\n lensBodyLodPerPx: 0.16,\n lensRimLodBias: 2.5,\n\n reducedTransparencyFrost: 1.75,\n increasedOcclusionLift: INCREASED_OCCLUSION_LIFT,\n strongBorderRim: { rimWidth: 2, rimAlpha: 0.95 },\n reducedTintAdaptation: 0.35,\n\n // ADVISORY (W3). The span 0.02 … 0.65 covers most of the canonical backdrop\n // range (0.003 … 0.891 linear), and the two ends are deliberately symmetric —\n // 0.45 of the seed's brightness at the dark end, 0.45 of the way to white at\n // the bright end — so the seed itself sits mid-range and the excursion reads\n // as glass rather than as two different colours.\n /*\n * FITTED (2026-08-31, active bed) — and the fit is that THE CURVE IS THE\n * IDENTITY. `floor` → 1 and `ceilMix` → 0 make `tintTone` return the seed\n * unchanged at every backdrop, which leaves `low` and `high` describing\n * nothing at all; they keep their provisional values so a bed that can\n * identify them has somewhere to land, exactly as `adaptiveTint` keeps two\n * equal ends.\n *\n * Monotone and uncontested over floor ∈ {0.45, 0.7, 0.85, 1} × ceilMix ∈\n * {0, 0.2, 0.45}: objective 0.26523 → 0.12676, a 2.09× spread, with ΔE\n * (0.01331 → 0.00831) and SSIM (0.9749 → 0.9788) agreeing. The reference\n * says the same thing directly — on three of the five calibration backdrops\n * its tinted interior is the declared seed EXACTLY in linear light, at a\n * per-channel standard deviation of 0.000. Apple's tint is the author's\n * colour, not a range of tones mapped to it; S219's wording described the\n * inactive material's residue. Claims §5.13.\n */\n tintToneFloor: 1,\n tintToneCeilMix: 0,\n tintToneLow: 0.02,\n tintToneHigh: 0.65,\n\n /*\n * MEASURED (W7), against the settled apple-macos-26.5 bed, on the light and\n * dark standard profiles jointly and at both scales.\n *\n * The observable these four are set from is the one quantity in this bed that\n * isolates adaptation from everything else: the *separation* between the light\n * and dark references over the same backdrop, on the same component. Under this\n * mechanism that separation is `(1 − tintAlpha)(1 − a)(tintLight − tintDark)`,\n * so the material's transmission, the backdrop's structure and each scheme's\n * own tint all cancel and what is left is `a`. Normalised at the checkerboard,\n * where nothing adapts, it reads:\n *\n * span 44: 0.000 at backdrop 0.500, 0.030 at 0.205, 1.000 at 0.0117, 1.000 at 0.0049\n * span 96: 0.000 at backdrop 0.500, 0.028 at 0.216, 0.256 at 0.0117\n *\n * and the 2× bed reproduces every one of those to three decimals (0.2553\n * against 0.2556 on the one that is not a boundary). Two facts follow. The\n * adaptation is off across the whole ordinary range and turns on only below\n * roughly a fifth of the backdrop scale — so it cannot disturb a cell that\n * already passes. And it is size-gated hard: same backdrop, same material, 1.000\n * against 0.256.\n *\n * The band's dark end is not identifiable from this bed and the fit says so:\n * the reference's backdrops jump from 0.0117 to 0.205 with nothing in between,\n * so `backdropToneLow` is bounded only by \"at or below the darkest calibration\n * backdrop\". What the two dark backdrops DO pin is the curve's slope near zero —\n * the 96 px surface reads 0.256 at 0.0117 and 0.356 at 0.0039, which is a\n * measured intermediate rather than a step, and it is what fixes\n * `backdropToneSizeBias` against `backdropToneHigh`. `impulse__rrect-md__rest`\n * is a VALIDATION cell and was not fitted to: the calibration set predicts\n * 0.34 there and the cell reads 0.356.\n */\n backdropToneMax: 1,\n backdropToneLow: 0.03,\n backdropToneHigh: 0.14,\n /*\n * REFITTED 0.09 → 0.13 (2026-08-31, active bed). The law's SHAPE is untouched\n * (Decision Log 13 stands; the two-axis rework is next wave) and `max`, `low`\n * and `high` are unmoved — only the size gate widened.\n *\n * What it changes is one cell: a 96 pt surface over the darkest backdrop now\n * barely adapts, where at 0.09 it adapted by a quarter. Two independent reads\n * of the reference disagreed about that and the validation set broke the tie.\n * The light-versus-dark separation estimator §5.8 fitted on says the 96 pt\n * surface adapts by 0.30; the reference's own interior LEVEL says it does not\n * (0.4844, against 0.466 for an unadapted surface at the refitted tint alpha\n * and 0.3566 for an adapted one). Measured once on\n * `impulse__rrect-md__rest`, which is validation and was fitted to by\n * neither: 0.09 renders 0.2858 against a reference of 0.4358 at ΔE 0.02344;\n * 0.13 renders 0.4594 at ΔE 0.00378, six times better. The separation\n * estimator's algebra assumes the two colour schemes share one tint alpha,\n * and this profile pair does not (0.46 against 0.97) — recorded in §5.13 as\n * the reason it is no longer the primary evidence for this constant.\n */\n backdropToneSizeBias: 0.13,\n\n /*\n * FITTED (recalibration cascade, 2026-08-31). W8's geometry SURVIVES the fit\n * unchanged — `sigmaPx` 15.55, `offsetPx` 7.95, `spreadPx` 3.10 — and only the\n * two amplitudes moved: `occlusion` 0.33 → 0.285 and\n * `reducedTransparencyOcclusion` 0.566 → 0.70. The dark scheme's amplitude\n * (0.09) lands as a profile patch, not as a branch here.\n *\n * The fit is `scripts/sweep.ts --objective shadow`, whose term is the mean over\n * calibration cells of |Δ meanDeparture| — the light each side removes from the\n * whole exterior, in linear light, which is the one commensurate quantity the\n * facet has. The amplitude is a genuine interior optimum over 0.18…0.44 (a\n * 2.23× spread) and flat to 1.04% across 0.255…0.315, which is exactly the\n * scene-to-scene amplitude spread the reference itself shows. The geometry is\n * NOT identifiable against this objective — σ ∈ {13.5, 15.55, 17.5} × offset ∈\n * {6.5, 7.95, 9.4} spans 1.04× with 15.55 the argmin — because an integral over\n * the exterior is insensitive to how the darkening is distributed within it.\n * W8's own two-dimensional fit against the occlusion field measures the\n * geometry far more powerfully (RMS 0.0021 over 142,550 pixels), and the\n * instrument's independent shadow axis agrees, so the geometry stands on those\n * two and this objective is not asked to re-decide it.\n *\n * `reducedTransparencyOcclusion` 0.70 is sharp where the amplitude is flat: a\n * 3.83× spread over 0.45…0.95 with a clear minimum. It also reconciles two\n * routes — 0.285 × 0.70 = 0.1995 against the reference's directly measured\n * reduce-transparency amplitude of 0.203 at a 44 px span. W8's 0.566 was the\n * ratio of the reference's two amplitudes; this is the ratio that makes\n * vitrea's shadow match the reference's under the preference, and the two\n * differ because the base amplitude is a compromise across scenes whose spread\n * is much wider in the standard profile than under reduced transparency.\n *\n * Extracted from the active bed's native fixtures directly —\n * `results/2026-08-31-active-bed-stage0.json` measured the gap, these numbers\n * measure the facet — and left provisional deliberately: X1 gives the fit to\n * the recalibration cascade, which owns the holdout discipline. This child owns\n * the mechanism.\n *\n * Method: for each `rest` fixture, the occlusion field `1 − L_capture/L_background`\n * in linear Rec.709 luminance, over every pixel outside the declared component\n * geometry with a backdrop bright enough to carry a signal; fitted in two\n * dimensions against `occlusion · Φ(−sd/σ)`, where `sd` is the signed distance\n * to the component's own rounded silhouette translated down by `offsetPx` and\n * outset by `spreadPx`.\n *\n * The fit and its residual, on `1x-light-standard` and `2x-light-standard`:\n *\n * backdrop span occlusion σ (1×/2×) offset (1×/2×) RMS\n * photo 44 0.323 15.5/31.1 7.9/15.8 0.0021\n * checkerboard 44 0.338 15.7/31.0 8.0/15.9 0.0016\n * hc-text 44 0.339 15.7/31.1 8.0/15.9 0.0014\n * photo 32 0.321 15.5/30.9 8.1/16.2 0.0018\n * mid-dark-solid 44 0.310 — — 0.0079\n *\n * — against a peak occlusion of 0.24, so the model carries the facet to under\n * 1% of its own amplitude, over up to 142,550 pixels per cell. The three\n * lengths are the consensus across every well-conditioned cell; `occlusion` is\n * the light-standard amplitude at a span the size law leaves alone.\n *\n * What the amplitude does NOT yet have is a mechanism for its scene-to-scene\n * spread. Over the flat near-white `light-solid` backdrop the same fit reads\n * 0.123 rather than 0.33, reproducibly and at both scales, while the other flat\n * backdrop (`mid-dark-solid`, linear 0.0595) reads 0.310 — so it is not a\n * function of the backdrop's luminance, its structure, or the material's\n * interior level, and no compositing model in either colour space produces both.\n * The dark-scheme profile is a separate amplitude entirely (0.046…0.061 at a\n * 44 px span — the dark material's shadow is nearly invisible) and lands as a\n * profile patch, not as a branch here. Both are stated in the claims doc as the\n * open question the cascade's fit inherits.\n */\n outerShadow: {\n offsetPx: 7.95,\n sigmaPx: 15.55,\n spreadPx: 3.1,\n occlusion: 0.285,\n reducedTransparencyOcclusion: 0.7,\n sizeGain: 0,\n },\n\n lightDirection: [-0.3714, -0.9285],\n sweepBandRadians: 0.55,\n glowRadiusCss: 44,\n glowGain: 0.6,\n sweepGain: 0.85,\n};\n\n// The default profile's numbers, under the names the rest of the package and its\n// tests already know them by. Derived rather than duplicated: a re-tuned default\n// moves both at once, and there is no second place for the two to disagree.\nexport const REFRACTION_SCALE = DEFAULT_MATERIAL_PROFILE.refractionScale;\nexport const MATERIAL_OPTICS = DEFAULT_MATERIAL_PROFILE.optics;\nexport const ADAPTIVE_TINT_DARK = DEFAULT_MATERIAL_PROFILE.adaptiveTintDark;\nexport const ADAPTIVE_TINT_LIGHT = DEFAULT_MATERIAL_PROFILE.adaptiveTintLight;\nexport const ADAPTIVE_LUMINANCE_LOW = DEFAULT_MATERIAL_PROFILE.adaptiveLuminanceLow;\nexport const ADAPTIVE_LUMINANCE_HIGH = DEFAULT_MATERIAL_PROFILE.adaptiveLuminanceHigh;\nexport const SIZE_SPAN_MIN = DEFAULT_MATERIAL_PROFILE.sizeSpanMin;\nexport const SIZE_SPAN_MAX = DEFAULT_MATERIAL_PROFILE.sizeSpanMax;\nexport const LENS_SIZE_GAIN_MAX = DEFAULT_MATERIAL_PROFILE.lensSizeGainMax;\nexport const SIZE_SCATTER_GAIN_MAX = DEFAULT_MATERIAL_PROFILE.sizeScatterGainMax;\nexport const SIZE_OCCLUSION_GAIN = DEFAULT_MATERIAL_PROFILE.sizeOcclusionGain;\nexport const SIZE_SHADOW_GAIN_MAX = DEFAULT_MATERIAL_PROFILE.sizeShadowGainMax;\nexport const LENS_BODY_LOD_PER_PX = DEFAULT_MATERIAL_PROFILE.lensBodyLodPerPx;\nexport const LENS_RIM_LOD_BIAS = DEFAULT_MATERIAL_PROFILE.lensRimLodBias;\nexport const BACKDROP_TONE_MAX = DEFAULT_MATERIAL_PROFILE.backdropToneMax;\nexport const BACKDROP_TONE_LOW = DEFAULT_MATERIAL_PROFILE.backdropToneLow;\nexport const BACKDROP_TONE_HIGH = DEFAULT_MATERIAL_PROFILE.backdropToneHigh;\nexport const BACKDROP_TONE_SIZE_BIAS = DEFAULT_MATERIAL_PROFILE.backdropToneSizeBias;\nexport const OUTER_SHADOW = DEFAULT_MATERIAL_PROFILE.outerShadow;\n\n/**\n * A profile patch: any subset, to any depth, of what a profile holds.\n *\n * A colour is one leaf, not three: patching a tint means naming the whole triple,\n * because two channels of a fitted colour and one of the default is not a colour\n * anybody measured.\n */\nexport interface MaterialProfilePatch {\n readonly optics?: Readonly<Partial<Record<MaterialVariant, Readonly<Partial<MaterialOptics>>>>>;\n readonly adaptiveTintDark?: Rgb;\n readonly adaptiveTintLight?: Rgb;\n readonly adaptiveLuminanceLow?: number;\n readonly adaptiveLuminanceHigh?: number;\n readonly refractionScale?: Readonly<Partial<Record<RefractionQuality, number>>>;\n readonly sizeSpanMin?: number;\n readonly sizeSpanMax?: number;\n readonly lensSizeGainMax?: number;\n readonly sizeScatterGainMax?: number;\n readonly sizeOcclusionGain?: number;\n readonly sizeShadowGainMax?: number;\n readonly lensBodyLodPerPx?: number;\n readonly lensRimLodBias?: number;\n readonly reducedTransparencyFrost?: number;\n readonly increasedOcclusionLift?: number;\n readonly strongBorderRim?: Readonly<Partial<MaterialRim>>;\n readonly reducedTintAdaptation?: number;\n readonly tintToneFloor?: number;\n readonly tintToneCeilMix?: number;\n readonly tintToneLow?: number;\n readonly tintToneHigh?: number;\n readonly backdropToneMax?: number;\n readonly backdropToneLow?: number;\n readonly backdropToneHigh?: number;\n readonly backdropToneSizeBias?: number;\n readonly outerShadow?: Readonly<Partial<MaterialOuterShadow>>;\n readonly lightDirection?: readonly [number, number];\n readonly sweepBandRadians?: number;\n readonly glowRadiusCss?: number;\n readonly glowGain?: number;\n readonly sweepGain?: number;\n}\n\n/**\n * Apply a patch. This is how a calibration profile lands: C7 emits the measured\n * numbers, the host passes them here, and every constant above is replaceable\n * without touching this file.\n *\n * The nested records merge per field and per rung, so a patch naming one tint\n * alpha keeps that variant's blur, rim and specular rather than dropping them.\n */\nexport function withMaterialOverrides(\n base: MaterialProfile,\n patch: MaterialProfilePatch,\n): MaterialProfile {\n const optics = {} as Record<MaterialVariant, MaterialOptics>;\n for (const variant of MATERIAL_VARIANTS) {\n optics[variant] = { ...base.optics[variant], ...patch.optics?.[variant] };\n }\n\n const refractionScale = {} as Record<RefractionQuality, number>;\n for (const rung of REFRACTION_LADDER) {\n refractionScale[rung] = patch.refractionScale?.[rung] ?? base.refractionScale[rung];\n }\n\n return {\n optics,\n adaptiveTintDark: patch.adaptiveTintDark ?? base.adaptiveTintDark,\n adaptiveTintLight: patch.adaptiveTintLight ?? base.adaptiveTintLight,\n adaptiveLuminanceLow: patch.adaptiveLuminanceLow ?? base.adaptiveLuminanceLow,\n adaptiveLuminanceHigh: patch.adaptiveLuminanceHigh ?? base.adaptiveLuminanceHigh,\n refractionScale,\n sizeSpanMin: patch.sizeSpanMin ?? base.sizeSpanMin,\n sizeSpanMax: patch.sizeSpanMax ?? base.sizeSpanMax,\n lensSizeGainMax: patch.lensSizeGainMax ?? base.lensSizeGainMax,\n sizeScatterGainMax: patch.sizeScatterGainMax ?? base.sizeScatterGainMax,\n sizeOcclusionGain: patch.sizeOcclusionGain ?? base.sizeOcclusionGain,\n sizeShadowGainMax: patch.sizeShadowGainMax ?? base.sizeShadowGainMax,\n lensBodyLodPerPx: patch.lensBodyLodPerPx ?? base.lensBodyLodPerPx,\n lensRimLodBias: patch.lensRimLodBias ?? base.lensRimLodBias,\n reducedTransparencyFrost: patch.reducedTransparencyFrost ?? base.reducedTransparencyFrost,\n increasedOcclusionLift: patch.increasedOcclusionLift ?? base.increasedOcclusionLift,\n strongBorderRim: { ...base.strongBorderRim, ...patch.strongBorderRim },\n reducedTintAdaptation: patch.reducedTintAdaptation ?? base.reducedTintAdaptation,\n tintToneFloor: patch.tintToneFloor ?? base.tintToneFloor,\n tintToneCeilMix: patch.tintToneCeilMix ?? base.tintToneCeilMix,\n tintToneLow: patch.tintToneLow ?? base.tintToneLow,\n tintToneHigh: patch.tintToneHigh ?? base.tintToneHigh,\n backdropToneMax: patch.backdropToneMax ?? base.backdropToneMax,\n backdropToneLow: patch.backdropToneLow ?? base.backdropToneLow,\n backdropToneHigh: patch.backdropToneHigh ?? base.backdropToneHigh,\n backdropToneSizeBias: patch.backdropToneSizeBias ?? base.backdropToneSizeBias,\n outerShadow: { ...base.outerShadow, ...patch.outerShadow },\n lightDirection: patch.lightDirection ?? base.lightDirection,\n sweepBandRadians: patch.sweepBandRadians ?? base.sweepBandRadians,\n glowRadiusCss: patch.glowRadiusCss ?? base.glowRadiusCss,\n glowGain: patch.glowGain ?? base.glowGain,\n sweepGain: patch.sweepGain ?? base.sweepGain,\n };\n}\n\n/**\n * Fold core's resolved material *regime* onto this package's numbers.\n *\n * core decides which regime applies and nothing here re-decides it. One branch\n * per axis of `MaterialPolicyView`, so a new axis in core surfaces as a missing\n * branch here rather than as silence.\n */\nexport function opticsUnderPolicy(\n optics: MaterialOptics,\n policy: MaterialPolicyView,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): MaterialOptics {\n let next = optics;\n\n if (policy.frost === \"increased\") {\n next = { ...next, blurSigma: next.blurSigma * profile.reducedTransparencyFrost };\n } else if (policy.frost === \"none\") {\n next = { ...next, blurSigma: 0 };\n }\n\n next = {\n ...next,\n tintAlpha: occlusionAlphaUnderPolicy(\n next.tintAlpha,\n policy.occlusion,\n profile.increasedOcclusionLift,\n ),\n };\n\n if (policy.border === \"strong\") next = { ...next, ...profile.strongBorderRim };\n\n return next;\n}\n\n/** How much of the analysis-driven tint is applied, under the contrast regime. */\nexport function adaptationStrength(\n policy: MaterialPolicyView,\n analysisExact: boolean,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n if (!analysisExact) return 0;\n switch (policy.ambientTint) {\n case \"nominal\":\n return 1;\n case \"reduced\":\n return profile.reducedTintAdaptation;\n case \"none\":\n return 0;\n }\n}\n\n/**\n * How much of the tint's tone excursion survives the contrast regime.\n *\n * The tone map is the tinted material's response to what is behind it, so it\n * rides the axis that already governs exactly that — `ambientTint` — rather\n * than inventing a second one. Under increased contrast the range narrows\n * toward the bare seed, which is the direction W1 measured Apple's own\n * accessibility material moving (its interior \"has all but stopped\n * transmitting the backdrop\"); under forced colours there is no material to\n * tint at all and the caller never reaches here.\n *\n * The author's colour is never changed by a policy. Only how far the material\n * is allowed to move it is.\n */\nexport function tintToneAdaptation(\n policy: MaterialPolicyView,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n switch (policy.ambientTint) {\n case \"nominal\":\n return 1;\n case \"reduced\":\n return profile.reducedTintAdaptation;\n case \"none\":\n return 0;\n }\n}\n\n/**\n * The tone the seed shows over a given backdrop, in linear light — the CPU\n * statement of what `WGSL_OPTICS_PASS` evaluates per pixel.\n *\n * Exported because two other things have to agree with the shader without being\n * it: the CSS tier converts this quantity into one flat `rgba()`, and the\n * foreground decision has to be taken against the material the surface actually\n * shows. A second implementation of the curve is how those two drift, so there\n * is one, here, and the shader mirrors it line for line.\n */\nexport function tintTone(\n seed: Rgb,\n backdropLuminance: number,\n toneAdaptation: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): Rgb {\n const t = smoothstep(profile.tintToneLow, profile.tintToneHigh, backdropLuminance);\n const k = Math.min(1, Math.max(0, toneAdaptation));\n const channel = (index: 0 | 1 | 2): number => {\n const s = seed[index];\n const low = s * profile.tintToneFloor;\n const high = s + (1 - s) * profile.tintToneCeilMix;\n return s + (low + (high - low) * t - s) * k;\n };\n return [channel(0), channel(1), channel(2)];\n}\n\n/**\n * The material's tint colour once an author tint is folded onto the neutral one.\n *\n * `neutral` is what the material would tint with on its own — the profile's\n * tint, already crossed with whatever adaptation the renderer resolved. The\n * author's tone displaces it by `strength` and nothing else: the tint alpha,\n * which is the material's occlusion and the axis every accessibility policy and\n * the system's own Clear/Tinted preference operate on, is untouched here by\n * construction.\n */\nexport function tintedTintColour(\n neutral: Rgb,\n tint: { readonly color: Rgb; readonly strength: number } | undefined,\n backdropLuminance: number,\n toneAdaptation: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): Rgb {\n if (tint === undefined) return neutral;\n const tone = tintTone(tint.color, backdropLuminance, toneAdaptation, profile);\n const k = Math.min(1, Math.max(0, tint.strength));\n return [\n neutral[0] + (tone[0] - neutral[0]) * k,\n neutral[1] + (tone[1] - neutral[1]) * k,\n neutral[2] + (tone[2] - neutral[2]) * k,\n ];\n}\n\n/**\n * **Backdrop tone adaptation, the curve** — how far this surface's tint is pulled\n * onto the backdrop it is looking at, 0…1, before any accessibility fold.\n *\n * `thickness` is the size law's own factor (`sizeThickness`), and it enters the\n * curve's argument rather than scaling its result: a thicker surface reads its\n * backdrop as brighter than it is, so it holds its own appearance longer. See\n * `MaterialProfile.backdropToneSizeBias` for the measurement that shape came from.\n *\n * Exported for the same reason `tintTone` is: the CSS tier evaluates it at one\n * backdrop level, the foreground decision has to be taken against the material the\n * surface actually shows, and `WGSL_OPTICS_PASS` mirrors it per pixel. One curve,\n * three consumers, no second implementation.\n */\nexport function backdropToneAdaptation(\n backdropLuminance: number,\n thickness: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n const x = backdropLuminance + profile.backdropToneSizeBias * Math.min(1, Math.max(0, thickness));\n const span = Math.max(profile.backdropToneHigh - profile.backdropToneLow, 1e-6);\n const t = Math.min(1, Math.max(0, (x - profile.backdropToneLow) / span));\n return Math.min(1, Math.max(0, profile.backdropToneMax)) * (1 - t * t * (3 - 2 * t));\n}\n\n/**\n * How much of the backdrop adaptation survives an accessibility regime.\n *\n * Two folds, each with its own reason, and the product is what the material gets.\n *\n * `ambientTint` is the axis the wave's composition contract names for \"how far\n * the material may move its colour\", and it is what carries increased contrast\n * (narrowed toward the scheme's own neutral) and forced colours (no material to\n * adapt — the optics pass stands down before it reaches here).\n *\n * The refraction ladder read at the **accessibility cap** carries reduced\n * transparency, which touches no tint axis at all and would otherwise get the\n * adaptation at full strength — and adaptation at full strength dissolves the\n * surface into its backdrop, which is precisely the occlusion that preference\n * asked to be *raised*. A policy has to win against a material law, so it does.\n * The same cap, for the same reason, that `sizeThicknessUnderPolicy` reads.\n *\n * Deliberately unmeasured rather than fitted: neither accessibility profile's\n * scene set contains a backdrop dark enough for this axis to act on, so the fold\n * is a statement about which way to be wrong, not a number the bed chose. It is\n * named in the claims doc with the capture that would close it.\n */\nexport function backdropToneUnderPolicy(\n policy: MaterialPolicyView,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n return tintToneAdaptation(policy, profile) * profile.refractionScale[accessibilityRefractionCap(policy)];\n}\n\n/**\n * The size bias to hand a consumer that will multiply it by a **policy-folded**\n * thickness (`sizeThicknessUnderPolicy`) — the shader and the CSS tier both do.\n *\n * The gate is geometric: it says how much material stands between the viewer and\n * the backdrop, which no preference changes. But there is one thickness in the\n * pipeline and it is the folded one (it rides `aux.z` through the field pass's\n * union, and widening `aux` for a second copy of the same quantity would be a\n * per-pixel channel spent on arithmetic). Dividing the bias by the same cap\n * restores the geometric product exactly: `bias' * thickness_folded ===\n * bias * thickness_raw`, pinned as a test rather than promised here.\n *\n * At `cap = none` the fold above is already 0, so the adaptation is off and the\n * bias is not read; 0 is returned rather than an infinity.\n */\nexport function backdropToneSizeBiasUnderPolicy(\n policy: MaterialPolicyView,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n const cap = profile.refractionScale[accessibilityRefractionCap(policy)];\n return cap <= 0 ? 0 : profile.backdropToneSizeBias / cap;\n}\n\n/**\n * The neutral tint after the backdrop has had its say — step two of the wave's\n * composition contract (colour scheme → **backdrop adaptation** → author tint).\n *\n * `backdrop` is the **averaged** light the surface's body transmits, not one\n * pixel's lens-displaced sample: a fully adapted material shows its backdrop's\n * tone, and a tone is a mean. Over a flat backdrop the two are the same value and\n * the surface disappears into it exactly, which is what the reference's capsule\n * over `dark-solid` does — byte-identical to its own background.\n */\nexport function adaptedTintColour(\n neutral: Rgb,\n backdrop: Rgb,\n adaptation: number,\n tintAlpha: number,\n): Rgb {\n const k = Math.min(1, Math.max(0, adaptation));\n if (k === 0) return neutral;\n // The pair (colour, alpha) that makes the interior composite CONVERGE on the\n // backdrop's tone: mix(mix(b, T, α), M, k) === mix(b, T', α') exactly, with α'\n // from `adaptedTintAlpha`. Solving it here rather than lerping the two\n // parameters separately is the difference between an adaptation and a\n // brightening — a lerped alpha over a still-mostly-neutral tint makes a\n // partially adapted surface *lighter* than the one it started from, which the\n // 96 px cells caught immediately (interior 0.4545 → 0.5179 against a reference\n // of 0.4542).\n const alpha = adaptedTintAlpha(tintAlpha, k);\n if (alpha <= 0) return neutral;\n const wNeutral = (1 - k) * tintAlpha;\n return [\n (neutral[0] * wNeutral + backdrop[0] * k) / alpha,\n (neutral[1] * wNeutral + backdrop[1] * k) / alpha,\n (neutral[2] * wNeutral + backdrop[2] * k) / alpha,\n ];\n}\n\n/**\n * The material's occlusion once the backdrop has had its say — the second half of\n * the adaptation, and the half a cross-tier measurement forced.\n *\n * An adapting material does not merely take its backdrop's colour, it stops\n * transmitting: the settled reference's capsule over the `impulse` backdrop is a\n * flat body at its backdrop's own mean, with the impulse grid *hidden* behind it\n * (interior standard deviation 0.0008 against the backdrop's 0.056), not a\n * transparent pane showing it through.\n *\n * Adapting the colour alone made the material fully transparent at full strength,\n * and that is where the two tiers part company: this one blurs its backdrop in\n * linear light and the CSS tier's `backdrop-filter` blurs in the encoded space, so\n * over a high-dynamic-range backdrop a transparent material renders *different\n * pixels* on the two tiers by construction. Measured on that cell, GPU over CSS\n * interior ratio 23.5 against a gated band of 0.80…1.25 — a hard failure of the\n * cross-tier bound, and the reason this exists. A material that shows its\n * backdrop's mean is a colour, and a colour is tier-independent.\n *\n * The same \"fraction of what is left\" shape as `increasedOcclusionLift`, and for\n * the same reason: it lifts strictly for every nominal below 1, whatever a later\n * tuning pass moves nominal to.\n *\n * This is the one place a colour axis reaches the alpha, and it is not an\n * exception to the composition contract's rule that an author's tint may not:\n * that rule is about an *author's* choice not moving the material's occlusion.\n * This is the material's own response to its surroundings, which is what the\n * occlusion axis is for.\n */\nexport function adaptedTintAlpha(tintAlpha: number, adaptation: number): number {\n const k = Math.min(1, Math.max(0, adaptation));\n return tintAlpha + k * (1 - tintAlpha);\n}\n\nconst smoothstep = (edge0: number, edge1: number, x: number): number => {\n if (edge1 <= edge0) return x < edge0 ? 0 : 1;\n const t = Math.min(1, Math.max(0, (x - edge0) / (edge1 - edge0)));\n return t * t * (3 - 2 * t);\n};\n\n/**\n * **The size law's one input**: how thick a surface of this span reads, 0…1.\n *\n * Every thickness-derived facet is a gain on this number and on nothing else —\n * see `MaterialProfile.sizeSpanMin`. Exactly 0 at or below `sizeSpanMin`, so the\n * whole law is inert on a small control, and exactly 1 at or above `sizeSpanMax`,\n * so nothing keeps growing off the end of the canonical range.\n *\n * Mirrored by `@vitreajs/vitrea-web`'s `sizeThickness`, pinned in both directions\n * by `packages/calibration/test/tier-coherence.test.ts`.\n */\nexport function sizeThickness(\n spanPx: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n return smoothstep(profile.sizeSpanMin, profile.sizeSpanMax, spanPx);\n}\n\n/**\n * The size law under an accessibility regime — the fold every other optic gets,\n * and the law does not get to skip it.\n *\n * **MEASURED (W2), and it was measured the hard way.** The law was first landed\n * unfolded, and the regeneration caught it: under both accessibility profiles the\n * large-span cells' ΔE p95 rose past their adopted bounds while every\n * light-standard cell improved. The reason is legible in the reference. Under\n * reduce-transparency Apple's material is nearly opaque and its interior level is\n * *flat* in span (0.9465 at a 44 px span, 0.9526 at 96), where in the standard\n * profile it is not — so a size term that deepens the material's own shadow is\n * modelling something the accessibility reference does not do, and vitrea's\n * accessibility fold already under-occludes against it (W1's Surprise), so the\n * extra depth compounds an error instead of closing one.\n *\n * The scale is the profile's own refraction ladder rather than a new constant,\n * read at the **accessibility** cap alone: 1 nominal, 0.45 reduced, 0 none. That\n * is the number that already means \"how much depth this preference allows\", and\n * the law is nothing but a depth simulation. Deliberately not the *resolved* cap,\n * which also carries the group's sampling capability — a group demoted to a CSS\n * proxy should still look as thick as it is, because being demoted is not a\n * statement about the material.\n *\n * One consequence, stated rather than hidden: the lens displacement is scaled by\n * `refractionScale` again in the shader, so under a reduced regime the size\n * gain's contribution to it is scaled twice. That is the safe direction — a\n * preference asking for less refraction gets less — and the base thickness, which\n * is most of the depth, is scaled exactly once.\n */\nexport function sizeThicknessUnderPolicy(\n spanPx: number,\n policy: MaterialPolicyView,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n return (\n sizeThickness(spanPx, profile) * profile.refractionScale[accessibilityRefractionCap(policy)]\n );\n}\n\n/** The lens's size gain — see `MaterialProfile.lensSizeGainMax`. */\nexport function lensSizeGain(\n spanPx: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n return 1 + (profile.lensSizeGainMax - 1) * sizeThickness(spanPx, profile);\n}\n\n/** `lensSizeGain` for a surface whose thickness factor the policy has already folded. */\nexport function lensSizeGainFromThickness(\n thickness: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n return 1 + (profile.lensSizeGainMax - 1) * thickness;\n}\n\n/**\n * The body blur σ a surface of this span actually runs at — the scattering facet.\n *\n * One function for both tiers, which is what stops them scattering differently:\n * `platform-web` calls its mirror of this to write `blur()`, and this package\n * calls it to derive the chain level the optics pass lerps its body sample\n * toward. It is also what a group's `samplingPadding` floor must be taken over —\n * a wider blur needs a wider proxy, and the group's floor is set by its *largest*\n * member (S1's 3σ rule, applied to the σ the material will really use).\n */\nexport function sizeScatterSigma(\n sigmaPx: number,\n spanPx: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n return sizeScatterSigmaAt(sigmaPx, sizeThickness(spanPx, profile), profile);\n}\n\n/**\n * The same, for a caller that has already resolved the thickness factor — which\n * is every caller with a policy to fold under.\n *\n * The two-function shape is deliberate and it is mirrored on the CSS tier: the\n * thickness form is the law, the span form is the convenience that computes an\n * unfolded thickness for it. One formula, so a policy fold cannot end up applied\n * to one facet and not another.\n */\nexport function sizeScatterSigmaAt(\n sigmaPx: number,\n thickness: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n return sigmaPx * (1 + (profile.sizeScatterGainMax - 1) * thickness);\n}\n\n/**\n * The occlusion alpha a surface of this span carries — the opacity facet.\n *\n * Composes with `occlusionAlphaUnderPolicy` rather than replacing it: both close\n * a fraction of whatever transparency is left, so the order they are applied in\n * changes the result by less than either term and neither can cancel the other.\n * The accessibility policy is applied first, because a preference outranks a\n * material law.\n */\nexport function sizeOcclusionAlpha(\n alpha: number,\n spanPx: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n return sizeOcclusionAlphaAt(alpha, sizeThickness(spanPx, profile), profile);\n}\n\n/** The same, for a caller that has already resolved the thickness factor. */\nexport function sizeOcclusionAlphaAt(\n alpha: number,\n thickness: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n return Math.min(1, alpha + profile.sizeOcclusionGain * thickness * (1 - alpha));\n}\n\n/** The inner shadow's depth at this span — see `MaterialProfile.sizeShadowGainMax`. */\nexport function sizeShadowDepth(\n shadowDepth: number,\n spanPx: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n return sizeShadowDepthAt(shadowDepth, sizeThickness(spanPx, profile), profile);\n}\n\n/** The same, for a caller that has already resolved the thickness factor. */\nexport function sizeShadowDepthAt(\n shadowDepth: number,\n thickness: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n return shadowDepth * (1 + (profile.sizeShadowGainMax - 1) * thickness);\n}\n\n/**\n * The outer shadow's peak occlusion at this span — see\n * `MaterialOuterShadow.sizeGain`. At the shipped gain of 0 this is the identity,\n * exactly, which is the point.\n */\nexport function sizeOuterShadowOcclusion(\n occlusion: number,\n spanPx: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n return sizeOuterShadowOcclusionAt(occlusion, sizeThickness(spanPx, profile), profile);\n}\n\n/** The same, for a caller that has already resolved the thickness factor. */\nexport function sizeOuterShadowOcclusionAt(\n occlusion: number,\n thickness: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n return Math.min(1, occlusion + profile.outerShadow.sizeGain * thickness * (1 - occlusion));\n}\n\n/**\n * The outer shadow under an accessibility regime.\n *\n * One branch per axis that can reach it, on `opticsUnderPolicy`'s rule. `frost`\n * is the axis reduced transparency alone sets, and the amplitude it multiplies by\n * is measured — see `MaterialOuterShadow.reducedTransparencyOcclusion`. Under\n * forced colours the material is gone, so its shadow goes with it rather than\n * outliving the surface that cast it.\n */\nexport function outerShadowUnderPolicy(\n policy: MaterialPolicyView,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): MaterialOuterShadow {\n const shadow = profile.outerShadow;\n if (policy.glass === \"none\" || policy.frost === \"none\") return { ...shadow, occlusion: 0 };\n if (policy.frost === \"increased\") {\n return { ...shadow, occlusion: shadow.occlusion * shadow.reducedTransparencyOcclusion };\n }\n return shadow;\n}\n\n/**\n * The Gaussian CDF the shadow's edge falls off by, at a signed distance OUTSIDE\n * the shadow's own silhouette: 1 deep inside, 0.5 exactly on it, 0 far outside.\n *\n * A Gaussian-blurred silhouette is what `box-shadow` specifies and what the\n * reference measures, so this is the one curve, evaluated identically by both\n * tiers and by the shader. Written as the tanh form rather than as `erf` because\n * WGSL has no `erf` and a curve the shader cannot evaluate is not one shape: the\n * approximation's worst error is 1.8e-4 across the whole line, which at the\n * shipped occlusion is 0.015 of one 8-bit code.\n */\n/** sRGB's power-law exponent — the one `outerShadowAlpha` inverts. */\nexport const SRGB_ENCODING_EXPONENT = 2.4;\n\nexport function outerShadowFalloff(signedDistancePx: number, sigmaPx: number): number {\n const x = -signedDistancePx / Math.max(sigmaPx, 1e-4);\n return 0.5 * (1 + Math.tanh(0.7978845608028654 * (x + 0.044715 * x * x * x)));\n}\n\n/**\n * The compositing-space alpha that reproduces a linear-light occlusion.\n *\n * Both tiers paint the shadow the same way — a pure BLACK layer at some alpha,\n * composited source-over — and that is already a multiplicative occlusion by\n * compositing algebra alone: `out = (1 − α)·backdrop + α·0 = backdrop·(1 − α)`.\n * The shadow's colour being zero is what collapses source-over onto multiply, and\n * it is also why the facet is exactly inert over black on both tiers, with no\n * special case anywhere.\n *\n * What does NOT come free is the space. The reference removes a fraction of the\n * backdrop's LINEAR light; a browser composites a `box-shadow` — and a\n * premultiplied canvas — in ENCODED sRGB. So the same visual result needs a\n * different alpha, and the conversion is exact under sRGB's power law:\n * `enc(L(1−occ)) = enc(L)·(1−α)` gives `α = 1 − (1−occ)^(1/2.4)`, independent of\n * the backdrop, which is the same conversion `cssTintAlpha` performs for the tint\n * and the same reason it exists.\n *\n * The residual is the transfer function's linear toe, and it is small and stated:\n * across every backdrop level from 0.004 to 1.0 the worst departure from the\n * reference's own composite is 2.1 of 255 at the shipped occlusion, against a bed\n * whose own reproducibility is ±4 of 255 (Decision Log 10). A per-pixel exact\n * conversion is not available to either tier — `box-shadow` takes one alpha, and\n * the canvas composites outside the shader — so this is the honest floor rather\n * than a shortcut.\n */\nexport function outerShadowAlpha(occlusion: number): number {\n const occ = Math.min(1, Math.max(0, occlusion));\n return 1 - Math.pow(1 - occ, 1 / SRGB_ENCODING_EXPONENT);\n}\n\n/**\n * How far past a surface's own contour the shadow can still change a pixel, CSS\n * px — the margin the GPU tier has to rasterise into, since a scissor rect that\n * stops at the contour would slice the facet off.\n *\n * The cut-off is where the shadow stops moving an 8-bit code over a white\n * backdrop, and it is taken against the **compositing-space alpha** rather than\n * against the linear occlusion, because the alpha is what the canvas actually\n * writes: `page × (1 − α·falloff)` moves one code when `α·falloff` reaches\n * 1/255. Thresholding the linear occlusion instead over-allocated by about 5 CSS\n * px on every edge at the shipped constants — pure cost on a facet already\n * measured at 3.2× the frame's GPU time.\n *\n * `shadow.occlusion` must be the EFFECTIVE amplitude — after the accessibility\n * fold and after the size law — which is the caller's to resolve, because only\n * it knows the group's membership. A pad taken from the base amplitude while the\n * shader emits an amplified one slices the deepest surface's shadow off at the\n * scissor, while the CSS tier, which has no scissor, goes on drawing it.\n *\n * The solve runs over the signed distance to the shadow's OWN silhouette, which\n * may be negative — a pixel just outside the contour is already inside the\n * offset, spread silhouette — so `occlusion = 0`, and any amplitude too faint to\n * move a code anywhere, both fall out as a reach of zero rather than needing a\n * case of their own.\n */\nexport function outerShadowReachPx(shadow: MaterialOuterShadow): number {\n const alpha = outerShadowAlpha(shadow.occlusion);\n if (!(alpha > 0)) return 0;\n const cutoff = 1 / 255 / alpha;\n // Even a pixel the silhouette covers outright cannot move a code.\n if (cutoff >= 1) return 0;\n\n const sigma = Math.max(shadow.sigmaPx, 1e-4);\n // Bisected on the falloff itself, so the reach cannot disagree with what the\n // shader draws.\n let lo = -(8 * sigma + Math.abs(shadow.offsetPx) + Math.abs(shadow.spreadPx));\n let hi = 8 * sigma;\n for (let i = 0; i < 48; i += 1) {\n const mid = (lo + hi) / 2;\n if (outerShadowFalloff(mid, sigma) > cutoff) lo = mid;\n else hi = mid;\n }\n\n /*\n * Back to a distance from the COMPONENT's contour, in whichever direction\n * reaches furthest — the pad is applied to all four edges, so one bound has to\n * cover them all. The offset enters by magnitude (downward when positive,\n * upward when negative) and the spread carries its own sign, because a\n * negative spread pulls every direction in together.\n */\n return Math.max(0, hi + Math.abs(shadow.offsetPx) + shadow.spreadPx);\n}\n\nexport function lensDepthPx(\n thicknessPx: number,\n spanPx: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n const gain = lensSizeGain(spanPx, profile);\n return Math.min(Math.max(thicknessPx, 0) * gain, spanPx * 0.5);\n}\n\n/** Body blur LOD on the chain for a given lens depth — thicker glass diffuses more. */\nexport function bodyLod(\n lensDepth: number,\n maxLod: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n return Math.min(Math.max(lensDepth * profile.lensBodyLodPerPx, 0), maxLod);\n}\n","/**\n * Backdrop analysis on the CPU side: the stats a reduction produced, and the\n * temporal hysteresis that makes them usable.\n *\n * §Motion binds `backdrop-adaptation values` to the *exponential low-pass +\n * hysteresis* driver, and §Motion also puts every driver on the CPU. So the shape\n * is: the GPU reduces (exactly — X2's `analysis: \"exact\"`), the result is read\n * back at a low rate, and `LowPassHysteresisDriver` from `@vitrea/motion` — the\n * same class the rest of the runtime uses, not a reimplementation — smooths it.\n * The shader reads the driver's output as a uniform and never sees the raw stat.\n *\n * ## Why the readback is not a per-frame cost\n *\n * §Foreground adaptation caps the readback at an advisory 15 Hz (Decision Log\n * #19), and the governor lowers it further. That is not a performance\n * concession — it is what keeps the adaptation honest. A per-frame readback would\n * either stall the pipeline waiting for the map, or produce a value two frames old\n * and pretend it was current. At 15 Hz with a 500 ms low-pass the staleness is far\n * inside the filter's own time constant, so it is invisible in the output.\n *\n * ## The band is on the input, not the output\n *\n * `LowPassHysteresisDriver` commits a new observation only once it departs the\n * *committed* value by more than the band, then low-passes the committed\n * staircase. Measuring against the moving output instead would let a slow drift\n * leak through one small step at a time, which is exactly the foreground pumping\n * §Foreground adaptation rules out. That property is the driver's, and it is the\n * reason to use the driver rather than an `exp()` here.\n */\n\nimport { LowPassHysteresisDriver } from \"@vitrea/motion\";\n\nimport { DEFAULT_MATERIAL_PROFILE, type MaterialProfile } from \"./material\";\nimport type { Rgb } from \"./color\";\n\n/** The four floats the reduction writes. */\nexport interface BackdropStats {\n /** Mean linear luminance, 0..1-ish (an HDR-ish source can exceed 1). */\n readonly luminance: number;\n /** Variance of linear luminance. */\n readonly variance: number;\n /** Mean luminance-gradient magnitude per texel — the edge-density measure. */\n readonly edgeDensity: number;\n /** Samples the reduction actually took. 0 means \"never reduced\". */\n readonly sampleCount: number;\n}\n\nexport const ZERO_STATS: BackdropStats = {\n luminance: 0,\n variance: 0,\n edgeDensity: 0,\n sampleCount: 0,\n};\n\nexport function statsFromBuffer(values: ArrayLike<number>): BackdropStats {\n return {\n luminance: values[0] ?? 0,\n variance: values[1] ?? 0,\n edgeDensity: values[2] ?? 0,\n sampleCount: values[3] ?? 0,\n };\n}\n\n/**\n * Driver configuration for the three adaptation channels.\n *\n * The time constant and band are §Motion's `backdropAdaptation` defaults — a long\n * constant and a wide band so scrolling past a contrast edge cannot pump the\n * material. Restated as a literal rather than read off `DEFAULT_MOTION_PROFILE`\n * because `edgeDensity` and `variance` live on different scales from luminance and\n * want their own bands; the *shape* is motion's, the widths are this package's.\n */\nconst LUMINANCE_CONFIG = {\n kind: \"low-pass-hysteresis\",\n timeConstantMs: 500,\n hysteresis: 0.04,\n restDistance: 1e-3,\n} as const;\n\nconst VARIANCE_CONFIG = { ...LUMINANCE_CONFIG, hysteresis: 0.01 } as const;\nconst EDGE_CONFIG = { ...LUMINANCE_CONFIG, hysteresis: 0.01 } as const;\n\nexport interface AdaptationValues {\n readonly luminance: number;\n readonly variance: number;\n readonly edgeDensity: number;\n /** The tint the optics pass should mix toward, in linear light. */\n readonly tint: Rgb;\n /** True once at least one reduction has been observed. */\n readonly observed: boolean;\n}\n\nexport interface AdaptationState {\n /** Commit a fresh reduction. Cheap — the band may reject it outright. */\n observe(stats: BackdropStats): void;\n /** Advance the filters by a frame delta in ms. */\n advance(deltaMs: number): void;\n /** Jump the filters to a reduction with no transient. Used on the first frame. */\n reset(stats: BackdropStats): void;\n readonly values: AdaptationValues;\n readonly settled: boolean;\n}\n\nconst smoothstep = (edge0: number, edge1: number, x: number): number => {\n if (edge1 <= edge0) return x < edge0 ? 0 : 1;\n const t = Math.min(1, Math.max(0, (x - edge0) / (edge1 - edge0)));\n return t * t * (3 - 2 * t);\n};\n\n/**\n * The adaptive tint: a crossfade between the dark-backdrop and light-backdrop\n * tints across a luminance band.\n *\n * The crossfade is deliberately not a hard threshold. §Motion gives the\n * *foreground* light/dark decision a threshold-plus-crossfade driver because it\n * feeds a DOM `color`, which is discrete; the material's own tint is continuous\n * and can simply follow the smoothed luminance, so it does. One fewer driver, and\n * no risk of the tint and the foreground disagreeing at the threshold.\n */\nexport function adaptiveTint(\n luminance: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): Rgb {\n const dark = profile.adaptiveTintDark;\n const light = profile.adaptiveTintLight;\n const t = smoothstep(profile.adaptiveLuminanceLow, profile.adaptiveLuminanceHigh, luminance);\n return [\n dark[0] + (light[0] - dark[0]) * t,\n dark[1] + (light[1] - dark[1]) * t,\n dark[2] + (light[2] - dark[2]) * t,\n ];\n}\n\nexport function createAdaptationState(\n initial: BackdropStats = ZERO_STATS,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): AdaptationState {\n const luminance = new LowPassHysteresisDriver(LUMINANCE_CONFIG, initial.luminance);\n const variance = new LowPassHysteresisDriver(VARIANCE_CONFIG, initial.variance);\n const edge = new LowPassHysteresisDriver(EDGE_CONFIG, initial.edgeDensity);\n let observed = initial.sampleCount > 0;\n\n return {\n observe(stats) {\n if (stats.sampleCount <= 0) return;\n observed = true;\n luminance.retarget(stats.luminance);\n variance.retarget(stats.variance);\n edge.retarget(stats.edgeDensity);\n },\n\n advance(deltaMs) {\n luminance.advance(deltaMs);\n variance.advance(deltaMs);\n edge.advance(deltaMs);\n },\n\n reset(stats) {\n observed = stats.sampleCount > 0;\n luminance.jumpTo(stats.luminance);\n variance.jumpTo(stats.variance);\n edge.jumpTo(stats.edgeDensity);\n },\n\n get values() {\n return {\n luminance: luminance.value,\n variance: variance.value,\n edgeDensity: edge.value,\n tint: adaptiveTint(luminance.value, profile),\n observed,\n };\n },\n\n get settled() {\n return luminance.settled && variance.settled && edge.settled;\n },\n };\n}\n\n/**\n * Whether a readback is due, given the governor's cadence.\n *\n * A single-slot gate rather than a queue: if the previous map has not resolved the\n * next one is simply skipped. Queueing readbacks under pressure is how a renderer\n * ends up with a backlog of stale buffers and a growing memory footprint, and the\n * consumer here cannot use two answers from the same frame anyway.\n */\nexport function readbackDue(\n lastAtMs: number | undefined,\n nowMs: number,\n cadenceHz: number,\n): boolean {\n if (cadenceHz <= 0) return false;\n if (lastAtMs === undefined) return true;\n return nowMs - lastAtMs >= 1000 / cadenceHz;\n}\n","/**\n * The renderer's typed failures.\n *\n * X3 asks for one specific behaviour and this class exists to deliver it:\n * \"App-supplied views must satisfy declared usage/format/dimension requirements\n * — **validated at registration with a typed error, never discovered at draw\n * time**.\" So every provider validates its descriptor before it touches the\n * device, and every rejection carries a code a caller can branch on plus a\n * message that says which requirement failed and what to pass instead.\n *\n * The split from core's diagnostics channel is deliberate and mirrors the one\n * `scene.ts` draws: a structural mistake — a view of the wrong format, a\n * duplicate source id, a draw against a torn-down device — throws, because\n * continuing leaves the resource graph describing textures that are not there.\n * Recoverable, per-frame findings are not errors: those travel as\n * `demotionReason`s through core's state model, which is the honest place for\n * \"this still renders, just less\".\n */\n\nexport const RENDERER_ERROR_CODES = [\n /** A `GPUTextureView`'s backing texture lacks a required usage flag. */\n \"texture-usage\",\n /** Format outside the set the sampling path can read. */\n \"texture-format\",\n /** Wrong view dimension, or a depth/array layer count the pass cannot bind. */\n \"texture-dimension\",\n /** Zero or absurd extent, or a size that exceeds the device's limits. */\n \"texture-size\",\n /** A source id registered twice, or an unknown id referenced. */\n \"source-identity\",\n /** The provider was asked for a frame it cannot produce (closed video, detached canvas). */\n \"source-unavailable\",\n /** No device is attached, or the attached one is lost. */\n \"device-unavailable\",\n /** A frame was acquired twice without a release, or released without an acquire. */\n \"frame-protocol\",\n /** A pass was asked to draw something the current resources cannot express. */\n \"pass-input\",\n] as const;\n\nexport type RendererErrorCode = (typeof RENDERER_ERROR_CODES)[number];\n\nexport class RendererError extends Error {\n readonly code: RendererErrorCode;\n /** The source, group or node the failure is about, when there is one. */\n readonly subject: string | undefined;\n\n constructor(code: RendererErrorCode, message: string, subject?: string) {\n super(message);\n this.name = \"RendererError\";\n this.code = code;\n this.subject = subject;\n }\n}\n\nexport function rendererError(\n code: RendererErrorCode,\n message: string,\n subject?: string,\n): RendererError {\n return new RendererError(code, message, subject);\n}\n","/**\n * X3 — the BackdropFrame acquisition protocol, and a provider for every source\n * kind §Backdrop contracts names.\n *\n * The spec calls this contract \"operational, not aspirational\", and the reason is\n * a hard WebGPU fact: **there is no cross-device texture sharing.** So every\n * source, however it arrives, is normalised through one protocol —\n * `acquire(frame)` at frame start, `release()` after submit — and the frame\n * carries the four things a consumer cannot infer: the binding, the size epoch,\n * the colour space, and the alpha mode.\n *\n * ## The five kinds, and what is actually different about each\n *\n * | kind | mechanism | alpha | re-acquired |\n * | --- | --- | --- | --- |\n * | `image` | `copyExternalImageToTexture` | premultiplied | only when dirty |\n * | `video` | `importExternalTexture` | **unpremultiplied** | **every sampling frame** |\n * | `canvas` | `copyExternalImageToTexture` | premultiplied | every frame by default |\n * | `gradient` | `queue.writeTexture` of CPU-generated texels | opaque | never |\n * | `app-texture-view` | the app's own `GPUTexture` | declared by the app | every frame |\n *\n * Two of those cells are WebGPU semantics rather than choices, and §Surprises\n * records them as such: `importExternalTexture` handles **expire at task end**, so\n * a video must be re-imported on every frame that samples it; and imported video\n * arrives **unpremultiplied** while copied images arrive premultiplied. The import\n * pass normalises both to premultiplied linear, so nothing downstream branches on\n * either fact.\n *\n * ## VideoFrame ownership\n *\n * X3: \"`VideoFrame` close ownership held by the provider.\" When the app hands in a\n * `VideoFrame`, this provider closes it in `release()` — after submit, because an\n * imported external texture must outlive the submission that samples it. When the\n * app hands in an `HTMLVideoElement` the browser owns the frames and the provider\n * closes nothing. Getting that backwards leaks decoder buffers until playback\n * stalls, which is why the two cases are separate provider inputs rather than one\n * permissive union.\n *\n * ## Device generations\n *\n * The same WebGPU fact has a second consequence, and it is the one easiest to get\n * wrong: a provider closes over the device it was built with, so when that device\n * dies the provider holds storage nothing can bind and a texture handle nothing\n * will complain about. `invalidate(generation, device)` is how a provider crosses\n * that boundary — new device adopted, old storage dropped, re-import armed — and\n * `generation` is the tag that says which side of it the provider is on. The\n * app-texture provider is the exception on purpose: the renderer cannot re-make\n * someone else's texture, so it refuses rather than binding a foreign-device view\n * that would render nothing and report nothing.\n *\n * ## Validation at registration\n *\n * Also X3: app-supplied views \"must satisfy declared usage/format/dimension\n * requirements — validated at registration with a typed error, never discovered at\n * draw time.\" `registerAppTexture` therefore takes the `GPUTexture`, not just a\n * view: a `GPUTextureView` exposes none of its own properties, so a contract that\n * accepted only a view could not be checked at all.\n */\n\nimport {\n type BackdropAlphaMode,\n type BackdropColorSpace,\n linearToSrgbChannel,\n srgbToLinearChannel,\n} from \"./color\";\nimport { rendererError } from \"./errors\";\n\nexport const BACKDROP_KINDS = [\n \"image\",\n \"video\",\n \"canvas\",\n \"gradient\",\n \"app-texture-view\",\n] as const;\n\nexport type BackdropKind = (typeof BACKDROP_KINDS)[number];\n\n/** How the import pass binds the source. `external` needs its own pipeline. */\nexport type BackdropBinding =\n | { readonly kind: \"sampled\"; readonly view: GPUTextureView }\n | { readonly kind: \"external\"; readonly texture: GPUExternalTexture };\n\nexport interface BackdropFrame {\n readonly sourceId: string;\n readonly binding: BackdropBinding;\n /** Source extent in texture px. */\n readonly width: number;\n readonly height: number;\n /** Bumped when the extent changes; invalidates every dependent allocation. */\n readonly sizeEpoch: number;\n readonly colorSpace: BackdropColorSpace;\n readonly alphaMode: BackdropAlphaMode;\n /** True when the sampled values are sRGB-encoded rather than linear. */\n readonly encoded: boolean;\n}\n\n/** The frame facts a provider is handed. Matches core's `FrameInfo`. */\nexport interface FrameInfoView {\n readonly id: number;\n readonly timeMs: number;\n}\n\nexport interface BackdropProvider {\n readonly id: string;\n readonly kind: BackdropKind;\n /**\n * The device generation this provider's storage belongs to (`device.ts`'s\n * counter). A provider built under one generation holds nothing a later\n * generation can bind, and the failure is silent — so the number is here to be\n * compared, cheaply, before anything of the provider's is used.\n */\n readonly generation: number;\n /** True when content may have changed since the last successful import. */\n isDirty(): boolean;\n /** X3: at frame start. Throws `source-unavailable` if the source cannot serve. */\n acquire(frame: FrameInfoView): BackdropFrame;\n /** X3: after submit. Releases whatever the acquire took ownership of. */\n release(): void;\n /** Called once the import pass has consumed the frame's pixels. */\n markImported(): void;\n /**\n * Adopt `device` at `generation`: the device that built this provider's storage\n * is gone.\n *\n * Every provider closes over the device it was built with, so a reset that only\n * cleared the dirty flags would re-import onto the dead device and hand the new\n * one a foreign texture. Hence the device travels with the call.\n *\n * A provider whose storage the renderer allocated drops it and arms a\n * re-import, so recovery flows through the ordinary dirty path. A provider\n * wrapping the *app's* own texture cannot be re-pointed at all — WebGPU has no\n * cross-device sharing, and the app owns the texture — so it refuses every\n * later `acquire` with a typed error instead of binding a foreign-device view.\n */\n invalidate(generation: number, device: BackdropDevice): void;\n /**\n * Re-declare the source's extent. Implemented where the renderer allocates the\n * storage (image, canvas); absent where the source declares its own size.\n */\n resize?(width: number, height: number): void;\n destroy(): void;\n}\n\n/** Formats the sampling path can read. Everything else is refused at registration. */\nexport const SUPPORTED_APP_TEXTURE_FORMATS: readonly GPUTextureFormat[] = [\n \"rgba8unorm\",\n \"rgba8unorm-srgb\",\n \"bgra8unorm\",\n \"bgra8unorm-srgb\",\n \"rgba16float\",\n \"rgba32float\",\n];\n\n/** The slice of `GPUDevice` the providers need. `GPUDevice` satisfies it as-is. */\nexport interface BackdropDevice {\n readonly queue: GPUQueue;\n readonly limits: GPUSupportedLimits;\n createTexture(descriptor: GPUTextureDescriptor): GPUTexture;\n importExternalTexture(descriptor: GPUExternalTextureDescriptor): GPUExternalTexture;\n}\n\n/** Computed on first use, not at module scope — see the note in `passes.ts`. */\nconst copyUsage = (): GPUTextureUsageFlags =>\n GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT;\n\ninterface SizeTracker {\n epoch: number;\n width: number;\n height: number;\n}\n\nfunction trackSize(tracker: SizeTracker, width: number, height: number): void {\n if (tracker.width === width && tracker.height === height) return;\n tracker.width = width;\n tracker.height = height;\n tracker.epoch += 1;\n}\n\n// ---------------------------------------------------------------------------\n// image and canvas — copyExternalImageToTexture\n// ---------------------------------------------------------------------------\n\n/** Anything `copyExternalImageToTexture` accepts as a source. */\nexport type CopyableSource =\n | ImageBitmap\n | HTMLImageElement\n | HTMLCanvasElement\n | OffscreenCanvas\n | ImageData\n | VideoFrame;\n\nexport interface CopyProviderOptions {\n readonly id: string;\n readonly kind: \"image\" | \"canvas\";\n readonly device: BackdropDevice;\n readonly source: CopyableSource;\n readonly width: number;\n readonly height: number;\n readonly colorSpace?: BackdropColorSpace;\n /**\n * Whether content changes every frame. `true` for a live canvas, `false` for a\n * decoded image — which is what makes a static backdrop rebuild nothing at all\n * (§Core model invariant).\n */\n readonly live?: boolean;\n /** The device generation this provider is being built under. See `BackdropProvider.generation`. */\n readonly generation?: number;\n}\n\nexport function createCopyProvider(options: CopyProviderOptions): BackdropProvider {\n let device = options.device;\n const size = { epoch: 0, width: options.width, height: options.height };\n const live = options.live ?? options.kind === \"canvas\";\n let dirty = true;\n let texture: GPUTexture | undefined;\n let generation = options.generation ?? 0;\n\n const ensureTexture = (): GPUTexture => {\n if (texture !== undefined && texture.width === size.width && texture.height === size.height) {\n return texture;\n }\n texture?.destroy();\n texture = device.createTexture({\n label: `vitrea:backdrop:${options.id}:upload`,\n size: { width: size.width, height: size.height, depthOrArrayLayers: 1 },\n // 8-bit is the honest storage for an image or a canvas: both are 8-bit\n // sources, and the import pass promotes to float on the way into level 0.\n format: \"rgba8unorm\",\n usage: copyUsage(),\n });\n return texture;\n };\n\n return {\n id: options.id,\n kind: options.kind,\n\n get generation() {\n return generation;\n },\n\n isDirty() {\n return dirty || live;\n },\n\n acquire() {\n if (size.width <= 0 || size.height <= 0) {\n throw rendererError(\n \"source-unavailable\",\n `Backdrop \"${options.id}\" has a zero extent (${size.width}×${size.height}); nothing can be copied from it.`,\n options.id,\n );\n }\n const target = ensureTexture();\n if (dirty || live) {\n device.queue.copyExternalImageToTexture(\n { source: options.source, flipY: false },\n {\n texture: target,\n colorSpace: options.colorSpace ?? \"srgb\",\n // X3: copied images arrive premultiplied. Declaring it here is what\n // makes that true rather than assumed — the copy performs the multiply\n // when the source is not already premultiplied.\n premultipliedAlpha: true,\n },\n { width: size.width, height: size.height },\n );\n }\n return {\n sourceId: options.id,\n binding: { kind: \"sampled\", view: target.createView() },\n width: size.width,\n height: size.height,\n sizeEpoch: size.epoch,\n colorSpace: options.colorSpace ?? \"srgb\",\n alphaMode: \"premultiplied\",\n encoded: true,\n };\n },\n\n release() {\n // Nothing to release: the destination texture is this provider's own and\n // outlives the frame.\n },\n\n markImported() {\n dirty = false;\n },\n\n invalidate(next, nextDevice) {\n generation = next;\n device = nextDevice;\n // The upload texture belonged to the dead device. Dropping it and arming\n // the dirty flag is the whole recovery: the next acquire allocates on the\n // new device and re-copies, through the same path a content change takes.\n texture?.destroy();\n texture = undefined;\n dirty = true;\n },\n\n resize(width, height) {\n const changed = size.width !== width || size.height !== height;\n trackSize(size, width, height);\n if (changed) dirty = true;\n },\n\n destroy() {\n texture?.destroy();\n texture = undefined;\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// video — importExternalTexture\n// ---------------------------------------------------------------------------\n\nexport interface VideoProviderOptions {\n readonly id: string;\n readonly device: BackdropDevice;\n /**\n * Either a live element the browser keeps frames for, or a callback producing a\n * `VideoFrame` this provider then owns and closes. The two are separate because\n * their ownership rules are opposite — see the module note.\n */\n readonly source:\n | { readonly kind: \"element\"; readonly element: HTMLVideoElement }\n | { readonly kind: \"frames\"; readonly next: () => VideoFrame | undefined };\n readonly colorSpace?: BackdropColorSpace;\n /** The device generation this provider is being built under. See `BackdropProvider.generation`. */\n readonly generation?: number;\n}\n\nexport function createVideoProvider(options: VideoProviderOptions): BackdropProvider {\n let device = options.device;\n const size = { epoch: 0, width: 0, height: 0 };\n let ownedFrame: VideoFrame | undefined;\n let acquired = false;\n let generation = options.generation ?? 0;\n\n return {\n id: options.id,\n kind: \"video\",\n\n get generation() {\n return generation;\n },\n\n isDirty() {\n // `importExternalTexture` handles expire at task end, so a video is dirty\n // on every frame that samples it. That is a WebGPU semantic, not a policy.\n return true;\n },\n\n acquire() {\n if (acquired) {\n throw rendererError(\n \"frame-protocol\",\n `Backdrop \"${options.id}\" was acquired twice without a release. X3 pairs one acquire per frame with one release after submit.`,\n options.id,\n );\n }\n\n let source: HTMLVideoElement | VideoFrame;\n if (options.source.kind === \"element\") {\n const element = options.source.element;\n if (element.readyState < 2 || element.videoWidth === 0) {\n throw rendererError(\n \"source-unavailable\",\n `Backdrop \"${options.id}\" is a video with no decoded frame yet (readyState ${element.readyState}). Wait for \"loadeddata\" before registering it, or let the group render without a backdrop until it arrives.`,\n options.id,\n );\n }\n trackSize(size, element.videoWidth, element.videoHeight);\n source = element;\n } else {\n const frame = options.source.next();\n if (frame === undefined) {\n throw rendererError(\n \"source-unavailable\",\n `Backdrop \"${options.id}\" produced no VideoFrame for this frame.`,\n options.id,\n );\n }\n ownedFrame = frame;\n trackSize(size, frame.displayWidth, frame.displayHeight);\n source = frame;\n }\n\n let texture: GPUExternalTexture;\n try {\n texture = device.importExternalTexture({\n label: `vitrea:backdrop:${options.id}:external`,\n source,\n colorSpace: \"srgb\",\n });\n } catch (error) {\n // The frame is already this provider's to close, and a throw here leaves\n // `acquired` false — so no release is queued and the next acquire would\n // overwrite `ownedFrame`, leaking one decoder buffer per failure until\n // playback stalls. Closing before the rethrow keeps the ownership rule\n // (\"close ownership held by the provider\") true on the failure path too.\n ownedFrame?.close();\n ownedFrame = undefined;\n throw error;\n }\n acquired = true;\n\n return {\n sourceId: options.id,\n binding: { kind: \"external\", texture },\n width: size.width,\n height: size.height,\n sizeEpoch: size.epoch,\n colorSpace: options.colorSpace ?? \"srgb\",\n // X3: imported video arrives UNPREMULTIPLIED.\n alphaMode: \"unpremultiplied\",\n encoded: true,\n };\n },\n\n release() {\n acquired = false;\n // After submit, and only for a frame this provider owns.\n ownedFrame?.close();\n ownedFrame = undefined;\n },\n\n markImported() {\n // A video is dirty again immediately; nothing to record.\n },\n\n invalidate(next, nextDevice) {\n generation = next;\n device = nextDevice;\n // An external texture from the dead device is already gone — imports expire\n // at task end — so all that is owed here is the frame this provider holds\n // and the acquire/release pairing, which the loss interrupted mid-flight.\n ownedFrame?.close();\n ownedFrame = undefined;\n acquired = false;\n },\n\n destroy() {\n ownedFrame?.close();\n ownedFrame = undefined;\n acquired = false;\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// gradient — procedural, generated once on the CPU\n// ---------------------------------------------------------------------------\n\nexport interface GradientStop {\n /** 0..1 along the gradient axis. */\n readonly offset: number;\n /** sRGB-encoded 0..1, plus alpha. */\n readonly color: readonly [number, number, number, number];\n}\n\nexport interface GradientProviderOptions {\n readonly id: string;\n readonly device: BackdropDevice;\n readonly stops: readonly GradientStop[];\n /** Gradient direction in the source's own uv space. Defaults to top-to-bottom. */\n readonly direction?: readonly [number, number];\n readonly width?: number;\n readonly height?: number;\n /** The device generation this provider is being built under. See `BackdropProvider.generation`. */\n readonly generation?: number;\n}\n\n/**\n * Generated on the CPU and uploaded once, rather than rendered with a pipeline of\n * its own.\n *\n * A procedural gradient is static by definition, so it rebuilds nothing after the\n * first frame and a whole render pipeline for it would be dead weight in the\n * pipeline cache. Interpolation is in **linear light** and the result is\n * re-encoded, because a gradient interpolated in sRGB has a visible dark band\n * through its middle — the one place where doing the maths in the wrong space is\n * obvious to the eye rather than to a metric.\n */\nexport function createGradientProvider(options: GradientProviderOptions): BackdropProvider {\n const width = Math.max(1, options.width ?? 64);\n const height = Math.max(1, options.height ?? 64);\n const direction = options.direction ?? [0, 1];\n const stops = [...options.stops].sort((a, b) => a.offset - b.offset);\n\n if (stops.length === 0) {\n throw rendererError(\n \"source-unavailable\",\n `Gradient backdrop \"${options.id}\" has no stops.`,\n options.id,\n );\n }\n\n const texels = new Uint8Array(width * height * 4);\n const axisLength = Math.hypot(direction[0], direction[1]) || 1;\n const ax = direction[0] / axisLength;\n const ay = direction[1] / axisLength;\n\n const sample = (t: number): readonly [number, number, number, number] => {\n const clamped = Math.min(1, Math.max(0, t));\n let lower = stops[0] as GradientStop;\n let upper = stops[stops.length - 1] as GradientStop;\n for (let i = 0; i < stops.length - 1; i += 1) {\n const a = stops[i] as GradientStop;\n const b = stops[i + 1] as GradientStop;\n if (clamped >= a.offset && clamped <= b.offset) {\n lower = a;\n upper = b;\n break;\n }\n }\n const span = upper.offset - lower.offset;\n const local = span <= 0 ? 0 : (clamped - lower.offset) / span;\n const mix = (from: number, to: number): number => from + (to - from) * local;\n // Colour channels are decoded, mixed, and re-encoded; alpha is already\n // linear and is mixed as-is. Mixing the encoded values instead puts a\n // visible dark band through the middle of every gradient — the one place\n // where working in the wrong space is obvious to the eye rather than to a\n // metric.\n const channel = (index: 0 | 1 | 2): number =>\n linearToSrgbChannel(\n mix(srgbToLinearChannel(lower.color[index]), srgbToLinearChannel(upper.color[index])),\n );\n return [channel(0), channel(1), channel(2), mix(lower.color[3], upper.color[3])];\n };\n\n for (let y = 0; y < height; y += 1) {\n for (let x = 0; x < width; x += 1) {\n const u = width === 1 ? 0 : x / (width - 1);\n const v = height === 1 ? 0 : y / (height - 1);\n // Project onto the axis and rescale so the endpoints of the projected\n // range land on stops 0 and 1 whatever the direction.\n const t = (u * ax + v * ay + Math.max(0, -ax) + Math.max(0, -ay)) / (Math.abs(ax) + Math.abs(ay) || 1);\n const [r, g, b, a] = sample(t);\n const index = (y * width + x) * 4;\n texels[index + 0] = Math.round(Math.min(1, Math.max(0, r)) * 255);\n texels[index + 1] = Math.round(Math.min(1, Math.max(0, g)) * 255);\n texels[index + 2] = Math.round(Math.min(1, Math.max(0, b)) * 255);\n texels[index + 3] = Math.round(Math.min(1, Math.max(0, a)) * 255);\n }\n }\n\n let texture: GPUTexture | undefined;\n let uploaded = false;\n let device = options.device;\n let generation = options.generation ?? 0;\n\n return {\n id: options.id,\n kind: \"gradient\",\n\n get generation() {\n return generation;\n },\n\n isDirty() {\n return !uploaded;\n },\n\n acquire() {\n texture ??= device.createTexture({\n label: `vitrea:backdrop:${options.id}:gradient`,\n size: { width, height, depthOrArrayLayers: 1 },\n format: \"rgba8unorm\",\n usage: copyUsage(),\n });\n if (!uploaded) {\n device.queue.writeTexture(\n { texture },\n texels,\n { bytesPerRow: width * 4, rowsPerImage: height },\n { width, height },\n );\n }\n return {\n sourceId: options.id,\n binding: { kind: \"sampled\", view: texture.createView() },\n width,\n height,\n sizeEpoch: 0,\n colorSpace: \"srgb\",\n alphaMode: \"premultiplied\",\n encoded: true,\n };\n },\n\n release() {\n // Nothing acquired that needs releasing.\n },\n\n markImported() {\n uploaded = true;\n },\n\n invalidate(next, nextDevice) {\n generation = next;\n device = nextDevice;\n // A gradient is static, so `uploaded` is the only thing standing between it\n // and a silent black backdrop after a loss: without the reset the next\n // acquire hands out a view of a texture the dead device made and never\n // writes the texels again. The pixels themselves are CPU-side and survive.\n texture?.destroy();\n texture = undefined;\n uploaded = false;\n },\n\n destroy() {\n texture?.destroy();\n texture = undefined;\n uploaded = false;\n },\n };\n}\n\n/** Two-stop convenience, in linear light, for tests and for the golden scenes. */\nexport function linearGradientStops(\n from: readonly [number, number, number],\n to: readonly [number, number, number],\n): readonly GradientStop[] {\n const encode = (c: readonly [number, number, number]): readonly [number, number, number, number] =>\n [linearToSrgbChannel(c[0]), linearToSrgbChannel(c[1]), linearToSrgbChannel(c[2]), 1];\n return [\n { offset: 0, color: encode(from) },\n { offset: 1, color: encode(to) },\n ];\n}\n\n// ---------------------------------------------------------------------------\n// app-texture-view — validated at registration\n// ---------------------------------------------------------------------------\n\nexport interface AppTextureProviderOptions {\n readonly id: string;\n readonly device: BackdropDevice;\n /**\n * The app's texture. Required rather than a bare view because a\n * `GPUTextureView` exposes none of its own properties, so a view-only contract\n * could not be validated at all — and X3 requires validation at registration.\n */\n readonly texture: GPUTexture;\n /** Optional pre-made view. One is created per acquire when absent. */\n readonly view?: GPUTextureView;\n readonly colorSpace?: BackdropColorSpace;\n readonly alphaMode?: BackdropAlphaMode;\n /** Whether the app's values are sRGB-encoded. A float target is usually linear. */\n readonly encoded?: boolean;\n /**\n * The device generation the app's texture belongs to. See\n * `BackdropProvider.generation` — this is the number `acquire` refuses against\n * once the renderer has moved on to a later device.\n */\n readonly generation?: number;\n}\n\n/**\n * Validate an app-supplied texture against the sampling path's requirements.\n *\n * Exported separately so a host can check before it registers, and so the checks\n * are testable without a device — every one of them reads only the texture's own\n * declared properties.\n */\nexport function validateAppTexture(\n texture: Pick<GPUTexture, \"width\" | \"height\" | \"format\" | \"usage\" | \"dimension\" | \"depthOrArrayLayers\">,\n limits: Pick<GPUSupportedLimits, \"maxTextureDimension2D\">,\n subject: string,\n): void {\n if (texture.dimension !== \"2d\") {\n throw rendererError(\n \"texture-dimension\",\n `Backdrop \"${subject}\" supplied a ${texture.dimension} texture. The sampling path binds a 2d texture; register a 2d texture or a 2d view of one slice.`,\n subject,\n );\n }\n if (texture.depthOrArrayLayers !== 1) {\n throw rendererError(\n \"texture-dimension\",\n `Backdrop \"${subject}\" supplied a texture with ${texture.depthOrArrayLayers} array layers. Bind a single-layer view.`,\n subject,\n );\n }\n if ((texture.usage & GPUTextureUsage.TEXTURE_BINDING) === 0) {\n throw rendererError(\n \"texture-usage\",\n `Backdrop \"${subject}\" supplied a texture without GPUTextureUsage.TEXTURE_BINDING, so it cannot be sampled. Add TEXTURE_BINDING to the texture's usage when you create it.`,\n subject,\n );\n }\n if (!SUPPORTED_APP_TEXTURE_FORMATS.includes(texture.format)) {\n throw rendererError(\n \"texture-format\",\n `Backdrop \"${subject}\" supplied a \"${texture.format}\" texture. Supported formats are ${SUPPORTED_APP_TEXTURE_FORMATS.join(\", \")}.`,\n subject,\n );\n }\n if (texture.width <= 0 || texture.height <= 0) {\n throw rendererError(\n \"texture-size\",\n `Backdrop \"${subject}\" supplied a ${texture.width}×${texture.height} texture.`,\n subject,\n );\n }\n const max = limits.maxTextureDimension2D;\n if (texture.width > max || texture.height > max) {\n throw rendererError(\n \"texture-size\",\n `Backdrop \"${subject}\" supplied a ${texture.width}×${texture.height} texture, past this adapter's maxTextureDimension2D of ${max}.`,\n subject,\n );\n }\n}\n\nexport function createAppTextureProvider(options: AppTextureProviderOptions): BackdropProvider {\n // Registration-time validation. Throwing here — not at draw time — is the whole\n // point of X3's sentence about app-supplied views.\n validateAppTexture(options.texture, options.device.limits, options.id);\n\n const encoded = options.encoded ?? !options.texture.format.includes(\"float\");\n const size = {\n epoch: 0,\n width: options.texture.width,\n height: options.texture.height,\n };\n\n const builtGeneration = options.generation ?? 0;\n let generation = builtGeneration;\n\n return {\n id: options.id,\n kind: \"app-texture-view\",\n\n get generation() {\n return generation;\n },\n\n isDirty() {\n // The app may redraw into its own texture at any time and the renderer has\n // no way to know. Assuming dirty is the honest default; an app that knows\n // better re-registers with a static source.\n return true;\n },\n\n acquire() {\n // One integer compare, which is the only check available: a\n // `GPUTextureView` carries no evidence of the device that made it, and\n // binding one from a superseded device produces no error the renderer can\n // see — only a pass that quietly renders nothing. X3's \"never discovered at\n // draw time\" cuts the other way here, so the refusal is loud and names the\n // handshake that clears it.\n if (generation !== builtGeneration) {\n throw rendererError(\n \"source-unavailable\",\n `Backdrop \"${options.id}\" wraps a GPUTexture from device generation ${builtGeneration}, and the renderer is now on generation ${generation}. WebGPU has no cross-device texture sharing: unregister this source and register the replacement texture the app made on the new device.`,\n options.id,\n );\n }\n return {\n sourceId: options.id,\n binding: {\n kind: \"sampled\",\n view: options.view ?? options.texture.createView(),\n },\n width: size.width,\n height: size.height,\n sizeEpoch: size.epoch,\n colorSpace: options.colorSpace ?? \"srgb\",\n alphaMode: options.alphaMode ?? \"premultiplied\",\n encoded,\n };\n },\n\n release() {\n // The app owns the texture; the renderer releases nothing.\n },\n\n markImported() {\n // Nothing to record.\n },\n\n invalidate(next) {\n // Nothing to drop and nothing to re-point: the texture is the app's, made\n // on a device this provider does not own. Recording the generation is what\n // turns the next acquire into a refusal.\n generation = next;\n },\n\n destroy() {\n // The app owns the texture; destroying it here would be taking ownership we\n // were never given.\n },\n };\n}\n","/**\n * Device ownership, loss teardown, and rebuild (§GPU device ownership).\n *\n * `platform-web` owns the *browser* half of the story — is there an adapter, get\n * a device, notice when it goes away. This module owns the *resource* half: what\n * has to be thrown away when a device dies, when it is safe to build again, and\n * what core's capability inputs should read while that is in flight.\n *\n * ## The two ownership modes, and why they are not symmetric\n *\n * - **vitrea-owned** — this module can re-request a device by itself, so loss is\n * a transient it recovers from: tear down, re-request, re-attach, rebuild.\n * Every backdrop source is re-imported on the next frame because loss marks\n * them all dirty, which routes recovery through the same\n * one-rebuild-per-dirty-source-per-frame path a content change takes rather\n * than through a special case.\n * - **app-owned** — the app owns the resources that would have to be\n * re-registered, so this module reports the loss, raises\n * `replacementPending`, and **waits**. Groups stay demoted until\n * `replaceDevice` arrives and the re-registration handshake completes. Inventing\n * a device the app did not give us would break the one guarantee app-ownership\n * exists for: that every texture the renderer samples came from the app's own\n * device, because WebGPU has no cross-device sharing.\n *\n * `info.reason === \"destroyed\"` is our own teardown and is not recovered from —\n * re-requesting there would resurrect a renderer the host just destroyed.\n *\n * ## Generations\n *\n * Every attach bumps a generation counter, and every GPU object this package\n * holds is tagged with the generation it was made under. A resource from a lost\n * device is unusable forever, and the failure mode is silent — bindings simply\n * produce nothing — so \"is this from the current device\" has to be a cheap\n * integer comparison somewhere. It is here.\n */\n\nimport { rendererError } from \"./errors\";\n\n/**\n * Structurally identical to `vitrea`'s `WebGPUAvailability` (X2's K1\n * amendment, Decision Log #21c). Declared here rather than imported because this\n * package sits *below* core in the dependency graph — core reaches the renderer\n * through a dynamic import, so an import back would close a cycle. A test pins\n * the two unions to the same members.\n */\nexport type WebGPUAvailability = \"not-requested\" | \"unavailable\" | \"available\";\n\nexport type DeviceOwnership = \"vitrea\" | \"app\";\n\nexport interface RendererDeviceStatus {\n /** Feeds core's `PlatformProbe.webgpu` unchanged. */\n readonly webgpu: WebGPUAvailability;\n readonly deviceHealth: \"ok\" | \"lost\";\n readonly ownership: DeviceOwnership;\n readonly device: GPUDevice | undefined;\n /** Bumped on every attach. Tags every resource built under it. */\n readonly generation: number;\n /** True while an app-owned device is lost and no replacement has arrived. */\n readonly replacementPending: boolean;\n /** Why there is no device, when there is a reason worth reporting. */\n readonly unavailableReason?: \"no-adapter\" | \"device-request-failed\" | \"lost\";\n}\n\n/** The capability facts a host folds into core's `PlatformProbe`. */\nexport interface DeviceCapabilityInput {\n readonly webgpu: WebGPUAvailability;\n readonly deviceHealth: \"ok\" | \"lost\";\n}\n\n/** Run on loss and on teardown. Must be idempotent and must not touch the device. */\nexport type TeardownHook = () => void;\n\nexport interface DeviceHostOptions {\n readonly onStatusChange?: (status: RendererDeviceStatus) => void;\n /** Raised when an app-owned device is lost and only the app can replace it. */\n readonly onReplacementNeeded?: () => void;\n /**\n * Re-request a vitrea-owned device. Absent means \"no automatic recovery\",\n * which is the honest configuration when the host owns the adapter handshake.\n */\n readonly reacquire?: () => Promise<GPUDevice | undefined>;\n}\n\nexport interface DeviceHost {\n readonly status: RendererDeviceStatus;\n readonly capabilityInput: DeviceCapabilityInput;\n /** The current device, or a thrown `device-unavailable` if there is none. */\n requireDevice(): GPUDevice;\n attach(device: GPUDevice, ownership: DeviceOwnership): void;\n /** Hand in a replacement for a lost device. Also clears `replacementPending`. */\n replaceDevice(device: GPUDevice): void;\n /**\n * Record that WebGPU *was* asked for and could not be had. Moves `webgpu` off\n * `\"not-requested\"`, which is the difference K1 exists to preserve.\n */\n markUnavailable(reason: \"no-adapter\" | \"device-request-failed\"): void;\n addTeardownHook(hook: TeardownHook): () => void;\n /** Awaits the in-flight recovery, if any. Test and shutdown seam. */\n settled(): Promise<void>;\n destroy(): void;\n}\n\nexport function createDeviceHost(options: DeviceHostOptions = {}): DeviceHost {\n let status: RendererDeviceStatus = {\n webgpu: \"not-requested\",\n deviceHealth: \"ok\",\n ownership: \"vitrea\",\n device: undefined,\n generation: 0,\n replacementPending: false,\n };\n const hooks = new Set<TeardownHook>();\n let destroyed = false;\n let recovery: Promise<void> | undefined;\n\n const publish = (next: RendererDeviceStatus): void => {\n status = next;\n if (!destroyed) options.onStatusChange?.(status);\n };\n\n const runTeardown = (): void => {\n // A hook that throws must not stop the others: half-torn-down state after a\n // device loss is the one condition from which nothing can recover.\n for (const hook of [...hooks]) {\n try {\n hook();\n } catch {\n // Deliberately swallowed — see above.\n }\n }\n };\n\n const watchLoss = (device: GPUDevice, generation: number): void => {\n void device.lost.then((info) => {\n // A loss from a superseded device is not this device's loss.\n if (destroyed || status.generation !== generation) return;\n\n runTeardown();\n const ownership = status.ownership;\n publish({\n webgpu: \"available\",\n deviceHealth: \"lost\",\n ownership,\n device: undefined,\n generation,\n replacementPending: ownership === \"app\",\n unavailableReason: \"lost\",\n });\n\n if (info.reason === \"destroyed\") return;\n\n if (ownership === \"app\") {\n options.onReplacementNeeded?.();\n return;\n }\n\n const reacquire = options.reacquire;\n if (reacquire === undefined) return;\n recovery = (async () => {\n const replacement = await reacquire();\n // A `destroy()` that lands while the re-request is in flight still has to\n // account for what the re-request produced. Returning without destroying\n // it leaks a whole GPUDevice on the one path where this module IS the\n // owner — the host has no handle to it, because it never learned the\n // reacquire had finished.\n if (destroyed) {\n replacement?.destroy();\n return;\n }\n if (replacement === undefined) return;\n attach(replacement, \"vitrea\");\n })();\n });\n };\n\n function attach(device: GPUDevice, ownership: DeviceOwnership): void {\n const generation = status.generation + 1;\n publish({\n webgpu: \"available\",\n deviceHealth: \"ok\",\n ownership,\n device,\n generation,\n replacementPending: false,\n });\n watchLoss(device, generation);\n }\n\n return {\n get status() {\n return status;\n },\n\n get capabilityInput() {\n return { webgpu: status.webgpu, deviceHealth: status.deviceHealth };\n },\n\n requireDevice() {\n const { device } = status;\n if (device === undefined) {\n throw rendererError(\n \"device-unavailable\",\n status.replacementPending\n ? \"The app-owned GPUDevice was lost and no replacement has been handed in yet. Call replaceDevice() and re-register the app's texture views before drawing again.\"\n : \"No GPUDevice is attached. Attach one (platform-web's WebGPU lifecycle produces it) before building resources or drawing.\",\n );\n }\n return device;\n },\n\n attach,\n\n replaceDevice(device) {\n attach(device, status.ownership);\n },\n\n markUnavailable(reason) {\n publish({\n ...status,\n webgpu: \"unavailable\",\n device: undefined,\n unavailableReason: reason,\n });\n },\n\n addTeardownHook(hook) {\n hooks.add(hook);\n return () => hooks.delete(hook);\n },\n\n async settled() {\n await recovery;\n },\n\n destroy() {\n destroyed = true;\n runTeardown();\n // Only a device this renderer owns is ours to destroy.\n if (status.ownership === \"vitrea\") status.device?.destroy();\n hooks.clear();\n status = { ...status, device: undefined };\n },\n };\n}\n","/**\n * The governor's knobs.\n *\n * §Performance envelope: \"The governor degrades **within** a tier first\n * (refraction resolution, adaptation cadence, edge analysis) and switches tiers\n * only with long hysteresis and cooldown.\" Decision Log #19 adds that intra-tier\n * degradation is **not a state change** — a group under `degrade-in-tier`\n * pressure keeps `activeRenderer: \"webgpu\"` and its whole resolved state.\n *\n * So the split is: **the policy lives in core, the knobs live here.** This module\n * exposes what can be turned and publishes a suggested ladder as *data*; it never\n * decides to turn anything, never reads a clock, and never applies hysteresis.\n * A governor that lived in the renderer would be a governor that could not see\n * the scene it is governing.\n *\n * ## The three knobs, weakest cost first\n *\n * 1. **`fieldFamily`** — `rsupn` → `rsup`. S2 priced this at 29% of the field's\n * cost for a bound that degrades from 0.170 px / 2.91° to 0.574 px / 4.26°.\n * It is the *first* step because it is one uniform and one pipeline: no\n * resolution change, so nothing resamples and nothing shimmers as it engages.\n * **Conditional on the f32 cross-check** (Decision Log #20) — and the check\n * has now been run, so the condition is met. See `FAMILY_C_CROSS_CHECK`.\n * 2. **`refractionResolutionScale`** — the group's **field** targets are\n * rasterised at a fraction of device resolution, and the optics and highlight\n * passes filter them instead of indexing them (`passes.ts`, and the\n * `fieldUpsampled` flag both shaders branch on). Quadratic saving on the pass\n * that evaluates the pseudo-SDF union per pixel per member, and the most\n * visible step, so it comes second.\n *\n * What it does **not** yet do is shrink the optics and highlight passes\n * themselves: those still render at full device resolution into the plane\n * canvases, because rendering them smaller means an offscreen target and a\n * resolve pass rather than a change of extent. So rungs 2 and 3 deliver the\n * field's quadratic saving and the cadence saving, not the full quadratic\n * saving on both heavy passes. Recorded here rather than implied, because a\n * ladder whose rungs are priced for savings they do not deliver is a ladder\n * core's policy will walk too far down.\n * 3. **`adaptationCadenceHz`** — how often analysis is reduced and read back.\n * Cheapest of the three in visual terms because the values it feeds are\n * already low-passed over hundreds of milliseconds; dropping the cadence\n * mostly changes how quickly a scroll's new backdrop is noticed.\n */\n\nexport type FieldFamily = \"rsupn\" | \"rsup\";\n\nexport interface GovernorKnobs {\n /** Which pseudo-SDF family the field pass compiles. */\n readonly fieldFamily: FieldFamily;\n /**\n * Device-resolution fraction the group's field targets are rasterised at,\n * 0 < s <= 1. The optics and highlight passes upsample what they read. See the\n * module note for what this does and does not save.\n */\n readonly refractionResolutionScale: number;\n /** Analysis reduction + readback rate. 0 disables adaptation entirely. */\n readonly adaptationCadenceHz: number;\n}\n\n/**\n * Full fidelity. `adaptationCadenceHz` is core's advisory 15 Hz readback ceiling\n * (Decision Log #19) — the analysis pass has no reason to run faster than the\n * values it produces can be consumed.\n */\nexport const NOMINAL_GOVERNOR: GovernorKnobs = {\n fieldFamily: \"rsupn\",\n refractionResolutionScale: 1,\n adaptationCadenceHz: 15,\n};\n\n/**\n * The suggested intra-tier ladder, as data for core's policy to walk. Each step\n * is cumulative on the one before it, weakest visual cost first.\n */\nexport const GOVERNOR_LADDER: readonly GovernorKnobs[] = [\n NOMINAL_GOVERNOR,\n { fieldFamily: \"rsup\", refractionResolutionScale: 1, adaptationCadenceHz: 15 },\n { fieldFamily: \"rsup\", refractionResolutionScale: 0.75, adaptationCadenceHz: 7.5 },\n { fieldFamily: \"rsup\", refractionResolutionScale: 0.5, adaptationCadenceHz: 4 },\n];\n\n/**\n * Decision Log #20's condition, and its answer.\n *\n * The spec makes family C's shipping \"conditional on C6 running the f32\n * cross-check on its WGSL\". C6 ran it, twice and independently:\n *\n * - **On hardware** (`e2e/gpu/cross-check.spec.ts`, apple/metal-3): the shipped\n * `sd_rsup` kernel against `@vitrea/geometry`'s f64 `rsupField` over 5535\n * points on and around three shapes' contours — **3.042e-5 px max, 0.0053% of\n * the declared 0.574 px bound.** The same run measured family D at 4.073e-5 px\n * / 0.0240%, reproducing S2's own 4.08e-5 / 0.024% on that adapter class,\n * which is what makes the two runs comparable at all.\n * - **In the unit suite** (`test/f32-cross-check.test.ts`): the same arithmetic\n * emulated in f32 through `Math.fround`, so the answer exists on a machine\n * with no adapter. 3.523e-5 px, the same order.\n *\n * So the gate is open by default, and the option below is the opt-out rather than\n * the opt-in. What keeps that honest is that both checks run in CI and that\n * `@vitrea/geometry` fingerprints the kernel strings: editing `sd_rsup` trips the\n * fingerprint test, which says in as many words to re-run the cross-check.\n */\nexport const FAMILY_C_CROSS_CHECK = {\n ran: true,\n adapter: \"apple/metal-3\",\n points: 5535,\n maxAbsDiffPx: 3.042e-5,\n boundPx: 0.574,\n} as const;\n\nexport interface GovernorOptions {\n /**\n * Whether family C's WGSL has been through the f32 cross-check (Decision Log\n * #20). Defaults to `FAMILY_C_CROSS_CHECK.ran` — see above. Pass `false` to\n * hold the governor to family D regardless.\n */\n readonly familyCVerified?: boolean;\n readonly onChange?: (knobs: GovernorKnobs) => void;\n}\n\nexport interface Governor {\n readonly knobs: GovernorKnobs;\n /** True when `fieldFamily: \"rsup\"` is permitted to engage. */\n readonly familyCVerified: boolean;\n set(patch: Partial<GovernorKnobs>): GovernorKnobs;\n /** Move to a rung of the suggested ladder. Out-of-range clamps to the ends. */\n setLevel(level: number): GovernorKnobs;\n reset(): GovernorKnobs;\n /** Record that the cross-check passed, unlocking family C. */\n recordFamilyCVerified(): void;\n}\n\nconst clampScale = (s: number): number => Math.min(1, Math.max(0.125, s));\n\nexport function createGovernor(options: GovernorOptions = {}): Governor {\n let knobs = NOMINAL_GOVERNOR;\n let verified = options.familyCVerified ?? FAMILY_C_CROSS_CHECK.ran;\n\n const apply = (next: GovernorKnobs): GovernorKnobs => {\n const family: FieldFamily = next.fieldFamily === \"rsup\" && !verified ? \"rsupn\" : next.fieldFamily;\n knobs = {\n fieldFamily: family,\n refractionResolutionScale: clampScale(next.refractionResolutionScale),\n adaptationCadenceHz: Math.max(0, next.adaptationCadenceHz),\n };\n options.onChange?.(knobs);\n return knobs;\n };\n\n return {\n get knobs() {\n return knobs;\n },\n\n get familyCVerified() {\n return verified;\n },\n\n set(patch) {\n return apply({ ...knobs, ...patch });\n },\n\n setLevel(level) {\n const index = Math.min(GOVERNOR_LADDER.length - 1, Math.max(0, Math.round(level)));\n return apply(GOVERNOR_LADDER[index] as GovernorKnobs);\n },\n\n reset() {\n return apply(NOMINAL_GOVERNOR);\n },\n\n recordFamilyCVerified() {\n verified = true;\n },\n };\n}\n","/**\n * Shader-module and pipeline caches.\n *\n * Pipeline creation is the single most expensive thing a WebGPU renderer can do\n * per frame, and this renderer's pipeline set is small and fixed: two field\n * families, two import kinds, the chain, the analysis reduction, optics,\n * highlight. So the cache is a plain memo keyed by a descriptor string, and the\n * only interesting part is what goes into that key.\n *\n * Two rules about keys, both learned the same way — a cache that returns a\n * pipeline compiled against a different target format fails at draw time with an\n * error that names neither the format nor the cache:\n *\n * - **Every property that changes the compiled artefact is in the key.** Target\n * format, blend state, and the entry points, not just the shader name.\n * - **Nothing else is.** Uniform *values* never are; they travel in buffers. A\n * key that grew a tint colour would make the cache a leak.\n *\n * Like the texture pool, this is written over the narrow slice of `GPUDevice` it\n * uses, so eviction and key discipline are testable without an adapter.\n */\n\n/** The slice of `GPUDevice` the caches need. `GPUDevice` satisfies it as-is. */\nexport interface PipelineFactory {\n createShaderModule(descriptor: GPUShaderModuleDescriptor): GPUShaderModule;\n createRenderPipeline(descriptor: GPURenderPipelineDescriptor): GPURenderPipeline;\n createComputePipeline(descriptor: GPUComputePipelineDescriptor): GPUComputePipeline;\n}\n\nexport interface PipelineCacheStats {\n readonly modules: number;\n readonly renderPipelines: number;\n readonly computePipelines: number;\n readonly hits: number;\n readonly misses: number;\n}\n\nexport interface PipelineCache {\n readonly stats: PipelineCacheStats;\n module(key: string, source: () => string): GPUShaderModule;\n renderPipeline(key: string, describe: () => GPURenderPipelineDescriptor): GPURenderPipeline;\n computePipeline(key: string, describe: () => GPUComputePipelineDescriptor): GPUComputePipeline;\n clear(): void;\n}\n\nexport function createPipelineCache(factory: PipelineFactory): PipelineCache {\n const modules = new Map<string, GPUShaderModule>();\n const renderPipelines = new Map<string, GPURenderPipeline>();\n const computePipelines = new Map<string, GPUComputePipeline>();\n let hits = 0;\n let misses = 0;\n\n function memo<T>(store: Map<string, T>, key: string, make: () => T): T {\n const existing = store.get(key);\n if (existing !== undefined) {\n hits += 1;\n return existing;\n }\n misses += 1;\n const made = make();\n store.set(key, made);\n return made;\n }\n\n return {\n get stats() {\n return {\n modules: modules.size,\n renderPipelines: renderPipelines.size,\n computePipelines: computePipelines.size,\n hits,\n misses,\n };\n },\n\n module(key, source) {\n return memo(modules, key, () => factory.createShaderModule({ label: key, code: source() }));\n },\n\n renderPipeline(key, describe) {\n return memo(renderPipelines, key, () => factory.createRenderPipeline(describe()));\n },\n\n computePipeline(key, describe) {\n return memo(computePipelines, key, () => factory.createComputePipeline(describe()));\n },\n\n clear() {\n // GPU pipelines and modules have no explicit destroy: dropping the last\n // reference is the release. Clearing the maps IS the teardown, and it has to\n // happen on device loss because objects from a lost device stay unusable\n // forever.\n modules.clear();\n renderPipelines.clear();\n computePipelines.clear();\n },\n };\n}\n\n/** Pipeline keys, so the \"everything that changes the artefact\" rule is visible. */\nexport const pipelineKey = {\n field: (family: string, format: GPUTextureFormat): string => `field:${family}:${format}`,\n import: (kind: string, format: GPUTextureFormat): string => `import:${kind}:${format}`,\n chain: (entry: string, format: GPUTextureFormat): string => `chain:${entry}:${format}`,\n analysis: (): string => \"analysis\",\n optics: (format: GPUTextureFormat, blend: string): string => `optics:${format}:${blend}`,\n highlight: (format: GPUTextureFormat, blend: string): string => `highlight:${format}:${blend}`,\n} as const;\n","/**\n * The texture pool, with size-epoch invalidation.\n *\n * §GPU device ownership: \"Resizes bump a size epoch that invalidates dependent\n * pyramid allocations.\" Two properties follow from taking that literally, and\n * both are what the pool exists for:\n *\n * - **A texture is keyed by purpose, not by shape.** Callers ask for\n * `\"pyramid:bg-video:level-2\"`, not for \"a 512×256 rgba16float\". So a resize\n * replaces an allocation in place rather than leaking a second one beside it,\n * and the leak is impossible rather than unlikely.\n * - **The epoch is compared, not the size.** A texture allocated under an older\n * epoch is destroyed even when its dimensions happen to match, because a size\n * epoch also covers DPR changes and resolution-policy changes that leave the\n * pixel count alone. Comparing sizes would silently keep a texture whose\n * *meaning* changed.\n *\n * The pool is written over a two-method `TextureAllocator` rather than against\n * `GPUDevice` directly. That is not indirection for its own sake: it makes the\n * keying, the epoch sweep, and the destroy-exactly-once accounting testable\n * without a GPU, which is the half of this file most likely to harbour a leak.\n */\n\nexport interface TextureRequest {\n readonly width: number;\n readonly height: number;\n readonly format: GPUTextureFormat;\n readonly usage: GPUTextureUsageFlags;\n /** Mip levels. The blur chain is the only caller that asks for more than one. */\n readonly mipLevelCount?: number;\n readonly label?: string;\n}\n\n/** The slice of `GPUDevice` the pool needs. `GPUDevice` satisfies it as-is. */\nexport interface TextureAllocator {\n createTexture(descriptor: GPUTextureDescriptor): GPUTexture;\n}\n\ninterface PoolEntry {\n readonly texture: GPUTexture;\n readonly request: TextureRequest;\n readonly epoch: number;\n}\n\nexport interface TexturePoolStats {\n readonly live: number;\n readonly created: number;\n readonly destroyed: number;\n readonly reused: number;\n readonly epoch: number;\n}\n\nexport interface TexturePool {\n readonly sizeEpoch: number;\n readonly stats: TexturePoolStats;\n /**\n * The texture for `key` at the current epoch, allocating or reallocating as\n * needed. Two calls with the same key and the same request in one epoch return\n * the same texture.\n */\n acquire(key: string, request: TextureRequest): GPUTexture;\n /** The texture for `key`, or undefined if nothing is allocated under it. */\n peek(key: string): GPUTexture | undefined;\n release(key: string): void;\n /** Bump the size epoch. Nothing is destroyed until the next `acquire` or `sweep`. */\n bumpSizeEpoch(): number;\n /** Destroy everything allocated under an older epoch. */\n sweep(): number;\n /** Destroy everything. Used by device-loss teardown and by `destroy`. */\n clear(): void;\n}\n\nconst sameShape = (a: TextureRequest, b: TextureRequest): boolean =>\n a.width === b.width &&\n a.height === b.height &&\n a.format === b.format &&\n a.usage === b.usage &&\n (a.mipLevelCount ?? 1) === (b.mipLevelCount ?? 1);\n\nexport function createTexturePool(allocator: TextureAllocator): TexturePool {\n const entries = new Map<string, PoolEntry>();\n let epoch = 0;\n let created = 0;\n let destroyed = 0;\n let reused = 0;\n\n const destroy = (entry: PoolEntry): void => {\n entry.texture.destroy();\n destroyed += 1;\n };\n\n return {\n get sizeEpoch() {\n return epoch;\n },\n\n get stats() {\n return { live: entries.size, created, destroyed, reused, epoch };\n },\n\n acquire(key, request) {\n const existing = entries.get(key);\n if (existing !== undefined) {\n if (existing.epoch === epoch && sameShape(existing.request, request)) {\n reused += 1;\n return existing.texture;\n }\n destroy(existing);\n }\n\n const texture = allocator.createTexture({\n size: {\n width: Math.max(1, Math.floor(request.width)),\n height: Math.max(1, Math.floor(request.height)),\n depthOrArrayLayers: 1,\n },\n format: request.format,\n usage: request.usage,\n mipLevelCount: request.mipLevelCount ?? 1,\n ...(request.label === undefined ? {} : { label: request.label }),\n });\n created += 1;\n entries.set(key, { texture, request, epoch });\n return texture;\n },\n\n peek(key) {\n return entries.get(key)?.texture;\n },\n\n release(key) {\n const entry = entries.get(key);\n if (entry === undefined) return;\n destroy(entry);\n entries.delete(key);\n },\n\n bumpSizeEpoch() {\n epoch += 1;\n return epoch;\n },\n\n sweep() {\n let swept = 0;\n for (const [key, entry] of [...entries]) {\n if (entry.epoch === epoch) continue;\n destroy(entry);\n entries.delete(key);\n swept += 1;\n }\n return swept;\n },\n\n clear() {\n for (const entry of entries.values()) destroy(entry);\n entries.clear();\n },\n };\n}\n\n/** Pool keys, in one place so a typo is a compile error rather than a leak. */\nexport const poolKey = {\n backdropLevel0: (sourceId: string): string => `backdrop:${sourceId}:level0`,\n backdropChain: (sourceId: string): string => `backdrop:${sourceId}:chain`,\n backdropChainScratch: (sourceId: string, level: number): string =>\n `backdrop:${sourceId}:chain-scratch:${level}`,\n backdropBody: (sourceId: string): string => `backdrop:${sourceId}:body`,\n backdropBodyScratch: (sourceId: string): string => `backdrop:${sourceId}:body-scratch`,\n backdropUpload: (sourceId: string): string => `backdrop:${sourceId}:upload`,\n groupField: (groupId: string): string => `group:${groupId}:field`,\n groupAux: (groupId: string): string => `group:${groupId}:aux`,\n} as const;\n","/**\n * Everything that belongs to one device generation, in one object.\n *\n * A device loss makes every GPU object made from that device permanently\n * unusable, and the failure is *silent* — bindings simply stop producing pixels.\n * So the pool, the pipeline cache, the samplers and the uniform buffers are held\n * together with the generation they were made under, and recovery replaces the\n * whole context rather than reaching into it. That makes \"did I just bind a\n * resource from a dead device\" impossible to get wrong instead of merely unlikely.\n */\n\nimport { createPipelineCache, type PipelineCache } from \"./pipeline-cache\";\nimport { createTexturePool, type TexturePool } from \"./texture-pool\";\n\nexport interface GpuContext {\n readonly device: GPUDevice;\n /** The device generation this context belongs to. */\n readonly generation: number;\n readonly pool: TexturePool;\n readonly cache: PipelineCache;\n /** Linear min/mag with linear mip filtering — the pyramid's sampler. */\n readonly chainSampler: GPUSampler;\n /** Linear min/mag, no mips — the body blur and import samplers. */\n readonly flatSampler: GPUSampler;\n destroy(): void;\n}\n\nexport function createGpuContext(device: GPUDevice, generation: number): GpuContext {\n const pool = createTexturePool(device);\n const cache = createPipelineCache(device);\n\n // Clamp-to-edge on every axis. A repeating pyramid would wrap the backdrop\n // across the refraction offset at a group's edge, which reads as a hard seam\n // exactly where the lens is strongest.\n const chainSampler = device.createSampler({\n label: \"vitrea:sampler:chain\",\n magFilter: \"linear\",\n minFilter: \"linear\",\n mipmapFilter: \"linear\",\n addressModeU: \"clamp-to-edge\",\n addressModeV: \"clamp-to-edge\",\n });\n\n const flatSampler = device.createSampler({\n label: \"vitrea:sampler:flat\",\n magFilter: \"linear\",\n minFilter: \"linear\",\n addressModeU: \"clamp-to-edge\",\n addressModeV: \"clamp-to-edge\",\n });\n\n return {\n device,\n generation,\n pool,\n cache,\n chainSampler,\n flatSampler,\n destroy() {\n pool.clear();\n cache.clear();\n },\n };\n}\n\n/** A uniform buffer sized to a fixed float count, reused across frames. */\nexport interface UniformSlot {\n readonly buffer: GPUBuffer;\n readonly data: Float32Array;\n write(): void;\n}\n\nexport function createUniformSlot(\n device: GPUDevice,\n floats: number,\n label: string,\n): UniformSlot {\n // Uniform buffers must be a multiple of 16 bytes, and every struct in this\n // package is laid out as vec4 rows precisely so this rounding never silently\n // truncates a member.\n const size = Math.ceil((floats * 4) / 16) * 16;\n const buffer = device.createBuffer({\n label,\n size,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n });\n const data = new Float32Array(size / 4);\n return {\n buffer,\n data,\n write() {\n device.queue.writeBuffer(buffer, 0, data.buffer, data.byteOffset, data.byteLength);\n },\n };\n}\n\n/** A storage buffer that grows in place when the instance count outgrows it. */\nexport interface StorageSlot {\n readonly buffer: GPUBuffer;\n ensure(byteLength: number): GPUBuffer;\n write(data: Float32Array, floatCount: number): void;\n destroy(): void;\n}\n\nexport function createStorageSlot(\n device: GPUDevice,\n initialBytes: number,\n label: string,\n): StorageSlot {\n let capacity = Math.max(initialBytes, 256);\n let buffer = device.createBuffer({\n label,\n size: capacity,\n usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,\n });\n\n return {\n get buffer() {\n return buffer;\n },\n ensure(byteLength) {\n if (byteLength <= capacity) return buffer;\n buffer.destroy();\n // Grow in powers of two: a group that gains one surface per frame during a\n // morph would otherwise reallocate every frame.\n capacity = 1 << Math.ceil(Math.log2(byteLength));\n buffer = device.createBuffer({\n label,\n size: capacity,\n usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,\n });\n return buffer;\n },\n write(data, floatCount) {\n device.queue.writeBuffer(buffer, 0, data.buffer, data.byteOffset, floatCount * 4);\n },\n destroy() {\n buffer.destroy();\n },\n };\n}\n","/**\n * What the renderer consumes each frame, and why it is declared here rather than\n * imported from `vitrea`.\n *\n * The renderer sits **below** core in the dependency graph: core reaches it\n * through a dynamic import (X7's lazy seam), so importing core back would close a\n * cycle that neither `pnpm -r build` nor `tsc` can order. The types below are\n * therefore declared as the *minimal structural contract* the renderer reads, and\n * core's own types satisfy them without an adapter — `SceneResolution`,\n * `FrameContext` and `FrameParticipant` are assignable to the views here, which\n * `test/core-contract.test.ts` asserts against core's real modules.\n *\n * Two things genuinely do not come from core, and both are flagged as\n * parent-impact rather than papered over:\n *\n * - **The corner reference.** `GlassNodeDescriptor` carries `shapeFamily` and\n * the X8 channel vector but not which of the two corner references the shape\n * is fit against (Decision Log #22a made those two separate references, not\n * one axis). It defaults to `\"apple-continuous\"`, which is what the public\n * `profile: \"continuous\"` — the default — resolves to.\n * - **The concentric parent link.** X8 rider 2 binds the renderer to draw a\n * concentric child as a level set *of its parent's field*, which needs to know\n * which surface the parent is. core's node descriptor has no parent edge, so it\n * arrives as a render input.\n *\n * Interaction values arrive as **numbers**, never as time. §Motion puts the\n * drivers on the CPU and the spec is explicit that this package consumes their\n * outputs; there is no clock anywhere in this package for the same reason there is\n * none in core.\n */\n\nimport type {\n CornerReference,\n GroupUnionParams,\n ShapeChannels,\n ShapeFamily,\n} from \"@vitrea/geometry\";\n\nimport type { Rgb } from \"./color\";\nimport type { MaterialPolicyView, MaterialVariant, RefractionQuality } from \"./material\";\n\n/** Viewport-space rectangle in CSS px. Matches core's `Rect`. */\nexport interface Rect {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n}\n\n/** Motion-driver outputs for one surface. Every one is a value, never a time. */\nexport interface SurfaceChannels {\n /** `pressCompression`, 0..1. Scaled by motion's `pressCompressionScale`. */\n readonly press: number;\n /** `glow`, 0..1, from the fast-attack / slow-decay driver. */\n readonly glow: number;\n /** Specular sweep position, 0..1 around the contour. */\n readonly sweep: number;\n /** `lensStrength`, 0..1. Multiplies the resolved refraction scale. */\n readonly lensStrength: number;\n /** Press point in viewport CSS px. Defaults to the surface's centre. */\n readonly pressPoint?: readonly [number, number];\n}\n\nexport const IDLE_CHANNELS: SurfaceChannels = {\n press: 0,\n glow: 0,\n sweep: 0,\n lensStrength: 1,\n};\n\n/** An author tint as this package takes it: a seed in linear light, and a strength. */\nexport interface MaterialTintInput {\n readonly color: readonly [number, number, number];\n readonly strength: number;\n}\n\nexport interface SurfaceInput {\n readonly nodeId: string;\n readonly family: ShapeFamily;\n /** X8, in viewport CSS px. `centre` is the surface's centre, `size` its full extent. */\n readonly shape: ShapeChannels;\n /** Defaults to `\"apple-continuous\"` — see the module note. */\n readonly reference?: CornerReference;\n readonly variant?: MaterialVariant;\n /**\n * The author's tint (core's `ResolvedMaterial.tint`), in **linear** light —\n * the host converts, because this package's whole optical model is linear and\n * the seed is about to be mixed into it.\n *\n * The strength travels per surface and reaches the fragment stage per pixel;\n * the seed colour is resolved once per group, because a group is one optics\n * pass. Core warns when a group's members ask for different seeds\n * (`tint-mixing`), and the first tinted member's colour is the one drawn.\n */\n readonly tint?: MaterialTintInput;\n readonly channels?: Partial<SurfaceChannels>;\n /**\n * X8 rider 2. When present this surface renders as `parentField + inset`, and\n * the parent must be declared in the same group — as a member, or as a\n * `fieldReferenceOnly` shape.\n */\n readonly concentricOf?: { readonly nodeId: string; readonly inset: number };\n /**\n * Declared so a concentric child can be a level set of it, but not itself\n * drawn.\n *\n * This exists because of what a union is: a concentric child's field is its\n * parent's plus a positive inset, so inside the parent the child is always the\n * larger value and `min` discards it. A child nested in the same union as its\n * parent is therefore invisible *by construction* — correct, and not what an\n * inset indicator inside a segmented control's track wants. There, the track\n * and the indicator are separate surfaces with separate material, and the\n * indicator's group needs the track's geometry only as the field its own\n * contour is offset from.\n */\n readonly fieldReferenceOnly?: boolean;\n}\n\nexport interface GroupRenderInput {\n readonly groupId: string;\n readonly surfaces: readonly SurfaceInput[];\n /** The backdrop source to sample. Absent means the group draws with no backdrop. */\n readonly backdropSourceId?: string;\n /** X2's resolved refraction quality for this group. Half of the dual cap. */\n readonly refraction: RefractionQuality;\n /** True where X2 resolved `analysis: \"exact\"`; gates adaptive tint. */\n readonly analysisExact: boolean;\n /**\n * The backdrop source's own average colour, linear light — what backdrop tone\n * adaptation (W7) adapts toward, and the luminance it decides from.\n *\n * A **per-source scalar rather than a per-pixel sample**, and that is why it\n * arrives from outside rather than being read off the pyramid. The host measures\n * it once from the pixels it already supplied and both tiers then read the\n * identical number: the CSS tier cannot sample per pixel at all, and a per-pixel\n * GPU adaptation beside a per-surface CSS one puts the two tiers on different\n * pictures wherever the backdrop has structure — measured on the impulse cell at\n * an interior level ratio of 79 against a gated band of 0.80…1.25. It is also\n * what the reference does: its capsule over a sparse bright grid is a *flat*\n * body, not a window onto the grid.\n *\n * Absent means the adaptation stands down for this group, rather than falling\n * back to a level nobody measured.\n */\n readonly backdropTone?: Rgb;\n readonly variant?: MaterialVariant;\n /** Overrides the calibration-delegated union defaults. */\n readonly union?: GroupUnionParams;\n}\n\n/** The whole frame's render input. */\nexport interface FrameRenderInput {\n readonly groups: readonly GroupRenderInput[];\n /** The other half of the dual cap. Defaults to the nominal policy. */\n readonly accessibility?: MaterialPolicyView;\n}\n\n/**\n * The structural view of core's `SceneResolution` the renderer reads, so a host\n * can hand core's own object straight through.\n */\nexport interface SceneResolutionView {\n readonly groups: readonly {\n readonly groupId: string;\n readonly state: {\n readonly refraction: RefractionQuality;\n readonly analysis: \"exact\" | \"hint\" | \"none\";\n readonly samplingBackend: \"gpu-texture\" | \"css-backdrop\" | \"none\";\n };\n }[];\n readonly accessibility: { readonly material: MaterialPolicyView };\n}\n\n/** The structural view of core's `BackdropRebuildRequest`. */\nexport interface RebuildRequestView {\n readonly sourceId: string;\n readonly epoch: number;\n readonly resolution: { readonly scale: number; readonly maxDimension: number };\n readonly groupIds: readonly string[];\n}\n\n/** The structural view of core's `FrameContext`. */\nexport interface FrameContextView {\n readonly frame: { readonly id: number; readonly timeMs: number };\n readonly phase: \"collect\" | \"read\" | \"update\" | \"write\" | \"render\";\n readonly resolution?: SceneResolutionView;\n consumeDirtyBackdropSources(): readonly RebuildRequestView[];\n}\n\n/** The structural view of core's `FrameParticipant`. */\nexport interface FrameParticipantView {\n readonly id: string;\n readonly write?: (context: FrameContextView) => void;\n readonly render?: (context: FrameContextView) => void;\n}\n","/**\n * Instance packing: X8's channel vector plus the six derived floats, into the\n * storage buffer the field pass walks.\n *\n * ## X8 rider 2, made unavoidable\n *\n * The rider (tightened at C3's landing, Decision Log #22b) says a renderer MUST\n * draw a concentric child as a **level set of the parent's field**, because\n * instantiating the child as its own resolved shape adds an offset-approximation\n * error that grows with inset — 0.326 px at 8 px, past the field's own declared\n * bound, and dominant past about 4 px.\n *\n * The way that is honoured here is not a check: a concentric surface is packed\n * with its **parent's** `half/re/k` and its own `inset`, and the shader's only\n * expression is `field(p; those params) + inset`. There is no instantiated-shape\n * path to take, so no future caller can take it by accident. `resolveConcentric`\n * — geometry's other path — is still the right answer for bounds and hit-testing,\n * and this module uses it for exactly that and nothing else.\n *\n * ## Press compression\n *\n * §Motion: \"The `pressCompression` channel runs 0…1; this is what 1 means, so the\n * renderer needs no constant of its own.\" So the scale comes from\n * `DEFAULT_MOTION_PROFILE.pressCompressionScale` rather than from a literal here,\n * and it is applied to `size` before the corner is derived — which matters,\n * because the corner budget is a function of size, so a compressed surface must\n * re-derive its corner rather than scale a corner derived at rest.\n */\n\nimport {\n DEFAULT_GROUP_UNION,\n type FieldParams,\n fieldParams,\n governorFieldParams,\n type GroupUnionParams,\n resolveConcentric,\n resolveFromChannels,\n type ResolvedShape,\n type ShapeChannels,\n} from \"@vitrea/geometry\";\nimport { DEFAULT_MOTION_PROFILE } from \"@vitrea/motion\";\n\nimport { rendererError } from \"./errors\";\nimport type { FieldFamily } from \"./governor\";\nimport {\n DEFAULT_MATERIAL_PROFILE,\n lensSizeGainFromThickness,\n NOMINAL_MATERIAL_POLICY,\n sizeThicknessUnderPolicy,\n type MaterialPolicyView,\n type MaterialProfile,\n} from \"./material\";\nimport { IDLE_CHANNELS, type GroupRenderInput, type Rect, type SurfaceChannels, type SurfaceInput } from \"./render-model\";\n\n/**\n * 18 floats, 72 bytes, matching `WGSL_INSTANCE_STRUCT`.\n *\n * It was 16 until W2 and W3 landed in the same cut, each needing a per-surface\n * scalar the fragment stage reads per pixel — the size law's thickness factor and\n * the author tint's strength. 17 is not a legal stride: `centre` and `half` are\n * `vec2f`, which aligns the struct to 8 bytes, so its size has to be a multiple\n * of 8 and 72 is the next one up. The eighteenth float is that padding, written\n * as zero rather than left to whatever the buffer held.\n */\nexport const INSTANCE_FLOATS = 18;\nexport const INSTANCE_BYTES = INSTANCE_FLOATS * 4;\n\nexport interface ResolvedSurface {\n readonly nodeId: string;\n /** The surface's own resolved shape — bounds, hit-testing, and the rim's scale. */\n readonly shape: ResolvedShape;\n /** The field parameters actually packed: the parent's, for a concentric child. */\n readonly field: FieldParams;\n /** Level-set offset. 0 for an ordinary surface. */\n readonly inset: number;\n readonly centre: readonly [number, number];\n readonly channels: SurfaceChannels;\n /** Shorter extent in CSS px — what the whole size law is a function of. */\n readonly spanPx: number;\n readonly lensDepthPx: number;\n /** The author tint's strength, 0 where the surface is untinted. */\n readonly tintStrength: number;\n /**\n * The size law's thickness factor for this surface, 0…1 (`sizeThickness`).\n *\n * Resolved here rather than in the fragment stage because it is a property of\n * the surface, and the group's field is one texture: a 44 px button and a\n * 280 px platter in the same `GlassEffectContainer` have to read as different\n * thicknesses, so the factor rides the union per pixel like the lens depth —\n * and like the tint strength above it, for the same reason.\n */\n readonly sizeThickness: number;\n}\n\nconst channelsOf = (input: SurfaceInput): SurfaceChannels => ({\n ...IDLE_CHANNELS,\n ...input.channels,\n});\n\n/** `size` after press compression, which the corner is then derived from. */\nfunction compressedChannels(shape: ShapeChannels, press: number): ShapeChannels {\n if (press <= 0) return shape;\n const scale = 1 - Math.min(1, Math.max(0, press)) * DEFAULT_MOTION_PROFILE.pressCompressionScale;\n return { ...shape, size: [shape.size[0] * scale, shape.size[1] * scale] };\n}\n\n/**\n * Resolve one group's surfaces, ordered so that a concentric child always follows\n * its parent. The order matters only for the resolution pass, not for the union —\n * `smoothUnion2` is commutative, which `union.ts` asserts rather than assumes.\n */\nexport function resolveSurfaces(\n group: GroupRenderInput,\n family: FieldFamily,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n policy: MaterialPolicyView = NOMINAL_MATERIAL_POLICY,\n): readonly ResolvedSurface[] {\n const byId = new Map<string, SurfaceInput>();\n for (const surface of group.surfaces) {\n if (byId.has(surface.nodeId)) {\n throw rendererError(\n \"source-identity\",\n `Group \"${group.groupId}\" lists surface \"${surface.nodeId}\" twice.`,\n surface.nodeId,\n );\n }\n byId.set(surface.nodeId, surface);\n }\n\n const resolvedShapes = new Map<string, ResolvedShape>();\n const resolving = new Set<string>();\n const resolveShapeOf = (surface: SurfaceInput): ResolvedShape => {\n const cached = resolvedShapes.get(surface.nodeId);\n if (cached !== undefined) return cached;\n if (resolving.has(surface.nodeId)) {\n throw rendererError(\n \"pass-input\",\n `Concentric surfaces in group \"${group.groupId}\" form a cycle through \"${surface.nodeId}\". A level set needs a parent field that resolves without it.`,\n surface.nodeId,\n );\n }\n resolving.add(surface.nodeId);\n\n const channels = channelsOf(surface);\n const reference = surface.reference ?? \"apple-continuous\";\n\n if (surface.concentricOf === undefined) {\n const shape = resolveFromChannels(\n compressedChannels(surface.shape, channels.press),\n reference,\n surface.family,\n { devMode: false },\n );\n resolvedShapes.set(surface.nodeId, shape);\n resolving.delete(surface.nodeId);\n return shape;\n }\n\n const parentInput = byId.get(surface.concentricOf.nodeId);\n if (parentInput === undefined) {\n throw rendererError(\n \"pass-input\",\n `Surface \"${surface.nodeId}\" is concentric to \"${surface.concentricOf.nodeId}\", which is not a member of group \"${group.groupId}\". X8 rider 2 renders a concentric child as a level set of its parent's field, so the parent has to be in the same field pass.`,\n surface.nodeId,\n );\n }\n // The child's OWN resolved shape, for bounds and hit-testing only. What gets\n // packed is the parent's field plus the inset — see the module note.\n const shape = resolveConcentric(resolveShapeOf(parentInput), {\n inset: surface.concentricOf.inset,\n }).shape;\n resolvedShapes.set(surface.nodeId, shape);\n resolving.delete(surface.nodeId);\n return shape;\n };\n\n const paramsFor = (shape: ResolvedShape): FieldParams =>\n family === \"rsup\" ? governorFieldParams(shape) : fieldParams(shape);\n\n // Reference shapes are resolved (a child needs its parent's field) and then\n // dropped: they contribute no instance, no bounds, and no coverage.\n return group.surfaces\n .filter((surface) => surface.fieldReferenceOnly !== true)\n .map((surface): ResolvedSurface => {\n const channels = channelsOf(surface);\n const shape = resolveShapeOf(surface);\n\n const fieldSource =\n surface.concentricOf === undefined\n ? shape\n : resolveShapeOf(byId.get(surface.concentricOf.nodeId) as SurfaceInput);\n const inset = surface.concentricOf?.inset ?? 0;\n\n const spanPx = Math.min(shape.channels.size[0], shape.channels.size[1]);\n // The size law's one input, already folded under the accessibility regime —\n // see `sizeThicknessUnderPolicy`. Resolved once here so the lens depth and the\n // per-pixel factor cannot disagree about how thick this surface reads.\n const thickness = sizeThicknessUnderPolicy(spanPx, policy, profile);\n return {\n nodeId: surface.nodeId,\n shape,\n field: paramsFor(fieldSource),\n inset,\n centre: [fieldSource.channels.center[0], fieldSource.channels.center[1]],\n channels,\n spanPx,\n lensDepthPx: Math.min(\n Math.max(shape.channels.thickness, 0) * lensSizeGainFromThickness(thickness, profile),\n spanPx * 0.5,\n ),\n sizeThickness: thickness,\n tintStrength: Math.min(1, Math.max(0, surface.tint?.strength ?? 0)),\n };\n });\n}\n\n/**\n * The group's field-pass rect, in viewport CSS px.\n *\n * Padded by whatever can reach beyond a surface's own contour: the rim band, the\n * union's bulge cap, one coverage pixel, and — since W8 — the outer shadow's\n * reach. Not padded by the lens depth — the lens displaces where the backdrop is\n * *sampled from*, not where the material is *drawn*, so paying for it here would\n * widen every group's field pass for nothing.\n *\n * The shadow is the one term that is genuinely large: `outerShadowReachPx` runs\n * to roughly 45 CSS px at the shipped profile, against a rim-and-bulge pad of\n * about 3. It is not optional — the optics pass scissors to this rect, so a rect\n * that stops at the contour draws no shadow at all — and it is not unconditional\n * either: a profile whose shadow occlusion is zero has a reach of zero and pays\n * exactly what it used to.\n */\nexport function groupFieldRect(\n surfaces: readonly ResolvedSurface[],\n union: GroupUnionParams = DEFAULT_GROUP_UNION,\n rimWidthPx = 2,\n outerShadowReachPx = 0,\n): Rect {\n if (surfaces.length === 0) return { x: 0, y: 0, width: 0, height: 0 };\n\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n\n for (const surface of surfaces) {\n const [cx, cy] = surface.shape.channels.center;\n const [w, h] = surface.shape.channels.size;\n minX = Math.min(minX, cx - w / 2);\n minY = Math.min(minY, cy - h / 2);\n maxX = Math.max(maxX, cx + w / 2);\n maxY = Math.max(maxY, cy + h / 2);\n }\n\n const pad = Math.max(rimWidthPx + union.maxBulge + 1, Math.max(outerShadowReachPx, 0));\n return {\n x: minX - pad,\n y: minY - pad,\n width: maxX - minX + 2 * pad,\n height: maxY - minY + 2 * pad,\n };\n}\n\n/** A rectangle in whole device pixels: what a viewport and a scissor take. */\nexport interface DevicePixelRect {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n}\n\n/**\n * A group's field rect in device pixels, clipped to the plane canvas.\n *\n * `groupFieldRect` grows the surface union by the rim and bulge margin, so a\n * surface within a few CSS px of the viewport's top or left edge produces a rect\n * with a negative origin. The optics and highlight passes set that rect as the\n * canvas viewport *and* scissor, and `setScissorRect` takes unsigned values, so an\n * unclipped rect is a hard `RangeError` out of the WebGPU binding rather than a\n * clipped draw. A toolbar pinned to the left edge is enough to reach it.\n *\n * Returns `undefined` where nothing of the rect is on the canvas, which is the\n * caller's signal to skip the group entirely.\n *\n * The caller must derive the instance frame from the returned rect rather than\n * from the CSS rect it passed in. The field texture is allocated at this size and\n * `fs_optics` reads it by `uv` over the viewport, so a viewport that moved without\n * the texture and the instance origin moving with it would stretch the glass\n * instead of clipping it. What clipping costs is the part of the field outside the\n * canvas, which is the part nothing can see.\n */\nexport function clipFieldRectToCanvas(\n snapped: Rect,\n devicePixelRatio: number,\n canvasDevice: readonly [number, number],\n): DevicePixelRect | undefined {\n const left = Math.max(0, Math.round(snapped.x * devicePixelRatio));\n const top = Math.max(0, Math.round(snapped.y * devicePixelRatio));\n const right = Math.min(\n canvasDevice[0],\n Math.round((snapped.x + snapped.width) * devicePixelRatio),\n );\n const bottom = Math.min(\n canvasDevice[1],\n Math.round((snapped.y + snapped.height) * devicePixelRatio),\n );\n if (right <= left || bottom <= top) return undefined;\n return { x: left, y: top, width: right - left, height: bottom - top };\n}\n\n/** The same rect snapped outward to whole device pixels. */\nexport function snapRectToDevicePixels(rect: Rect, devicePixelRatio: number): Rect {\n const x = Math.floor(rect.x * devicePixelRatio) / devicePixelRatio;\n const y = Math.floor(rect.y * devicePixelRatio) / devicePixelRatio;\n const right = Math.ceil((rect.x + rect.width) * devicePixelRatio) / devicePixelRatio;\n const bottom = Math.ceil((rect.y + rect.height) * devicePixelRatio) / devicePixelRatio;\n return { x, y, width: Math.max(right - x, 0), height: Math.max(bottom - y, 0) };\n}\n\n/**\n * Pack resolved surfaces into the storage buffer, with centres made relative to\n * the group's rect so the shader's coordinates stay small however far down a long\n * page the group sits — f32 loses resolution at large magnitudes, and a field\n * evaluated at y = 40000 would quantise its own corner.\n */\nexport function packInstances(\n surfaces: readonly ResolvedSurface[],\n origin: readonly [number, number],\n into?: Float32Array,\n): { readonly data: Float32Array; readonly count: number } {\n const needed = Math.max(surfaces.length, 1) * INSTANCE_FLOATS;\n const data =\n into !== undefined && into.length >= needed ? into : new Float32Array(needed);\n\n for (let i = 0; i < surfaces.length; i += 1) {\n const s = surfaces[i] as ResolvedSurface;\n const o = i * INSTANCE_FLOATS;\n data[o + 0] = s.centre[0] - origin[0];\n data[o + 1] = s.centre[1] - origin[1];\n data[o + 2] = s.field.halfW;\n data[o + 3] = s.field.halfH;\n data[o + 4] = s.field.reach;\n data[o + 5] = s.field.k[0];\n data[o + 6] = s.field.k[1];\n data[o + 7] = s.field.k[2];\n data[o + 8] = s.field.k[3];\n data[o + 9] = s.field.k[4];\n data[o + 10] = s.inset;\n data[o + 11] = s.shape.channels.thickness;\n data[o + 12] = s.channels.press;\n data[o + 13] = s.channels.glow;\n // The shader's `lensDepth` slot: the size-parameterised depth from\n // `material.ts`, already scaled by the `lensStrength` motion channel, so the\n // fragment stage multiplies nothing it could get wrong.\n data[o + 14] = s.lensDepthPx * Math.min(1, Math.max(0, s.channels.lensStrength));\n // The shader's `tintK` slot, and the only per-surface half of the author\n // tint: the seed is a group uniform, this is how much of it this pixel gets.\n data[o + 15] = s.tintStrength;\n // The size law's per-pixel input. Resolved on the CPU from the surface's own\n // span so the fragment stage has no geometry to re-derive and no profile\n // constant of its own — see `ResolvedSurface.sizeThickness`.\n data[o + 16] = s.sizeThickness;\n data[o + 17] = 0;\n }\n\n return { data, count: surfaces.length };\n}\n","/**\n * Pass-by-pass timing, for the benchmark §Performance envelope pins the ~2 ms\n * hypothesis to.\n *\n * The spec asks for the budget to be \"measured per pass (backdrop import, blur,\n * analysis, body, highlight, composite) alongside browser end-to-end frame time\",\n * which needs GPU-side timestamps: wall-clock around `submit()` measures the\n * queue, not the work. WebGPU's only timestamp mechanism is `timestampWrites` on\n * a pass descriptor — `encoder.writeTimestamp` was removed from the spec — so the\n * timeline hands out begin/end query indices by label and each pass spreads them\n * into its descriptor.\n *\n * Where `timestamp-query` is unavailable the timeline is simply absent and the\n * benchmark falls back to wall-clock totals, reported as such. A number labelled\n * as a GPU pass time that was actually a CPU submit time would be worse than no\n * number, and §Risks already names timestamp-query availability as an engine\n * variance to record rather than to assume.\n *\n * One caveat worth stating because it changes how the results read: Chrome\n * quantises timestamp results to 100 µs by default, so a single short pass reads\n * as 0. The benchmark works around it the way S2's harness did — by launching with\n * `--disable-dawn-features=timestamp_quantization`, and by measuring many\n * repetitions when it cannot.\n */\n\nexport interface PassTimeline {\n /** Query indices for a render pass, or undefined when timing is off. */\n renderSlot(label: string): GPURenderPassTimestampWrites | undefined;\n computeSlot(label: string): GPUComputePassTimestampWrites | undefined;\n}\n\nexport interface TimingCollector extends PassTimeline {\n readonly capacity: number;\n readonly used: number;\n /** Queue the resolve + copy. Call once, after the last pass of the frame. */\n resolve(encoder: GPUCommandEncoder): void;\n /** Read the resolved timings. Labels map to elapsed nanoseconds. */\n read(): Promise<ReadonlyMap<string, number>>;\n /**\n * Slots whose resolved pair was not a positive duration, since the collector\n * was created. A non-zero count means some number reported here is missing a\n * pass, and saying so is better than quietly averaging it in.\n */\n readonly anomalies: number;\n reset(): void;\n destroy(): void;\n}\n\nexport function supportsTimestamps(device: GPUDevice): boolean {\n return device.features.has(\"timestamp-query\");\n}\n\nexport function createTimingCollector(device: GPUDevice, capacity = 64): TimingCollector {\n const querySet = device.createQuerySet({\n label: \"vitrea:timing\",\n type: \"timestamp\",\n count: capacity * 2,\n });\n const byteLength = capacity * 2 * 8;\n const resolveBuffer = device.createBuffer({\n label: \"vitrea:timing:resolve\",\n size: byteLength,\n usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC,\n });\n const staging = device.createBuffer({\n label: \"vitrea:timing:staging\",\n size: byteLength,\n usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,\n });\n\n let used = 0;\n let anomalies = 0;\n const labels: string[] = [];\n\n const take = (label: string): { begin: number; end: number } | undefined => {\n if (used >= capacity) return undefined;\n const index = used;\n used += 1;\n labels[index] = label;\n return { begin: index * 2, end: index * 2 + 1 };\n };\n\n return {\n capacity,\n get used() {\n return used;\n },\n\n get anomalies() {\n return anomalies;\n },\n\n renderSlot(label) {\n const slot = take(label);\n if (slot === undefined) return undefined;\n return {\n querySet,\n beginningOfPassWriteIndex: slot.begin,\n endOfPassWriteIndex: slot.end,\n };\n },\n\n computeSlot(label) {\n const slot = take(label);\n if (slot === undefined) return undefined;\n return {\n querySet,\n beginningOfPassWriteIndex: slot.begin,\n endOfPassWriteIndex: slot.end,\n };\n },\n\n resolve(encoder) {\n if (used === 0) return;\n encoder.resolveQuerySet(querySet, 0, used * 2, resolveBuffer, 0);\n encoder.copyBufferToBuffer(resolveBuffer, 0, staging, 0, used * 2 * 8);\n },\n\n async read() {\n const out = new Map<string, number>();\n if (used === 0) return out;\n await staging.mapAsync(GPUMapMode.READ, 0, used * 2 * 8);\n const view = new BigInt64Array(staging.getMappedRange(0, used * 2 * 8).slice(0));\n staging.unmap();\n for (let i = 0; i < used; i += 1) {\n const begin = view[i * 2] ?? 0n;\n const end = view[i * 2 + 1] ?? 0n;\n const label = labels[i] ?? `pass-${i}`;\n const elapsed = Number(end - begin);\n // Zero IS a legitimate duration — a clear-only pass with no draw really\n // does take no measurable time. What is not legitimate is a *negative*\n // one, or a pair where both endpoints are zero: WebGPU leaves a slot\n // unspecified when its pass did not run, and averaging that in would\n // corrupt every number in the report. Those are dropped and counted.\n if (!Number.isFinite(elapsed) || elapsed < 0 || (begin === 0n && end === 0n)) {\n anomalies += 1;\n continue;\n }\n // Several passes share a label (one per group, one per pyramid level), and\n // the interesting number is the total the budget is spent on, so labels\n // accumulate rather than overwrite.\n out.set(label, (out.get(label) ?? 0) + elapsed);\n }\n return out;\n },\n\n reset() {\n used = 0;\n labels.length = 0;\n },\n\n destroy() {\n querySet.destroy();\n resolveBuffer.destroy();\n staging.destroy();\n },\n };\n}\n\n/** Pass labels, so the benchmark's report and the passes agree on the names. */\nexport const PASS_LABEL = {\n import: \"backdrop-import\",\n chain: \"blur-chain\",\n bodyBlur: \"body-blur\",\n analysis: \"analysis\",\n field: \"group-field\",\n optics: \"optics\",\n highlight: \"highlight\",\n} as const;\n","/**\n * The f32 cross-check pass (Decision Log #20's obligation on C6).\n *\n * S2 measured family D's WGSL against an f64 evaluation of the same arithmetic and\n * got 4.08e-5 px — 0.024% of the declared 0.170 px bound. Family C, the quality\n * governor's first within-tier step, was priced but only inspection-verified, and\n * the spec makes its shipping conditional on it going through the same check.\n *\n * The reason this pass lives in `src/` rather than in a test harness is the point\n * of the whole exercise: it compiles **the same kernel strings the renderer\n * ships** — `WGSL_FIELD_KERNELS`, the constants `fieldPassSource` is assembled\n * from — over a caller-supplied point set. A check that compiled a separate copy\n * of the algebra would prove something about the copy.\n *\n * It is a compute pass rather than a render pass because the output is numbers:\n * a render target would quantise them at whatever the attachment format is, and\n * `rgba16float` has ten mantissa bits, which is coarser than the difference being\n * measured by three orders of magnitude.\n */\n\nexport const CROSS_CHECK_SHAPE_FLOATS = 12;\nexport const CROSS_CHECK_WORKGROUP = 64;\n\nexport const WGSL_CROSS_CHECK_PASS = `struct CheckShape {\n centre : vec2f,\n half : vec2f,\n re : f32,\n k0 : f32,\n k1 : f32,\n k2 : f32,\n k3 : f32,\n k4 : f32,\n _pad0 : f32,\n _pad1 : f32,\n};\n\n/// point.xy = shape-local coordinates, point.z = shape index, point.w unused\n@group(0) @binding(0) var<storage, read> checkShapes : array<CheckShape>;\n@group(0) @binding(1) var<storage, read> checkPoints : array<vec4f>;\n@group(0) @binding(2) var<storage, read_write> outRsupn : array<f32>;\n@group(0) @binding(3) var<storage, read_write> outRsup : array<f32>;\n@group(0) @binding(4) var<uniform> checkCount : vec4u;\n\n@compute @workgroup_size(${CROSS_CHECK_WORKGROUP})\nfn cs_cross_check(@builtin(global_invocation_id) gid : vec3u) {\n let i = gid.x;\n if (i >= checkCount.x) { return; }\n\n let p = checkPoints[i];\n let s = checkShapes[u32(p.z)];\n let k = vec4f(s.k0, s.k1, s.k2, s.k3);\n let local = p.xy - s.centre;\n\n outRsupn[i] = sd_rsupn(local, s.half, s.re, k, s.k4);\n outRsup[i] = sd_rsup(local, s.half, s.re, k, s.k4);\n}`;\n","/**\n * Backdrop import and the blur pyramid.\n *\n * ## Import (X3, X5)\n *\n * One pass normalises every source kind into level 0 of the pyramid:\n * **premultiplied, linear-light, sRGB-primaries `rgba16float`**. The three\n * things that differ between providers — encoding, alpha mode, colour space —\n * arrive as uniforms resolved on the CPU, where the provider's contract is\n * known, so no shader ever guesses at them. That is what X3's \"the compositor\n * normalizes at import\" means operationally: imported video is unpremultiplied\n * and copied images are premultiplied, and after this pass neither fact is\n * visible downstream.\n *\n * The unpremultiply happens *before* the transfer-function decode and the\n * re-premultiply *after* it. Decoding a premultiplied value is meaningless — the\n * curve is not linear, so `decode(c·a) != decode(c)·a` — and getting that order\n * wrong shows up as dark fringes on every soft edge.\n *\n * ## The chain\n *\n * Progressive downsample, 13 taps per level, sampled bilinearly so the 13 taps\n * cover a 4×4 footprint. This is the standard bloom-pyramid filter, and it is\n * here for the reason it exists there: it is the cheapest filter whose repeated\n * application does not produce the boxy, aliasing-prone result a naive 2×2 average\n * gives, and it is one pass per level rather than the three a\n * downsample-then-separable-blur chain needs.\n *\n * With `mipmapFilter: \"linear\"` on the sampler, `textureSampleLevel(chain, s, uv,\n * lod)` is then a continuously variable blur — which is exactly what the optics\n * pass needs for \"LOD by thickness/size\".\n *\n * ## The body blur\n *\n * The chain gives blur in powers of two. The material's own σ is not a power of\n * two, so the body — the large, flat region of frost behind a surface — gets one\n * dedicated separable Gaussian at the residual σ on top of the nearest chain\n * level. Two passes for the whole scene, not two per level: the refraction path\n * has no use for it, because a rim sample wants the sharpest level it can get.\n */\n\n/**\n * `srcEncoded`: 1 when the sampled values are sRGB-encoded (every 8-bit copy and\n * every external video texture), 0 when they are already linear (an app-supplied\n * float view can be either, so the provider declares it).\n *\n * `alphaMode`: 0 premultiplied, 1 unpremultiplied, 2 opaque — the enumeration\n * `alphaNormalisationMode` in `color.ts` produces.\n */\nexport const WGSL_IMPORT_PASS = `struct ImportUniforms {\n m0 : vec4f, // colour matrix row 0 (xyz), srcEncoded (w)\n m1 : vec4f, // row 1 (xyz), alphaMode (w)\n m2 : vec4f, // row 2 (xyz), unused (w)\n fit : vec4f, // uv scale (xy), uv offset (zw) — the source's fit into the target\n};\n\n@group(0) @binding(0) var<uniform> iu : ImportUniforms;\n@group(0) @binding(1) var srcSampler : sampler;\n@group(0) @binding(2) var srcTexture : SRC_TEXTURE_TYPE;\n\nfn sample_src(uv : vec2f) -> vec4f {\n return SRC_SAMPLE_EXPR;\n}\n\n@fragment\nfn fs_import(in : FullscreenOut) -> @location(0) vec4f {\n let uv = in.uv * iu.fit.xy + iu.fit.zw;\n var raw = sample_src(clamp(uv, vec2f(0.0), vec2f(1.0)));\n\n let alphaMode = iu.m1.w;\n var alpha = raw.a;\n var colour = raw.rgb;\n\n if (alphaMode > 1.5) {\n alpha = 1.0;\n } else if (alphaMode > 0.5) {\n // Already unpremultiplied: nothing to undo.\n } else {\n // Premultiplied input — undo it before the non-linear decode. A fully\n // transparent texel carries zero colour, so the floored divide returns zero\n // there without a branch.\n colour = colour / max(alpha, 1e-6);\n }\n\n if (iu.m0.w > 0.5) {\n colour = srgb_to_linear(clamp(colour, vec3f(0.0), vec3f(1.0)));\n }\n\n // Colour-space conversion in linear light. Identity for sRGB sources.\n colour = vec3f(dot(iu.m0.xyz, colour), dot(iu.m1.xyz, colour), dot(iu.m2.xyz, colour));\n\n return vec4f(max(colour, vec3f(0.0)) * alpha, alpha);\n}`;\n\n/** `SRC_TEXTURE_TYPE`/`SRC_SAMPLE_EXPR` per source kind. */\nexport function importPassSource(kind: \"sampled\" | \"external\"): string {\n const type = kind === \"external\" ? \"texture_external\" : \"texture_2d<f32>\";\n const expr =\n kind === \"external\"\n ? \"textureSampleBaseClampToEdge(srcTexture, srcSampler, uv)\"\n : \"textureSampleLevel(srcTexture, srcSampler, uv, 0.0)\";\n return WGSL_IMPORT_PASS.replace(\"SRC_TEXTURE_TYPE\", type).replace(\"SRC_SAMPLE_EXPR\", expr);\n}\n\n/**\n * 13-tap progressive downsample. Offsets are in the SOURCE level's texels; the\n * caller passes `1 / srcSize` so the pass needs no texture-dimension query.\n */\nexport const WGSL_DOWNSAMPLE_PASS = `struct ChainUniforms {\n texel : vec4f, // 1/srcSize (xy), unused (zw)\n params : vec4f, // sigma in texels (x), direction (yz), unused (w)\n};\n\n@group(0) @binding(0) var<uniform> cu : ChainUniforms;\n@group(0) @binding(1) var chainSampler : sampler;\n@group(0) @binding(2) var chainTexture : texture_2d<f32>;\n\nfn tap(uv : vec2f, o : vec2f) -> vec4f {\n return textureSampleLevel(chainTexture, chainSampler, uv + o * cu.texel.xy, 0.0);\n}\n\n@fragment\nfn fs_downsample(in : FullscreenOut) -> @location(0) vec4f {\n let uv = in.uv;\n\n let a = tap(uv, vec2f(-2.0, 2.0));\n let b = tap(uv, vec2f( 0.0, 2.0));\n let c = tap(uv, vec2f( 2.0, 2.0));\n let d = tap(uv, vec2f(-2.0, 0.0));\n let e = tap(uv, vec2f( 0.0, 0.0));\n let f = tap(uv, vec2f( 2.0, 0.0));\n let g = tap(uv, vec2f(-2.0, -2.0));\n let h = tap(uv, vec2f( 0.0, -2.0));\n let i = tap(uv, vec2f( 2.0, -2.0));\n let j = tap(uv, vec2f(-1.0, 1.0));\n let k = tap(uv, vec2f( 1.0, 1.0));\n let l = tap(uv, vec2f(-1.0, -1.0));\n let m = tap(uv, vec2f( 1.0, -1.0));\n\n // Weights: the centre cross carries 0.5 across four inner taps, the corners\n // and edges the remaining 0.5. Sums to exactly 1, so the chain neither gains\n // nor loses energy — which is what keeps the analysis pass's luminance honest\n // however many levels it reads through.\n var out = (j + k + l + m) * 0.5 * 0.25;\n out = out + (a + b + d + e) * 0.125 * 0.25;\n out = out + (b + c + e + f) * 0.125 * 0.25;\n out = out + (d + e + g + h) * 0.125 * 0.25;\n out = out + (e + f + h + i) * 0.125 * 0.25;\n return out;\n}\n\n/// Separable Gaussian, nine taps, run once horizontally and once vertically to\n/// take the nearest chain level up to the material's exact sigma.\n@fragment\nfn fs_blur(in : FullscreenOut) -> @location(0) vec4f {\n let dir = cu.params.yz;\n let sigma = max(cu.params.x, 1e-4);\n let inv = -0.5 / (sigma * sigma);\n\n var sum = vec4f(0.0);\n var weight = 0.0;\n for (var t = -4; t <= 4; t = t + 1) {\n let ft = f32(t);\n let w = exp(ft * ft * inv);\n sum = sum + textureSampleLevel(chainTexture, chainSampler, in.uv + dir * ft * cu.texel.xy, 0.0) * w;\n weight = weight + w;\n }\n return sum / weight;\n}`;\n","/**\n * The group field pass (§Geometry: \"instances → group SDF/coverage field → one\n * optical pass\").\n *\n * Three contract points are structural here rather than conventional, which is\n * the only way a shader can be held to them:\n *\n * 1. **X8 rider 2 — a concentric child renders as a LEVEL SET of its parent's\n * field.** There is no second path. `Instance` carries the *parent's*\n * `half/re/k` plus its own `inset`, and the evaluator always computes\n * `field(p; parent params) + inset`. For an ordinary surface `inset` is 0 and\n * the expression is the surface's own field. So the instantiated-shape path —\n * whose offset error grows with inset and dominates the declared bound past\n * about 4 px — is not expressible in this shader at all.\n * 2. **The families come from `@vitrea/geometry` verbatim.** `sd_rsupn` and\n * `sd_rsup` are the fingerprinted strings that package owns, spliced in\n * unchanged, so the cost figures and the f32 result transfer with them. What\n * this module adds is their gradients and the union, which S2 did not price and\n * which are therefore written to be as close to free as the algebra allows.\n * 3. **The gradient is analytic and costs no extra field evaluations.**\n * `sd_rsupn_grad` is a port of `rsupnFieldAndGradient` — the ≤2.92° normal at\n * the free normal's price. Family C's normal is the closed-form level-set\n * normal (≤4.26°), which is the honest pairing: taking family C means taking\n * family C's gradient too. Being a port, it moves when the value moves:\n * `sd_rsupn` anchors its normalization at the contour radius, so this selects\n * the same arm and differentiates the arm it selected. `test/wgsl-contract.test.ts`\n * pins that pairing, because a normal computed from the unanchored form on top\n * of an anchored depth is exactly the kind of half-applied edit no fingerprint\n * would notice.\n *\n * The union mirrors `union.ts` exactly on the value — the same bulge cap applied\n * to `k`, the same separation gate, the same single clamp at the end of the fold.\n * `union_blend` returns that value **and the blend weight `h`**, because the pass\n * has more than a distance to fold: the gradient and the four per-surface optical\n * scalars have to travel through the same seam, and doing it with the same `h`\n * keeps one copy of the union's algebra instead of four. Blending the gradient by\n * `h` drops the union's term in `dk`, which makes it exact wherever `h` saturates\n * — everywhere except inside a real seam.\n */\n\nimport { WGSL_RSUP, WGSL_RSUPN } from \"@vitrea/geometry\";\n\n/**\n * Instance layout — `@vitrea/geometry`'s `Shape` struct widened by the render\n * channels, 64 bytes, every member 4- or 8-byte aligned so the CPU packing is a\n * flat `Float32Array` with a 16-float stride.\n *\n * `centre/half/re/k0..k4` are the X8 channel vector's geometric half plus the\n * six derived floats. `inset` is rider 2's level-set offset. The rest are motion\n * driver outputs, sampled by the host and handed in as data (§Motion: this\n * package consumes driver outputs, never time).\n */\nexport const WGSL_INSTANCE_STRUCT = `struct Instance {\n centre : vec2f, // 0 group-local CSS px\n half : vec2f, // 8 half-extents of the field's OWN shape (the parent's, for a concentric child)\n re : f32, // 16 corner reach\n k0 : f32, // 20\n k1 : f32, // 24\n k2 : f32, // 28\n k3 : f32, // 32\n k4 : f32, // 36\n inset : f32, // 40 X8 rider 2: level-set offset. 0 for an ordinary surface.\n thick : f32, // 44 material thickness, CSS px\n press : f32, // 48 interaction channel value, 0..1\n glow : f32, // 52 interaction channel value, 0..1\n lensDepth : f32, // 56 CPU-resolved lens depth in CSS px (material.ts), already scaled by the lensStrength channel\n tintK : f32, // 60 author tint strength, 0..1 — the seed itself is a group uniform\n sizeK : f32, // 64 the size law's thickness factor, 0..1 — material.ts's sizeThickness(span)\n _pad : f32, // 68 stride padding: vec2f aligns the struct to 8, so 72 is the next legal size\n};`;\n\n/** `FieldSample` mirrors geometry's, minus `kink`: the shader has no use for it. */\nexport const WGSL_FIELD_SAMPLE = `struct FieldSample {\n d : f32,\n g : vec2f,\n};`;\n\n/**\n * Family D's value and exact gradient in one pass — the port of\n * `rsupnFieldAndGradient`.\n *\n * The masks at the end are what extend the corner-sector chain rule to every\n * region: `mx`/`my` gate the clamped-coordinate terms, and the box-branch term\n * carries the derivative where `max(qx, qy) <= 0`. The `<=` there is not a\n * typo — at `m == 0` both clamped terms are masked off, so the box term has to\n * fire or the gradient reads (0, 0) on the corner-sector boundary. C3 found and\n * fixed exactly that bug while deriving this.\n */\nexport const WGSL_RSUPN_GRAD = `fn sd_rsupn_grad(p : vec2f, half : vec2f, re : f32, k : vec4f, k4 : f32) -> FieldSample {\n let q = abs(p) - half + vec2f(re, re);\n let c = max(q, vec2f(0.0, 0.0));\n let r2 = max(dot(c, c), 1e-20);\n let inv = 1.0 / r2;\n let rho = sqrt(r2);\n let s2 = 2.0 * c.x * c.y * inv;\n let c2 = (c.x * c.x - c.y * c.y) * inv;\n\n // A = sum k_i s2^i, B = sum (i+2) k_i s2^i, C = sum (i+1)(i+2) k_i s2^i.\n var accA = k4;\n accA = accA * s2 + k.w;\n accA = accA * s2 + k.z;\n accA = accA * s2 + k.y;\n accA = accA * s2 + k.x;\n\n var accB = 6.0 * k4;\n accB = accB * s2 + 5.0 * k.w;\n accB = accB * s2 + 4.0 * k.z;\n accB = accB * s2 + 3.0 * k.y;\n accB = accB * s2 + 2.0 * k.x;\n\n var accC = 30.0 * k4;\n accC = accC * s2 + 20.0 * k.w;\n accC = accC * s2 + 12.0 * k.z;\n accC = accC * s2 + 6.0 * k.y;\n accC = accC * s2 + 2.0 * k.x;\n\n let R = re * (1.0 + s2 * s2 * accA);\n let dRds2 = re * s2 * accB;\n let d2Rds2 = re * accC;\n let dRdt = dRds2 * (2.0 * c2);\n\n let mm = min(max(q.x, q.y), 0.0);\n let base = rho + mm - R;\n // Anchored at the contour radius, mirroring sd_rsupn: the normalization's\n // slope is read at the foot of the Newton step, never at a sample radius\n // inside the contour. See geometry's field.ts, \"The normalization\".\n let atRho = rho >= R;\n let w = select(R, rho, atRho);\n let g = select(dRdt / R, dRdt * inv * rho, atRho);\n let norm = sqrt(1.0 + g * g);\n let n = 1.0 / norm;\n\n let ds2dcx = -2.0 * c.y * c2 * inv;\n let ds2dcy = 2.0 * c.x * c2 * inv;\n let dc2dcx = 2.0 * c.x * inv * (1.0 - c2);\n let dc2dcy = -2.0 * c.y * inv * (1.0 + c2);\n\n let drhodcx = c.x / rho;\n let drhodcy = c.y / rho;\n\n let dRdcx = dRds2 * ds2dcx;\n let dRdcy = dRds2 * ds2dcy;\n\n let dTermdcx = 2.0 * (d2Rds2 * ds2dcx * c2 + dRds2 * dc2dcx);\n let dTermdcy = 2.0 * (d2Rds2 * ds2dcy * c2 + dRds2 * dc2dcy);\n\n // w's derivative follows whichever of rho and R is larger. Exact across the\n // switch because the switch locus is rho == R, the contour, where base == 0\n // kills the only term the jump lives in.\n let dwdcx = select(dRdcx, drhodcx, atRho);\n let dwdcy = select(dRdcy, drhodcy, atRho);\n\n let dgdcx = dTermdcx / w - (dRdt * dwdcx) / (w * w);\n let dgdcy = dTermdcy / w - (dRdt * dwdcy) / (w * w);\n\n let n3 = n * n * n;\n let dddcx = (drhodcx - dRdcx) * n + base * (-g * n3 * dgdcx);\n let dddcy = (drhodcy - dRdcy) * n + base * (-g * n3 * dgdcy);\n\n let mx = select(0.0, 1.0, q.x > 0.0);\n let my = select(0.0, 1.0, q.y > 0.0);\n let inBox = max(q.x, q.y) <= 0.0;\n let dmmdqx = select(0.0, 1.0, inBox && q.x >= q.y);\n let dmmdqy = select(0.0, 1.0, inBox && q.y > q.x);\n\n let sx = select(1.0, -1.0, p.x < 0.0);\n let sy = select(1.0, -1.0, p.y < 0.0);\n\n var out : FieldSample;\n out.d = base * n;\n out.g = vec2f((dddcx * mx + n * dmmdqx) * sx, (dddcy * my + n * dmmdqy) * sy);\n return out;\n}`;\n\n/**\n * Family C's value and its closed-form level-set normal.\n *\n * The value is `sd_rsup` verbatim; the normal is\n * `normalize(rhoHat - (R'/rho) * thetaHat)`, which is free because every term is\n * already computed. It is identical to family D's gradient *on* the contour to\n * four decimal places — the normalization moves level sets only away from the\n * zero set — so rim lighting is indifferent between them and only refraction at\n * depth pays the 1.5–1.7× difference.\n */\nexport const WGSL_RSUP_GRAD = `fn sd_rsup_grad(p : vec2f, half : vec2f, re : f32, k : vec4f, k4 : f32) -> FieldSample {\n let q = abs(p) - half + vec2f(re, re);\n let c = max(q, vec2f(0.0, 0.0));\n let r2 = max(dot(c, c), 1e-20);\n let rho = sqrt(r2);\n let s2 = 2.0 * c.x * c.y / r2;\n\n var accA = k4;\n accA = accA * s2 + k.w;\n accA = accA * s2 + k.z;\n accA = accA * s2 + k.y;\n accA = accA * s2 + k.x;\n\n var accB = 6.0 * k4;\n accB = accB * s2 + 5.0 * k.w;\n accB = accB * s2 + 4.0 * k.z;\n accB = accB * s2 + 3.0 * k.y;\n accB = accB * s2 + 2.0 * k.x;\n\n let c2 = (c.x * c.x - c.y * c.y) / r2;\n let R = re * (1.0 + s2 * s2 * accA);\n\n let sx = select(1.0, -1.0, p.x < 0.0);\n let sy = select(1.0, -1.0, p.y < 0.0);\n\n var out : FieldSample;\n out.d = rho + min(max(q.x, q.y), 0.0) - R;\n\n if (c.x <= 0.0 && c.y <= 0.0) {\n // Straight-edge and deep-interior: the normal is the axis the box branch is\n // measuring along.\n out.g = select(vec2f(0.0, sy), vec2f(sx, 0.0), q.x > q.y);\n return out;\n }\n\n let dRdt = re * s2 * accB * (2.0 * c2);\n let rhoHat = c / rho;\n let gg = dRdt / rho;\n let nx = rhoHat.x + gg * rhoHat.y;\n let ny = rhoHat.y - gg * rhoHat.x;\n let len = max(length(vec2f(nx, ny)), 1e-20);\n out.g = vec2f(sx * nx / len, sy * ny / len);\n return out;\n}`;\n\n/**\n * The bounded smooth union of `union.ts`, value for value.\n *\n * `separation * 0.5` is floored away from zero because WGSL's `smoothstep` is\n * undefined when its two edges coincide, where the TypeScript's own `smoothstep`\n * degrades to a step. A group configured with no separation threshold therefore\n * blends everywhere, which is the same thing the TypeScript does.\n */\nexport const WGSL_SMOOTH_UNION = `fn union_blend(a : f32, b : f32, u : vec3f) -> vec2f {\n let neck = u.x;\n let maxBulge = u.y;\n let sep = max(u.z * 0.5, 1e-6);\n\n let nearest = min(a, b);\n let capped = min(neck, 4.0 * maxBulge);\n let gate = 1.0 - smoothstep(0.0, sep, max(nearest, 0.0));\n let k = capped * gate;\n\n if (k <= 0.0) {\n return vec2f(nearest, select(0.0, 1.0, a <= b));\n }\n\n let h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0);\n return vec2f(b + h * (a - b) - k * h * (1.0 - h), h);\n}`;\n\n/**\n * The pass itself.\n *\n * Scoped to the group's bounds, never fullscreen: the target IS the group rect,\n * so the fullscreen triangle covers exactly the pixels the group can touch.\n * §Performance envelope prices the field at ~5% of the mobile budget on that\n * assumption, and a fullscreen field pass per group would multiply it by the\n * ratio of viewport area to group area.\n *\n * The output is one `rgba16float` texel per device pixel: signed field in CSS\n * px, the unit normal, and analytic coverage. Everything downstream — optics,\n * highlight, and any future pass — reads this and never re-evaluates the field.\n */\nexport const WGSL_FIELD_PASS = `struct FieldUniforms {\n /// screen.xy = target size in device px, screen.z = CSS px per device px,\n /// screen.w = coverage ramp width in CSS px\n screen : vec4f,\n /// neckWidth, maxBulge, separationThreshold, unused\n unionP : vec4f,\n counts : vec4u,\n};\n\n// Per-surface optical scalars ride through the union in 'aux': the group is one\n// field but its members are not one size, and carrying them per pixel is what\n// lets a 40 px button and a 320 px platter share a field pass and still lens by\n// their own depth — parent acceptance #2 inside a GlassEffectContainer.\n// aux = (lensDepthPx, glow, sizeK, tintStrength)\n//\n// The third and fourth slots both changed hands, and neither of the values they\n// used to carry was ever read by a fragment stage. 'thick' left because\n// 'lensDepth' is the thickness times the size gain, so the raw number told the\n// shader nothing the depth had not already said; 'press' left because press\n// compression is resolved on the CPU, as a transform on the surface's own size\n// (instances.ts). Both are still packed into the instance buffer, unchanged, for\n// a future consumer that wants them per pixel; they simply no longer ride here.\n//\n// What replaced them are the two quantities that genuinely have to be per pixel,\n// because a group is one field pass and one optics pass while its members are\n// not one thing:\n//\n// 'sizeK' — the size law's thickness factor (W2). A 40 px button and a\n// 320 px platter in one container lens, scatter, occlude and\n// shadow by their own size.\n// 'tintStrength' — the author tint's strength (W3). One emphasised control\n// among plain ones is the composition Apple's guidance\n// describes; the seed itself is a group uniform.\n//\n// They compose rather than compete: the size law moves what the material does to\n// the backdrop, the tint moves what colour it does it in.\n\n@group(0) @binding(0) var<uniform> fu : FieldUniforms;\n@group(0) @binding(1) var<storage, read> instances : array<Instance>;\n\nstruct Member {\n d : f32,\n g : vec2f,\n aux : vec4f,\n};\n\nfn eval_instance(i : u32, p : vec2f) -> Member {\n let s = instances[i];\n let k = vec4f(s.k0, s.k1, s.k2, s.k3);\n // X8 rider 2 in one line: the child is the parent's field, shifted. There is\n // no branch and no second path, so no caller can opt into the instantiated\n // shape whose offset error the rider rules out.\n let f = FIELD_FN(p - s.centre, s.half, s.re, k, s.k4);\n var m : Member;\n m.d = f.d + s.inset;\n m.g = f.g;\n m.aux = vec4f(s.lensDepth, s.glow, s.sizeK, s.tintK);\n return m;\n}\n\nstruct FieldOut {\n @location(0) field : vec4f,\n @location(1) aux : vec4f,\n};\n\n@fragment\nfn fs_field(in : FullscreenOut) -> FieldOut {\n // GROUP-LOCAL CSS px. The instance buffer's centres were already made relative\n // to the group's rect on the CPU (f32 loses resolution at large magnitudes, so\n // a field evaluated at viewport y = 40000 would quantise its own corner), and\n // adding the origin back here would offset every shape by it twice.\n let p = in.uv * fu.screen.xy * fu.screen.z;\n\n var out : FieldOut;\n let count = fu.counts.x;\n if (count == 0u) {\n // Large but FINITE: rgba16float overflows to +Inf past ~65504, and NaN\n // coverage downstream is not reliably zero.\n out.field = vec4f(65000.0, 0.0, -1.0, 0.0);\n out.aux = vec4f(0.0);\n return out;\n }\n\n var acc = eval_instance(0u, p);\n var nearest = acc.d;\n for (var i = 1u; i < count; i = i + 1u) {\n let s = eval_instance(i, p);\n let blend = union_blend(acc.d, s.d, fu.unionP.xyz);\n let h = blend.y;\n acc.d = blend.x;\n acc.g = mix(s.g, acc.g, h);\n acc.aux = mix(s.aux, acc.aux, h);\n nearest = min(nearest, s.d);\n }\n // One clamp at the end of the fold, so |union - min| <= maxBulge holds for any\n // member count and any order rather than per blend step.\n acc.d = max(acc.d, nearest - fu.unionP.y);\n\n let len = max(length(acc.g), 1e-6);\n let normal = acc.g / len;\n let coverage = clamp(0.5 - acc.d / max(fu.screen.w, 1e-6), 0.0, 1.0);\n\n out.field = vec4f(acc.d, normal.x, normal.y, coverage);\n out.aux = acc.aux;\n return out;\n}`;\n\n/** The field module for one family. `FIELD_FN` is bound at assembly time. */\nexport function fieldPassSource(family: \"rsupn\" | \"rsup\"): string {\n const kernels = family === \"rsupn\" ? [WGSL_RSUPN, WGSL_RSUPN_GRAD] : [WGSL_RSUP, WGSL_RSUP_GRAD];\n const fn = family === \"rsupn\" ? \"sd_rsupn_grad\" : \"sd_rsup_grad\";\n return [\n WGSL_INSTANCE_STRUCT,\n WGSL_FIELD_SAMPLE,\n ...kernels,\n WGSL_SMOOTH_UNION,\n WGSL_FIELD_PASS.replace(\"FIELD_FN\", fn),\n ].join(\"\\n\\n\");\n}\n\n/**\n * Both families' value kernels plus both gradients, with no pass around them.\n *\n * This is what the f32 cross-check compiles: Decision Log #20 makes family C's\n * shipping conditional on its WGSL going through the same check family D passed,\n * and a check that compiled a *different* string from the one the renderer ships\n * would prove nothing. So the pass source above and the harness below are both\n * assembled from these same constants.\n */\nexport const WGSL_FIELD_KERNELS = [\n WGSL_INSTANCE_STRUCT,\n WGSL_FIELD_SAMPLE,\n WGSL_RSUPN,\n WGSL_RSUP,\n WGSL_RSUPN_GRAD,\n WGSL_RSUP_GRAD,\n WGSL_SMOOTH_UNION,\n].join(\"\\n\\n\");\n","/**\n * The highlight pass: specular sweep and press glow.\n *\n * X1 puts this canvas **above** the semantic host DOM, which is the whole reason\n * it is a separate pass and not three more lines in the optics shader: a\n * highlight has to fall across the label, and the label is real DOM sitting\n * between the two canvases. Nothing else about the material does.\n *\n * Both effects are driven by motion-driver *outputs*, never by time (§Motion —\n * the renderer consumes driver values as data):\n *\n * - **`sweep`** ∈ [0, 1] is the shimmer's position along the rim. The band is a\n * Gaussian in the angular coordinate of the gradient, so it travels around the\n * contour rather than sliding across a bounding box, and it exists only where\n * the rim exists. Reduced Motion sets `shimmer: \"none\"`, which the CPU turns\n * into a zero gain — the band is not drawn stationary, it is not drawn.\n * - **`glow`** ∈ [0, 1] is the press illumination, from the fast-attack /\n * slow-decay driver. It arrives **per pixel**, unioned through the field pass,\n * multiplied by a radial falloff around the press point and clipped to the\n * surface's coverage so it never leaks past the material's edge.\n *\n * The sweep phase and the press *point* are per group rather than per surface:\n * there is one pointer, and a sweep travelling around a `GlassEffectContainer`'s\n * unioned contour is the behaviour the container exists to produce. v1's\n * components never register two simultaneous presses inside one group.\n *\n * Output is additive over the page: premultiplied with the glow's own alpha, so a\n * zero-intensity highlight writes nothing at all rather than a transparent black\n * that a wrong blend state could darken with.\n */\n\nexport const WGSL_HIGHLIGHT_PASS = `struct HighlightUniforms {\n /// viewport size in device px (xy), CSS px per device px (z), unused (w)\n screen : vec4f,\n /// sweep position 0..1 (x), band width in radians (y), sweep gain (z), rim width px (w)\n sweep : vec4f,\n /// press point in viewport CSS px (xy), glow radius px (z), glow gain (w)\n glow : vec4f,\n /// highlight colour, linear light (xyz), unused (w)\n colour : vec4f,\n /// fieldSize.xy, fieldUpsampled (z), unused (w)\n flags : vec4f,\n /// backdrop tone adaptation (W7), exactly as the optics pass takes it:\n /// backdropToneLow, backdropToneHigh, the size bias already divided by the\n /// accessibility refraction cap, and the resolved strength — zero where there\n /// is no measured backdrop tone, which stands the fade down\n toneAdapt : vec4f,\n /// the backdrop source's own average luminance (x); yzw unused\n toneLevel : vec4f,\n /// this pass's uv into the FIELD texture's uv: scale (xy), offset (zw).\n ///\n /// The identity for a pass whose scissor is the field's own rect, and not the\n /// identity since W8: the outer shadow made the field rect much larger than\n /// anything this pass draws in, so the highlight is scoped back to the rect it\n /// had before and reads the field through this remap instead. Derived from the\n /// two rects by highlightPass in passes.ts.\n fieldFit : vec4f,\n};\n\n@group(0) @binding(0) var<uniform> hu : HighlightUniforms;\n@group(0) @binding(1) var fieldTexture : texture_2d<f32>;\n@group(0) @binding(2) var auxTexture : texture_2d<f32>;\n@group(0) @binding(3) var fieldSampler : sampler;\n\nconst TAU = 6.283185307179586;\n\n/// Shortest angular distance, so the band wraps continuously past the seam\n/// instead of stalling there for one revolution.\nfn angle_delta(a : f32, b : f32) -> f32 {\n let raw = abs(a - b);\n return min(raw, TAU - raw);\n}\n\n@fragment\nfn fs_highlight(in : FullscreenOut) -> @location(0) vec4f {\n // Exact load nominally; filtered when the governor's resolution knob had the\n // field rasterised below the group's rect. The sweep rides the rim, which is\n // the one place a nearest read of a coarse field would show its grid.\n let fieldUv = in.uv * hu.fieldFit.xy + hu.fieldFit.zw;\n var field : vec4f;\n var aux : vec4f;\n if (hu.flags.z > 0.5) {\n field = textureSampleLevel(fieldTexture, fieldSampler, fieldUv, 0.0);\n aux = textureSampleLevel(auxTexture, fieldSampler, fieldUv, 0.0);\n } else {\n let texel = vec2i(fieldUv * hu.flags.xy);\n field = textureLoad(fieldTexture, texel, 0);\n aux = textureLoad(auxTexture, texel, 0);\n }\n let d = field.x;\n let normal = field.yz;\n let coverage = field.w;\n\n if (coverage <= 0.0) {\n return vec4f(0.0);\n }\n\n // Specular sweep: a travelling band in the rim's angular coordinate.\n let rim = clamp(1.0 - abs(d) / max(hu.sweep.w, 1e-4), 0.0, 1.0);\n let theta = atan2(normal.y, normal.x) + TAU * 0.5;\n let centre = hu.sweep.x * TAU;\n let width = max(hu.sweep.y, 1e-4);\n let band = exp(-pow(angle_delta(theta, centre) / width, 2.0));\n let sweep = rim * rim * band * hu.sweep.z;\n\n // Press glow: radial, in CSS px, clipped by coverage so it cannot leak past\n // the material's edge.\n let posCss = in.position.xy * hu.screen.z;\n let dist = length(posCss - hu.glow.xy);\n let radial = clamp(1.0 - dist / max(hu.glow.z, 1e-4), 0.0, 1.0);\n // 'aux.y' is the per-pixel glow channel, unioned in the field pass, so a group\n // whose members glow independently does not need a pass each.\n let press = radial * radial * hu.glow.w * aux.y;\n\n /*\n * Backdrop tone adaptation (W7) fades this pass with the rest of the surface's\n * own appearance. A highlight is the material catching light, and a material\n * that has taken its backdrop's tone is not there to catch any — the settled\n * reference's capsule over a near-black backdrop is byte-identical to that\n * background, sweep included.\n *\n * The curve is the optics pass's, evaluated the same way off the same uniforms\n * and the same per-pixel 'sizeK', because two statements of one curve is how\n * they drift. This pass would otherwise have gone on drawing a bright crescent\n * around a surface the optics pass had made invisible — measured at 60 pixels\n * past 2/255, peaking at 97/255, on exactly that cell.\n */\n let sizeK = clamp(aux.z, 0.0, 1.0);\n var toneAdapt = 0.0;\n if (hu.toneAdapt.w > 0.0) {\n let toneX = hu.toneLevel.x + hu.toneAdapt.z * sizeK;\n let toneT = clamp(\n (toneX - hu.toneAdapt.x) / max(hu.toneAdapt.y - hu.toneAdapt.x, 1e-6),\n 0.0,\n 1.0,\n );\n toneAdapt = clamp(hu.toneAdapt.w, 0.0, 1.0) * (1.0 - toneT * toneT * (3.0 - 2.0 * toneT));\n }\n\n let intensity = clamp(sweep + press, 0.0, 1.0) * coverage * (1.0 - toneAdapt);\n if (intensity <= 0.0) {\n return vec4f(0.0);\n }\n return encode_output(hu.colour.rgb, intensity);\n}`;\n","/**\n * The optics pass: refraction, adaptive tint, inner shadow, rim and specular —\n * the glass body.\n *\n * Reads the group's two field targets (value + unit normal + coverage, and the\n * per-surface optical scalars) and the backdrop pyramid; writes premultiplied sRGB\n * into the optics canvas over the group's rect. Everything optical happens in\n * linear light and is encoded exactly once, on the way out (X5).\n *\n * The pass is scoped, not fullscreen: the render pass sets its viewport *and* its\n * scissor to the group's device-pixel rect, so `in.uv` runs 0..1 over the group\n * and indexes the group's own field textures one-to-one, while `in.position.xy`\n * stays in canvas device pixels and gives the backdrop coordinate. Nothing outside\n * the group's bounds is touched — §Performance envelope prices the field and\n * optics passes on exactly that assumption.\n *\n * ## The size law, and the four things it moves\n *\n * Parent acceptance #2 asks for the *mechanism*, not a look: \"a larger surface\n * shows deeper shadow and stronger lensing than a small button over the same\n * backdrop.\" Apple states it as one mechanism with four consequences — a larger\n * surface \"casts deeper, richer shadows, has more pronounced lensing and\n * refraction effects, and a softer scattering of light\" (S219), and \"a larger\n * size is more opaque. A smaller size is clearer\" (S284) — so this pass reads one\n * per-pixel number and applies four gains to it.\n *\n * The number is `aux.z`, `material.ts`'s `sizeThickness(span)`, resolved per\n * surface on the CPU and carried **per pixel** through the field pass's union.\n * That is what lets a 40 px button and a 320 px platter share one group's field\n * pass and still read as different thicknesses. The lens's share of it arrives\n * pre-folded, because it is a length rather than a gain:\n *\n * ```\n * lensDepthPx = min(thickness * lensSizeGain(span), span / 2)\n * ```\n *\n * The clamp is what keeps a small control from being all lens: a 24 px-tall\n * button cannot bend more than 12 px of backdrop however thick it is authored.\n * The other three — scattering, occlusion, inner shadow — are applied below, each\n * multiplied by `sizeK`, so every one of them is exactly inert at `sizeK = 0`.\n *\n * The displacement is the normal times a profile that peaks at the rim and dies in\n * the interior, where the glass is flat and shows the backdrop straight through.\n * **Sampling LOD follows the same profile and the same depth**: the body sits at\n * `lensDepth * bodyLodPerPx` — thicker glass diffuses more — and the rim is biased\n * sharper, because a compressed backdrop reads as detail. That is the inverse of\n * the naive \"blur more at the edge\", and it is most of what makes an edge read as\n * glass rather than as a smudge.\n *\n * Every coefficient is advisory and calibration-delegated (C7), named on the CPU.\n *\n * ## The dual cap\n *\n * `refractionScale` arrives as one number the CPU already resolved through\n * `effectiveRefraction(accessibilityCap, stateQuality)` — Decision Log #19's rule\n * that renderers honour the lower of the two caps. The shader never sees them\n * separately, so it cannot honour the wrong one.\n */\n\nexport const WGSL_OPTICS_PASS = `struct OpticsUniforms {\n /// viewport size in device px (xy), CSS px per device px (z), coverage ramp px (w)\n screen : vec4f,\n /// backdrop uv transform on viewport-normalised coords: scale (xy), offset (zw)\n fit : vec4f,\n /// refractionScale, bodyLodPerPx, rimLodBias, chainMaxLod\n lens : vec4f,\n /// fixed tint colour, linear light (xyz), tint alpha (w)\n tint : vec4f,\n /// adapted tint colour, linear light (xyz), adaptation strength (w)\n adapt : vec4f,\n /// author tint seed, linear light (xyz), tone adaptation under the contrast regime (w)\n seed : vec4f,\n /// tintToneFloor, tintToneCeilMix, tintToneLow, tintToneHigh\n tone : vec4f,\n /// rimWidthPx, rimAlpha, specularPower, specularGain\n rim : vec4f,\n /// light direction, unit (xy), shadowDepth (z), shadowAlpha (w)\n light : vec4f,\n /// hasBackdrop, fieldSize.xy, fieldUpsampled\n flags : vec4f,\n /// the size law's gains (W2): scatterGainMax, occlusionGain, shadowGainMax,\n /// bodyChainLod — the last being the chain level whose blur already matches the\n /// body texture, which is what the scattering term measures its octaves from\n size : vec4f,\n /// backdrop tone adaptation (W7): backdropToneLow, backdropToneHigh, the size\n /// bias ALREADY divided by the accessibility refraction cap (so that it may be\n /// multiplied by the policy-folded 'sizeK' below and still mean the geometric\n /// thickness), and the strength the accessibility policy resolved — zero where\n /// the host could not measure a backdrop tone, which stands the axis down\n toneAdapt : vec4f,\n /// the backdrop source's own average colour, linear (xyz), and its luminance (w)\n toneColour : vec4f,\n /// the outer shadow (W8): its compositing-space alpha before the size law (x),\n /// the blur's sigma in group-local CSS px (y), the silhouette's outward spread\n /// in the same units (z), and the downward offset expressed in field-texture UV\n /// (w) — a UV so the offset silhouette is one texture read rather than a\n /// gradient extrapolation, which is exact only on a straight edge and a capsule\n /// is mostly not one\n shadow : vec4f,\n /// the outer shadow's size-law gain (x), read against the casting surface's own\n /// thickness, and the field rect's height in CSS px (y) — the conversion the\n /// shadow's shift needs when it lands outside the texture; z and w are the\n /// padding a uniform's vec4 alignment requires\n shadowSize : vec4f,\n};\n\n@group(0) @binding(0) var<uniform> ou : OpticsUniforms;\n@group(0) @binding(1) var fieldTexture : texture_2d<f32>;\n@group(0) @binding(2) var auxTexture : texture_2d<f32>;\n@group(0) @binding(3) var backdropSampler : sampler;\n@group(0) @binding(4) var backdropChain : texture_2d<f32>;\n@group(0) @binding(5) var backdropBody : texture_2d<f32>;\n@group(0) @binding(6) var fieldSampler : sampler;\n\n/// Rim proximity: 1 exactly on the contour, falling to 0 by 'width' on either\n/// side. Symmetric, so the rim is a band on the boundary rather than a plateau\n/// that keeps burning outward where coverage has already faded.\nfn rim_weight(d : f32, width : f32) -> f32 {\n let t = clamp(1.0 - abs(d) / max(width, 1e-4), 0.0, 1.0);\n return t * t;\n}\n\n/// The Gaussian CDF the outer shadow's edge falls off by: 1 deep inside the\n/// shadow's silhouette, 0.5 exactly on it, 0 far outside. The tanh form of the\n/// normal CDF — WGSL has no erf, and this is within 1.8e-4 of it everywhere,\n/// which is 0.015 of one 8-bit code at the shipped occlusion. Mirrors\n/// material.ts's 'outerShadowFalloff' term for term.\nfn outer_shadow_falloff(signedDistance : f32, sigma : f32) -> f32 {\n let x = -signedDistance / max(sigma, 1e-4);\n return 0.5 * (1.0 + tanh(0.7978845608028654 * (x + 0.044715 * x * x * x)));\n}\n\n/// The outer shadow's alpha at this pixel (W8).\n///\n/// The shadow is the group's OWN field, translated down by 'shadow.w' in field\n/// UV and outset by 'shadow.z', then blurred. Reading the offset silhouette from\n/// the field texture rather than extrapolating the local distance along the\n/// normal is what keeps a corner a corner: the first-order estimate is exact only\n/// on a straight edge, and a capsule is mostly not one.\n///\n/// The value is an ALPHA on pure black, so what it composites to is the backdrop\n/// times '1 - alpha' — multiplicative occlusion, and exactly zero over black,\n/// with no branch for it.\nfn outer_shadow_alpha(uv : vec2f, upsampled : f32, fieldSize : vec2f) -> f32 {\n if (ou.shadow.x <= 0.0) {\n return 0.0;\n }\n /*\n * The shift can leave the field texture, and clamping alone reads a lie there.\n *\n * Two ways it happens, and the second is not an edge case: the rect is clipped\n * to the canvas, so a surface within the shadow's reach of the viewport's TOP\n * has no rows above it to shift into; and even unclipped, the rect's pad is the\n * shadow's reach, so the topmost band of every group needs rows a further\n * 'offset' above that. Clamped, both repeat the edge texel — a distance that is\n * too SMALL, which reads as a flat, too-dark falloff exactly where the shadow\n * should be fading out, and diverges from the CSS tier, which has no texture to\n * run out of.\n *\n * Reconstructed instead of clamped. A signed distance field is 1-Lipschitz, and\n * in the region this happens in — directly above the surface — moving away from\n * it increases the distance by exactly the displacement. So adding back the\n * distance that was clamped off is exact there, and past the surface's corners\n * it over-estimates, which errs toward LESS shadow rather than more.\n */\n let shiftedY = uv.y - ou.shadow.w;\n let clampedOffCss =\n (max(0.0, -shiftedY) + max(0.0, shiftedY - 1.0)) * ou.shadowSize.y;\n let shadowUv = clamp(vec2f(uv.x, shiftedY), vec2f(0.0), vec2f(1.0));\n var shadowField : vec4f;\n var shadowAux : vec4f;\n if (upsampled > 0.5) {\n shadowField = textureSampleLevel(fieldTexture, fieldSampler, shadowUv, 0.0);\n shadowAux = textureSampleLevel(auxTexture, fieldSampler, shadowUv, 0.0);\n } else {\n let texel = clamp(vec2i(shadowUv * fieldSize), vec2i(0), vec2i(fieldSize) - vec2i(1));\n shadowField = textureLoad(fieldTexture, texel, 0);\n shadowAux = textureLoad(auxTexture, texel, 0);\n }\n\n // The size law reaches the amplitude and nothing else — the reference's three\n // lengths are span-invariant across 32…160 px. The gain rides the thickness of\n // the surface that CAST the shadow, which is the one read at the offset\n // position rather than the one under the pixel being shaded.\n //\n // Applied on '1 - alpha' rather than on the alpha: the gain is a fraction of\n // the remaining transparency in LINEAR light ('sizeOuterShadowOcclusionAt'),\n // and (1 - occ) is exactly what raising to 1/2.4 turns into (1 - alpha), so the\n // two forms are the same law and neither needs the other's space.\n let sizeK = clamp(shadowAux.z, 0.0, 1.0);\n let sizeFold = pow(max(1.0 - ou.shadowSize.x * sizeK, 0.0), 1.0 / 2.4);\n let alpha = 1.0 - (1.0 - ou.shadow.x) * sizeFold;\n\n return alpha * outer_shadow_falloff(shadowField.x + clampedOffCss - ou.shadow.z, ou.shadow.y);\n}\n\n@fragment\nfn fs_optics(in : FullscreenOut) -> @location(0) vec4f {\n // Nominally the field is one texel per device pixel, so the read is an exact\n // load and no filter touches the distance or the normal. Under the governor's\n // 'refractionResolutionScale' the field was rasterised smaller than the group's\n // rect, and then it has to be filtered: a nearest read would quantise the\n // contour to the coarse grid and the rim would step along it.\n var field : vec4f;\n var aux : vec4f;\n if (ou.flags.w > 0.5) {\n field = textureSampleLevel(fieldTexture, fieldSampler, in.uv, 0.0);\n aux = textureSampleLevel(auxTexture, fieldSampler, in.uv, 0.0);\n } else {\n let texel = vec2i(in.uv * ou.flags.yz);\n field = textureLoad(fieldTexture, texel, 0);\n aux = textureLoad(auxTexture, texel, 0);\n }\n\n let d = field.x;\n let normal = field.yz;\n let coverage = field.w;\n\n /*\n * The outer shadow (W8) sits UNDER the material, so it is resolved before the\n * body and carried into the output's alpha rather than into its colour: the\n * pass writes premultiplied black there, and premultiplied black over the page\n * IS the multiplication. Outside the contour that is the whole of what this\n * pixel is; inside it the surface covers the shadow, exactly as a 'box-shadow'\n * is clipped out of its own border box, and the two meet across the coverage\n * ramp with no seam because it is one expression.\n */\n let shadowAlpha = outer_shadow_alpha(in.uv, ou.flags.w, ou.flags.yz);\n if (coverage <= 0.0) {\n return vec4f(0.0, 0.0, 0.0, shadowAlpha);\n }\n\n let viewport01 = in.position.xy / ou.screen.xy;\n let viewportCss = ou.screen.xy * ou.screen.z;\n\n // Per-pixel, unioned through the field pass. See the module note.\n let lensDepth = max(aux.x, 1e-4);\n // The size law's thickness factor for whichever surface owns this pixel, 0..1.\n // Zero on anything at or below the profile's 'sizeSpanMin', and every term\n // below multiplies by it — so a small control takes the pre-law path exactly.\n let sizeK = clamp(aux.z, 0.0, 1.0);\n // '-d' is depth inside the surface, so the profile runs 1 at the contour to 0\n // at 'lensDepth' inward, and the square makes the falloff read as curvature\n // rather than as a linear ramp.\n let depth = clamp(-d / lensDepth, 0.0, 1.0);\n let profile = (1.0 - depth) * (1.0 - depth);\n\n let displaceCss = -normal * lensDepth * profile * ou.lens.x;\n let refracted01 = viewport01 + displaceCss / viewportCss;\n\n let straightUv = clamp(viewport01 * ou.fit.xy + ou.fit.zw, vec2f(0.0), vec2f(1.0));\n let refractedUv = clamp(refracted01 * ou.fit.xy + ou.fit.zw, vec2f(0.0), vec2f(1.0));\n\n let bodyLod = clamp(lensDepth * ou.lens.y, 0.0, ou.lens.w);\n let lod = clamp(bodyLod - ou.lens.z * profile, 0.0, ou.lens.w);\n\n /*\n * The scattering facet of the size law: \"a softer scattering of light\".\n *\n * The body texture is one blur for the whole backdrop source — it is built once\n * per source per frame, so it cannot be per-surface. The chain beside it can:\n * 'size.w' is the chain level whose blur already matches that body, so\n * 'size.w + log2(scatterGain)' is the level whose blur is 'scatterGain' times\n * wider, and lerping the body toward it by 'sizeK' widens the kernel with the\n * surface. At sizeK = 0 the weight is zero and the body sample stands alone,\n * which is what makes the whole facet inert on a small control.\n */\n let scatterGain = 1.0 + (ou.size.x - 1.0) * sizeK;\n let scatterLod = clamp(ou.size.w + log2(max(scatterGain, 1e-4)), 0.0, ou.lens.w);\n\n var backdrop = vec3f(0.0);\n if (ou.flags.x > 0.5) {\n let lensSample = textureSampleLevel(backdropChain, backdropSampler, refractedUv, lod);\n let bodySample = textureSampleLevel(backdropBody, backdropSampler, straightUv, 0.0);\n let scatterSample = textureSampleLevel(backdropChain, backdropSampler, straightUv, scatterLod);\n // Premultiplied linear in, straight colour out: the material composites over\n // whatever is behind it, so a partially transparent backdrop must not darken\n // the glass.\n let lensColour = lensSample.rgb / max(lensSample.a, 1e-6);\n let scatterColour = scatterSample.rgb / max(scatterSample.a, 1e-6);\n let bodyColour = mix(bodySample.rgb / max(bodySample.a, 1e-6), scatterColour, sizeK);\n backdrop = mix(bodyColour, lensColour, profile);\n }\n\n // Adaptive tint. 'adapt.w' is the strength the accessibility policy and the\n // group's analysis quality already agreed on; at 0 the fixed tint stands, which\n // is what a 'hint' or 'none' group gets.\n let neutral = mix(ou.tint.rgb, ou.adapt.rgb, ou.adapt.w);\n\n let backdropLuma = dot(backdrop, vec3f(0.2126, 0.7152, 0.0722));\n\n /*\n * Backdrop tone adaptation (W7) — step two of the composition contract, between\n * the colour scheme's neutral and the author's tint.\n *\n * Read against 'toneColour': the backdrop SOURCE's own average, measured by the\n * host from the pixels it supplied and handed to both tiers as one number. Not a\n * per-pixel sample, and that is the load-bearing choice — see\n * 'GroupRenderInput.backdropTone' for the cross-tier measurement that settled\n * it, and note that the reference agrees: its capsule over a sparse bright grid\n * is a flat body rather than a window onto the grid.\n *\n * 'sizeK' is still per pixel, so a container holding a small control and a large\n * platter adapts each of them by its own thickness out of one pass.\n *\n * Strength is zero where the host measured no tone, and the whole axis stands\n * down where there is no backdrop at all rather than reading the zero vector as\n * a black backdrop and dissolving the surface into nothing.\n *\n * Written out instead of calling smoothstep() so that a profile patched with\n * low >= high degrades to a step rather than to NaN.\n */\n var toneAdapt = 0.0;\n if (ou.flags.x > 0.5 && ou.toneAdapt.w > 0.0) {\n let toneX = ou.toneColour.w + ou.toneAdapt.z * sizeK;\n let toneT = clamp(\n (toneX - ou.toneAdapt.x) / max(ou.toneAdapt.y - ou.toneAdapt.x, 1e-6),\n 0.0,\n 1.0,\n );\n toneAdapt = clamp(ou.toneAdapt.w, 0.0, 1.0) * (1.0 - toneT * toneT * (3.0 - 2.0 * toneT));\n }\n /*\n * Both the colour and the alpha move, together and not separately. What the\n * adaptation means is that the INTERIOR converges on the backdrop's tone —\n * mix(interior, tone, k) — and this is the (colour, alpha) pair that composites\n * to exactly that. Lerping the two independently makes a partially adapted\n * surface lighter than it started (more opaque toward a tint still mostly\n * neutral), which the 96 px cells caught at once: interior 0.4545 → 0.5179\n * against a reference of 0.4542. The alpha half is not a colour axis reaching\n * the occlusion axis — an adapting material stops transmitting, which is what\n * the reference's flat body over the impulse grid is. See 'adaptedTintColour'\n * and 'adaptedTintAlpha' in material.ts.\n */\n let sizedAlpha = ou.tint.w + ou.size.y * sizeK * (1.0 - ou.tint.w);\n let adaptedAlpha = sizedAlpha + toneAdapt * (1.0 - sizedAlpha);\n var adapted = neutral;\n if (toneAdapt > 0.0 && adaptedAlpha > 0.0) {\n adapted =\n (neutral * ((1.0 - toneAdapt) * sizedAlpha) + ou.toneColour.rgb * toneAdapt) / adaptedAlpha;\n }\n\n // The author tint. 'aux.w' is the per-pixel strength, unioned in the field pass,\n // so a toolbar can carry one tinted control among plain ones; the seed is a\n // group uniform. At strength 0 this is the identity and the material is the one\n // the calibration bed measures, byte for byte.\n //\n // Apple's mechanism, not a fill: the seed is the middle of a range of tones\n // 'mapped to content brightness underneath'. 'backdrop' is what this pixel is\n // actually looking through — lens-displaced, LOD-sampled, already the thing the\n // material transmits — so the tone is taken against the same light the tint is\n // about to be mixed into, and a tinted surface over a dark backdrop settles to a\n // shade of the author's colour rather than sitting on it as paint.\n //\n // That 'backdrop' is also where the size law's scattering has already been\n // applied (above), and that is the right order rather than a coincidence: a\n // large surface diffuses more of what is behind it, so the tone the tint maps\n // to should be the diffused light, not the sharp light nobody sees through it.\n //\n // It displaces the ADAPTED neutral, not the raw one: a full-strength tint is its\n // own adaptation and replaces this axis outright, while a partial one moves with\n // it. That order is the wave's composition contract, in one line.\n var tintColour = adapted;\n if (aux.w > 0.0) {\n let t = smoothstep(ou.tone.z, ou.tone.w, backdropLuma);\n let low = ou.seed.rgb * ou.tone.x;\n let high = ou.seed.rgb + (vec3f(1.0) - ou.seed.rgb) * ou.tone.y;\n // 'seed.w' is the contrast regime's grip on the excursion, never on the hue:\n // at 0 the material shows the author's colour flat and stops responding.\n let tone = mix(ou.seed.rgb, mix(low, high, t), clamp(ou.seed.w, 0.0, 1.0));\n tintColour = mix(adapted, tone, clamp(aux.w, 0.0, 1.0));\n }\n\n // The tint layer's ALPHA is untouched by the author's colour. It is the\n // material's occlusion — what reduced transparency lifts, and the axis the\n // system's own Clear-to-Tinted preference runs on — and an author choosing a\n // colour does not get to move it.\n //\n // The size law does move it, and the two do not collide: \"a larger size is more\n // opaque, a smaller size is clearer\" is a statement about how much material\n // there is, not about what colour it is. A fraction of whatever transparency\n // the resolved alpha still has, for the reason 'increasedOcclusionLift' is a\n // fraction — see material.ts.\n //\n // The backdrop adaptation moves it, above, and the author's colour does not.\n var colour = mix(backdrop, tintColour, adaptedAlpha);\n\n /*\n * Everything below is the surface's own APPEARANCE — the marks that say a\n * surface is here rather than what is behind it — and all of it fades with the\n * adaptation, on the one factor.\n *\n * That is not symmetry for its own sake; it is what the reference does, and it\n * is a calibration cell rather than an inference: the reference's capsule over\n * the dark-solid backdrop is byte-identical to that background, rim included. A\n * material that has taken its backdrop's tone has no lit edge to show, because\n * there is no light in front of it to show one with.\n *\n * The gap was invisible until this axis existed. A rim of up to 130/255 sat\n * unnoticed inside a bright capsule body; with the body gone it is a white\n * outline around a surface that should not be there at all — 595 pixels past\n * 2/255 on that one cell, and OKLab ΔE max 0.47 where p95 already read 0.0000.\n * The same lesson W3 recorded from the other direction: a term that happens to\n * be hidden is one feature away from being visible.\n */\n let present = 1.0 - toneAdapt;\n\n // Inner shadow: the material's own occlusion, deepest where the lens is\n // strongest, which is what makes a thicker surface read as heavier — and the\n // shadow facet of the size law deepens it further with the span.\n let shadowDepth = ou.light.z * (1.0 + (ou.size.z - 1.0) * sizeK);\n colour = colour * (1.0 - profile * shadowDepth * ou.light.w * present);\n\n // Rim and specular from the gradient. The rim is unlit ambient edge brightness;\n // the specular term is the same edge lit from 'light.xy'.\n let rw = rim_weight(d, ou.rim.x);\n let facing = dot(normal, ou.light.xy);\n let spec = pow(clamp(facing, 0.0, 1.0), max(ou.rim.z, 1e-3)) * ou.rim.w;\n colour = colour + vec3f(rw * (ou.rim.y + spec) * present);\n\n // The material over its own shadow over the page, in one premultiplied vector:\n // the colour is the surface's, weighted by its coverage, and the alpha is what\n // the two of them together leave the page — 'coverage' from the surface, and\n // the shadow filling whatever transparency is left.\n let body = encode_output(max(colour, vec3f(0.0)), coverage);\n return vec4f(body.rgb, body.a + shadowAlpha * (1.0 - body.a));\n}`;\n","/**\n * Shared WGSL: the colour pipeline (X5) and the fullscreen-triangle vertex stage\n * every pass here uses.\n *\n * The marker comment on the first line is load-bearing beyond documentation:\n * `packages/core/test/bundle-shape.test.ts` greps built chunks for it to prove\n * that WGSL reaches exactly one lazily-imported chunk and never core's entry\n * chunk (X7). Keep it in a module every pass pulls in, and keep it spelled\n * exactly as it is.\n */\n\nexport const WGSL_PRELUDE = `// vitrea:wgsl-marker\n// ---------------------------------------------------------------------------\n// X5 colour pipeline. Piecewise sRGB, matching color.ts channel for channel:\n// a golden regenerated against one and asserted against the other must not\n// drift by a code unit, so the 2.2-gamma approximation is not used anywhere.\n// ---------------------------------------------------------------------------\n\nfn srgb_to_linear(c : vec3f) -> vec3f {\n let lo = c / 12.92;\n let hi = pow((c + vec3f(0.055)) / 1.055, vec3f(2.4));\n return select(hi, lo, c <= vec3f(0.04045));\n}\n\nfn linear_to_srgb(c : vec3f) -> vec3f {\n let lo = c * 12.92;\n let hi = 1.055 * pow(max(c, vec3f(0.0)), vec3f(1.0 / 2.4)) - vec3f(0.055);\n return select(hi, lo, c <= vec3f(0.0031308));\n}\n\n/// Rec.709 weights on LINEAR light. Weighting encoded values would make the\n/// analysis pass measure something that is not energy.\nfn luminance(linear : vec3f) -> f32 {\n return dot(linear, vec3f(0.2126, 0.7152, 0.0722));\n}\n\n/// The one output encoding: encode, then premultiply in the ENCODED space,\n/// because that is the space the browser composites a canvas in. Premultiplying\n/// in linear and encoding afterwards darkens every partially covered pixel.\nfn encode_output(linear : vec3f, alpha : f32) -> vec4f {\n let a = clamp(alpha, 0.0, 1.0);\n return vec4f(linear_to_srgb(linear) * a, a);\n}\n\n// ---------------------------------------------------------------------------\n// Fullscreen triangle. Three vertices, no vertex buffer, no index buffer: the\n// oversized triangle is clipped to the target and costs one fewer primitive\n// than a quad, and every pass here writes exactly one screen-space region.\n// ---------------------------------------------------------------------------\n\nstruct FullscreenOut {\n @builtin(position) position : vec4f,\n @location(0) uv : vec2f,\n};\n\n@vertex\nfn vs_fullscreen(@builtin(vertex_index) index : u32) -> FullscreenOut {\n // (-1,-1) (3,-1) (-1,3) in clip space; uv follows with y flipped so (0,0) is\n // the target's top-left, matching texture and viewport conventions.\n let x = f32((index << 1u) & 2u) * 2.0 - 1.0;\n let y = f32(index & 2u) * 2.0 - 1.0;\n var out : FullscreenOut;\n out.position = vec4f(x, y, 0.0, 1.0);\n out.uv = vec2f((x + 1.0) * 0.5, (1.0 - y) * 0.5);\n return out;\n}\n`;\n","/**\n * Shader-module assembly.\n *\n * Every module is `prelude + pass`, so the colour pipeline and the fullscreen\n * vertex stage are defined once and there is no way for a pass to acquire its own\n * private transfer function. Assembly is a plain string concatenation performed\n * on demand and cached by the pipeline cache — no build step, no bundler plugin,\n * and the WGSL stays greppable in the built artifact, which is what core's X7\n * bundle test relies on.\n */\n\nimport { WGSL_ANALYSIS_PASS } from \"./analysis\";\nimport { WGSL_CROSS_CHECK_PASS } from \"./cross-check\";\nimport { importPassSource, WGSL_DOWNSAMPLE_PASS } from \"./backdrop\";\nimport { fieldPassSource, WGSL_FIELD_KERNELS } from \"./field\";\nimport { WGSL_HIGHLIGHT_PASS } from \"./highlight\";\nimport { WGSL_OPTICS_PASS } from \"./optics\";\nimport { WGSL_PRELUDE } from \"./prelude\";\n\nexport * from \"./analysis\";\nexport * from \"./cross-check\";\nexport * from \"./backdrop\";\nexport * from \"./field\";\nexport * from \"./highlight\";\nexport * from \"./optics\";\nexport * from \"./prelude\";\n\nconst withPrelude = (pass: string): string => `${WGSL_PRELUDE}\\n${pass}\\n`;\n\nexport type FieldFamily = \"rsupn\" | \"rsup\";\n\nexport const fieldModule = (family: FieldFamily): string => withPrelude(fieldPassSource(family));\n\nexport const importModule = (kind: \"sampled\" | \"external\"): string =>\n withPrelude(importPassSource(kind));\n\nexport const chainModule = (): string => withPrelude(WGSL_DOWNSAMPLE_PASS);\n\nexport const analysisModule = (): string => withPrelude(WGSL_ANALYSIS_PASS);\n\nexport const opticsModule = (): string => withPrelude(WGSL_OPTICS_PASS);\n\nexport const highlightModule = (): string => withPrelude(WGSL_HIGHLIGHT_PASS);\n\n/**\n * The kernel-only module the f32 cross-check compiles (Decision Log #20).\n *\n * It is assembled from the same constants the field pass is, which is the point:\n * a check that compiled a different string from the one the renderer ships would\n * prove nothing about the shipped shader.\n */\nexport const crossCheckKernelModule = (): string =>\n withPrelude([WGSL_FIELD_KERNELS, WGSL_CROSS_CHECK_PASS].join(\"\\n\\n\"));\n\n/**\n * Every shader this package can compile, concatenated.\n *\n * Exposed as `GlassRenderer.shaderSource` — the seam's honest answer to \"what\n * WGSL does this renderer carry\", and the string core's bundle-shape test finds\n * the marker in.\n */\nexport function allShaderSource(): string {\n return [\n WGSL_PRELUDE,\n fieldPassSource(\"rsupn\"),\n fieldPassSource(\"rsup\"),\n importPassSource(\"sampled\"),\n importPassSource(\"external\"),\n WGSL_DOWNSAMPLE_PASS,\n WGSL_ANALYSIS_PASS,\n WGSL_OPTICS_PASS,\n WGSL_HIGHLIGHT_PASS,\n ].join(\"\\n\\n\");\n}\n","/**\n * The three drawing passes, as GPU work: field, optics, highlight.\n *\n * Each is scoped to the group's device-pixel rect. The field pass renders *into*\n * a group-sized pair of textures; the optics and highlight passes render into the\n * plane canvases with the viewport and the scissor both set to that rect, so the\n * fullscreen triangle's `uv` indexes the field textures one-to-one and\n * `position.xy` stays in canvas coordinates. X1 forbids two glass surfaces\n * overlapping inside one plane, so those rects are disjoint and the scissor is\n * enough — no depth, no stencil, no sorting.\n *\n * Blending is premultiplied source-over on both canvas passes. Against a cleared\n * canvas it is indistinguishable from no blending, and the reason to have it is\n * the case that is not that: an overlay-plane surface drawn over a base-plane one\n * during a cross-plane morph, where the promotion moves the surface as a unit but\n * the frame in flight can still hold both.\n */\n\nimport { OUTPUT_TEXTURE_FORMAT, WORKING_TEXTURE_FORMAT } from \"./color\";\nimport { type GpuContext, createUniformSlot, createStorageSlot, type StorageSlot, type UniformSlot } from \"./gpu-context\";\nimport type { FieldFamily } from \"./governor\";\nimport { INSTANCE_BYTES } from \"./instances\";\nimport { pipelineKey } from \"./pipeline-cache\";\nimport { poolKey } from \"./texture-pool\";\nimport { PASS_LABEL, type PassTimeline } from \"./timing\";\nimport { fieldModule, highlightModule, opticsModule } from \"./wgsl\";\n\n/**\n * Usage masks are computed on FIRST USE, never at module scope.\n *\n * `GPUTextureUsage` is a browser global, and this module is imported outside a\n * browser: `vitrea`'s lazy seam resolves this package in Node to check the\n * renderer's shape (`packages/core/test/renderer-seam.test.ts`). A mask evaluated\n * at module scope makes the whole package throw on import there — a\n * `ReferenceError` from a file that never intended to run, in a test that only\n * wanted to read `backend` and `ready`.\n */\nconst fieldUsage = (): GPUTextureUsageFlags =>\n GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING;\n\n/** Premultiplied source-over. See the module note. */\nconst PREMULTIPLIED_OVER: GPUBlendState = {\n color: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n alpha: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n};\n\n/** A rect in device pixels. Integers by construction — see `snapRectToDevicePixels`. */\nexport interface DeviceRect {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n}\n\nexport interface FieldPassArgs {\n readonly groupId: string;\n readonly family: FieldFamily;\n readonly rectDevice: DeviceRect;\n /** CSS px per device px. */\n readonly cssPerDevice: number;\n /** Coverage ramp width in CSS px. One device pixel, unless the governor widens it. */\n readonly coverageRampCss: number;\n /**\n * The governor's `refractionResolutionScale`, 0 < s <= 1. The field targets are\n * allocated at `rectDevice * s` and the optics and highlight passes upsample\n * them; the *rect* is unchanged, so the group still covers the same pixels.\n * `1` is the nominal path and takes exactly the arithmetic it took before the\n * knob existed.\n */\n readonly renderScale: number;\n readonly instances: Float32Array;\n readonly instanceCount: number;\n readonly union: { readonly neckWidth: number; readonly maxBulge: number; readonly separationThreshold: number };\n}\n\nexport interface FieldTargets {\n readonly field: GPUTexture;\n readonly aux: GPUTexture;\n /** The field textures' extent in texels — the group's rect times `renderScale`. */\n readonly width: number;\n readonly height: number;\n /**\n * True when that extent is smaller than the group's rect, so a reader has to\n * filter rather than index. False on the nominal path, where one texel is one\n * device pixel and the read is an exact `textureLoad`.\n */\n readonly upsampled: boolean;\n}\n\nexport interface OpticsPassArgs {\n readonly groupId: string;\n readonly target: GPUTextureView;\n readonly targetFormat: GPUTextureFormat;\n readonly rectDevice: DeviceRect;\n readonly fields: FieldTargets;\n /** Viewport in device px, and CSS px per device px. */\n readonly viewportDevice: readonly [number, number];\n readonly cssPerDevice: number;\n readonly coverageRampCss: number;\n /** Backdrop uv transform on viewport-normalised coordinates. */\n readonly fit: readonly [number, number, number, number];\n readonly refractionScale: number;\n readonly bodyLodPerPx: number;\n readonly rimLodBias: number;\n readonly chainMaxLod: number;\n readonly tint: readonly [number, number, number];\n readonly tintAlpha: number;\n readonly adaptTint: readonly [number, number, number];\n readonly adaptStrength: number;\n /** The group's author tint seed in linear light, and the tone map it is read through. */\n readonly tintSeed: readonly [number, number, number];\n readonly tintToneAdaptation: number;\n readonly tintTone: readonly [number, number, number, number];\n readonly rimWidth: number;\n readonly rimAlpha: number;\n readonly specularPower: number;\n readonly specularGain: number;\n readonly lightDirection: readonly [number, number];\n readonly shadowDepth: number;\n readonly shadowAlpha: number;\n /**\n * The size law's gains (W2), applied per pixel against the field pass's\n * `sizeK` channel. `bodyChainLod` is not a gain but the chain level whose blur\n * already matches the body texture — the origin the scattering term measures\n * its extra octaves from, which only the pyramid that built the body knows.\n */\n readonly sizeScatterGainMax: number;\n readonly sizeOcclusionGain: number;\n readonly sizeShadowGainMax: number;\n readonly bodyChainLod: number;\n /**\n * Backdrop tone adaptation (W7): `[low, high, sizeBiasUnderPolicy, strength]`.\n *\n * The bias is the profile's own divided by the accessibility refraction cap\n * (`backdropToneSizeBiasUnderPolicy`), because the shader multiplies it by the\n * policy-folded `sizeK` while the gate it expresses is geometric.\n */\n readonly backdropTone: readonly [number, number, number, number];\n /**\n * The backdrop source's average colour in linear light, and its luminance —\n * what the adaptation adapts toward, measured by the host. `backdropTone`'s\n * strength is 0 where there is none, so this is not read.\n */\n readonly backdropToneColour: readonly [number, number, number, number];\n /**\n * The outer shadow (W8): `[alpha, sigmaCss, spreadCss, offsetFieldUv]`.\n *\n * `alpha` is already in the canvas's compositing space (`outerShadowAlpha`) and\n * already folded under the accessibility policy; the size law is per pixel and\n * stays in the shader. The offset arrives as a **field-texture UV** rather than\n * as CSS px, because only the caller knows how tall the rect the field was\n * rasterised into is.\n */\n readonly outerShadow: readonly [number, number, number, number];\n /** The outer shadow's size-law gain — see `MaterialOuterShadow.sizeGain`. */\n readonly outerShadowSizeGain: number;\n /**\n * The field rect's height in CSS px — what the shadow's shift converts through\n * when it lands outside the field texture.\n *\n * The rect is clipped to the canvas and its pad is only the shadow's reach, so\n * the shift runs off the top of the texture both for a surface near the\n * viewport's top edge and, always, for the topmost band of every group. The\n * shader reconstructs the distance it could not read; this is the scale it\n * reconstructs in.\n */\n readonly outerShadowRectCssHeight: number;\n readonly backdrop: { readonly chain: GPUTextureView; readonly body: GPUTextureView } | undefined;\n}\n\nexport interface HighlightPassArgs {\n readonly groupId: string;\n readonly target: GPUTextureView;\n readonly targetFormat: GPUTextureFormat;\n readonly rectDevice: DeviceRect;\n readonly fields: FieldTargets;\n readonly viewportDevice: readonly [number, number];\n readonly cssPerDevice: number;\n readonly sweep: number;\n readonly sweepBandRadians: number;\n readonly sweepGain: number;\n readonly rimWidth: number;\n readonly pressPointCss: readonly [number, number];\n readonly glowRadiusCss: number;\n readonly glowGain: number;\n readonly colour: readonly [number, number, number];\n /**\n * The optics pass's `backdropTone` and the backdrop's own luminance, forwarded\n * unchanged (W7). A highlight is the material catching light, and a material\n * that has taken its backdrop's tone is not there to catch any — so this pass\n * evaluates the same curve off the same numbers rather than a second copy.\n */\n readonly backdropTone: readonly [number, number, number, number];\n readonly backdropToneLevel: number;\n /**\n * The rect the FIELD textures were rasterised into, which since W8 is bigger\n * than `rectDevice`.\n *\n * The outer shadow made the field rect grow by the shadow's reach — about 46\n * CSS px against the rim-and-bulge margin's 3 — and this pass draws nothing out\n * there: `fs_highlight` returns on `coverage <= 0`, so every one of those\n * fragments was rasterised, read twice and discarded. So the pass keeps the\n * small rect as its viewport and scissor and reads the field through the remap\n * this pair implies.\n *\n * **Worth less than it looks, and the number is here rather than a hope.** A/B\n * against the same tree without this scoping, three interleaved bench runs\n * each, comparing the shadow-on to shadow-off ratio on the mobile scene: 3.11\n * against 3.35 at the median, with the two ranges overlapping (2.92…3.37\n * against 3.20…3.62). So this recovers roughly 7% of the shadow's cost, not the\n * third this pass's own timestamp suggested — most of that timestamp is the\n * field texture's write draining into the next pass rather than this pass's own\n * fragments. It stays because it is strictly less work for byte-identical\n * output (the `highlight-press-glow` golden does not move), not because the\n * benchmark can see it clearly.\n */\n readonly fieldRectDevice: DeviceRect;\n}\n\nexport interface PassRunner {\n fieldPass(encoder: GPUCommandEncoder, args: FieldPassArgs): FieldTargets;\n opticsPass(encoder: GPUCommandEncoder, args: OpticsPassArgs): void;\n highlightPass(encoder: GPUCommandEncoder, args: HighlightPassArgs): void;\n /** A 1×1 transparent texture, for binding a backdrop that is not there. */\n readonly placeholderView: GPUTextureView;\n /** Clear a plane canvas before the group passes, which load rather than clear. */\n clearPass(encoder: GPUCommandEncoder, target: GPUTextureView): void;\n /** Attach a timing collector for this frame, or `undefined` to time nothing. */\n setTimeline(timeline: PassTimeline | undefined): void;\n forget(groupId: string): void;\n destroy(): void;\n}\n\nexport function createPassRunner(context: GpuContext): PassRunner {\n const { device, pool, cache } = context;\n const uniforms = new Map<string, UniformSlot>();\n const storages = new Map<string, StorageSlot>();\n\n // `rgba16float` tops out near 65504, so the \"no surface here\" distance is a\n // large FINITE value: an overflow to +Inf would make every later arithmetic on\n // it a NaN, and NaN coverage is not reliably zero.\n const EMPTY_DISTANCE = 65000;\n\n const placeholder = device.createTexture({\n label: \"vitrea:placeholder\",\n size: { width: 1, height: 1, depthOrArrayLayers: 1 },\n format: WORKING_TEXTURE_FORMAT,\n usage: fieldUsage(),\n });\n\n const uniformSlot = (key: string, floats: number): UniformSlot => {\n let slot = uniforms.get(key);\n if (slot === undefined) {\n slot = createUniformSlot(device, floats, `vitrea:uniform:${key}`);\n uniforms.set(key, slot);\n }\n return slot;\n };\n\n const storageSlot = (key: string): StorageSlot => {\n let slot = storages.get(key);\n if (slot === undefined) {\n slot = createStorageSlot(device, 8 * INSTANCE_BYTES, `vitrea:instances:${key}`);\n storages.set(key, slot);\n }\n return slot;\n };\n\n const fieldPipeline = (family: FieldFamily): GPURenderPipeline =>\n cache.renderPipeline(pipelineKey.field(family, WORKING_TEXTURE_FORMAT), () => {\n const module = cache.module(`module:field:${family}`, () => fieldModule(family));\n return {\n label: `vitrea:pipeline:field:${family}`,\n layout: \"auto\",\n vertex: { module, entryPoint: \"vs_fullscreen\" },\n fragment: {\n module,\n entryPoint: \"fs_field\",\n targets: [{ format: WORKING_TEXTURE_FORMAT }, { format: WORKING_TEXTURE_FORMAT }],\n },\n primitive: { topology: \"triangle-list\" },\n };\n });\n\n const opticsPipeline = (format: GPUTextureFormat): GPURenderPipeline =>\n cache.renderPipeline(pipelineKey.optics(format, \"premultiplied-over\"), () => {\n const module = cache.module(\"module:optics\", opticsModule);\n return {\n label: \"vitrea:pipeline:optics\",\n layout: \"auto\",\n vertex: { module, entryPoint: \"vs_fullscreen\" },\n fragment: {\n module,\n entryPoint: \"fs_optics\",\n targets: [{ format, blend: PREMULTIPLIED_OVER }],\n },\n primitive: { topology: \"triangle-list\" },\n };\n });\n\n const highlightPipeline = (format: GPUTextureFormat): GPURenderPipeline =>\n cache.renderPipeline(pipelineKey.highlight(format, \"premultiplied-over\"), () => {\n const module = cache.module(\"module:highlight\", highlightModule);\n return {\n label: \"vitrea:pipeline:highlight\",\n layout: \"auto\",\n vertex: { module, entryPoint: \"vs_fullscreen\" },\n fragment: {\n module,\n entryPoint: \"fs_highlight\",\n targets: [{ format, blend: PREMULTIPLIED_OVER }],\n },\n primitive: { topology: \"triangle-list\" },\n };\n });\n\n const scoped = (\n pass: GPURenderPassEncoder,\n rect: DeviceRect,\n ): void => {\n pass.setViewport(rect.x, rect.y, rect.width, rect.height, 0, 1);\n // The oversized fullscreen triangle reaches past the viewport; the scissor is\n // what stops it writing another group's pixels.\n pass.setScissorRect(rect.x, rect.y, rect.width, rect.height);\n };\n\n const placeholderView = placeholder.createView();\n let timeline: PassTimeline | undefined;\n\n /** `timestampWrites` is only legal when the device enabled `timestamp-query`. */\n const timed = (label: string): { timestampWrites?: GPURenderPassTimestampWrites } => {\n const slot = timeline?.renderSlot(label);\n return slot === undefined ? {} : { timestampWrites: slot };\n };\n\n return {\n placeholderView,\n\n fieldPass(encoder, args) {\n // The rect the group occupies on the canvas, and the extent the field is\n // rasterised at. They differ only under the governor's resolution knob, and\n // at scale 1 the second is the first — `Math.round(w * 1)` on an integer.\n const rectWidth = Math.max(1, Math.round(args.rectDevice.width));\n const rectHeight = Math.max(1, Math.round(args.rectDevice.height));\n const width = Math.max(1, Math.round(args.rectDevice.width * args.renderScale));\n const height = Math.max(1, Math.round(args.rectDevice.height * args.renderScale));\n\n const field = pool.acquire(poolKey.groupField(args.groupId), {\n width,\n height,\n format: WORKING_TEXTURE_FORMAT,\n usage: fieldUsage(),\n label: `vitrea:group:${args.groupId}:field`,\n });\n const aux = pool.acquire(poolKey.groupAux(args.groupId), {\n width,\n height,\n format: WORKING_TEXTURE_FORMAT,\n usage: fieldUsage(),\n label: `vitrea:group:${args.groupId}:aux`,\n });\n\n // Twelve floats: screen, unionP, counts. The group's origin is deliberately\n // absent — instance centres are packed relative to it, so the shader works\n // in group-local coordinates and never adds it back.\n //\n // `screen.xy` is the group's extent in DEVICE px, not the target's, because\n // the shader multiplies it by `screen.z` to recover group-local CSS. Under\n // the resolution knob the target shrinks while the group does not, and it\n // is the group the geometry is expressed in.\n const slot = uniformSlot(`field:${args.groupId}`, 12);\n slot.data[0] = rectWidth;\n slot.data[1] = rectHeight;\n slot.data[2] = args.cssPerDevice;\n // One TARGET pixel wide, so the analytic coverage stays one texel of\n // antialiasing however coarse the target is. At scale 1 the ratio is 1.\n slot.data[3] = args.coverageRampCss * (rectWidth / width);\n slot.data[4] = args.union.neckWidth;\n slot.data[5] = args.union.maxBulge;\n slot.data[6] = args.union.separationThreshold;\n slot.data[7] = 0;\n // `counts` is a vec4u in the shader; a Float32Array cannot write a u32, so\n // the count goes through a Uint32 view of the same words.\n slot.data[9] = 0;\n slot.data[10] = 0;\n slot.data[11] = 0;\n new Uint32Array(slot.data.buffer, slot.data.byteOffset + 32, 1)[0] = args.instanceCount;\n slot.write();\n\n const instances = storageSlot(args.groupId);\n instances.ensure(Math.max(args.instanceCount, 1) * INSTANCE_BYTES);\n instances.write(args.instances, Math.max(args.instanceCount, 1) * (INSTANCE_BYTES / 4));\n\n const pipeline = fieldPipeline(args.family);\n const pass = encoder.beginRenderPass({\n label: `vitrea:pass:field:${args.groupId}`,\n ...timed(PASS_LABEL.field),\n colorAttachments: [\n {\n view: field.createView(),\n loadOp: \"clear\",\n storeOp: \"store\",\n clearValue: { r: EMPTY_DISTANCE, g: 0, b: -1, a: 0 },\n },\n {\n view: aux.createView(),\n loadOp: \"clear\",\n storeOp: \"store\",\n clearValue: { r: 0, g: 0, b: 0, a: 0 },\n },\n ],\n });\n pass.setPipeline(pipeline);\n pass.setBindGroup(\n 0,\n device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [\n { binding: 0, resource: { buffer: slot.buffer } },\n { binding: 1, resource: { buffer: instances.buffer } },\n ],\n }),\n );\n pass.draw(3);\n pass.end();\n\n return {\n field,\n aux,\n width,\n height,\n upsampled: width !== rectWidth || height !== rectHeight,\n };\n },\n\n opticsPass(encoder, args) {\n const slot = uniformSlot(`optics:${args.groupId}`, 60);\n const d = slot.data;\n d[0] = args.viewportDevice[0];\n d[1] = args.viewportDevice[1];\n d[2] = args.cssPerDevice;\n d[3] = args.coverageRampCss;\n d[4] = args.fit[0];\n d[5] = args.fit[1];\n d[6] = args.fit[2];\n d[7] = args.fit[3];\n d[8] = args.refractionScale;\n d[9] = args.bodyLodPerPx;\n d[10] = args.rimLodBias;\n d[11] = args.chainMaxLod;\n d[12] = args.tint[0];\n d[13] = args.tint[1];\n d[14] = args.tint[2];\n d[15] = args.tintAlpha;\n d[16] = args.adaptTint[0];\n d[17] = args.adaptTint[1];\n d[18] = args.adaptTint[2];\n d[19] = args.adaptStrength;\n d[20] = args.tintSeed[0];\n d[21] = args.tintSeed[1];\n d[22] = args.tintSeed[2];\n d[23] = args.tintToneAdaptation;\n d[24] = args.tintTone[0];\n d[25] = args.tintTone[1];\n d[26] = args.tintTone[2];\n // WGSL's `smoothstep` is undefined when its edges coincide, so the high\n // edge is floored above the low one here rather than trusted from a\n // profile — the same guard `union_blend` makes for its separation.\n d[27] = Math.max(args.tintTone[3], args.tintTone[2] + 1e-4);\n d[28] = args.rimWidth;\n d[29] = args.rimAlpha;\n d[30] = args.specularPower;\n d[31] = args.specularGain;\n d[32] = args.lightDirection[0];\n d[33] = args.lightDirection[1];\n d[34] = args.shadowDepth;\n d[35] = args.shadowAlpha;\n d[36] = args.backdrop === undefined ? 0 : 1;\n d[37] = args.fields.width;\n d[38] = args.fields.height;\n d[39] = args.fields.upsampled ? 1 : 0;\n d[40] = args.sizeScatterGainMax;\n d[41] = args.sizeOcclusionGain;\n d[42] = args.sizeShadowGainMax;\n d[43] = args.bodyChainLod;\n d[44] = args.backdropTone[0];\n // The shader divides by `max(high - low, 1e-6)` rather than calling\n // `smoothstep`, so a coinciding pair degrades to a step instead of a NaN —\n // but the floor is kept here too so both tiers see the same edges.\n d[45] = Math.max(args.backdropTone[1], args.backdropTone[0] + 1e-4);\n d[46] = args.backdropTone[2];\n d[47] = args.backdropTone[3];\n d[48] = args.backdropToneColour[0];\n d[49] = args.backdropToneColour[1];\n d[50] = args.backdropToneColour[2];\n d[51] = args.backdropToneColour[3];\n d[52] = args.outerShadow[0];\n d[53] = args.outerShadow[1];\n d[54] = args.outerShadow[2];\n d[55] = args.outerShadow[3];\n d[56] = args.outerShadowSizeGain;\n d[57] = args.outerShadowRectCssHeight;\n d[58] = 0;\n d[59] = 0;\n slot.write();\n\n const chain = args.backdrop?.chain ?? placeholderView;\n const body = args.backdrop?.body ?? placeholderView;\n\n const pipeline = opticsPipeline(args.targetFormat);\n const pass = encoder.beginRenderPass({\n label: `vitrea:pass:optics:${args.groupId}`,\n ...timed(PASS_LABEL.optics),\n colorAttachments: [{ view: args.target, loadOp: \"load\", storeOp: \"store\" }],\n });\n pass.setPipeline(pipeline);\n scoped(pass, args.rectDevice);\n pass.setBindGroup(\n 0,\n device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [\n { binding: 0, resource: { buffer: slot.buffer } },\n { binding: 1, resource: args.fields.field.createView() },\n { binding: 2, resource: args.fields.aux.createView() },\n { binding: 3, resource: context.chainSampler },\n { binding: 4, resource: chain },\n { binding: 5, resource: body },\n // Linear, no mips: the field targets have one level, and this is only\n // read at all when the governor shrank them below the group's rect.\n { binding: 6, resource: context.flatSampler },\n ],\n }),\n );\n pass.draw(3);\n pass.end();\n },\n\n highlightPass(encoder, args) {\n const slot = uniformSlot(`highlight:${args.groupId}`, 32);\n const d = slot.data;\n d[0] = args.viewportDevice[0];\n d[1] = args.viewportDevice[1];\n d[2] = args.cssPerDevice;\n d[3] = 0;\n d[4] = args.sweep;\n d[5] = args.sweepBandRadians;\n d[6] = args.sweepGain;\n d[7] = args.rimWidth;\n d[8] = args.pressPointCss[0];\n d[9] = args.pressPointCss[1];\n d[10] = args.glowRadiusCss;\n d[11] = args.glowGain;\n d[12] = args.colour[0];\n d[13] = args.colour[1];\n d[14] = args.colour[2];\n d[15] = 0;\n d[16] = args.fields.width;\n d[17] = args.fields.height;\n d[18] = args.fields.upsampled ? 1 : 0;\n d[19] = 0;\n d[20] = args.backdropTone[0];\n d[21] = Math.max(args.backdropTone[1], args.backdropTone[0] + 1e-4);\n d[22] = args.backdropTone[2];\n d[23] = args.backdropTone[3];\n d[24] = args.backdropToneLevel;\n d[25] = 0;\n d[26] = 0;\n d[27] = 0;\n /*\n * This pass's uv into the field texture's uv (W8). The field rect is the\n * one the shadow needs; this pass is scoped to the one the surface needs,\n * which is smaller, so the two no longer index one-to-one.\n *\n * Derived from the two rects rather than passed in already-divided, so the\n * one place that knows both is the one place that computes it.\n */\n const fieldRect = args.fieldRectDevice;\n d[28] = args.rectDevice.width / Math.max(fieldRect.width, 1e-6);\n d[29] = args.rectDevice.height / Math.max(fieldRect.height, 1e-6);\n d[30] = (args.rectDevice.x - fieldRect.x) / Math.max(fieldRect.width, 1e-6);\n d[31] = (args.rectDevice.y - fieldRect.y) / Math.max(fieldRect.height, 1e-6);\n slot.write();\n\n const pipeline = highlightPipeline(args.targetFormat);\n const pass = encoder.beginRenderPass({\n label: `vitrea:pass:highlight:${args.groupId}`,\n ...timed(PASS_LABEL.highlight),\n colorAttachments: [{ view: args.target, loadOp: \"load\", storeOp: \"store\" }],\n });\n pass.setPipeline(pipeline);\n scoped(pass, args.rectDevice);\n pass.setBindGroup(\n 0,\n device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [\n { binding: 0, resource: { buffer: slot.buffer } },\n { binding: 1, resource: args.fields.field.createView() },\n { binding: 2, resource: args.fields.aux.createView() },\n { binding: 3, resource: context.flatSampler },\n ],\n }),\n );\n pass.draw(3);\n pass.end();\n },\n\n clearPass(encoder, target) {\n // Deliberately untimed. A render pass with no draw commands is resolved by\n // the driver without ever writing its timestamp pair, so a slot taken here\n // comes back as (0, 0) — indistinguishable from a query that failed. Leaving\n // it out is what lets a non-zero anomaly count mean something.\n const pass = encoder.beginRenderPass({\n label: \"vitrea:pass:clear\",\n colorAttachments: [\n {\n view: target,\n loadOp: \"clear\",\n storeOp: \"store\",\n clearValue: { r: 0, g: 0, b: 0, a: 0 },\n },\n ],\n });\n pass.end();\n },\n\n setTimeline(next) {\n timeline = next;\n },\n\n forget(groupId) {\n pool.release(poolKey.groupField(groupId));\n pool.release(poolKey.groupAux(groupId));\n storages.get(groupId)?.destroy();\n storages.delete(groupId);\n for (const key of [`field:${groupId}`, `optics:${groupId}`, `highlight:${groupId}`]) {\n uniforms.get(key)?.buffer.destroy();\n uniforms.delete(key);\n }\n },\n\n destroy() {\n for (const slot of uniforms.values()) slot.buffer.destroy();\n uniforms.clear();\n for (const slot of storages.values()) slot.destroy();\n storages.clear();\n placeholder.destroy();\n },\n };\n}\n\n/** The output format the plane canvases and the golden readback both use (X5). */\nexport const CANVAS_FORMAT = OUTPUT_TEXTURE_FORMAT;\n","/**\n * How large a backdrop's pyramid is, and which level each consumer reads —\n * decided on the CPU, in one pure function, before any texture exists.\n *\n * §Performance envelope: \"Effect-texture resolution is decoupled from DOM DPR.\"\n * That decoupling lives here: level 0 is the *source's* size scaled by the\n * resolution policy and capped by `maxDimension`, never the viewport's device\n * pixel count. A 4K video behind a 390-px-wide phone viewport does not get a 4K\n * pyramid, and a governor that halves `scale` halves the whole chain's cost\n * without touching a shader.\n *\n * ## Level count\n *\n * The chain stops when the shorter side would fall below `MIN_LEVEL_EXTENT`. Below\n * about 8 px a level carries no usable structure and the bilinear taps of the\n * 13-tap downsample start reading mostly clamped edge, so the levels past that\n * point cost bandwidth and add nothing. That also bounds the maximum LOD the\n * optics pass may ask for, which is why `maxLod` is part of the plan rather than\n * computed in the shader.\n *\n * ## The analysis level\n *\n * Not the coarsest: the coarsest level has had every edge blurred out of it, so an\n * edge-density measurement there would report the same small number for a\n * photograph and for a flat colour. The plan picks the level nearest\n * `ANALYSIS_TARGET_EXTENT`, which keeps the measurement's spatial frequency band\n * fixed as the source's resolution changes — a stat that moved when the\n * resolution policy moved would make the governor's own degradation look like a\n * change in the backdrop.\n */\n\nexport const MIN_LEVEL_EXTENT = 8;\nexport const MAX_CHAIN_LEVELS = 12;\n/** Shorter-side extent the analysis level aims for. */\nexport const ANALYSIS_TARGET_EXTENT = 96;\n\nexport interface PyramidPlan {\n /** Level 0 size in texture px. */\n readonly width: number;\n readonly height: number;\n readonly levelCount: number;\n /** The highest LOD the optics pass may sample: `levelCount - 1`. */\n readonly maxLod: number;\n /** Which level the analysis reduction reads. */\n readonly analysisLevel: number;\n /** Per-level sizes, index 0 = level 0. */\n readonly levels: readonly { readonly width: number; readonly height: number }[];\n}\n\nexport interface ResolutionPolicyView {\n readonly scale: number;\n readonly maxDimension: number;\n}\n\nexport function planPyramid(\n sourceWidth: number,\n sourceHeight: number,\n policy: ResolutionPolicyView,\n): PyramidPlan {\n const scale = Math.max(policy.scale, 1e-3);\n let width = Math.max(1, Math.round(sourceWidth * scale));\n let height = Math.max(1, Math.round(sourceHeight * scale));\n\n const cap = Math.max(MIN_LEVEL_EXTENT, Math.floor(policy.maxDimension));\n const longest = Math.max(width, height);\n if (longest > cap) {\n const shrink = cap / longest;\n width = Math.max(1, Math.round(width * shrink));\n height = Math.max(1, Math.round(height * shrink));\n }\n\n const levels: { width: number; height: number }[] = [{ width, height }];\n while (levels.length < MAX_CHAIN_LEVELS) {\n const previous = levels[levels.length - 1] as { width: number; height: number };\n const next = {\n width: Math.max(1, previous.width >> 1),\n height: Math.max(1, previous.height >> 1),\n };\n if (Math.min(next.width, next.height) < MIN_LEVEL_EXTENT) break;\n if (next.width === previous.width && next.height === previous.height) break;\n levels.push(next);\n }\n\n // Nearest level to the analysis target on the shorter side, in log space so\n // \"nearest\" means nearest by octave rather than by pixel count.\n let analysisLevel = 0;\n let bestDistance = Number.POSITIVE_INFINITY;\n for (let i = 0; i < levels.length; i += 1) {\n const level = levels[i] as { width: number; height: number };\n const shorter = Math.min(level.width, level.height);\n const distance = Math.abs(Math.log2(shorter / ANALYSIS_TARGET_EXTENT));\n if (distance < bestDistance) {\n bestDistance = distance;\n analysisLevel = i;\n }\n }\n\n return {\n width,\n height,\n levelCount: levels.length,\n maxLod: levels.length - 1,\n analysisLevel,\n levels,\n };\n}\n\n/**\n * The chain LOD whose blur is nearest σ, and the residual σ the separable pass\n * still has to apply on top of it.\n *\n * The 13-tap downsample's effective σ roughly doubles per level and is about 1.2\n * source texels at level 1; the constant is advisory (calibration-delegated like\n * every other optical number here) and exists so the body blur lands on the\n * material's σ rather than on the nearest power of two.\n */\nexport const CHAIN_SIGMA_AT_LEVEL_1 = 1.2;\n\n/**\n * The **continuous** chain level whose blur is σ level-0 texels — the same\n * doubling `bodyBlurPlan` steps through, inverted and left continuous because its\n * one consumer samples the chain trilinearly rather than picking a level.\n *\n * The size law's scattering facet needs it (W2). The body texture is one blur for\n * a whole backdrop source — built at most once per source per frame, so it cannot\n * be per-surface — while the chain beside it carries every octave at once. So the\n * optics pass reaches a wider kernel per surface by sampling the chain, and this\n * is the origin it measures its extra octaves from. Below level 1's own σ there\n * is no coarser level to name, so the answer ramps linearly to 0 at σ = 0 rather\n * than diverging the way a bare logarithm would.\n */\nexport function chainLodForSigma(sigmaTexels: number): number {\n if (!(sigmaTexels > 0)) return 0;\n if (sigmaTexels <= CHAIN_SIGMA_AT_LEVEL_1) return sigmaTexels / CHAIN_SIGMA_AT_LEVEL_1;\n return 1 + Math.log2(sigmaTexels / CHAIN_SIGMA_AT_LEVEL_1);\n}\n\nexport function bodyBlurPlan(\n sigmaPx: number,\n plan: PyramidPlan,\n): { readonly level: number; readonly residualSigmaTexels: number } {\n if (sigmaPx <= 0) return { level: 0, residualSigmaTexels: 0 };\n\n // Level n's sigma in level-0 texels.\n const sigmaAt = (level: number): number =>\n level === 0 ? 0 : CHAIN_SIGMA_AT_LEVEL_1 * Math.pow(2, level - 1);\n\n let level = 0;\n for (let i = 1; i < plan.levelCount; i += 1) {\n if (sigmaAt(i) > sigmaPx) break;\n level = i;\n }\n\n // The residual is applied at the chosen level's own resolution, so convert.\n const covered = sigmaAt(level);\n const residualLevel0 = Math.sqrt(Math.max(sigmaPx * sigmaPx - covered * covered, 0));\n return { level, residualSigmaTexels: residualLevel0 / Math.pow(2, level) };\n}\n","/**\n * The §Core model invariant, as a testable object.\n *\n * > blur/analysis pyramids belong to `BackdropSource`, rebuilt **at most once per\n * > dirty source per frame** — never per group.\n *\n * core enforces one half of that: `consumeDirtyBackdropSources(frameId)` hands out\n * one pass over the dirty set per frame id, so a second caller in the same frame\n * gets nothing. What core cannot see is the renderer's side — a renderer that also\n * rebuilt lazily on first draw, or that rebuilt once per group from a single\n * request, would satisfy core's guard and still violate the invariant.\n *\n * So the ledger lives here, apart from the GPU work it guards, for one reason: it\n * makes the invariant assertable against core's real scheduler with no adapter and\n * no device. `pyramid.ts` claims through it before it encodes a single pass, and\n * `test/dirty-epoch.test.ts` drives core's own scene and scheduler over this same\n * object. An invariant tested only through a GPU is an invariant tested only where\n * a GPU exists.\n */\n\nexport interface RebuildLedger {\n /**\n * Begin a frame. Clears the per-frame tally — unless `frameId` is the frame\n * already being recorded, which is not a new frame and must not reopen the\n * tally. The renderer draws one plane per call with the same `FrameInfo`, so\n * that case is the ordinary one rather than the exception.\n */\n beginFrame(frameId: number): void;\n readonly frameId: number | undefined;\n /**\n * Claim the one rebuild this source is allowed this frame. `false` means it has\n * already had it — the caller must not encode a second one.\n */\n claim(sourceId: string): boolean;\n /** Record that a claim did no work because the source was clean. */\n recordClean(): void;\n /** Rebuilds recorded for `sourceId` in the frame being recorded. */\n countInFrame(sourceId: string): number;\n readonly rebuilds: number;\n readonly refusedDuplicates: number;\n readonly skippedClean: number;\n /**\n * Highest per-source rebuild count seen in any single frame. The invariant is\n * exactly the statement that this never exceeds 1.\n */\n readonly peakPerSourcePerFrame: number;\n}\n\nexport function createRebuildLedger(): RebuildLedger {\n const perFrame = new Map<string, number>();\n let frameId: number | undefined;\n let rebuilds = 0;\n let refused = 0;\n let clean = 0;\n let peak = 0;\n\n return {\n beginFrame(next) {\n // Repeating a frame id is not a new frame, and clearing the tally for one\n // would quietly hand every source a second rebuild. The renderer calls\n // `drawFrame` once per PLANE with the same `FrameInfo`, so this is the\n // ordinary case rather than a defensive one: without the guard the\n // \"at most once per dirty source per frame\" invariant is unguarded across\n // planes, and `countInFrame` reports 0 for a frame that rebuilt.\n // `FrameInfo.id` is contractually monotonic (core/src/frame.ts), so\n // equality is the whole test.\n if (frameId === next) return;\n frameId = next;\n perFrame.clear();\n },\n\n get frameId() {\n return frameId;\n },\n\n claim(sourceId) {\n const already = perFrame.get(sourceId) ?? 0;\n if (already > 0) {\n refused += 1;\n return false;\n }\n const count = already + 1;\n perFrame.set(sourceId, count);\n peak = Math.max(peak, count);\n rebuilds += 1;\n return true;\n },\n\n recordClean() {\n clean += 1;\n },\n\n countInFrame(sourceId) {\n return perFrame.get(sourceId) ?? 0;\n },\n\n get rebuilds() {\n return rebuilds;\n },\n\n get refusedDuplicates() {\n return refused;\n },\n\n get skippedClean() {\n return clean;\n },\n\n get peakPerSourcePerFrame() {\n return peak;\n },\n };\n}\n","/**\n * The blur/analysis pyramid, one per `BackdropSource`, and the ledger that proves\n * the §Core model invariant.\n *\n * > **Invariant:** blur/analysis pyramids belong to `BackdropSource`, rebuilt **at\n * > most once per dirty source per frame** — never per group. Static backdrops\n * > rebuild nothing.\n *\n * core enforces half of that already: `consumeDirtyBackdropSources(frameId)`\n * hands out one pass over the dirty set per frame id, so however many\n * participants ask, the second call returns nothing. What core *cannot* see is\n * this side of the wire — a renderer that also rebuilt lazily on first draw, or\n * that rebuilt once per group from one request, would satisfy core's guard and\n * violate the invariant. So the ledger here counts rebuilds per source per frame\n * on the renderer's own books, refuses a second one, and exposes the counters.\n * That is what makes the invariant *instrumented* rather than asserted.\n *\n * ## Pass structure per rebuild\n *\n * ```\n * import provider frame -> chain mip 0 (premultiplied linear, X5)\n * downsample mip n-1 -> chain mip n (13-tap, one pass per level)\n * blur x2 chain[bodyLvl] -> body (separable, residual sigma)\n * analysis chain[anaLvl] -> stats buffer (compute, one workgroup)\n * ```\n *\n * Reading mip n-1 while rendering into mip n is legal because they are distinct\n * subresources, and every view here is created with an explicit\n * `baseMipLevel`/`mipLevelCount: 1` so that is true by construction rather than by\n * the driver's interpretation of a full-texture view.\n */\n\nimport { ANALYSIS_STATS_FLOATS, ANALYSIS_GRID, ANALYSIS_WORKGROUP } from \"./wgsl/analysis\";\nimport {\n alphaNormalisationMode,\n importColorMatrix,\n WORKING_TEXTURE_FORMAT,\n} from \"./color\";\nimport { statsFromBuffer, type BackdropStats } from \"./analysis\";\nimport type { BackdropFrame, BackdropProvider } from \"./backdrop\";\nimport { type GpuContext, createUniformSlot, type UniformSlot } from \"./gpu-context\";\nimport { pipelineKey } from \"./pipeline-cache\";\nimport { bodyBlurPlan, planPyramid, type PyramidPlan, type ResolutionPolicyView } from \"./pyramid-plan\";\nimport { createRebuildLedger, type RebuildLedger } from \"./rebuild-ledger\";\nimport { poolKey } from \"./texture-pool\";\nimport { PASS_LABEL, type PassTimeline } from \"./timing\";\nimport { analysisModule, chainModule, importModule } from \"./wgsl\";\n\n/** Computed on first use, not at module scope — see the note in `passes.ts`. */\nconst chainUsage = (): GPUTextureUsageFlags =>\n GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING;\n\nexport interface PyramidResources {\n readonly sourceId: string;\n readonly plan: PyramidPlan;\n readonly chain: GPUTexture;\n readonly body: GPUTexture;\n readonly stats: GPUBuffer;\n /** Source size epoch this allocation was made for. */\n readonly sizeEpoch: number;\n /** The dirty epoch the last successful rebuild satisfied. */\n readonly builtEpoch: number;\n /**\n * The body blur's σ in **level-0 texels** — the CSS-px σ the material asked\n * for, through the same cover fit and plan downscale the build applied.\n *\n * Published because the conversion is only knowable here: it needs the frame's\n * real extent, which is exactly why `bodySigmaCss` arrives in CSS px. The size\n * law's scattering facet consumes it (W2) — the optics pass widens the body blur\n * per surface by sampling the chain, and it cannot find the level to measure\n * from without knowing where the body already sits.\n */\n readonly bodySigmaTexels: number;\n}\n\nexport interface PyramidInstrumentation {\n /** Successful rebuilds since the store was created. */\n readonly rebuilds: number;\n /** Rebuild attempts refused because the source had already rebuilt this frame. */\n readonly refusedDuplicates: number;\n /** Rebuilds skipped because the source was clean. */\n readonly skippedClean: number;\n readonly reallocations: number;\n /** Rebuild count for one source within the frame currently being recorded. */\n rebuildsInFrame(sourceId: string): number;\n /** Highest per-source rebuild count seen in any single frame. Must stay <= 1. */\n readonly peakRebuildsPerSourcePerFrame: number;\n}\n\nexport interface PyramidBuildRequest {\n readonly sourceId: string;\n readonly epoch: number;\n readonly resolution: ResolutionPolicyView;\n /**\n * The material's body blur, in **CSS px**, with the viewport it is measured\n * against.\n *\n * Not in source texels, because the conversion between the two is a property of\n * the frame that has not been acquired yet: a 3840-wide video behind a 390 px\n * viewport packs ten source texels into every CSS px, so a σ of 8 texels would\n * be a σ of 0.8 CSS px on screen — a tenth of the frost the material asked for.\n * The build resolves it once the frame's real extent is known.\n */\n readonly bodySigmaCss: number;\n readonly viewportCss: readonly [number, number];\n}\n\nexport type PyramidBuildOutcome =\n | { readonly status: \"built\"; readonly resources: PyramidResources }\n | { readonly status: \"duplicate\" }\n | { readonly status: \"clean\"; readonly resources: PyramidResources }\n | { readonly status: \"unavailable\"; readonly reason: string };\n\nexport interface PyramidStore {\n readonly instrumentation: PyramidInstrumentation;\n /** The invariant's ledger, exposed so a test can drive it without a device. */\n readonly ledger: RebuildLedger;\n /** Start recording a new frame. Clears the per-frame rebuild tally. */\n beginFrame(frameId: number): void;\n /** Attach a timing collector for this frame, or `undefined` to time nothing. */\n setTimeline(timeline: PassTimeline | undefined): void;\n build(\n request: PyramidBuildRequest,\n provider: BackdropProvider,\n encoder: GPUCommandEncoder,\n ): PyramidBuildOutcome;\n /**\n * Release every provider acquired this frame.\n *\n * Split from `afterSubmit` because the two halves have opposite failure rules.\n * A release is owed whether or not the frame reached the queue — an acquired\n * `VideoFrame` held across a frame stalls decoding — so this belongs in a\n * `finally` around the whole encode/submit. Call it after `queue.submit` on the\n * success path: an imported external texture must outlive the submission that\n * samples it.\n */\n releaseAcquired(): void;\n /**\n * Start the analysis readback maps. **Success path only**: `mapAsync` makes a\n * buffer unavailable to submits from the moment it is called, so starting a map\n * for a copy that was never submitted is its own bug — see `requestStats`.\n */\n afterSubmit(): void;\n /**\n * The source's pyramid, or `undefined` when it has none the pool still owns.\n * A caller may bind what this returns without checking anything further.\n */\n resources(sourceId: string): PyramidResources | undefined;\n /** Copy a source's stats into a staging buffer and map it. Cadence-gated by the caller. */\n requestStats(sourceId: string, encoder: GPUCommandEncoder): boolean;\n /** Resolve any completed stats readbacks. Returns what arrived. */\n collectStats(): Promise<ReadonlyMap<string, BackdropStats>>;\n forget(sourceId: string): void;\n destroy(): void;\n}\n\ninterface StatsReadback {\n readonly staging: GPUBuffer;\n inFlight: boolean;\n}\n\nexport function createPyramidStore(context: GpuContext): PyramidStore {\n const { device, pool, cache } = context;\n\n const resources = new Map<string, PyramidResources>();\n const uniforms = new Map<string, UniformSlot>();\n const readbacks = new Map<string, StatsReadback>();\n const pendingRelease: BackdropProvider[] = [];\n const pendingStats = new Map<string, Promise<BackdropStats | undefined>>();\n /** Readbacks whose copy is encoded but whose map must wait for the submit. */\n const pendingMaps: string[] = [];\n\n let timeline: PassTimeline | undefined;\n const timedRender = (label: string): { timestampWrites?: GPURenderPassTimestampWrites } => {\n const slot = timeline?.renderSlot(label);\n return slot === undefined ? {} : { timestampWrites: slot };\n };\n const timedCompute = (label: string): { timestampWrites?: GPUComputePassTimestampWrites } => {\n const slot = timeline?.computeSlot(label);\n return slot === undefined ? {} : { timestampWrites: slot };\n };\n\n let frameId = -1;\n let reallocations = 0;\n const ledger: RebuildLedger = createRebuildLedger();\n\n const uniformSlot = (key: string, floats: number): UniformSlot => {\n let slot = uniforms.get(key);\n if (slot === undefined) {\n slot = createUniformSlot(device, floats, `vitrea:uniform:${key}`);\n uniforms.set(key, slot);\n }\n return slot;\n };\n\n const importPipeline = (kind: \"sampled\" | \"external\"): GPURenderPipeline =>\n cache.renderPipeline(pipelineKey.import(kind, WORKING_TEXTURE_FORMAT), () => ({\n label: `vitrea:pipeline:import:${kind}`,\n layout: \"auto\",\n vertex: {\n module: cache.module(`module:import:${kind}`, () => importModule(kind)),\n entryPoint: \"vs_fullscreen\",\n },\n fragment: {\n module: cache.module(`module:import:${kind}`, () => importModule(kind)),\n entryPoint: \"fs_import\",\n targets: [{ format: WORKING_TEXTURE_FORMAT }],\n },\n primitive: { topology: \"triangle-list\" },\n }));\n\n const chainPipeline = (entry: \"fs_downsample\" | \"fs_blur\"): GPURenderPipeline =>\n cache.renderPipeline(pipelineKey.chain(entry, WORKING_TEXTURE_FORMAT), () => ({\n label: `vitrea:pipeline:chain:${entry}`,\n layout: \"auto\",\n vertex: {\n module: cache.module(\"module:chain\", chainModule),\n entryPoint: \"vs_fullscreen\",\n },\n fragment: {\n module: cache.module(\"module:chain\", chainModule),\n entryPoint: entry,\n targets: [{ format: WORKING_TEXTURE_FORMAT }],\n },\n primitive: { topology: \"triangle-list\" },\n }));\n\n const analysisPipeline = (): GPUComputePipeline =>\n cache.computePipeline(pipelineKey.analysis(), () => ({\n label: \"vitrea:pipeline:analysis\",\n layout: \"auto\",\n compute: {\n module: cache.module(\"module:analysis\", analysisModule),\n entryPoint: \"cs_analysis\",\n },\n }));\n\n /**\n * The source's resources, or `undefined` when the handles it recorded are no\n * longer the pool's.\n *\n * The pool owns the lifetime of both textures and can destroy them without this\n * store hearing about it — a size-epoch sweep, a device-loss `clear()`. The\n * recorded handles then name destroyed textures, and binding one is a WebGPU\n * validation error that takes the whole plane's encoder down with it. Two\n * identity compares turn that into \"there is no backdrop this frame\", which the\n * optics pass already has a placeholder for: unrefracted glass for a frame,\n * rather than a dropped one.\n */\n const liveResources = (sourceId: string): PyramidResources | undefined => {\n const target = resources.get(sourceId);\n if (target === undefined) return undefined;\n if (pool.peek(poolKey.backdropChain(sourceId)) !== target.chain) return undefined;\n if (pool.peek(poolKey.backdropBody(sourceId)) !== target.body) return undefined;\n return target;\n };\n\n const mipView = (texture: GPUTexture, level: number): GPUTextureView =>\n texture.createView({ baseMipLevel: level, mipLevelCount: 1, dimension: \"2d\" });\n\n function allocate(\n sourceId: string,\n plan: PyramidPlan,\n bodyLevel: number,\n sizeEpoch: number,\n builtEpoch: number,\n bodySigmaTexels: number,\n ): PyramidResources {\n const existing = resources.get(sourceId);\n const bodyWidth = (plan.levels[bodyLevel] ?? plan.levels[0] as { width: number; height: number }).width;\n const bodyHeight = (plan.levels[bodyLevel] ?? plan.levels[0] as { width: number; height: number }).height;\n\n const chain = pool.acquire(poolKey.backdropChain(sourceId), {\n width: plan.width,\n height: plan.height,\n format: WORKING_TEXTURE_FORMAT,\n usage: chainUsage(),\n mipLevelCount: plan.levelCount,\n label: `vitrea:pyramid:${sourceId}:chain`,\n });\n const body = pool.acquire(poolKey.backdropBody(sourceId), {\n width: bodyWidth,\n height: bodyHeight,\n format: WORKING_TEXTURE_FORMAT,\n usage: chainUsage(),\n label: `vitrea:pyramid:${sourceId}:body`,\n });\n\n let stats = existing?.stats;\n if (stats === undefined) {\n stats = device.createBuffer({\n label: `vitrea:pyramid:${sourceId}:stats`,\n size: ANALYSIS_STATS_FLOATS * 4,\n usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,\n });\n }\n\n if (existing === undefined || existing.chain !== chain || existing.body !== body) {\n reallocations += 1;\n }\n\n const next: PyramidResources = {\n sourceId,\n plan,\n chain,\n body,\n stats,\n sizeEpoch,\n builtEpoch,\n bodySigmaTexels,\n };\n resources.set(sourceId, next);\n return next;\n }\n\n function runImport(\n encoder: GPUCommandEncoder,\n sourceId: string,\n frame: BackdropFrame,\n chain: GPUTexture,\n ): void {\n const kind = frame.binding.kind;\n const pipeline = importPipeline(kind);\n const slot = uniformSlot(`import:${sourceId}`, 16);\n const matrix = importColorMatrix(frame.colorSpace);\n\n slot.data[0] = matrix[0] as number;\n slot.data[1] = matrix[1] as number;\n slot.data[2] = matrix[2] as number;\n slot.data[3] = frame.encoded ? 1 : 0;\n slot.data[4] = matrix[3] as number;\n slot.data[5] = matrix[4] as number;\n slot.data[6] = matrix[5] as number;\n slot.data[7] = alphaNormalisationMode(frame.alphaMode);\n slot.data[8] = matrix[6] as number;\n slot.data[9] = matrix[7] as number;\n slot.data[10] = matrix[8] as number;\n slot.data[11] = 0;\n // Stretch fit: level 0 IS the source, resampled to the planned extent, so the\n // uv transform is the identity. A group's own framing of the backdrop happens\n // in the optics pass, where the viewport is known.\n slot.data[12] = 1;\n slot.data[13] = 1;\n slot.data[14] = 0;\n slot.data[15] = 0;\n slot.write();\n\n const entries: GPUBindGroupEntry[] = [\n { binding: 0, resource: { buffer: slot.buffer } },\n { binding: 1, resource: context.flatSampler },\n {\n binding: 2,\n resource:\n frame.binding.kind === \"external\" ? frame.binding.texture : frame.binding.view,\n },\n ];\n\n const pass = encoder.beginRenderPass({\n label: `vitrea:pass:import:${sourceId}`,\n ...timedRender(PASS_LABEL.import),\n colorAttachments: [\n { view: mipView(chain, 0), loadOp: \"clear\", storeOp: \"store\", clearValue: { r: 0, g: 0, b: 0, a: 0 } },\n ],\n });\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, device.createBindGroup({ layout: pipeline.getBindGroupLayout(0), entries }));\n pass.draw(3);\n pass.end();\n }\n\n function runChain(\n encoder: GPUCommandEncoder,\n sourceId: string,\n plan: PyramidPlan,\n chain: GPUTexture,\n ): void {\n const pipeline = chainPipeline(\"fs_downsample\");\n for (let level = 1; level < plan.levelCount; level += 1) {\n const source = plan.levels[level - 1] as { width: number; height: number };\n const slot = uniformSlot(`chain:${sourceId}:${level}`, 8);\n slot.data[0] = 1 / source.width;\n slot.data[1] = 1 / source.height;\n slot.data[2] = 0;\n slot.data[3] = 0;\n slot.data[4] = 0;\n slot.data[5] = 0;\n slot.data[6] = 0;\n slot.data[7] = 0;\n slot.write();\n\n const pass = encoder.beginRenderPass({\n label: `vitrea:pass:downsample:${sourceId}:${level}`,\n ...timedRender(PASS_LABEL.chain),\n colorAttachments: [\n { view: mipView(chain, level), loadOp: \"clear\", storeOp: \"store\", clearValue: { r: 0, g: 0, b: 0, a: 0 } },\n ],\n });\n pass.setPipeline(pipeline);\n pass.setBindGroup(\n 0,\n device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [\n { binding: 0, resource: { buffer: slot.buffer } },\n { binding: 1, resource: context.flatSampler },\n { binding: 2, resource: mipView(chain, level - 1) },\n ],\n }),\n );\n pass.draw(3);\n pass.end();\n }\n }\n\n function runBodyBlur(\n encoder: GPUCommandEncoder,\n sourceId: string,\n plan: PyramidPlan,\n chain: GPUTexture,\n body: GPUTexture,\n level: number,\n residualSigmaTexels: number,\n ): void {\n const pipeline = chainPipeline(\"fs_blur\");\n const size = plan.levels[level] ?? (plan.levels[0] as { width: number; height: number });\n const scratch = pool.acquire(poolKey.backdropBodyScratch(sourceId), {\n width: size.width,\n height: size.height,\n format: WORKING_TEXTURE_FORMAT,\n usage: chainUsage(),\n label: `vitrea:pyramid:${sourceId}:body-scratch`,\n });\n\n const stages: { target: GPUTexture; source: GPUTextureView; dir: [number, number]; tag: string }[] = [\n { target: scratch, source: mipView(chain, level), dir: [1, 0], tag: \"h\" },\n { target: body, source: scratch.createView(), dir: [0, 1], tag: \"v\" },\n ];\n\n for (const stage of stages) {\n const slot = uniformSlot(`body:${sourceId}:${stage.tag}`, 8);\n slot.data[0] = 1 / size.width;\n slot.data[1] = 1 / size.height;\n slot.data[2] = 0;\n slot.data[3] = 0;\n slot.data[4] = residualSigmaTexels;\n slot.data[5] = stage.dir[0];\n slot.data[6] = stage.dir[1];\n slot.data[7] = 0;\n slot.write();\n\n const pass = encoder.beginRenderPass({\n label: `vitrea:pass:body-blur-${stage.tag}:${sourceId}`,\n ...timedRender(PASS_LABEL.bodyBlur),\n colorAttachments: [\n { view: stage.target.createView(), loadOp: \"clear\", storeOp: \"store\", clearValue: { r: 0, g: 0, b: 0, a: 0 } },\n ],\n });\n pass.setPipeline(pipeline);\n pass.setBindGroup(\n 0,\n device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [\n { binding: 0, resource: { buffer: slot.buffer } },\n { binding: 1, resource: context.flatSampler },\n { binding: 2, resource: stage.source },\n ],\n }),\n );\n pass.draw(3);\n pass.end();\n }\n }\n\n function runAnalysis(\n encoder: GPUCommandEncoder,\n sourceId: string,\n plan: PyramidPlan,\n chain: GPUTexture,\n stats: GPUBuffer,\n ): void {\n const pipeline = analysisPipeline();\n const level = plan.levels[plan.analysisLevel] ?? (plan.levels[0] as { width: number; height: number });\n const slot = uniformSlot(`analysis:${sourceId}`, 8);\n slot.data[0] = ANALYSIS_GRID;\n slot.data[1] = ANALYSIS_GRID;\n slot.data[2] = plan.analysisLevel;\n slot.data[3] = 1 / (ANALYSIS_GRID - 1);\n slot.data[4] = 1 / level.width;\n slot.data[5] = 1 / level.height;\n slot.data[6] = 0;\n slot.data[7] = 0;\n slot.write();\n\n const pass = encoder.beginComputePass({\n label: `vitrea:pass:analysis:${sourceId}`,\n ...timedCompute(PASS_LABEL.analysis),\n });\n pass.setPipeline(pipeline);\n pass.setBindGroup(\n 0,\n device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [\n { binding: 0, resource: { buffer: slot.buffer } },\n { binding: 1, resource: context.flatSampler },\n { binding: 2, resource: chain.createView() },\n { binding: 3, resource: { buffer: stats } },\n ],\n }),\n );\n // One workgroup: the reduction reads a fixed grid, so its cost does not\n // follow the backdrop's resolution. See wgsl/analysis.ts.\n pass.dispatchWorkgroups(1);\n pass.end();\n }\n\n return {\n instrumentation: {\n get rebuilds() {\n return ledger.rebuilds;\n },\n get refusedDuplicates() {\n return ledger.refusedDuplicates;\n },\n get skippedClean() {\n return ledger.skippedClean;\n },\n get reallocations() {\n return reallocations;\n },\n rebuildsInFrame(sourceId) {\n return ledger.countInFrame(sourceId);\n },\n get peakRebuildsPerSourcePerFrame() {\n return ledger.peakPerSourcePerFrame;\n },\n },\n\n /** The ledger the invariant is asserted against. See `rebuild-ledger.ts`. */\n ledger,\n\n beginFrame(next) {\n frameId = next;\n ledger.beginFrame(next);\n },\n\n setTimeline(next) {\n timeline = next;\n },\n\n build(request, provider, encoder) {\n // The LIVE resources, not merely the recorded ones: a clean-skip against a\n // handle the pool has already destroyed would leave the source with no\n // usable pyramid and no way back — the skip is exactly what stops the\n // reallocation that would heal it.\n const existing = liveResources(request.sourceId);\n if (\n existing !== undefined &&\n existing.builtEpoch >= request.epoch &&\n !provider.isDirty()\n ) {\n ledger.recordClean();\n return { status: \"clean\", resources: existing };\n }\n\n // Claimed BEFORE any pass is encoded: the ledger is the guard, not a\n // counter kept alongside one.\n if (!ledger.claim(request.sourceId)) {\n return { status: \"duplicate\" };\n }\n\n let frame: BackdropFrame;\n try {\n frame = provider.acquire({ id: frameId, timeMs: 0 });\n } catch (error) {\n return {\n status: \"unavailable\",\n reason: error instanceof Error ? error.message : String(error),\n };\n }\n pendingRelease.push(provider);\n\n const plan = planPyramid(frame.width, frame.height, request.resolution);\n // Source texels per CSS px, under the same cover fit the optics pass\n // samples with, times the downscale the plan actually applied (which\n // includes `maxDimension`, not just the policy's `scale`).\n const [viewportW, viewportH] = request.viewportCss;\n const cover =\n viewportW > 0 && viewportH > 0\n ? Math.max(frame.width / viewportW, frame.height / viewportH)\n : 1;\n const planScale = frame.width > 0 ? plan.width / frame.width : 1;\n const bodySigmaTexels = request.bodySigmaCss * cover * planScale;\n const bodyPlan = bodyBlurPlan(bodySigmaTexels, plan);\n const target = allocate(\n request.sourceId,\n plan,\n bodyPlan.level,\n frame.sizeEpoch,\n request.epoch,\n bodySigmaTexels,\n );\n\n runImport(encoder, request.sourceId, frame, target.chain);\n runChain(encoder, request.sourceId, plan, target.chain);\n runBodyBlur(\n encoder,\n request.sourceId,\n plan,\n target.chain,\n target.body,\n bodyPlan.level,\n bodyPlan.residualSigmaTexels,\n );\n runAnalysis(encoder, request.sourceId, plan, target.chain, target.stats);\n\n provider.markImported();\n return { status: \"built\", resources: target };\n },\n\n releaseAcquired() {\n // In acquisition order. A provider that throws on release must not strand\n // the others — a leaked VideoFrame stalls decoding.\n while (pendingRelease.length > 0) {\n const provider = pendingRelease.shift();\n try {\n provider?.release();\n } catch {\n // Deliberately swallowed; see above.\n }\n }\n },\n\n afterSubmit() {\n // The readback maps, now that the copies they read are in the queue.\n while (pendingMaps.length > 0) {\n const sourceId = pendingMaps.shift();\n if (sourceId === undefined) continue;\n const slot = readbacks.get(sourceId);\n if (slot === undefined) continue;\n const staging = slot.staging;\n pendingStats.set(\n sourceId,\n (async () => {\n try {\n await staging.mapAsync(GPUMapMode.READ);\n const values = new Float32Array(staging.getMappedRange().slice(0));\n staging.unmap();\n return statsFromBuffer(values);\n } catch {\n return undefined;\n } finally {\n slot.inFlight = false;\n }\n })(),\n );\n }\n },\n\n resources(sourceId) {\n return liveResources(sourceId);\n },\n\n requestStats(sourceId, encoder) {\n const target = liveResources(sourceId);\n if (target === undefined) return false;\n\n let readback = readbacks.get(sourceId);\n if (readback === undefined) {\n readback = {\n staging: device.createBuffer({\n label: `vitrea:pyramid:${sourceId}:stats-staging`,\n size: ANALYSIS_STATS_FLOATS * 4,\n usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,\n }),\n inFlight: false,\n };\n readbacks.set(sourceId, readback);\n }\n // Single slot, no queue: if the previous map has not resolved, this frame's\n // readback is simply skipped. Queueing them is how a renderer under pressure\n // accumulates stale buffers, and two answers from the same frame are no more\n // useful than one.\n if (readback.inFlight) return false;\n\n encoder.copyBufferToBuffer(target.stats, 0, readback.staging, 0, ANALYSIS_STATS_FLOATS * 4);\n readback.inFlight = true;\n // The map is NOT started here. `mapAsync` makes a buffer unavailable to\n // submits from the moment it is called, and the copy just encoded has not\n // been submitted yet — starting the map now makes this frame's own submit\n // invalid with \"used in submit while mapped\". So the map is deferred to\n // `afterSubmit`.\n pendingMaps.push(sourceId);\n return true;\n },\n\n async collectStats() {\n const out = new Map<string, BackdropStats>();\n const entries = [...pendingStats];\n pendingStats.clear();\n for (const [sourceId, promise] of entries) {\n const stats = await promise;\n if (stats !== undefined) out.set(sourceId, stats);\n }\n return out;\n },\n\n forget(sourceId) {\n pool.release(poolKey.backdropChain(sourceId));\n pool.release(poolKey.backdropBody(sourceId));\n pool.release(poolKey.backdropBodyScratch(sourceId));\n resources.get(sourceId)?.stats.destroy();\n resources.delete(sourceId);\n readbacks.get(sourceId)?.staging.destroy();\n readbacks.delete(sourceId);\n pendingStats.delete(sourceId);\n const queued = pendingMaps.indexOf(sourceId);\n if (queued >= 0) pendingMaps.splice(queued, 1);\n },\n\n destroy() {\n for (const sourceId of [...resources.keys()]) this.forget(sourceId);\n for (const slot of uniforms.values()) slot.buffer.destroy();\n uniforms.clear();\n pendingRelease.length = 0;\n pendingMaps.length = 0;\n },\n };\n}\n\n/** Exposed so a test can assert the workgroup size the reduction was written for. */\nexport const ANALYSIS_DISPATCH = { workgroupSize: ANALYSIS_WORKGROUP, workgroups: 1 } as const;\n","/**\n * The renderer: device, resources, and the frame.\n *\n * Two entry points, deliberately:\n *\n * - **`drawFrame`** — draw one frame into two texture views. No scene, no\n * scheduler, no DOM. This is what the golden suite and the benchmark drive, and\n * what makes the optical maths testable without standing up the whole runtime.\n * - **`frameParticipant`** — the same work split across core's `write` and\n * `render` phases, so `vitrea`'s scheduler drives it alongside\n * platform-web's DOM participant. Pyramid rebuilds land in `write` because that\n * is the phase core hands them out in; drawing lands in `render`, with the graph\n * frozen.\n *\n * The participant reads the frame's `resolution` when core supplies one, and\n * prefers it over the group input's own `refraction`/`analysis` — core is the\n * authority on resolved state (X2), and it is the frame's resolution that has been\n * through the whole transition table. The group input's copies are the fallback for\n * `drawFrame`, where there is no core.\n *\n * ## Device generations\n *\n * Everything GPU-shaped hangs off a `GpuContext` tagged with the device generation\n * that made it. On loss the context is dropped whole, and the first frame on the\n * replacement re-points every registered provider at the new device and marks it\n * for re-import — so recovery flows through the ordinary\n * one-rebuild-per-dirty-source-per-frame path instead of a special case, which\n * means the recovery path is exercised by the same tests as the steady state.\n *\n * `ensureContext` is where that happens rather than the loss teardown, and the\n * reason is timing: the teardown runs while there is no device to adopt, and this\n * is the one place that knows both that a generation was superseded and what\n * replaced it. It also runs before anything acquires on the new device, which the\n * teardown cannot promise.\n *\n * The one provider that cannot be re-pointed is a backdrop over the *app's* own\n * texture: WebGPU has no cross-device sharing and the renderer does not own the\n * texture, so that provider refuses instead, and the refused rebuild is reported\n * through `unbuiltSources` for the host to act on.\n */\n\nimport { DEFAULT_GROUP_UNION, type GroupUnionParams } from \"@vitrea/geometry\";\n\nimport { createAdaptationState, readbackDue, type AdaptationState } from \"./analysis\";\nimport type { BackdropProvider } from \"./backdrop\";\nimport { OUTPUT_TEXTURE_FORMAT, relativeLuminance } from \"./color\";\nimport {\n createDeviceHost,\n type DeviceCapabilityInput,\n type DeviceHost,\n type DeviceOwnership,\n type RendererDeviceStatus,\n} from \"./device\";\nimport { rendererError } from \"./errors\";\nimport { createGpuContext, type GpuContext } from \"./gpu-context\";\nimport { createGovernor, type Governor } from \"./governor\";\nimport {\n clipFieldRectToCanvas,\n groupFieldRect,\n packInstances,\n resolveSurfaces,\n snapRectToDevicePixels,\n type ResolvedSurface,\n} from \"./instances\";\nimport {\n accessibilityRefractionCap,\n adaptationStrength,\n backdropToneSizeBiasUnderPolicy,\n backdropToneUnderPolicy,\n DEFAULT_MATERIAL_PROFILE,\n effectiveRefraction,\n NOMINAL_MATERIAL_POLICY,\n opticsUnderPolicy,\n outerShadowAlpha,\n outerShadowReachPx,\n outerShadowUnderPolicy,\n sizeOuterShadowOcclusionAt,\n tintToneAdaptation,\n withMaterialOverrides,\n type MaterialPolicyView,\n type MaterialProfile,\n type MaterialProfilePatch,\n type MaterialVariant,\n} from \"./material\";\nimport { createPassRunner, type DeviceRect, type PassRunner } from \"./passes\";\nimport { createPyramidStore, type PyramidStore } from \"./pyramid\";\nimport { chainLodForSigma } from \"./pyramid-plan\";\nimport type {\n FrameContextView,\n FrameParticipantView,\n GroupRenderInput,\n RebuildRequestView,\n SceneResolutionView,\n} from \"./render-model\";\nimport type { TimingCollector } from \"./timing\";\nimport { allShaderSource } from \"./wgsl\";\n\nexport const OPTICS_PASS_ID = \"vitrea.optics\";\nexport const HIGHLIGHT_PASS_ID = \"vitrea.highlight\";\nexport const FIELD_PASS_ID = \"vitrea.field\";\nexport const BACKDROP_PASS_ID = \"vitrea.backdrop\";\nexport const ANALYSIS_PASS_ID = \"vitrea.analysis\";\n\nexport const RENDERER_PASS_IDS = [\n BACKDROP_PASS_ID,\n ANALYSIS_PASS_ID,\n FIELD_PASS_ID,\n OPTICS_PASS_ID,\n HIGHLIGHT_PASS_ID,\n] as const;\n\n/*\n * `NOMINAL_MATERIAL_POLICY` now lives in `material.ts` and is re-exported here so\n * every existing importer is unaffected. It moved because `instances.ts` needs it\n * as a default — the size law folds under the policy, so surface resolution takes\n * one — and instances sits below this module in the graph, so importing it from\n * here would have closed a cycle. It was always a material constant that happened\n * to be declared beside the renderer that first used it.\n */\nexport { NOMINAL_MATERIAL_POLICY } from \"./material\";\n\nexport interface ViewportState {\n /** Viewport size in CSS px. */\n readonly widthCss: number;\n readonly heightCss: number;\n readonly devicePixelRatio: number;\n}\n\nexport interface RendererInstrumentation {\n readonly pyramid: PyramidStore[\"instrumentation\"];\n readonly texturePool: { readonly live: number; readonly created: number; readonly destroyed: number };\n readonly pipelines: { readonly renderPipelines: number; readonly computePipelines: number };\n readonly framesDrawn: number;\n readonly deviceGenerations: number;\n}\n\nexport interface DrawFrameArgs {\n readonly frame: { readonly id: number; readonly timeMs: number };\n /** The optics canvas' current texture view. */\n readonly optics: GPUTextureView;\n /** The highlight canvas' view. Omit to skip the highlight pass entirely. */\n readonly highlight?: GPUTextureView;\n readonly format?: GPUTextureFormat;\n /**\n * The rebuild requests core handed out. Omitted means \"ask every registered\n * provider whether it is dirty\", which is what `drawFrame` does standalone.\n */\n readonly rebuild?: readonly RebuildRequestView[];\n /** Core's resolved state for this frame. Overrides the group inputs' copies. */\n readonly resolution?: SceneResolutionView;\n readonly timing?: TimingCollector;\n /** Clear the targets first. Default true. */\n readonly clear?: boolean;\n}\n\nexport interface DrawFrameResult {\n readonly groupsDrawn: number;\n readonly rebuilds: number;\n readonly skipped: readonly { readonly groupId: string; readonly reason: string }[];\n /**\n * Source ids core handed out a rebuild for that this frame did **not** build.\n * The same list as `GlassRenderer.unbuiltSources` — see it for what a caller\n * owes.\n */\n readonly unbuilt: readonly string[];\n}\n\nexport interface WebGPURendererOptions {\n /** An app-owned device. Given one, the renderer never requests its own. */\n readonly device?: GPUDevice;\n readonly ownership?: DeviceOwnership;\n /** Re-request a vitrea-owned device after loss. */\n readonly reacquire?: () => Promise<GPUDevice | undefined>;\n readonly onReplacementNeeded?: () => void;\n readonly onDeviceStatusChange?: (status: RendererDeviceStatus) => void;\n /** Whether family C's f32 cross-check has passed (Decision Log #20). */\n readonly familyCVerified?: boolean;\n readonly viewport?: ViewportState;\n /**\n * Optical tunables to override, on top of `DEFAULT_MATERIAL_PROFILE`. This is\n * where a calibrated set lands (C7): a patch, not a whole profile, so a host\n * naming one tint alpha inherits every number it did not measure.\n */\n readonly materialProfile?: MaterialProfilePatch;\n}\n\nexport interface GlassRenderer {\n readonly backend: \"webgpu\";\n /** True only with a live, unlost device attached. */\n readonly ready: boolean;\n readonly passes: readonly string[];\n readonly shaderSource: string;\n readonly deviceStatus: RendererDeviceStatus;\n /** The facts a host folds into core's `PlatformProbe`. */\n readonly capabilityInput: DeviceCapabilityInput;\n readonly governor: Governor;\n readonly instrumentation: RendererInstrumentation;\n /**\n * The source ids the most recent frame was handed a rebuild for and did not\n * build — because no provider is registered under the id, or because the\n * provider could not serve a frame.\n *\n * This exists because core commits `builtEpoch` when it *hands out* the\n * request, not when the renderer finishes: a request dropped here is a claim\n * spent on nothing, and the source would sit clean at an epoch whose pixels\n * were never imported. Core has no view of this side of the wire, so the\n * renderer names the losses and the platform layer re-dirties them — one frame\n * of latency, and no new core surface.\n *\n * Accumulated across the frame's planes, not per `drawFrame` call: a host draws\n * one plane per call with the same frame id and hands the dirty set to the\n * first of them only, so a later plane's empty answer must not erase what the\n * first one found. Read after the frame's last plane, or after the\n * participant's `render` phase. Empty on every ordinary frame.\n */\n readonly unbuiltSources: readonly string[];\n\n attachDevice(device: GPUDevice, ownership?: DeviceOwnership): void;\n replaceDevice(device: GPUDevice): void;\n markWebGPUUnavailable(reason: \"no-adapter\" | \"device-request-failed\"): void;\n\n registerBackdrop(provider: BackdropProvider): void;\n unregisterBackdrop(sourceId: string): void;\n backdrop(sourceId: string): BackdropProvider | undefined;\n\n setViewport(viewport: ViewportState): void;\n readonly viewport: ViewportState;\n\n setGroup(input: GroupRenderInput): void;\n removeGroup(groupId: string): void;\n setAccessibility(policy: MaterialPolicyView): void;\n /**\n * Replace the optical tunables. The patch is applied to\n * `DEFAULT_MATERIAL_PROFILE`, never to the profile currently in force, so two\n * calls do not compound — a profile is a set of measurements, and half of one\n * measurement set over half of another describes no material.\n */\n setMaterialProfile(patch: MaterialProfilePatch): void;\n /** The tunables in force. Read-only; `setMaterialProfile` is the way in. */\n readonly materialProfile: MaterialProfile;\n\n drawFrame(args: DrawFrameArgs): DrawFrameResult;\n /** Targets for the participant path, where core drives the phases. */\n setTargets(targets: { readonly optics: GPUTextureView; readonly highlight?: GPUTextureView; readonly format?: GPUTextureFormat }): void;\n frameParticipant(): FrameParticipantView;\n\n /** Resolve any completed analysis readbacks into the adaptation drivers. */\n collectAdaptation(): Promise<number>;\n destroy(): void;\n}\n\ninterface GroupEntry {\n readonly input: GroupRenderInput;\n}\n\nexport function createWebGPURenderer(options: WebGPURendererOptions = {}): GlassRenderer {\n const providers = new Map<string, BackdropProvider>();\n const groups = new Map<string, GroupEntry>();\n const adaptation = new Map<string, AdaptationState>();\n const lastReadbackAt = new Map<string, number>();\n\n let accessibility: MaterialPolicyView = NOMINAL_MATERIAL_POLICY;\n let material: MaterialProfile = withMaterialOverrides(\n DEFAULT_MATERIAL_PROFILE,\n options.materialProfile ?? {},\n );\n let viewport: ViewportState = options.viewport ?? {\n widthCss: 0,\n heightCss: 0,\n devicePixelRatio: 1,\n };\n let context: GpuContext | undefined;\n /**\n * The last device generation a context was built for. Kept apart from\n * `context` because it has to survive `dropContext()` — the loss teardown runs\n * long before the replacement arrives, and \"which generation did the providers\n * build against\" is the question the replacement has to answer.\n */\n let builtGeneration: number | undefined;\n let store: PyramidStore | undefined;\n let runner: PassRunner | undefined;\n let framesDrawn = 0;\n let generations = 0;\n let lastFrameTimeMs: number | undefined;\n let targets:\n | { optics: GPUTextureView; highlight?: GPUTextureView; format: GPUTextureFormat }\n | undefined;\n let pendingEncoder: GPUCommandEncoder | undefined;\n let pendingRebuilds = 0;\n let pendingUnbuilt: string[] = [];\n let unbuiltFrameId: number | undefined;\n\n /**\n * Accumulate the frame's unbuilt sources, across planes.\n *\n * A host draws one plane per `drawFrame` with the same frame id and hands the\n * dirty set to the first of them only, so the later planes' empty lists must\n * not erase what the first one found. Same rule as the rebuild ledger's, for\n * the same reason: a repeated frame id is one frame.\n */\n const recordUnbuilt = (frameId: number, ids: readonly string[]): void => {\n if (unbuiltFrameId !== frameId) {\n unbuiltFrameId = frameId;\n pendingUnbuilt = [];\n }\n for (const id of ids) if (!pendingUnbuilt.includes(id)) pendingUnbuilt.push(id);\n };\n\n const governor = createGovernor({\n ...(options.familyCVerified === undefined ? {} : { familyCVerified: options.familyCVerified }),\n });\n\n const dropContext = (): void => {\n store?.destroy();\n runner?.destroy();\n context?.destroy();\n store = undefined;\n runner = undefined;\n context = undefined;\n pendingEncoder = undefined;\n };\n\n const host: DeviceHost = createDeviceHost({\n ...(options.reacquire === undefined ? {} : { reacquire: options.reacquire }),\n ...(options.onReplacementNeeded === undefined\n ? {}\n : { onReplacementNeeded: options.onReplacementNeeded }),\n onStatusChange: (status) => {\n if (status.generation !== generations) generations = status.generation;\n options.onDeviceStatusChange?.(status);\n },\n });\n\n // Loss teardown: drop every resource, and mark every backdrop for re-import so\n // recovery uses the ordinary dirty path. Registered once — the hook survives\n // every generation, because the host outlives the contexts.\n host.addTeardownHook(() => {\n dropContext();\n adaptation.clear();\n lastReadbackAt.clear();\n });\n\n const ensureContext = (): { context: GpuContext; store: PyramidStore; runner: PassRunner } => {\n const device = host.requireDevice();\n const generation = host.status.generation;\n if (context === undefined || context.generation !== generation) {\n const superseded = builtGeneration;\n dropContext();\n context = createGpuContext(device, generation);\n builtGeneration = generation;\n store = createPyramidStore(context);\n runner = createPassRunner(context);\n // The providers outlive the context, and every one of them closes over the\n // device it was built with. Re-pointing them here — rather than in the loss\n // teardown — is what makes the timing right: this is the one place that\n // knows both that a device generation was superseded and what replaced it,\n // and it runs before any provider is acquired on the new device.\n //\n // Only a real transition invalidates. A provider registered before any\n // device existed has built nothing to throw away, and one already tagged\n // with this generation was built for this device.\n if (superseded !== undefined && superseded !== generation) {\n for (const provider of providers.values()) {\n if (provider.generation !== generation) provider.invalidate(generation, device);\n }\n }\n }\n return {\n context,\n store: store as PyramidStore,\n runner: runner as PassRunner,\n };\n };\n\n const adaptationFor = (sourceId: string): AdaptationState => {\n let state = adaptation.get(sourceId);\n if (state === undefined) {\n state = createAdaptationState(undefined, material);\n adaptation.set(sourceId, state);\n }\n return state;\n };\n\n /**\n * Cover fit: the backdrop fills the viewport and the overflow is cropped\n * symmetrically. Returned as a scale/offset on viewport-normalised coordinates,\n * which is the form the optics shader applies.\n */\n const coverFit = (\n sourceWidth: number,\n sourceHeight: number,\n ): readonly [number, number, number, number] => {\n const viewportAspect =\n viewport.heightCss > 0 ? viewport.widthCss / viewport.heightCss : 1;\n const sourceAspect = sourceHeight > 0 ? sourceWidth / sourceHeight : 1;\n if (sourceAspect > viewportAspect) {\n const scaleX = viewportAspect / sourceAspect;\n return [scaleX, 1, (1 - scaleX) / 2, 0];\n }\n const scaleY = sourceAspect / viewportAspect;\n return [1, scaleY, 0, (1 - scaleY) / 2];\n };\n\n const unionOf = (input: GroupRenderInput): GroupUnionParams =>\n input.union ?? DEFAULT_GROUP_UNION;\n\n const variantOf = (input: GroupRenderInput): MaterialVariant => input.variant ?? \"regular\";\n\n /**\n * The one tint seed this group's optics pass draws with.\n *\n * A group is one pass and one uniform, so the seed is per group while the\n * strength is per pixel — enough for the composition Apple's guidance actually\n * describes (one emphasised control among plain ones) and not enough for two\n * hues in one container, which core reports as `tint-mixing`. The first tinted\n * drawn member wins, deterministically, rather than an average nobody chose.\n */\n const groupTintSeed = (input: GroupRenderInput): readonly [number, number, number] | undefined =>\n input.surfaces.find(\n (surface) => surface.fieldReferenceOnly !== true && (surface.tint?.strength ?? 0) > 0,\n )?.tint?.color;\n\n const stateOf = (\n input: GroupRenderInput,\n resolution: SceneResolutionView | undefined,\n ): { refraction: GroupRenderInput[\"refraction\"]; analysisExact: boolean } => {\n const resolved = resolution?.groups.find((group) => group.groupId === input.groupId);\n if (resolved === undefined) {\n return { refraction: input.refraction, analysisExact: input.analysisExact };\n }\n return {\n refraction: resolved.state.refraction,\n analysisExact: resolved.state.analysis === \"exact\",\n };\n };\n\n function rebuildRequests(explicit: readonly RebuildRequestView[] | undefined): readonly RebuildRequestView[] {\n if (explicit !== undefined) return explicit;\n // Standalone path: ask each provider a group actually samples.\n const sampled = new Set<string>();\n for (const entry of groups.values()) {\n const id = entry.input.backdropSourceId;\n if (id !== undefined) sampled.add(id);\n }\n const requests: RebuildRequestView[] = [];\n for (const sourceId of sampled) {\n const provider = providers.get(sourceId);\n if (provider === undefined || !provider.isDirty()) continue;\n requests.push({\n sourceId,\n // Standalone, every dirty acquire is its own epoch: there is no core\n // keeping the books, so a monotonically rising number is the honest\n // stand-in and it keeps `build`'s clean-skip from firing spuriously.\n epoch: framesDrawn + 1,\n resolution: { scale: 1, maxDimension: 2048 },\n groupIds: [...groups.values()]\n .filter((entry) => entry.input.backdropSourceId === sourceId)\n .map((entry) => entry.input.groupId),\n });\n }\n return requests;\n }\n\n function runRebuilds(\n encoder: GPUCommandEncoder,\n requests: readonly RebuildRequestView[],\n frameTimeMs: number,\n ): { built: number; unbuilt: readonly string[] } {\n const { store: pyramids } = ensureContext();\n let built = 0;\n const unbuilt: string[] = [];\n\n for (const request of requests) {\n const provider = providers.get(request.sourceId);\n if (provider === undefined) {\n // Core spent the claim on a source this renderer has never heard of — a\n // group registered ahead of its backdrop, or a source unregistered\n // between the hand-out and here.\n unbuilt.push(request.sourceId);\n continue;\n }\n\n const variant = variantOf(\n [...groups.values()].find(\n (entry) => entry.input.backdropSourceId === request.sourceId,\n )?.input ?? { groupId: \"\", surfaces: [], refraction: \"none\", analysisExact: false },\n );\n const optics = opticsUnderPolicy(material.optics[variant], accessibility, material);\n\n const outcome = pyramids.build(\n {\n sourceId: request.sourceId,\n epoch: request.epoch,\n resolution: request.resolution,\n bodySigmaCss: optics.blurSigma,\n viewportCss: [viewport.widthCss, viewport.heightCss],\n },\n provider,\n encoder,\n );\n if (outcome.status === \"built\") built += 1;\n // \"clean\" and \"duplicate\" are both honest answers — the source already has\n // the pixels this epoch asked for. \"unavailable\" is not: the claim is spent\n // and nothing was imported.\n else if (outcome.status === \"unavailable\") unbuilt.push(request.sourceId);\n }\n\n // Analysis readback, cadence-gated by the governor. Every source with a\n // pyramid is eligible, whether or not it rebuilt this frame — a static\n // backdrop still needs its stats read once.\n const cadence = governor.knobs.adaptationCadenceHz;\n for (const sourceId of providers.keys()) {\n if (pyramids.resources(sourceId) === undefined) continue;\n if (!readbackDue(lastReadbackAt.get(sourceId), frameTimeMs, cadence)) continue;\n if (pyramids.requestStats(sourceId, encoder)) lastReadbackAt.set(sourceId, frameTimeMs);\n }\n\n return { built, unbuilt };\n }\n\n function drawGroups(\n encoder: GPUCommandEncoder,\n resolution: SceneResolutionView | undefined,\n ): DrawFrameResult {\n const { store: pyramids, runner: passes } = ensureContext();\n const active = targets;\n if (active === undefined) {\n throw rendererError(\n \"pass-input\",\n \"No render targets are set. Call setTargets() (or pass views to drawFrame) before drawing.\",\n );\n }\n\n const dpr = Math.max(viewport.devicePixelRatio, 1e-3);\n const cssPerDevice = 1 / dpr;\n const viewportDevice: readonly [number, number] = [\n Math.max(1, Math.round(viewport.widthCss * dpr)),\n Math.max(1, Math.round(viewport.heightCss * dpr)),\n ];\n\n const skipped: { groupId: string; reason: string }[] = [];\n let drawn = 0;\n\n for (const entry of groups.values()) {\n const input = entry.input;\n if (input.surfaces.length === 0) continue;\n\n // The frame's resolved material policy, read before the surfaces rather\n // than after: the size law folds under it (W2), so surface resolution needs\n // it to decide how thick each member reads.\n const policy = resolution?.accessibility.material ?? accessibility;\n\n let surfaces: readonly ResolvedSurface[];\n try {\n surfaces = resolveSurfaces(input, governor.knobs.fieldFamily, material, policy);\n } catch (error) {\n skipped.push({\n groupId: input.groupId,\n reason: error instanceof Error ? error.message : String(error),\n });\n continue;\n }\n\n const union = unionOf(input);\n /*\n * Clipped to the plane canvas, and clipped once, so that three things go on\n * describing the same rectangle.\n *\n * `groupFieldRect` grows the surface union by the rim and bulge margin, so a\n * surface within a few CSS px of the viewport's top or left edge produces a\n * rect with a negative origin. `opticsPass` and `highlightPass` scissor to\n * this rect on the plane canvas and `setScissorRect` takes unsigned values,\n * so an unclipped rect is a hard `RangeError` out of the WebGPU binding\n * rather than a clipped draw. A toolbar pinned to the left edge is enough to\n * hit it.\n *\n * The clip has to reach the instance frame too. The field texture is\n * allocated at this rect's size and `fs_optics` reads it by `uv` over the\n * *viewport*, so moving the viewport without moving the texture and the\n * instance origin with it would stretch the glass instead of clipping it.\n * That is why the origin handed to `packInstances` is derived from the\n * clipped device rect rather than from the CSS rect it came from. What is\n * lost is the part of the field that lies outside the canvas, which is the\n * part nothing can see.\n *\n * A group entirely on screen is unaffected: `snapRectToDevicePixels` has\n * already put both edges on device-pixel boundaries, so the arithmetic below\n * reproduces the previous origin and extent exactly.\n */\n /*\n * The outer shadow (W8) is resolved before the rect, because it is what\n * sizes the rect: the optics pass scissors to this rectangle, so the pad has\n * to reach as far as the shadow draws or the facet is sliced off at the\n * contour. Both folds land here on the CPU — the accessibility regime and\n * the linear-to-compositing-space conversion — so the shader carries the\n * curve and not the regime, as every other axis does.\n */\n const shadow = outerShadowUnderPolicy(policy, material);\n /*\n * The pad covers the DEEPEST shadow any member of this group can emit,\n * which is not the group's base amplitude. The size law amplifies the\n * amplitude per surface and the shader reads the CASTING surface's own\n * thickness, so a rect padded from the base while a thick platter emitted\n * more would slice that surface's shadow off at the scissor — and the CSS\n * tier, having no scissor, would go on drawing it, which is a cross-tier\n * divergence rather than a cost. The gain ships at the identity, so this is\n * inert today and correct for whatever the cascade fits.\n *\n * A maximum over the members rather than the thickest member's value,\n * because a profile is entitled to a negative gain and then the THINNEST\n * surface is the one that reaches furthest.\n */\n let reachOcclusion = shadow.occlusion;\n for (const surface of surfaces) {\n reachOcclusion = Math.max(\n reachOcclusion,\n sizeOuterShadowOcclusionAt(shadow.occlusion, surface.sizeThickness, material),\n );\n }\n const shadowReachPx = outerShadowReachPx({ ...shadow, occlusion: reachOcclusion });\n\n const snapped = snapRectToDevicePixels(\n groupFieldRect(surfaces, union, undefined, shadowReachPx),\n dpr,\n );\n const rectDevice: DeviceRect | undefined = clipFieldRectToCanvas(snapped, dpr, viewportDevice);\n if (rectDevice === undefined) continue;\n\n /*\n * The surface's OWN rect — the rect every pass used before W8, and the one\n * the highlight pass still uses.\n *\n * The shadow made the field rect several times larger on a small control,\n * and the highlight draws nothing out there: `fs_highlight` returns on\n * `coverage <= 0`, so those fragments were rasterised, read twice and\n * thrown away. On the benchmark's mobile scene that was 1.0 ms of a 3.1 ms\n * frame, interleaved against the same scene with the shadow declined. The\n * optics pass cannot be scoped this way — it is what draws the shadow.\n */\n const surfaceRectDevice: DeviceRect =\n shadowReachPx === 0\n ? rectDevice\n : (clipFieldRectToCanvas(\n snapRectToDevicePixels(groupFieldRect(surfaces, union), dpr),\n dpr,\n viewportDevice,\n ) ?? rectDevice);\n\n const packed = packInstances(surfaces, [\n rectDevice.x * cssPerDevice,\n rectDevice.y * cssPerDevice,\n ]);\n const fields = passes.fieldPass(encoder, {\n groupId: input.groupId,\n family: governor.knobs.fieldFamily,\n rectDevice,\n cssPerDevice,\n coverageRampCss: cssPerDevice,\n // Ladder rungs 2 and 3 turn this down; rung 0 and 1 leave it at 1, which\n // is the extent the group's rect already had.\n renderScale: governor.knobs.refractionResolutionScale,\n instances: packed.data,\n instanceCount: packed.count,\n union,\n });\n\n const state = stateOf(input, resolution);\n const variant = variantOf(input);\n const optics = opticsUnderPolicy(material.optics[variant], policy, material);\n\n /*\n * Backdrop tone adaptation (W7). Both policy folds resolve here, on the\n * CPU, so the shaders carry the curve and not the regime — and the optics\n * and highlight passes are handed the same four numbers, because a\n * highlight that outlived the surface it belongs to is exactly what two\n * copies of one curve produce.\n *\n * The strength is zero unless the host measured a backdrop tone for this\n * group. That is not a defensive default: this axis moves the material onto\n * a colour, and the only colour it may move onto is one somebody measured.\n */\n const backdropTone: readonly [number, number, number, number] = [\n material.backdropToneLow,\n material.backdropToneHigh,\n backdropToneSizeBiasUnderPolicy(policy, material),\n input.backdropTone === undefined\n ? 0\n : backdropToneUnderPolicy(policy, material) * material.backdropToneMax,\n ];\n const backdropToneLevel =\n input.backdropTone === undefined ? 0 : relativeLuminance(input.backdropTone);\n\n // Decision Log #19's dual cap, resolved once, on the CPU.\n const refraction = effectiveRefraction(\n accessibilityRefractionCap(policy),\n state.refraction,\n );\n const refractionScale = material.refractionScale[refraction];\n\n const sourceId = input.backdropSourceId;\n const pyramid = sourceId === undefined ? undefined : pyramids.resources(sourceId);\n const adapt =\n sourceId === undefined ? undefined : adaptationFor(sourceId).values;\n\n passes.opticsPass(encoder, {\n groupId: input.groupId,\n target: active.optics,\n targetFormat: active.format,\n rectDevice,\n fields,\n viewportDevice,\n cssPerDevice,\n coverageRampCss: cssPerDevice,\n fit:\n pyramid === undefined\n ? [1, 1, 0, 0]\n : coverFit(pyramid.plan.width, pyramid.plan.height),\n refractionScale,\n bodyLodPerPx: material.lensBodyLodPerPx,\n rimLodBias: material.lensRimLodBias,\n chainMaxLod: pyramid?.plan.maxLod ?? 0,\n tint: optics.tint,\n tintAlpha: optics.tintAlpha,\n adaptTint: adapt?.tint ?? optics.tint,\n adaptStrength:\n adapt?.observed === true\n ? adaptationStrength(policy, state.analysisExact, material)\n : 0,\n /*\n * `glass: \"none\"` is forced colours, and it takes the author's tint with\n * the rest of the material.\n *\n * The pass keeps running — it is what paints the surface at all on this\n * tier — but with no backdrop and an opaque occlusion, so whatever colour\n * sits here IS the surface. An author tint arriving into that lands as a\n * flat fill of the author's colour where the platform's palette is\n * required, which is the one composition forced colours exists to\n * prevent. Falling back to the material's own tint reproduces exactly\n * what an untinted surface draws.\n */\n tintSeed: (policy.glass === \"none\" ? undefined : groupTintSeed(input)) ?? optics.tint,\n tintToneAdaptation: tintToneAdaptation(policy, material),\n tintTone: [\n material.tintToneFloor,\n material.tintToneCeilMix,\n material.tintToneLow,\n material.tintToneHigh,\n ],\n rimWidth: optics.rimWidth,\n rimAlpha: optics.rimAlpha,\n specularPower: optics.specularPower,\n specularGain: optics.specularGain,\n lightDirection: material.lightDirection,\n shadowDepth: optics.shadowDepth,\n shadowAlpha: optics.shadowAlpha,\n // The size law's gains, per group (W2); the per-pixel factor they\n // multiply rides the field pass's aux channel, so one uniform serves a\n // group whose members are not one size. `bodyChainLod` is where the body\n // blur already sits on the chain — only the pyramid that built it knows\n // the CSS-px-to-texel conversion, so it publishes the σ and this converts.\n sizeScatterGainMax: material.sizeScatterGainMax,\n sizeOcclusionGain: material.sizeOcclusionGain,\n sizeShadowGainMax: material.sizeShadowGainMax,\n bodyChainLod: chainLodForSigma(pyramid?.bodySigmaTexels ?? 0),\n backdropTone,\n backdropToneColour: [\n input.backdropTone?.[0] ?? 0,\n input.backdropTone?.[1] ?? 0,\n input.backdropTone?.[2] ?? 0,\n backdropToneLevel,\n ],\n outerShadow: [\n outerShadowAlpha(shadow.occlusion),\n shadow.sigmaPx,\n shadow.spreadPx,\n // The offset in field-texture UV. The field spans exactly this rect, so\n // one CSS px is one over the rect's CSS height however the governor\n // scaled the rasterisation.\n shadow.offsetPx / Math.max(rectDevice.height * cssPerDevice, 1e-6),\n ],\n outerShadowSizeGain: shadow.sizeGain,\n outerShadowRectCssHeight: rectDevice.height * cssPerDevice,\n backdrop:\n pyramid === undefined || policy.glass === \"none\"\n ? undefined\n : {\n chain: pyramid.chain.createView(),\n body: pyramid.body.createView(),\n },\n });\n\n if (active.highlight !== undefined) {\n // One sweep phase and one press point per group: there is one pointer, and\n // a sweep travelling the container's unioned contour is what a\n // GlassEffectContainer is for. The per-pixel glow comes off the aux target.\n const lead = surfaces.reduce(\n (best, surface) => (surface.channels.glow > best.channels.glow ? surface : best),\n surfaces[0] as ResolvedSurface,\n );\n passes.highlightPass(encoder, {\n groupId: input.groupId,\n target: active.highlight,\n targetFormat: active.format,\n // The surface's own rect, not the shadow's — see `surfaceRectDevice`.\n rectDevice: surfaceRectDevice,\n fieldRectDevice: rectDevice,\n fields,\n viewportDevice,\n cssPerDevice,\n sweep: lead.channels.sweep,\n sweepBandRadians: material.sweepBandRadians,\n // Reduced Motion removes shimmer travel outright rather than freezing it.\n sweepGain: policy.glass === \"none\" ? 0 : material.sweepGain,\n rimWidth: optics.rimWidth,\n pressPointCss: lead.channels.pressPoint ?? lead.centre,\n glowRadiusCss: material.glowRadiusCss,\n glowGain: material.glowGain,\n colour: optics.highlight,\n // The same four numbers the optics pass took, so the two passes fade\n // the surface on one curve rather than on two copies of it.\n backdropTone,\n backdropToneLevel,\n });\n }\n\n drawn += 1;\n }\n\n return { groupsDrawn: drawn, rebuilds: pendingRebuilds, skipped, unbuilt: [...pendingUnbuilt] };\n }\n\n return {\n backend: \"webgpu\",\n\n get ready() {\n return host.status.device !== undefined && host.status.deviceHealth === \"ok\";\n },\n\n passes: RENDERER_PASS_IDS,\n shaderSource: allShaderSource(),\n\n get deviceStatus() {\n return host.status;\n },\n\n get capabilityInput() {\n return host.capabilityInput;\n },\n\n governor,\n\n get unbuiltSources() {\n return pendingUnbuilt;\n },\n\n get instrumentation() {\n const pool = context?.pool.stats;\n const cache = context?.cache.stats;\n return {\n pyramid:\n store?.instrumentation ?? {\n rebuilds: 0,\n refusedDuplicates: 0,\n skippedClean: 0,\n reallocations: 0,\n rebuildsInFrame: () => 0,\n peakRebuildsPerSourcePerFrame: 0,\n },\n texturePool: {\n live: pool?.live ?? 0,\n created: pool?.created ?? 0,\n destroyed: pool?.destroyed ?? 0,\n },\n pipelines: {\n renderPipelines: cache?.renderPipelines ?? 0,\n computePipelines: cache?.computePipelines ?? 0,\n },\n framesDrawn,\n deviceGenerations: generations,\n };\n },\n\n attachDevice(device, ownership) {\n host.attach(device, ownership ?? options.ownership ?? (options.device === device ? \"app\" : \"vitrea\"));\n },\n\n replaceDevice(device) {\n host.replaceDevice(device);\n },\n\n markWebGPUUnavailable(reason) {\n host.markUnavailable(reason);\n },\n\n registerBackdrop(provider) {\n if (providers.has(provider.id)) {\n throw rendererError(\n \"source-identity\",\n `Backdrop source \"${provider.id}\" is already registered. Unregister it first, or register the replacement under a new id.`,\n provider.id,\n );\n }\n providers.set(provider.id, provider);\n },\n\n unregisterBackdrop(sourceId) {\n const provider = providers.get(sourceId);\n if (provider === undefined) return;\n provider.destroy();\n providers.delete(sourceId);\n store?.forget(sourceId);\n adaptation.delete(sourceId);\n lastReadbackAt.delete(sourceId);\n },\n\n backdrop(sourceId) {\n return providers.get(sourceId);\n },\n\n setViewport(next) {\n const changed =\n next.widthCss !== viewport.widthCss ||\n next.heightCss !== viewport.heightCss ||\n next.devicePixelRatio !== viewport.devicePixelRatio;\n viewport = next;\n if (!changed) return;\n // A resize bumps the size epoch, which is what invalidates every dependent\n // allocation (§GPU device ownership) — group field textures included, since\n // their device extent is a function of the DPR.\n //\n // The bump alone, deliberately: `pool.acquire` destroys and reallocates a\n // stale-epoch entry on next use, so every allocation is replaced exactly\n // when it is next needed. Sweeping here instead destroyed the backdrop\n // chain and body textures *immediately*, and a static source rebuilds\n // nothing — so the very next frame bound two destroyed textures and lost\n // the whole plane's encoder to a validation error. Deferring costs one\n // frame's worth of superseded textures and nothing else.\n context?.pool.bumpSizeEpoch();\n },\n\n get viewport() {\n return viewport;\n },\n\n setGroup(input) {\n groups.set(input.groupId, { input });\n },\n\n removeGroup(groupId) {\n groups.delete(groupId);\n runner?.forget(groupId);\n },\n\n setAccessibility(policy) {\n accessibility = policy;\n },\n\n setMaterialProfile(patch) {\n material = withMaterialOverrides(DEFAULT_MATERIAL_PROFILE, patch);\n // The adaptation filters carry the old profile's tint ends, so they are\n // dropped rather than left to interpolate between two materials. Everything\n // else on the draw path reads the profile per frame, so the next frame\n // redraws with the new numbers on its own.\n adaptation.clear();\n },\n\n get materialProfile() {\n return material;\n },\n\n setTargets(next) {\n targets = {\n optics: next.optics,\n ...(next.highlight === undefined ? {} : { highlight: next.highlight }),\n format: next.format ?? OUTPUT_TEXTURE_FORMAT,\n };\n },\n\n drawFrame(args) {\n const { context: gpu, store: pyramids, runner: passes } = ensureContext();\n targets = {\n optics: args.optics,\n ...(args.highlight === undefined ? {} : { highlight: args.highlight }),\n format: args.format ?? OUTPUT_TEXTURE_FORMAT,\n };\n\n pyramids.beginFrame(args.frame.id);\n pyramids.setTimeline(args.timing);\n passes.setTimeline(args.timing);\n\n const encoder = gpu.device.createCommandEncoder({\n label: `vitrea:frame:${args.frame.id}`,\n });\n\n let result: DrawFrameResult;\n try {\n const rebuilt = runRebuilds(encoder, rebuildRequests(args.rebuild), args.frame.timeMs);\n pendingRebuilds = rebuilt.built;\n recordUnbuilt(args.frame.id, rebuilt.unbuilt);\n\n if (args.clear !== false) {\n passes.clearPass(encoder, args.optics);\n if (args.highlight !== undefined) passes.clearPass(encoder, args.highlight);\n }\n\n result = drawGroups(encoder, args.resolution);\n\n args.timing?.resolve(encoder);\n gpu.device.queue.submit([encoder.finish()]);\n // Success path only: starting a readback map for a copy that never\n // reached the queue is its own bug (see `requestStats`).\n pyramids.afterSubmit();\n } finally {\n // Owed whether or not the frame reached the queue. A throw anywhere above\n // leaves an acquired video held across the frame, and the next acquire\n // then fails the frame-protocol check — self-healing, but only after a\n // wasted frame and a decoder buffer nobody released.\n pyramids.releaseAcquired();\n }\n\n // Advance the adaptation filters by the real frame delta. The drivers are\n // frame-rate invariant by construction (§Motion), so a dropped frame and two\n // short ones produce the same value.\n const delta = lastFrameTimeMs === undefined ? 0 : args.frame.timeMs - lastFrameTimeMs;\n lastFrameTimeMs = args.frame.timeMs;\n if (delta > 0) {\n for (const state of adaptation.values()) state.advance(delta);\n }\n\n framesDrawn += 1;\n pyramids.setTimeline(undefined);\n passes.setTimeline(undefined);\n return result;\n },\n\n frameParticipant() {\n return {\n id: \"vitrea.renderer-webgpu\",\n\n write: (frameContext: FrameContextView) => {\n if (host.status.device === undefined || host.status.deviceHealth !== \"ok\") return;\n const { context: gpu, store: pyramids, runner: passes } = ensureContext();\n\n pyramids.beginFrame(frameContext.frame.id);\n pyramids.setTimeline(undefined);\n passes.setTimeline(undefined);\n\n pendingEncoder = gpu.device.createCommandEncoder({\n label: `vitrea:frame:${frameContext.frame.id}`,\n });\n // Core hands out the frame's rebuilds here and only here: one pass over\n // the dirty set per frame id, which is the §Core model invariant's other\n // half. This renderer's own ledger is what proves it kept its side.\n try {\n const rebuilt = runRebuilds(\n pendingEncoder,\n frameContext.consumeDirtyBackdropSources(),\n frameContext.frame.timeMs,\n );\n pendingRebuilds = rebuilt.built;\n recordUnbuilt(frameContext.frame.id, rebuilt.unbuilt);\n } catch (error) {\n // Nothing will submit this encoder, so the releases owed for what was\n // already acquired have to happen here rather than in `render`.\n pendingEncoder = undefined;\n pyramids.releaseAcquired();\n throw error;\n }\n },\n\n render: (frameContext: FrameContextView) => {\n const encoder = pendingEncoder;\n pendingEncoder = undefined;\n if (encoder === undefined || context === undefined) return;\n const passes = runner as PassRunner;\n const pyramids = store as PyramidStore;\n\n try {\n if (targets !== undefined) {\n passes.clearPass(encoder, targets.optics);\n if (targets.highlight !== undefined) passes.clearPass(encoder, targets.highlight);\n drawGroups(encoder, frameContext.resolution);\n }\n\n context.device.queue.submit([encoder.finish()]);\n pyramids.afterSubmit();\n } finally {\n pyramids.releaseAcquired();\n }\n\n const delta =\n lastFrameTimeMs === undefined ? 0 : frameContext.frame.timeMs - lastFrameTimeMs;\n lastFrameTimeMs = frameContext.frame.timeMs;\n if (delta > 0) {\n for (const state of adaptation.values()) state.advance(delta);\n }\n framesDrawn += 1;\n },\n };\n },\n\n async collectAdaptation() {\n if (store === undefined) return 0;\n const stats = await store.collectStats();\n for (const [sourceId, value] of stats) {\n const state = adaptationFor(sourceId);\n // The first observation jumps rather than filters: a 500 ms low-pass\n // starting from zero would fade the material in from black over half a\n // second on every page load.\n if (state.values.observed) state.observe(value);\n else state.reset(value);\n }\n return stats.size;\n },\n\n destroy() {\n for (const provider of providers.values()) provider.destroy();\n providers.clear();\n groups.clear();\n adaptation.clear();\n lastReadbackAt.clear();\n pendingUnbuilt = [];\n unbuiltFrameId = undefined;\n builtGeneration = undefined;\n dropContext();\n host.destroy();\n },\n };\n}\n"]}
|