@vitreajs/vitrea 0.2.0 → 0.4.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/dist/index.d.ts CHANGED
@@ -997,7 +997,7 @@ interface ZSlot {
997
997
  readonly order: number;
998
998
  }
999
999
  /** Viewport-space rectangle in CSS px, measured by platform-web and handed in as data. */
1000
- interface Rect {
1000
+ interface Rect$1 {
1001
1001
  readonly x: number;
1002
1002
  readonly y: number;
1003
1003
  readonly width: number;
@@ -1006,9 +1006,9 @@ interface Rect {
1006
1006
  /** Back-to-front ordering: every base node before every overlay node, then by `order`. */
1007
1007
  declare function compareZSlot(a: ZSlot, b: ZSlot): number;
1008
1008
  /** Smallest rect containing both. */
1009
- declare function unionRect(a: Rect, b: Rect): Rect;
1009
+ declare function unionRect(a: Rect$1, b: Rect$1): Rect$1;
1010
1010
  /** Grow a rect outwards on every side — how a group's proxy gets its padding. */
1011
- declare function inflateRect(rect: Rect, by: number): Rect;
1011
+ declare function inflateRect(rect: Rect$1, by: number): Rect$1;
1012
1012
  /**
1013
1013
  * The part of `rect` that survives every clip in the chain.
1014
1014
  *
@@ -1031,13 +1031,13 @@ declare function inflateRect(rect: Rect, by: number): Rect;
1031
1031
  * — an overlap check that over-reports warns about something real-ish, one that
1032
1032
  * under-reports misses a genuine double-filter.
1033
1033
  */
1034
- declare function clipRect(rect: Rect, clip: readonly Rect[] | undefined): Rect;
1034
+ declare function clipRect(rect: Rect$1, clip: readonly Rect$1[] | undefined): Rect$1;
1035
1035
  /**
1036
1036
  * Positive-area intersection. Touching edges are not an overlap — adjacent
1037
1037
  * surfaces in a toolbar are the common case and are legal. A degenerate rect
1038
1038
  * (an unmeasured or collapsed host) overlaps nothing.
1039
1039
  */
1040
- declare function rectsOverlap(a: Rect, b: Rect): boolean;
1040
+ declare function rectsOverlap(a: Rect$1, b: Rect$1): boolean;
1041
1041
 
1042
1042
  /**
1043
1043
  * The scene model (§Core model): the three registries and everything that
@@ -1236,9 +1236,9 @@ interface GlassNodeDescriptor {
1236
1236
  interface GlassNodeRecord {
1237
1237
  readonly descriptor: GlassNodeDescriptor;
1238
1238
  /** Measured by platform-web in the read phase; absent until then. */
1239
- readonly bounds?: Rect;
1239
+ readonly bounds?: Rect$1;
1240
1240
  /** Ancestor clip chain, viewport space. */
1241
- readonly clip?: readonly Rect[];
1241
+ readonly clip?: readonly Rect$1[];
1242
1242
  }
1243
1243
  /** One pyramid rebuild. `groupIds` is why there is one request and not one per group. */
1244
1244
  interface BackdropRebuildRequest {
@@ -1335,7 +1335,7 @@ interface GlassScene {
1335
1335
  glassNode(id: string): GlassNodeRecord | undefined;
1336
1336
  nodesOfGroup(groupId: string): readonly GlassNodeRecord[];
1337
1337
  /** Measured viewport geometry, from the read phase. */
1338
- setNodeBounds(id: string, bounds: Rect, clip?: readonly Rect[]): void;
1338
+ setNodeBounds(id: string, bounds: Rect$1, clip?: readonly Rect$1[]): void;
1339
1339
  /**
1340
1340
  * Scene-wide by default; per group when `groupId` is given.
1341
1341
  *
@@ -1638,6 +1638,33 @@ interface MaterialRim {
1638
1638
  * occlusion over 142,550 pixels on the finest cell, and the same three lengths
1639
1639
  * describe every profile, backdrop, span and scale in the bed.
1640
1640
  *
1641
+ * ## Two terms on ONE falloff (W14 G0, claims §5.62)
1642
+ *
1643
+ * The description above holds where W8 measured it and misses two things the bed
1644
+ * has since shown, both of which live in the AMPLITUDE and neither of which
1645
+ * moves a length. Outside the coverage, in the compositing (encoded) domain:
1646
+ *
1647
+ * out = bg · (1 − α_b(backdrop, span) · F(d)) + A_v(span) · F(d) · V
1648
+ *
1649
+ * with **one** falloff `F` — W8's own, at 15.55 / 7.95 / 3.1, re-read free and
1650
+ * unmoved on both terms (σ 14.8–16.2 and offset 7.93–8.00 for the black term,
1651
+ * σ 14.1–17.1 and offset 7.6–8.4 for the lift) — and `V` the backdrop's own
1652
+ * light blurred at `liftBlurSigmaCss`.
1653
+ *
1654
+ * The first term's amplitude ADAPTS below the knee: the reference's fill alpha
1655
+ * is 0.33 over the mid backdrops, 0.127 over `light-solid` and nothing over
1656
+ * black, keyed on the SAME backdrop luminance statistic W9's face response uses
1657
+ * (the ENCODED-space mean, decoded — `backdropToneAnchorX`'s own axis), through
1658
+ * the same thickness curve that gates that regime. Above the knee it is the
1659
+ * composite's transmission by span. The second term is the lift, GPU-tier only,
1660
+ * and it is exactly zero below the knee and exactly zero over black, so the
1661
+ * facet's "invisible over a black backdrop" property survives both terms.
1662
+ *
1663
+ * The layer tree's `inputShadowAmount` and `inputShadowHeight` are NOT either
1664
+ * term's spatial extent — the charter's advisory was wrong there, and G0's free
1665
+ * fits overturned it. Only `inputShadowBlurRadius` 40 belongs to the lift, as
1666
+ * the blur of the backdrop it copies.
1667
+ *
1641
1668
  * **Multiplicative, and not additively.** Mirrored pixel pairs either side of a
1642
1669
  * capsule over the `photo` backdrop see the same shadow over different backdrop
1643
1670
  * luminances: the darkening's ratio tracks the backdrop's ratio to 4.5% while a
@@ -1666,22 +1693,151 @@ interface MaterialOuterShadow {
1666
1693
  /** Outward spread of the silhouette before the blur, CSS px. */
1667
1694
  readonly spreadPx: number;
1668
1695
  /**
1669
- * Peak occlusion: the fraction of the backdrop's own LINEAR light removed deep
1670
- * inside the shadow. Zero stands the whole facet down, pad and all.
1696
+ * The black term's peak occlusion below the knee, over a backdrop the material
1697
+ * cannot see (linear luminance ≤ `OUTER_SHADOW_THIN_L.inert`): zero. Inert
1698
+ * over `dark-solid` and `impulse`, which is what the reference does — it
1699
+ * removes at most one or two of 255 codes there (claims §5.62 §5).
1700
+ */
1701
+ readonly thinOcclusionDark: number;
1702
+ /**
1703
+ * The black term's peak occlusion below the knee over the MID plateau —
1704
+ * backdrop linear luminance `OUTER_SHADOW_THIN_L.midFrom` … `midTo`.
1705
+ *
1706
+ * MEASURED (claims §5.62 §5): linear occlusion 0.347 over `mid-dark-solid`,
1707
+ * 0.334–0.339 over `photo`, 0.327–0.328 over the checkerboard and 0.329 over
1708
+ * `hc-text` — flat across a backdrop luminance range of 0.06…0.74, and a
1709
+ * constant 1.16–1.19× the fill alpha §5.50 §2 read off the layer tree.
1710
+ */
1711
+ readonly thinOcclusionMid: number;
1712
+ /**
1713
+ * The black term's peak occlusion below the knee over a BRIGHT backdrop, at
1714
+ * `OUTER_SHADOW_THIN_L.bright` and above.
1715
+ *
1716
+ * MEASURED (claims §5.62 §5): 0.127 over `light-solid` (linear luminance
1717
+ * 0.891), against the layer tree's tabulated 0.05 — so the reference's shadow
1718
+ * there is 0.39 of its shadow over the checkerboard, not one sixth. W8's
1719
+ * single 0.285 everywhere is 2.24× this, which is the whole of the user's
1720
+ * by-eye "the shadow is darker on the light-solid capsule" and, by the free
1721
+ * geometry fit on that cell (σ 14.81 / offset 7.97 / spread 3.17), no part of
1722
+ * it is shape.
1671
1723
  */
1672
- readonly occlusion: number;
1724
+ readonly thinOcclusionBright: number;
1673
1725
  /**
1674
- * What reduced transparency does to `occlusion` — MEASURED, not assumed, which
1675
- * is what the charter asked for before the fold was written.
1726
+ * The COMPOSITE occlusion above the knee at a casting span of 96 CSS px.
1727
+ *
1728
+ * FITTED in the renderer (claims §5.65), from G0's measurement of the
1729
+ * composite's transmission (0.379 on the checkerboard at span 96) to **0.370**.
1730
+ * It had to be fitted rather than adopted, because what G0 could identify at
1731
+ * the bed's noise floor is the composite transmission and the lift's peak
1732
+ * amplitude, not the split into (black alpha, vibrant alpha, vibrant colour):
1733
+ * both terms ride one falloff and their shapes correlate at 0.9998. So this
1734
+ * constant is the BLACK term of a two-term composite whose second term
1735
+ * (`liftAmplitude`) was fitted beside it, on X7's affine pair, and the pair is
1736
+ * what the referee reads.
1737
+ */
1738
+ readonly thickOcclusionAt96: number;
1739
+ /** The same at a casting span of 128 CSS px — FITTED to 0.448 from G0's
1740
+ * measured 0.497, for `thickOcclusionAt96`'s reason (claims §5.65). */
1741
+ readonly thickOcclusionAt128: number;
1742
+ /**
1743
+ * The same at a casting span of 160 CSS px — **UNFITTED**, and the one anchor
1744
+ * in this block that no calibration cell reaches.
1745
+ *
1746
+ * Every span above 128 in the bed is holdout, so 0.479 is carried by the stated
1747
+ * derivation from the two fitted anchors and not by a fit. The holdout, read
1748
+ * once and fitted to nothing, says it is 15% heavy (band `1 − a` 0.2436 against
1749
+ * the reference's 0.2117) and implies about 0.437 — which is BELOW the fitted
1750
+ * At128 and which no extrapolation from the calibration cells would have
1751
+ * produced. That reading is recorded and deliberately not adopted (claims §5.65
1752
+ * §4(b) and §6(iv)); closing it needs a calibration cell above span 128.
1753
+ */
1754
+ readonly thickOcclusionAt160: number;
1755
+ /**
1756
+ * **The lift (W14)** — the peak amplitude of the second term, in LINEAR light,
1757
+ * as a fraction of the backdrop's own blurred luminance. GPU tier only.
1758
+ *
1759
+ * The reference's thick shadow does not only remove light: on the
1760
+ * checkerboard's black squares, where a multiply is inert by construction, it
1761
+ * ADDS 7.4 of 255 (claims §5.62 §2). Pooled over six backdrops the addition
1762
+ * regresses on the σ-40 blurred backdrop at slope 0.0444 with intercept
1763
+ * −0.0042 and R² 0.983 — it is the backdrop's own light, blurred, composited
1764
+ * under the shadow, with no fixed colour left over. Zero over `impulse`, zero
1765
+ * over `dark-solid`, and zero below the knee, so the facet stays exactly inert
1766
+ * over black the way W8's multiply is.
1767
+ *
1768
+ * FITTED to **0.0100** in the renderer over seventeen sweep passes, read on
1769
+ * X7's affine pair together with the three thick anchors (claims §5.65). The
1770
+ * provisional 0.0073 was G0's +0.0038 of LINEAR lift at span 160 divided by
1771
+ * the ≈ 0.52 linear luminance the checkerboard's σ-40 blur sits at, and the fit
1772
+ * is 37% larger. The space matters and this wave names it everywhere (claims
1773
+ * §5.62 §3): §5.60's +0.039 is the same lift read in ENCODED luma.
1774
+ */
1775
+ readonly liftAmplitude: number;
1776
+ /**
1777
+ * Where the lift starts, in casting span, CSS px — the thin/thick knee, and it
1778
+ * is exact: the lift reads 0.0000 at spans 32 and 44 and is present at 96
1779
+ * (claims §5.62 §2). The layer tree's own `VibrancyContribution` clamps from
1780
+ * the same 64.
1781
+ */
1782
+ readonly liftSpanMin: number;
1783
+ /**
1784
+ * Where the lift saturates, in casting span, CSS px.
1785
+ *
1786
+ * FITTED to **118** (claims §5.65), from a provisional 128. The measured rise
1787
+ * is 0.52 / 0.96 / 1.00 of the span-160 value at spans 96 / 128 / 160, against
1788
+ * the layer tree's clamp((span − 64)/96) = 0.33 / 0.67 / 1.00 — so the lift is
1789
+ * NOT proportional to `VibrancyContribution`; it rises and saturates, reaching
1790
+ * 96% by span 128 (claims §5.62 §2), which a smoothstep from `liftSpanMin`
1791
+ * reproduces and the clamp does not. The holdout says the reach saturates a
1792
+ * little early — the lift's own residual there is one-signed and small, 5% low
1793
+ * at span 130 and 9% at 160 (claims §5.65 §4(d)) — and it was not refitted
1794
+ * after that reading.
1795
+ */
1796
+ readonly liftSpanFull: number;
1797
+ /**
1798
+ * The σ, in CSS px, of the blur the lift copies the backdrop through.
1676
1799
  *
1677
- * The reference's shadow under `reduce transparency` is the same shadow at
1678
- * 0.566 of the amplitude: 0.1830/0.3259, 0.1884/0.3309 and 0.1882/0.3314 on the
1679
- * three structured backdrops at a 44 px span, with σ, offset and spread
1680
- * unmoved. It does not vanish and it does not intensify.
1800
+ * MEASURED at 40 ± 8 CSS px on `rrect-lg` at both scales and in two rings, by
1801
+ * the probes' pitch axis — the pooled residual has a real minimum there, 12%
1802
+ * below the flat-copy residual (claims §5.62 §3). It is the layer tree's
1803
+ * `inputShadowBlurRadius` 40 read as a Gaussian standard deviation. NOT
1804
+ * identifiable on the mid spans (flat to 0.7%), and reported as such rather
1805
+ * than fitted there.
1806
+ */
1807
+ readonly liftBlurSigmaCss: number;
1808
+ /**
1809
+ * The shadow's amplitude UNDER reduced transparency — one absolute linear
1810
+ * occlusion that replaces both regimes, not a factor on either. MEASURED,
1811
+ * which is what the charter asked for before the fold was written.
1812
+ *
1813
+ * **0.197 (measured 0.192–0.202).** W14 G0 read the preference on the wider
1814
+ * bed and what it found is a flat number: the reference's exterior is
1815
+ * 0.192–0.202 under increased contrast and reduced transparency alike, **thin
1816
+ * and thick together** and over every backdrop it can be read on (claims §5.62
1817
+ * §5). The preference removes the material's adaptation, so the shadow it
1818
+ * leaves has neither the thin regime's backdrop keying nor the thick regime's
1819
+ * span law in it — one amplitude for every surface over every backdrop, which
1820
+ * is what `outerShadowUnderPolicy` writes into all six anchors. The lift goes
1821
+ * with it: a composite whose two regimes read the same number has no second
1822
+ * term left in it.
1823
+ *
1824
+ * It is stated as an ABSOLUTE occlusion rather than as a ratio because W8's
1825
+ * 0.70 multiplier was fitted when the amplitude was one span-flat number and a
1826
+ * ratio was the same thing as a level. It is not any more: multiplying six
1827
+ * unequal anchors keeps exactly the backdrop and span variation the preference
1828
+ * removes, and a span-160 surface over a mid-tone backdrop folded to 0.38
1829
+ * against the reference's 0.20. The number the reference states is a level, so
1830
+ * this constant is a level.
1831
+ *
1832
+ * Nothing is special-cased for a dark backdrop and nothing needs to be: an
1833
+ * occlusion is a fraction of the backdrop's own light, so a flat 0.197 over
1834
+ * black still removes nothing, and the facet stays as inert there as the thin
1835
+ * regime's own zero anchor makes it without the preference.
1681
1836
  *
1682
1837
  * The `increased contrast` reference reproduces the reduced-transparency
1683
- * amplitude to four decimals (0.1830, 0.1884, 0.1882 — the same numbers), which
1684
- * is Decision Log 8's finding again: macOS force-couples the two toggles, so the
1838
+ * amplitude to four decimals (0.1830, 0.1884, 0.1882 on the three structured
1839
+ * backdrops at a 44 px span, with σ, offset and spread unmoved), which is
1840
+ * Decision Log 8's finding again: macOS force-couples the two toggles, so the
1685
1841
  * contrast reference IS the reduced-transparency state and the bed cannot
1686
1842
  * separate them. The fold therefore keys on `frost`, the axis reduced
1687
1843
  * transparency alone sets, rather than on the contrast axes it would be
@@ -1747,11 +1903,13 @@ interface MaterialProfile {
1747
1903
  * substantial material. It casts deeper, richer shadows, has more pronounced
1748
1904
  * lensing and refraction effects, and a softer scattering of light" (S219). One
1749
1905
  * mechanism means one curve: `sizeThickness(span)` is a smoothstep from
1750
- * `sizeSpanMin` to `sizeSpanMax`, and **every** thickness-derived facet is a
1751
- * gain on it — the lens (`lensSizeGainMax`), the scattering
1752
- * (`sizeScatterGainMax`), the occlusion (`sizeOcclusionGain`) and the inner
1753
- * shadow (`sizeShadowGainMax`). Two curves would be two mechanisms, and the
1754
- * reference only has one.
1906
+ * `sizeSpanMin` to `sizeSpanMax`, and the thickness-derived facets are gains
1907
+ * on it — the lens (`lensSizeGainMax`), the occlusion (`sizeOcclusionGain`)
1908
+ * and the inner shadow (`sizeShadowGainMax`). The scattering was one of them
1909
+ * until W11c measured its curve to be a different one (a floor at small
1910
+ * spans, a rise past 96) and W13 measured that curve to be the projection of a
1911
+ * ramp in depth — see `sizeScatterFloor` and `sizeScatterRampStartThin1x`; the
1912
+ * scattering now rides its own law entirely, and this band is untouched by it.
1755
1913
  *
1756
1914
  * A smoothstep rather than a straight ratio, so two surfaces of nearly the same
1757
1915
  * size never read as differently thick, and so every gain saturates instead of
@@ -1769,12 +1927,17 @@ interface MaterialProfile {
1769
1927
  readonly sizeSpanMin: number;
1770
1928
  readonly sizeSpanMax: number;
1771
1929
  /**
1772
- * The lens's gain on the size curve — "more pronounced lensing and refraction".
1930
+ * The inner shadow's depth gain on the size curve — and, until W12 G2, the
1931
+ * lens's too.
1773
1932
  *
1774
- * `lensDepthPx` is `thickness × lensSizeGain(span)`, clamped to the shorter
1775
- * *half* extent. The clamp is what keeps a small control from being all lens: a
1776
- * 24 px-tall button cannot bend more than 12 px of backdrop however thick it is
1777
- * authored.
1933
+ * The inner shadow's depth is `thickness × (1 + (lensSizeGainMax − 1) ×
1934
+ * sizeThickness)`, clamped to the shorter *half* extent, and its profile is
1935
+ * `(1 − depth)²` on that depth: the landed law of W2, kept byte-for-byte for the
1936
+ * occlusion because nothing measured it as wrong. The LENS no longer reads it —
1937
+ * the reference's own lens height is a clamped linear function of the span
1938
+ * (`lensHeightPerSpan`, `lensHeightMax`), read straight from its layer tree
1939
+ * (claims §5.50), and the lens takes that law from W12 G2 on. The name stays so
1940
+ * the profile documents keep naming the constant they measured.
1778
1941
  */
1779
1942
  readonly lensSizeGainMax: number;
1780
1943
  /**
@@ -1796,8 +1959,213 @@ interface MaterialProfile {
1796
1959
  * Both tiers carry it, from one function (`sizeScatterSigma`): the CSS tier
1797
1960
  * multiplies its `blur()` σ, and the GPU tier lerps its body sample toward the
1798
1961
  * chain level whose blur is that σ.
1962
+ *
1963
+ * MEASURED (W11c G1, claims §5.41), and no longer a gain on `sizeThickness`
1964
+ * alone — see `sizeScatterFloor` and `sizeScatterRampStartThin1x` below for the
1965
+ * law it rides. 8: the heavy component of the reference's interior sits near
1966
+ * σ 10 device px against a body σ of 1.25, and the gain sweep has a clear
1967
+ * minimum at 8 (RMS 0.0164 against 0.0180 at 6 and 0.0191 at 10 on the probe
1968
+ * bed).
1799
1969
  */
1800
1970
  readonly sizeScatterGainMax: number;
1971
+ /**
1972
+ * **The scattering facet's frost** (W11c G1, claims §5.41; re-read by W13 G1).
1973
+ *
1974
+ * The reference's interior over structured content is two components, read
1975
+ * off the W9 probe bed across four checkerboard pitches and five spans: a
1976
+ * sharp one near σ 1.25 device px and a heavy one near σ 10, mixed by a share
1977
+ * that is already ≈ 0.4 at spans of 32–44 and still rising at 160. W11c
1978
+ * carried that mix as one number per span, a floor rising by a smoothstep to
1979
+ * a band top (`sizeScatterSpanMax`); W13 G0 measured the mix **per depth** on
1980
+ * both probes and found a ramp under the contour that the span law had been
1981
+ * summarising (claims §5.61 §2). W13 G1's first form replaced the span law
1982
+ * with the ramp outright and its runtime sweep refuted that: the ramp's own
1983
+ * projection onto one number per surface runs 0.43–0.56 where the span law it
1984
+ * replaced runs 0.41–1.00, so a ramp with a start and a reach is nearly
1985
+ * span-flat where the bed is strongly span-graded, and no point in 81 reached
1986
+ * the wave's stops (`results/2026-09-03-w13-ramp/g1/sweep/g1-sweep.md` §4,
1987
+ * §7). So the two are kept **together**: the span law is the ramp's DEEP
1988
+ * value and the ramp is a near-contour excursion above it. This floor is
1989
+ * unchanged in value and in meaning under either: the mix a surface carries
1990
+ * at any size, the material's own frost.
1991
+ *
1992
+ * It keeps its fold semantics, and they are now written on the ramp rather
1993
+ * than on a span curve:
1994
+ *
1995
+ * ```
1996
+ * kScatter(u) = floor + (k(u) − floor) · fold
1997
+ * ```
1998
+ *
1999
+ * — so at fold 1 the ramp is rendered exactly and at fold 0 the material sits
2000
+ * at this floor exactly, which is what the landed law did at fold 0 too. The
2001
+ * floor is the frost the material has whatever its size, and is **not**
2002
+ * folded under an accessibility preference; the excursion away from it is
2003
+ * depth, and is. Fitted with `rrect-lg` held out (W11c G1): 0.40 (0.0175 at
2004
+ * 0.3, 0.0174 at 0.45).
2005
+ */
2006
+ readonly sizeScatterFloor: number;
2007
+ /**
2008
+ * **The scattering facet's span curve** (W11c G1, claims §5.41) — the top of
2009
+ * the band the frost rises to, and, since W13 G1's re-forming, the span law
2010
+ * that supplies the depth ramp's DEEP value:
2011
+ *
2012
+ * ```
2013
+ * kDeep(span) = floor + (1 − floor) · smoothstep(sizeSpanMin, sizeScatterSpanMax, span)
2014
+ * ```
2015
+ *
2016
+ * — byte for byte the curve W11c fitted and W13 G1's first form retired. It
2017
+ * came back because the sweep measured what retiring it cost (§4 of
2018
+ * `results/2026-09-03-w13-ramp/g1/sweep/g1-sweep.md`): the span dependence of
2019
+ * the bed is real and strong, and the ramp's four constants cannot carry it
2020
+ * at the same time as the band's near-contour excursion. What the ramp adds
2021
+ * is what this curve never could — the depth structure inside one surface —
2022
+ * and it now adds it on top of this rather than instead of it, so the deep
2023
+ * interior of every span is exactly where W11c and W12 put it.
2024
+ *
2025
+ * `sizeThickness` — zero at `sizeSpanMin` and saturated at `sizeSpanMax` = 96
2026
+ * — can express neither the floor nor a band top past 96, and moving
2027
+ * `sizeSpanMax` would move the lens, the occlusion, the inner shadow and W9's
2028
+ * thin/thick response rows with it, which is why the scatter mix has its own
2029
+ * curve at all. Fitted with `rrect-lg` held out (W11c G1): band top 256
2030
+ * (0.0182 at 224, 0.0174 at 320); the held-out cell's residual 0.0366 →
2031
+ * 0.0174.
2032
+ */
2033
+ readonly sizeScatterSpanMax: number;
2034
+ /**
2035
+ * **The body's depth ramp** (W13 G1, from the measurement of claims §5.61 §2
2036
+ * and the re-forming its runtime sweep forced) — a near-contour excursion on
2037
+ * the sharp component's share, riding on top of the span law
2038
+ * `sizeScatterSpanMax` supplies rather than replacing it.
2039
+ *
2040
+ * ```
2041
+ * kDeep(span) = sizeScatterFloor + (1 − sizeScatterFloor)
2042
+ * · smoothstep(sizeSpanMin, sizeScatterSpanMax, span)
2043
+ * sDeep(span) = 1 − kDeep(span)
2044
+ * s₀(span) = startThin + (startThick − startThin) · sizeThickness(span)
2045
+ * s(u, span) = sDeep + max(0, s₀(span) − sDeep) · max(0, 1 − u / U(dpr))
2046
+ * k(u, span) = 1 − s(u, span)
2047
+ * ```
2048
+ *
2049
+ * with `u` the pixel's depth under the contour and `U` the reach, both in
2050
+ * DEVICE px. `s₀` is the sharp share **at the contour** and `U` is where the
2051
+ * excursion vanishes into the deep value — not where a line from the start
2052
+ * would hit zero, which is what the first form's reach meant. Deep inside any
2053
+ * surface the body is exactly the W11c/W12 material; within `U` of the
2054
+ * contour the sharp component is lifted toward `s₀`, which is the band the
2055
+ * reference has and the uniform share does not.
2056
+ *
2057
+ * **Why the start grades with the span, in the third form.** The second form
2058
+ * gave the excursion one start per scale and its runtime sweep refuted that
2059
+ * too, arithmetically rather than for want of a better point (claims §5.64
2060
+ * §2): `rrect-sm`'s span is exactly `sizeSpanMin`, so its deep sharp share is
2061
+ * exactly `1 − sizeScatterFloor` = 0.600 and no start at or below 0.600 can
2062
+ * touch it, while `rrect-ml`'s band only improves below a start near 0.583.
2063
+ * The window where both hold is empty, and the reach cannot open it — the
2064
+ * reach decides how much of a surface the excursion covers, never which
2065
+ * surfaces it touches, because `max(0, s₀ − sDeep(span))` has no reach in it.
2066
+ * G0 read the reference's start as strongly graded by span (0.637 / 0.642 on
2067
+ * the thin cells against 0.512 / 0.501 / 0.410 on the thick ones at 1x), so
2068
+ * the start is given exactly that grading — across `sizeThickness`, the
2069
+ * material's OWN thin/thick curve with its knee at 64, the one the face's
2070
+ * tone response and the outer shadow already blend across. Reusing it is the
2071
+ * point: it introduces no new span statistic, and `sizeSpanMax` stays where
2072
+ * every other facet reads it.
2073
+ *
2074
+ * **Why this form and not the ramp alone.** W13 G0 measured a ramp with a
2075
+ * free start, reach and floor (H2) and the first implementation took the free
2076
+ * start and reach with a floor of zero, retiring the span law. Its runtime
2077
+ * sweep — 81 points, both scales, the real renderer — could not reach the
2078
+ * wave's stops at any point, and named the mechanism: the ramp's projection
2079
+ * onto one number per surface runs 0.43–0.56 at 1x where the retired span law
2080
+ * ran 0.41–1.00, so the family is nearly span-flat and the bed is strongly
2081
+ * span-graded; small spans want a high start and large spans a low one and no
2082
+ * pair can be both (`.../g1/sweep/g1-sweep.md` §4). §7 of the same report
2083
+ * asked for exactly this: "the ramp's DEEP value wants to be the span-graded
2084
+ * heavy share the retired law supplied, and its near-contour excursion the
2085
+ * sharp term the band asks for." The floor H2 left free is therefore not one
2086
+ * more constant but the span law itself, which is already fitted.
2087
+ *
2088
+ * The reach stays a LENGTH in device pixels, which is the reading that did
2089
+ * survive the sweep: the free fits' reaches in absolute depth spread by 1.3×
2090
+ * across the spans (108 / 115 / 144 CSS px at 1x on `rrect-lg` / `-ml` /
2091
+ * `-md`) where the reaches as a fraction of the half-span spread by 2.2×, and
2092
+ * between the two scales that length roughly halves in CSS px — one length in
2093
+ * device pixels, the same reading as the widths (§5.55 §1, §5.56 §1).
2094
+ *
2095
+ * The start and the reach are anchored at the two scales the reference was
2096
+ * measured at rather than given a scale term: `…1x` is the value at dpr 1,
2097
+ * `…2x` at dpr 2, the pair interpolated linearly in dpr and held constant
2098
+ * outside [1, 2] (`scatterRampStart`, `scatterRampReachDevicePx`).
2099
+ *
2100
+ * **The FOURTH form: the start keeps falling past the thickness knee (W13
2101
+ * Decision Log 6; claims §5.67 §4, §6).** The third form's holdout failed on
2102
+ * one row for the form's own arithmetic: `sizeThickness` saturates at
2103
+ * `sizeSpanMax` 96, so spans 96, 128, 130 and 160 all received the identical
2104
+ * thick start while G0 read the reference's start FALLING across exactly
2105
+ * those spans (0.512 → 0.501 → 0.410), and because the deep value keeps
2106
+ * falling to `sizeScatterSpanMax` the excursion GREW with span (0.039 →
2107
+ * 0.156 → 0.284) where the reference's shrinks — `rrect-lg` overshot its
2108
+ * interior by 33%. So the start gets a slow decline along the scatter
2109
+ * facet's own curve above the knee, `startFar` being its value at span ≥
2110
+ * `sizeScatterSpanMax`:
2111
+ *
2112
+ * s₀(span) = thin + (thick − thin) · sizeThickness(span)
2113
+ * + (far − thick) · smoothstep(sizeSpanMax, sizeScatterSpanMax, span)
2114
+ *
2115
+ * Two curves the material already has, one more constant per scale, and no
2116
+ * new span statistic. At 2x `far` sits below the thick anchor, so the null
2117
+ * the third form verified bit-exactly (§5.67 §2) holds by construction: an
2118
+ * excursion that was zero at every span stays zero when its start falls
2119
+ * further.
2120
+ *
2121
+ * PROVISIONAL, all eight. The runtime sweep at this form sets them, because
2122
+ * the paper model over-credited the mip chain's heavy tap once already
2123
+ * (§5.58 §1) and no constant lands on a paper prediction again. What they
2124
+ * carry now:
2125
+ *
2126
+ * **1x — thin 0.64, thick 0.52, reach 120 device px.** G0's own start
2127
+ * readings are 0.637 on `rrect-sm` and 0.642 on the capsule at the thin end
2128
+ * and 0.512 / 0.501 / 0.410 on `rrect-md` / `-ml` / `-lg` at the thick end.
2129
+ * A thick anchor fitted to all three thick cells jointly comes out near 0.47,
2130
+ * and 0.47 sits 0.011 *below* `rrect-md`'s own deep sharp share of 0.481,
2131
+ * which would clamp the excursion to zero on that one cell. 0.52 is above it
2132
+ * and is also G0's reading on that cell, so the fit is not traded against the
2133
+ * form's own arithmetic.
2134
+ *
2135
+ * **2x — thin 0.46, thick 0.17, reach 100 device px, and the excursion clamps
2136
+ * to zero on every cell of the calibration bed.** These are G0's 2x readings
2137
+ * (0.483 / 0.437 on the thin cells, 0.192 / 0.179 / 0.141 on the thick ones),
2138
+ * and every one of them sits BELOW its cell's deep sharp share: the implied
2139
+ * excursions run −0.095 to −0.289 (claims §5.64 §4). `max(0, s₀ − sDeep)` is
2140
+ * therefore zero everywhere on this bed at dpr 2. That is not a special case
2141
+ * and not a disabled facet — it is the law evaluating to no excursion where
2142
+ * the reference's own contour share is heavier than vitrea's deep value. It
2143
+ * follows that **the 2x gap is a deep-value gap and not a ramp gap**: the
2144
+ * span law's floor, knee and top are what miss at that scale, and no
2145
+ * one-signed excursion above them can express it. That fit is W13's Deferred
2146
+ * charter and not this constant's business.
2147
+ *
2148
+ * **far — 0.20 at 1x (FITTED on the W14 bed), 0.15 at 2x.** The fourth
2149
+ * sweep (`results/2026-09-03-w13-ramp/g1/sweep-4/`) swept far over eight
2150
+ * points from 0.52 (the third form) down to 0.15: S1 and S4 pass at every
2151
+ * one, only `rrect-ml`'s rows move and they improve monotonically as far
2152
+ * falls, and the band is flat within the bed's noise below 0.30. The cell
2153
+ * the constant exists for is holdout, so the tie inside the noise is broken
2154
+ * by the reference's own reading — G0's `rrect-lg` start of 0.410 at span 160
2155
+ * is far = 0.207 through this form — and 0.20 is the measured grid point that
2156
+ * carries it. The confirmation read `rrect-lg` at `ssimMean` +0.0056 against
2157
+ * the W14 bed (the third form: −0.0026) with its interior 12% over the
2158
+ * reference (from 33% over). At 2x far is below the thick anchor so that the
2159
+ * null holds — re-verified bit-exact under this form.
2160
+ */
2161
+ readonly sizeScatterRampStartThin1x: number;
2162
+ readonly sizeScatterRampStartThick1x: number;
2163
+ readonly sizeScatterRampStartFar1x: number;
2164
+ readonly sizeScatterRampStartThin2x: number;
2165
+ readonly sizeScatterRampStartThick2x: number;
2166
+ readonly sizeScatterRampStartFar2x: number;
2167
+ readonly sizeScatterRampReach1xPx: number;
2168
+ readonly sizeScatterRampReach2xPx: number;
1801
2169
  /**
1802
2170
  * The occlusion gain — "a larger size is more opaque. A smaller size is
1803
2171
  * clearer" (S284). The fraction of the *remaining* transparency the size law
@@ -1828,9 +2196,64 @@ interface MaterialProfile {
1828
2196
  * an outer `box-shadow` the reference does not cast at all (Decision Log #32(c)).
1829
2197
  */
1830
2198
  readonly sizeShadowGainMax: number;
1831
- /** Chain LOD per CSS px of lens depth, and how much sharper the rim samples. */
1832
- readonly lensBodyLodPerPx: number;
1833
- readonly lensRimLodBias: number;
2199
+ /**
2200
+ * The lens (W12 G2, claims §5.51) — one steep power on the reference's own
2201
+ * span law, along a direction the reference ovalizes.
2202
+ *
2203
+ * The reference's `glassBackground` filter takes an inner refraction *amount*
2204
+ * and *height* that are clamped linear functions of the shape's shorter side
2205
+ * (claims §5.50: amount −min(0.8·span, 60), height min(0.25·span, 20)). What
2206
+ * those two numbers do spatially is not in the tree; measured as a field on
2207
+ * the captures (§5.49) and ranked on the pixels (§5.51), the band is
2208
+ *
2209
+ * D(u) = S · max(0, 1 − u / L′)^p, S = lensRefractionGain · A(span),
2210
+ * L′ = lensExtentGain · lensDepth,
2211
+ *
2212
+ * with `lensDepth = (thickness / lensThicknessReference) × H(span)` the
2213
+ * reference's height law scaled by the author's thickness (8 is the default
2214
+ * and the reference's unit — at 8 the depth IS Apple's height, 8 / 11 / 20 on
2215
+ * spans 32 / 44 / ≥ 80), `A(span)` the amount law scaled the same way, and
2216
+ * `p = lensProfileExponent`. Apple's own two-term profile at its literal
2217
+ * amounts was ranked too and lost on the pixels and the holdout; its span law
2218
+ * is adopted, its shape is not (§5.51 §2).
2219
+ *
2220
+ * `lensRefractionGain` is therefore re-based: it was 1.6 lens depths on the
2221
+ * W11c square profile (S = 1.6 × 20.8 = 33.3 at saturation), it is now the
2222
+ * scale on the reference's amount (S = 0.745 × 60 = 44.7), fitted on
2223
+ * `rrect-md` + `-ml` at 1x with `rrect-lg` held out.
2224
+ */
2225
+ readonly lensRefractionGain: number;
2226
+ /** The reference's inner refraction height law: `min(lensHeightPerSpan · span, lensHeightMax)`. */
2227
+ readonly lensHeightPerSpan: number;
2228
+ readonly lensHeightMax: number;
2229
+ /** The reference's inner refraction amount law: `min(lensAmountPerSpan · span, lensAmountMax)`. */
2230
+ readonly lensAmountPerSpan: number;
2231
+ readonly lensAmountMax: number;
2232
+ /**
2233
+ * The author `thickness` at which the lens depth equals the reference's own
2234
+ * height — the host's default, and what the bed was captured at. A thicker
2235
+ * authoring scales the depth and the magnitude together.
2236
+ */
2237
+ readonly lensThicknessReference: number;
2238
+ /** The profile's extent over the lens depth: D reaches zero at `lensExtentGain × lensDepth`. */
2239
+ readonly lensExtentGain: number;
2240
+ /** The profile's exponent — the square of W11c became a steeper power (§5.49 §2). */
2241
+ readonly lensProfileExponent: number;
2242
+ /**
2243
+ * The direction's ovalization (§5.49 §3, §5.50): the reference's SDF element
2244
+ * carries `gradientOvalization`, and the band is magnified *along* the edge by
2245
+ * up to 1.31× as a result. The shader displaces along the gradient of the
2246
+ * blended field `(1 − ω)·d_rrect + ω·d_oval`, `d_oval` the signed distance of
2247
+ * the ellipse inscribed in the surface's box, with the magnitude fixed. The
2248
+ * reference's value is 0.5 on thick shapes and 0 on thin ones; 0.6 is what the
2249
+ * pixels want on the box-inscribed ellipse (Apple's oval is more curved at the
2250
+ * edge midpoint than that ellipse). The switch is a step in the reference
2251
+ * between spans 64 and 72; here it is a smoothstep over that band, the same at
2252
+ * both ends and continuous through a morph.
2253
+ */
2254
+ readonly lensOvalization: number;
2255
+ readonly lensOvalizationSpanMin: number;
2256
+ readonly lensOvalizationSpanMax: number;
1834
2257
  /**
1835
2258
  * What each accessibility regime does to the numbers above. The multipliers
1836
2259
  * match `platform-web`'s CSS tier so the two renderers degrade the same way
@@ -1859,28 +2282,39 @@ interface MaterialProfile {
1859
2282
  readonly strongBorderRim: MaterialRim;
1860
2283
  readonly reducedTintAdaptation: number;
1861
2284
  /**
1862
- * The author tint's tone map — Apple's "range of tones **mapped to content
1863
- * brightness underneath**" (S219), as four numbers.
2285
+ * The author tint's shade law (W10) — Apple's "range of tones **mapped to
2286
+ * content brightness underneath**" (S219), measured per pixel on the frozen
2287
+ * bed and the W9 probe (claims §5.36).
1864
2288
  *
1865
- * The seed the author gives is not the colour the material paints. It is the
1866
- * middle of a range: over a dark backdrop the material shows a shade of the
1867
- * seed (`tintToneFloor`, a multiple of it in linear light, so hue and
1868
- * chromaticity survive); over a bright one it shows the seed washed toward
1869
- * white (`tintToneCeilMix`), which is what Apple's "changing its hue,
1870
- * brightness and saturation… without deviating too much from the intended
1871
- * color" describes. `tintToneLow`/`tintToneHigh` are the backdrop luminances
1872
- * the two ends are reached at, crossed with a smoothstep for the same reason
1873
- * `lensSpanMin`/`lensSpanMax` are.
2289
+ * The tinted material is an OPAQUE, hue-preserving shade of the seed: the seed
2290
+ * times a scalar, and the scalar is linear in the luminance the untinted
2291
+ * material shows at the same pixel — `mix(tintShadeDark, tintShadeLight, u)`,
2292
+ * clamped so a shade is never brighter than the seed. Over black content the
2293
+ * reference shows about half the seed's light; over white it shows the seed
2294
+ * itself; over a checkerboard it shows both, cell by cell, with the seed's
2295
+ * chromaticity intact to three decimals at every pitch measured. That layer
2296
+ * composites over the material at the AUTHOR's opacity (the colour's alpha) in
2297
+ * the encoded space — the half-strength cell is the 0.501 encoded-space mix
2298
+ * of its untinted and full-tinted twins, per channel — so the material's own
2299
+ * alpha is not what a tinted surface shows.
1874
2300
  *
1875
- * **Advisory and calibration-delegated**, like every other number in this
1876
- * profile: they are chosen so a tinted surface reads as coloured glass rather
1877
- * than as paint, and the tinted-capture extension fits them. Nothing here is
1878
- * measured yet, and no claim rests on these values.
2301
+ * `tintShadeStrength` is the law's provenance gate: 1 where the constants were
2302
+ * measured (the light scheme), 0 where they were not — the dark scheme
2303
+ * renders the pure seed over every backdrop it was measured on, which is
2304
+ * consistent with "a shade relative to the material's own body level" but is
2305
+ * not yet separable from "no shading in the dark scheme". The collapse (W7)
2306
+ * folds the shade out the same way, because a collapsed material IS a dark
2307
+ * body and the reference renders the pure seed there too.
2308
+ *
2309
+ * MEASURED, both scales, twelve light-standard cells across three pitches:
2310
+ * fitted on the five probe cells only (17 700 px, RMS 0.0035) and refereed by
2311
+ * every canonical tinted row. Mirrored by `@vitreajs/vitrea-web`'s
2312
+ * `TINT_SHADE`, pinned in both directions by
2313
+ * `packages/calibration/test/tier-coherence.test.ts`.
1879
2314
  */
1880
- readonly tintToneFloor: number;
1881
- readonly tintToneCeilMix: number;
1882
- readonly tintToneLow: number;
1883
- readonly tintToneHigh: number;
2315
+ readonly tintShadeDark: number;
2316
+ readonly tintShadeLight: number;
2317
+ readonly tintShadeStrength: number;
1884
2318
  /**
1885
2319
  * **Backdrop tone adaptation (W7)** — the axis Apple's material has and this
1886
2320
  * one did not: over a dark enough backdrop the material stops being a lighter
@@ -1918,6 +2352,58 @@ interface MaterialProfile {
1918
2352
  readonly backdropToneLow: number;
1919
2353
  readonly backdropToneHigh: number;
1920
2354
  readonly backdropToneSizeBias: number;
2355
+ /**
2356
+ * **The backdrop tone response (W9)** — the law that owns the interior MEAN,
2357
+ * where the four constants above own texture collapse and nothing else.
2358
+ *
2359
+ * The W9 probe falsified the mix-toward-backdrop form outright (claims
2360
+ * §5.33): six cells need mix strengths outside [0, 1], because the
2361
+ * reference adapts toward the material's own light/dark appearance, which
2362
+ * coincides with the backdrop's tone only over `dark-solid` — the one
2363
+ * background the mix was fitted on. What the probe measured instead is a
2364
+ * LAW: at equal encoded-space backdrop mean the reference's settled
2365
+ * interior is the same number regardless of the backdrop's structure
2366
+ * (checker vs text rows, 0.81 both at input 0.69), so the interior level is
2367
+ * a function `R(encodedMean, thickness)` and these constants are that
2368
+ * function's anchors.
2369
+ *
2370
+ * `backdropToneAnchorX` is the three solid anchors' encoded-space means —
2371
+ * measured backdrop luminances, not tuned. `backdropToneResponseThin` and
2372
+ * `...Thick` are the reference's settled interior levels at those anchors
2373
+ * for a thin surface (`sizeThickness` 0, the 32 px rrect) and a thick one
2374
+ * (saturated, the 96 px+ rrects pooled — their residual spread ±0.012 is
2375
+ * the accepted cost of `sizeSpanMax` saturation, claims §5.33). Between
2376
+ * the rows: smoothstep in thickness; between the anchors: monotone
2377
+ * (Fritsch–Carlson) interpolation in the ENCODED input, the space the
2378
+ * probe validated to RMS 0.034 with zero fitting.
2379
+ *
2380
+ * Below the dark anchor the surface has no data (the probe's grid floor
2381
+ * is `dark-solid`), and the one validation cell down there —
2382
+ * `impulse__rrect-md`, backdrop 0.0039, reference 0.4358 — reads DARKER
2383
+ * than the dark anchor's thick row, so clamping would regress it. The
2384
+ * solve's authority fades to zero from the dark anchor downward
2385
+ * (smoothstep over the anchor's own lower half, no new constant); the
2386
+ * extreme-dark region stays with the collapse constants that were fitted
2387
+ * on it.
2388
+ */
2389
+ readonly backdropToneAnchorX: readonly [number, number, number];
2390
+ readonly backdropToneResponseThin: readonly [number, number, number];
2391
+ readonly backdropToneResponseThick: readonly [number, number, number];
2392
+ /**
2393
+ * How much authority the response law has in THIS profile, 0…1 (W9).
2394
+ *
2395
+ * The anchors above are measurements of the LIGHT reference's settled
2396
+ * appearance. The dark scheme's material settles at its own levels over the
2397
+ * same backdrops (0.809 light against 0.055 dark over one checkerboard,
2398
+ * §5.8), so a dark profile running the light response surface brightens the
2399
+ * dark material toward the wrong scheme's appearance — measured on the
2400
+ * canonical dark bed as ΔE p95 0.08 → 0.58 before this constant existed.
2401
+ * The dark profiles set it to 0: the collapse (whose target is the
2402
+ * backdrop, not a scheme's appearance) still runs there, and a dark
2403
+ * response surface is follow-up work that needs the dark reference probed,
2404
+ * not an assumption.
2405
+ */
2406
+ readonly backdropToneResponseStrength: number;
1921
2407
  /** The outer shadow (W8) — see `MaterialOuterShadow`. */
1922
2408
  readonly outerShadow: MaterialOuterShadow;
1923
2409
  /**
@@ -1950,22 +2436,44 @@ interface MaterialProfilePatch {
1950
2436
  readonly sizeSpanMax?: number;
1951
2437
  readonly lensSizeGainMax?: number;
1952
2438
  readonly sizeScatterGainMax?: number;
2439
+ readonly sizeScatterFloor?: number;
2440
+ readonly sizeScatterSpanMax?: number;
2441
+ readonly sizeScatterRampStartThin1x?: number;
2442
+ readonly sizeScatterRampStartThick1x?: number;
2443
+ readonly sizeScatterRampStartFar1x?: number;
2444
+ readonly sizeScatterRampStartThin2x?: number;
2445
+ readonly sizeScatterRampStartThick2x?: number;
2446
+ readonly sizeScatterRampStartFar2x?: number;
2447
+ readonly sizeScatterRampReach1xPx?: number;
2448
+ readonly sizeScatterRampReach2xPx?: number;
1953
2449
  readonly sizeOcclusionGain?: number;
1954
2450
  readonly sizeShadowGainMax?: number;
1955
- readonly lensBodyLodPerPx?: number;
1956
- readonly lensRimLodBias?: number;
2451
+ readonly lensRefractionGain?: number;
2452
+ readonly lensHeightPerSpan?: number;
2453
+ readonly lensHeightMax?: number;
2454
+ readonly lensAmountPerSpan?: number;
2455
+ readonly lensAmountMax?: number;
2456
+ readonly lensThicknessReference?: number;
2457
+ readonly lensExtentGain?: number;
2458
+ readonly lensProfileExponent?: number;
2459
+ readonly lensOvalization?: number;
2460
+ readonly lensOvalizationSpanMin?: number;
2461
+ readonly lensOvalizationSpanMax?: number;
1957
2462
  readonly reducedTransparencyFrost?: number;
1958
2463
  readonly increasedOcclusionLift?: number;
1959
2464
  readonly strongBorderRim?: Readonly<Partial<MaterialRim>>;
1960
2465
  readonly reducedTintAdaptation?: number;
1961
- readonly tintToneFloor?: number;
1962
- readonly tintToneCeilMix?: number;
1963
- readonly tintToneLow?: number;
1964
- readonly tintToneHigh?: number;
2466
+ readonly tintShadeDark?: number;
2467
+ readonly tintShadeLight?: number;
2468
+ readonly tintShadeStrength?: number;
1965
2469
  readonly backdropToneMax?: number;
1966
2470
  readonly backdropToneLow?: number;
1967
2471
  readonly backdropToneHigh?: number;
1968
2472
  readonly backdropToneSizeBias?: number;
2473
+ readonly backdropToneAnchorX?: readonly [number, number, number];
2474
+ readonly backdropToneResponseThin?: readonly [number, number, number];
2475
+ readonly backdropToneResponseThick?: readonly [number, number, number];
2476
+ readonly backdropToneResponseStrength?: number;
1969
2477
  readonly outerShadow?: Readonly<Partial<MaterialOuterShadow>>;
1970
2478
  readonly lightDirection?: readonly [number, number];
1971
2479
  readonly sweepBandRadians?: number;
@@ -2189,137 +2697,6 @@ interface VideoProviderOptions {
2189
2697
  readonly generation?: number;
2190
2698
  }
2191
2699
 
2192
- /**
2193
- * Device ownership, loss teardown, and rebuild (§GPU device ownership).
2194
- *
2195
- * `platform-web` owns the *browser* half of the story — is there an adapter, get
2196
- * a device, notice when it goes away. This module owns the *resource* half: what
2197
- * has to be thrown away when a device dies, when it is safe to build again, and
2198
- * what core's capability inputs should read while that is in flight.
2199
- *
2200
- * ## The two ownership modes, and why they are not symmetric
2201
- *
2202
- * - **vitrea-owned** — this module can re-request a device by itself, so loss is
2203
- * a transient it recovers from: tear down, re-request, re-attach, rebuild.
2204
- * Every backdrop source is re-imported on the next frame because loss marks
2205
- * them all dirty, which routes recovery through the same
2206
- * one-rebuild-per-dirty-source-per-frame path a content change takes rather
2207
- * than through a special case.
2208
- * - **app-owned** — the app owns the resources that would have to be
2209
- * re-registered, so this module reports the loss, raises
2210
- * `replacementPending`, and **waits**. Groups stay demoted until
2211
- * `replaceDevice` arrives and the re-registration handshake completes. Inventing
2212
- * a device the app did not give us would break the one guarantee app-ownership
2213
- * exists for: that every texture the renderer samples came from the app's own
2214
- * device, because WebGPU has no cross-device sharing.
2215
- *
2216
- * `info.reason === "destroyed"` is our own teardown and is not recovered from —
2217
- * re-requesting there would resurrect a renderer the host just destroyed.
2218
- *
2219
- * ## Generations
2220
- *
2221
- * Every attach bumps a generation counter, and every GPU object this package
2222
- * holds is tagged with the generation it was made under. A resource from a lost
2223
- * device is unusable forever, and the failure mode is silent — bindings simply
2224
- * produce nothing — so "is this from the current device" has to be a cheap
2225
- * integer comparison somewhere. It is here.
2226
- */
2227
- /**
2228
- * Structurally identical to `vitrea`'s `WebGPUAvailability` (X2's K1
2229
- * amendment, Decision Log #21c). Declared here rather than imported because this
2230
- * package sits *below* core in the dependency graph — core reaches the renderer
2231
- * through a dynamic import, so an import back would close a cycle. A test pins
2232
- * the two unions to the same members.
2233
- */
2234
- type WebGPUAvailability = "not-requested" | "unavailable" | "available";
2235
- type DeviceOwnership = "vitrea" | "app";
2236
- interface RendererDeviceStatus {
2237
- /** Feeds core's `PlatformProbe.webgpu` unchanged. */
2238
- readonly webgpu: WebGPUAvailability;
2239
- readonly deviceHealth: "ok" | "lost";
2240
- readonly ownership: DeviceOwnership;
2241
- readonly device: GPUDevice | undefined;
2242
- /** Bumped on every attach. Tags every resource built under it. */
2243
- readonly generation: number;
2244
- /** True while an app-owned device is lost and no replacement has arrived. */
2245
- readonly replacementPending: boolean;
2246
- /** Why there is no device, when there is a reason worth reporting. */
2247
- readonly unavailableReason?: "no-adapter" | "device-request-failed" | "lost";
2248
- }
2249
- /** The capability facts a host folds into core's `PlatformProbe`. */
2250
- interface DeviceCapabilityInput {
2251
- readonly webgpu: WebGPUAvailability;
2252
- readonly deviceHealth: "ok" | "lost";
2253
- }
2254
-
2255
- /**
2256
- * The governor's knobs.
2257
- *
2258
- * §Performance envelope: "The governor degrades **within** a tier first
2259
- * (refraction resolution, adaptation cadence, edge analysis) and switches tiers
2260
- * only with long hysteresis and cooldown." Decision Log #19 adds that intra-tier
2261
- * degradation is **not a state change** — a group under `degrade-in-tier`
2262
- * pressure keeps `activeRenderer: "webgpu"` and its whole resolved state.
2263
- *
2264
- * So the split is: **the policy lives in core, the knobs live here.** This module
2265
- * exposes what can be turned and publishes a suggested ladder as *data*; it never
2266
- * decides to turn anything, never reads a clock, and never applies hysteresis.
2267
- * A governor that lived in the renderer would be a governor that could not see
2268
- * the scene it is governing.
2269
- *
2270
- * ## The three knobs, weakest cost first
2271
- *
2272
- * 1. **`fieldFamily`** — `rsupn` → `rsup`. S2 priced this at 29% of the field's
2273
- * cost for a bound that degrades from 0.170 px / 2.91° to 0.574 px / 4.26°.
2274
- * It is the *first* step because it is one uniform and one pipeline: no
2275
- * resolution change, so nothing resamples and nothing shimmers as it engages.
2276
- * **Conditional on the f32 cross-check** (Decision Log #20) — and the check
2277
- * has now been run, so the condition is met. See `FAMILY_C_CROSS_CHECK`.
2278
- * 2. **`refractionResolutionScale`** — the group's **field** targets are
2279
- * rasterised at a fraction of device resolution, and the optics and highlight
2280
- * passes filter them instead of indexing them (`passes.ts`, and the
2281
- * `fieldUpsampled` flag both shaders branch on). Quadratic saving on the pass
2282
- * that evaluates the pseudo-SDF union per pixel per member, and the most
2283
- * visible step, so it comes second.
2284
- *
2285
- * What it does **not** yet do is shrink the optics and highlight passes
2286
- * themselves: those still render at full device resolution into the plane
2287
- * canvases, because rendering them smaller means an offscreen target and a
2288
- * resolve pass rather than a change of extent. So rungs 2 and 3 deliver the
2289
- * field's quadratic saving and the cadence saving, not the full quadratic
2290
- * saving on both heavy passes. Recorded here rather than implied, because a
2291
- * ladder whose rungs are priced for savings they do not deliver is a ladder
2292
- * core's policy will walk too far down.
2293
- * 3. **`adaptationCadenceHz`** — how often analysis is reduced and read back.
2294
- * Cheapest of the three in visual terms because the values it feeds are
2295
- * already low-passed over hundreds of milliseconds; dropping the cadence
2296
- * mostly changes how quickly a scroll's new backdrop is noticed.
2297
- */
2298
- type FieldFamily = "rsupn" | "rsup";
2299
- interface GovernorKnobs {
2300
- /** Which pseudo-SDF family the field pass compiles. */
2301
- readonly fieldFamily: FieldFamily;
2302
- /**
2303
- * Device-resolution fraction the group's field targets are rasterised at,
2304
- * 0 < s <= 1. The optics and highlight passes upsample what they read. See the
2305
- * module note for what this does and does not save.
2306
- */
2307
- readonly refractionResolutionScale: number;
2308
- /** Analysis reduction + readback rate. 0 disables adaptation entirely. */
2309
- readonly adaptationCadenceHz: number;
2310
- }
2311
- interface Governor {
2312
- readonly knobs: GovernorKnobs;
2313
- /** True when `fieldFamily: "rsup"` is permitted to engage. */
2314
- readonly familyCVerified: boolean;
2315
- set(patch: Partial<GovernorKnobs>): GovernorKnobs;
2316
- /** Move to a rung of the suggested ladder. Out-of-range clamps to the ends. */
2317
- setLevel(level: number): GovernorKnobs;
2318
- reset(): GovernorKnobs;
2319
- /** Record that the cross-check passed, unlocking family C. */
2320
- recordFamilyCVerified(): void;
2321
- }
2322
-
2323
2700
  /**
2324
2701
  * What the renderer consumes each frame, and why it is declared here rather than
2325
2702
  * imported from `vitrea`.
@@ -2351,6 +2728,13 @@ interface Governor {
2351
2728
  * none in core.
2352
2729
  */
2353
2730
 
2731
+ /** Viewport-space rectangle in CSS px. Matches core's `Rect`. */
2732
+ interface Rect {
2733
+ readonly x: number;
2734
+ readonly y: number;
2735
+ readonly width: number;
2736
+ readonly height: number;
2737
+ }
2354
2738
  /** Motion-driver outputs for one surface. Every one is a value, never a time. */
2355
2739
  interface SurfaceChannels {
2356
2740
  /** `pressCompression`, 0..1. Scaled by motion's `pressCompressionScale`. */
@@ -2440,6 +2824,45 @@ interface GroupRenderInput {
2440
2824
  * back to a level nobody measured.
2441
2825
  */
2442
2826
  readonly backdropTone?: Rgb;
2827
+ /**
2828
+ * The backdrop's ENCODED-space tone level (W9, claims §5.31–§5.34): the mean
2829
+ * taken in sRGB-encoded space, decoded once — the input the reference's tone
2830
+ * response tracks, feeding the collapse band's argument and the response
2831
+ * curve. Distinct from `backdropTone` on any structured backdrop: the
2832
+ * COLOUR is the physical linear mean (what the collapse converges onto —
2833
+ * on the impulse grid the two differ 2.6×, and converging onto the encoded
2834
+ * reading was a measured ΔE p95 0.03 → 0.12 regression), while the LEVEL is
2835
+ * the encoded reading. Absent falls back to `backdropTone`'s own luminance.
2836
+ */
2837
+ readonly backdropToneLevel?: number;
2838
+ /**
2839
+ * The backdrop's LINEAR-space mean luminance, beside `backdropToneLevel`'s
2840
+ * encoded-space reading (W9, claims §5.31). The per-pixel tint-tone input
2841
+ * samples a chain that averages linearly, so the optics pass multiplies it by
2842
+ * `backdropToneLevel / backdropToneLinearLuminance` — locality is
2843
+ * preserved and the input's spatial mean matches the model exactly. Absent
2844
+ * (or equal to the tone's level) collapses the ratio to 1.
2845
+ */
2846
+ readonly backdropToneLinearLuminance?: number;
2847
+ /**
2848
+ * The material's tint and alpha for a group that samples NOTHING (W11a) — a
2849
+ * `css-backdrop` group whose blurred backdrop is a DOM proxy beneath the
2850
+ * canvas, or a `none` group over the page itself. Such a group's body is
2851
+ * not composited in the shader: the optics pass writes the material as a
2852
+ * premultiplied layer and the browser composites it over the DOM, in
2853
+ * encoded sRGB. A linear-light alpha written into that composite lands the
2854
+ * surface darker than the same material sampled on the GPU — the gap
2855
+ * `cssTintAlpha` closes for the CSS tier, at a declared reference level —
2856
+ * so the host, which owns that mapping, resolves the pair once and hands
2857
+ * the same numbers to both tiers. Linear light; the renderer folds the
2858
+ * accessibility policy over it exactly as over the profile's own. Ignored
2859
+ * wherever the group samples a backdrop; absent, the profile's pair is
2860
+ * written as it is (the golden harness, which has no host).
2861
+ */
2862
+ readonly unsampledMaterial?: {
2863
+ readonly tint: Rgb;
2864
+ readonly tintAlpha: number;
2865
+ };
2443
2866
  readonly variant?: MaterialVariant;
2444
2867
  /** Overrides the calibration-delegated union defaults. */
2445
2868
  readonly union?: GroupUnionParams;
@@ -2488,6 +2911,173 @@ interface FrameParticipantView {
2488
2911
  readonly render?: (context: FrameContextView) => void;
2489
2912
  }
2490
2913
 
2914
+ /**
2915
+ * Where a backdrop texture sits on the plane, and what that makes of a CSS px.
2916
+ *
2917
+ * The optics pass samples the backdrop through one uv transform on
2918
+ * viewport-normalised coordinates — `uv = viewport01 · scale + offset` — and
2919
+ * the pyramid converts the material's CSS-px σ into source texels once, at build.
2920
+ * Both numbers are functions of the same thing: the rectangle of the viewport the
2921
+ * texture's pixels actually occupy. This module is the one place that rectangle
2922
+ * turns into either.
2923
+ *
2924
+ * ## Placed
2925
+ *
2926
+ * A texture handed over from a DOM element — an `<img>`, a `<canvas>`, a
2927
+ * `<video>` — has a box the host measures every read phase, in CSS px relative
2928
+ * to the viewport, and that box IS the placement: a 320 px raster in the corner
2929
+ * of a 1440 px page maps the 320 px, not the page. The source's own extent is
2930
+ * still what the pyramid is built from; the placement only says where on the
2931
+ * plane its texels land, so one texel is `placement.width / sourceWidth` CSS px.
2932
+ *
2933
+ * Outside the placement the sampler clamps to the edge. A surface hanging past
2934
+ * the texture's box reads the nearest edge texel rather than nothing; the
2935
+ * unsampled layer (W11a) is not applied to partial overlap in this cut.
2936
+ *
2937
+ * ## Cover
2938
+ *
2939
+ * A source with no placement — an `ImageBitmap`, an `OffscreenCanvas`, an
2940
+ * element not in the document, or a renderer driven without a host at all —
2941
+ * keeps the original rule: the backdrop fills the viewport and the overflow is
2942
+ * cropped symmetrically. Every golden and every calibration capture was taken
2943
+ * with the texture the size of the stage, where the two rules coincide exactly;
2944
+ * the demo's reference panel is where they came apart (claims §5.47).
2945
+ */
2946
+
2947
+ /** A backdrop source's box on the plane, in CSS px relative to the viewport. */
2948
+ type BackdropPlacement = Rect;
2949
+
2950
+ /**
2951
+ * Device ownership, loss teardown, and rebuild (§GPU device ownership).
2952
+ *
2953
+ * `platform-web` owns the *browser* half of the story — is there an adapter, get
2954
+ * a device, notice when it goes away. This module owns the *resource* half: what
2955
+ * has to be thrown away when a device dies, when it is safe to build again, and
2956
+ * what core's capability inputs should read while that is in flight.
2957
+ *
2958
+ * ## The two ownership modes, and why they are not symmetric
2959
+ *
2960
+ * - **vitrea-owned** — this module can re-request a device by itself, so loss is
2961
+ * a transient it recovers from: tear down, re-request, re-attach, rebuild.
2962
+ * Every backdrop source is re-imported on the next frame because loss marks
2963
+ * them all dirty, which routes recovery through the same
2964
+ * one-rebuild-per-dirty-source-per-frame path a content change takes rather
2965
+ * than through a special case.
2966
+ * - **app-owned** — the app owns the resources that would have to be
2967
+ * re-registered, so this module reports the loss, raises
2968
+ * `replacementPending`, and **waits**. Groups stay demoted until
2969
+ * `replaceDevice` arrives and the re-registration handshake completes. Inventing
2970
+ * a device the app did not give us would break the one guarantee app-ownership
2971
+ * exists for: that every texture the renderer samples came from the app's own
2972
+ * device, because WebGPU has no cross-device sharing.
2973
+ *
2974
+ * `info.reason === "destroyed"` is our own teardown and is not recovered from —
2975
+ * re-requesting there would resurrect a renderer the host just destroyed.
2976
+ *
2977
+ * ## Generations
2978
+ *
2979
+ * Every attach bumps a generation counter, and every GPU object this package
2980
+ * holds is tagged with the generation it was made under. A resource from a lost
2981
+ * device is unusable forever, and the failure mode is silent — bindings simply
2982
+ * produce nothing — so "is this from the current device" has to be a cheap
2983
+ * integer comparison somewhere. It is here.
2984
+ */
2985
+ /**
2986
+ * Structurally identical to `vitrea`'s `WebGPUAvailability` (X2's K1
2987
+ * amendment, Decision Log #21c). Declared here rather than imported because this
2988
+ * package sits *below* core in the dependency graph — core reaches the renderer
2989
+ * through a dynamic import, so an import back would close a cycle. A test pins
2990
+ * the two unions to the same members.
2991
+ */
2992
+ type WebGPUAvailability = "not-requested" | "unavailable" | "available";
2993
+ type DeviceOwnership = "vitrea" | "app";
2994
+ interface RendererDeviceStatus {
2995
+ /** Feeds core's `PlatformProbe.webgpu` unchanged. */
2996
+ readonly webgpu: WebGPUAvailability;
2997
+ readonly deviceHealth: "ok" | "lost";
2998
+ readonly ownership: DeviceOwnership;
2999
+ readonly device: GPUDevice | undefined;
3000
+ /** Bumped on every attach. Tags every resource built under it. */
3001
+ readonly generation: number;
3002
+ /** True while an app-owned device is lost and no replacement has arrived. */
3003
+ readonly replacementPending: boolean;
3004
+ /** Why there is no device, when there is a reason worth reporting. */
3005
+ readonly unavailableReason?: "no-adapter" | "device-request-failed" | "lost";
3006
+ }
3007
+ /** The capability facts a host folds into core's `PlatformProbe`. */
3008
+ interface DeviceCapabilityInput {
3009
+ readonly webgpu: WebGPUAvailability;
3010
+ readonly deviceHealth: "ok" | "lost";
3011
+ }
3012
+
3013
+ /**
3014
+ * The governor's knobs.
3015
+ *
3016
+ * §Performance envelope: "The governor degrades **within** a tier first
3017
+ * (refraction resolution, adaptation cadence, edge analysis) and switches tiers
3018
+ * only with long hysteresis and cooldown." Decision Log #19 adds that intra-tier
3019
+ * degradation is **not a state change** — a group under `degrade-in-tier`
3020
+ * pressure keeps `activeRenderer: "webgpu"` and its whole resolved state.
3021
+ *
3022
+ * So the split is: **the policy lives in core, the knobs live here.** This module
3023
+ * exposes what can be turned and publishes a suggested ladder as *data*; it never
3024
+ * decides to turn anything, never reads a clock, and never applies hysteresis.
3025
+ * A governor that lived in the renderer would be a governor that could not see
3026
+ * the scene it is governing.
3027
+ *
3028
+ * ## The three knobs, weakest cost first
3029
+ *
3030
+ * 1. **`fieldFamily`** — `rsupn` → `rsup`. S2 priced this at 29% of the field's
3031
+ * cost for a bound that degrades from 0.170 px / 2.91° to 0.574 px / 4.26°.
3032
+ * It is the *first* step because it is one uniform and one pipeline: no
3033
+ * resolution change, so nothing resamples and nothing shimmers as it engages.
3034
+ * **Conditional on the f32 cross-check** (Decision Log #20) — and the check
3035
+ * has now been run, so the condition is met. See `FAMILY_C_CROSS_CHECK`.
3036
+ * 2. **`refractionResolutionScale`** — the group's **field** targets are
3037
+ * rasterised at a fraction of device resolution, and the optics and highlight
3038
+ * passes filter them instead of indexing them (`passes.ts`, and the
3039
+ * `fieldUpsampled` flag both shaders branch on). Quadratic saving on the pass
3040
+ * that evaluates the pseudo-SDF union per pixel per member, and the most
3041
+ * visible step, so it comes second.
3042
+ *
3043
+ * What it does **not** yet do is shrink the optics and highlight passes
3044
+ * themselves: those still render at full device resolution into the plane
3045
+ * canvases, because rendering them smaller means an offscreen target and a
3046
+ * resolve pass rather than a change of extent. So rungs 2 and 3 deliver the
3047
+ * field's quadratic saving and the cadence saving, not the full quadratic
3048
+ * saving on both heavy passes. Recorded here rather than implied, because a
3049
+ * ladder whose rungs are priced for savings they do not deliver is a ladder
3050
+ * core's policy will walk too far down.
3051
+ * 3. **`adaptationCadenceHz`** — how often analysis is reduced and read back.
3052
+ * Cheapest of the three in visual terms because the values it feeds are
3053
+ * already low-passed over hundreds of milliseconds; dropping the cadence
3054
+ * mostly changes how quickly a scroll's new backdrop is noticed.
3055
+ */
3056
+ type FieldFamily = "rsupn" | "rsup";
3057
+ interface GovernorKnobs {
3058
+ /** Which pseudo-SDF family the field pass compiles. */
3059
+ readonly fieldFamily: FieldFamily;
3060
+ /**
3061
+ * Device-resolution fraction the group's field targets are rasterised at,
3062
+ * 0 < s <= 1. The optics and highlight passes upsample what they read. See the
3063
+ * module note for what this does and does not save.
3064
+ */
3065
+ readonly refractionResolutionScale: number;
3066
+ /** Analysis reduction + readback rate. 0 disables adaptation entirely. */
3067
+ readonly adaptationCadenceHz: number;
3068
+ }
3069
+ interface Governor {
3070
+ readonly knobs: GovernorKnobs;
3071
+ /** True when `fieldFamily: "rsup"` is permitted to engage. */
3072
+ readonly familyCVerified: boolean;
3073
+ set(patch: Partial<GovernorKnobs>): GovernorKnobs;
3074
+ /** Move to a rung of the suggested ladder. Out-of-range clamps to the ends. */
3075
+ setLevel(level: number): GovernorKnobs;
3076
+ reset(): GovernorKnobs;
3077
+ /** Record that the cross-check passed, unlocking family C. */
3078
+ recordFamilyCVerified(): void;
3079
+ }
3080
+
2491
3081
  /**
2492
3082
  * Pass-by-pass timing, for the benchmark §Performance envelope pins the ~2 ms
2493
3083
  * hypothesis to.
@@ -2654,6 +3244,27 @@ interface PyramidResources {
2654
3244
  * from without knowing where the body already sits.
2655
3245
  */
2656
3246
  readonly bodySigmaTexels: number;
3247
+ /**
3248
+ * Source texels per CSS px the build converted `bodySigmaCss` with — the placed
3249
+ * density where the source had a placement, the cover ratio where it did not
3250
+ * (`backdrop-fit.ts`) — and the source extent it was computed from. Recorded so
3251
+ * a later request can tell whether the body it would produce differs from the
3252
+ * one on the chain: a static image never re-dirties, so a placement whose SIZE
3253
+ * moved is the only signal that the σ in texels has gone stale.
3254
+ */
3255
+ readonly texelsPerCss: number;
3256
+ readonly sourceWidth: number;
3257
+ readonly sourceHeight: number;
3258
+ /**
3259
+ * The CSS-px σ the build converted with (W13 G1, review finding). The density
3260
+ * alone does not determine the body: since the widths became device-pixel
3261
+ * quantities (W12 G3, claims §5.56) the material's σ in CSS px is
3262
+ * `blurSigma / dpr`, so a window dragged from a 1x display to a 2x one asks
3263
+ * for a different body from the same source at the same density. A static
3264
+ * image never re-dirties, so this recorded σ is the only signal that the
3265
+ * chain's body and `bodyChainLod` belong to the previous scale.
3266
+ */
3267
+ readonly bodySigmaCss: number;
2657
3268
  }
2658
3269
  interface PyramidInstrumentation {
2659
3270
  /** Successful rebuilds since the store was created. */
@@ -2684,6 +3295,11 @@ interface PyramidBuildRequest {
2684
3295
  */
2685
3296
  readonly bodySigmaCss: number;
2686
3297
  readonly viewportCss: readonly [number, number];
3298
+ /**
3299
+ * Where the source sits on the plane, in CSS px relative to the viewport, if
3300
+ * the host measured one. Absent, the source is cover-fit to the viewport.
3301
+ */
3302
+ readonly placement?: BackdropPlacement;
2687
3303
  }
2688
3304
  type PyramidBuildOutcome = {
2689
3305
  readonly status: "built";
@@ -2868,6 +3484,16 @@ interface GlassRenderer {
2868
3484
  registerBackdrop(provider: BackdropProvider): void;
2869
3485
  unregisterBackdrop(sourceId: string): void;
2870
3486
  backdrop(sourceId: string): BackdropProvider | undefined;
3487
+ /**
3488
+ * Where a source's pixels sit on the plane, in CSS px relative to the viewport
3489
+ * (`backdrop-fit.ts`). Set every read phase by a host that measured the source
3490
+ * element's box; `undefined` (or never set) is the cover fit, the rule every
3491
+ * golden and calibration capture was taken under. Accepted before the provider
3492
+ * is registered and kept across device generations; cleared by
3493
+ * `unregisterBackdrop`.
3494
+ */
3495
+ setBackdropPlacement(sourceId: string, placement: BackdropPlacement | undefined): void;
3496
+ backdropPlacement(sourceId: string): BackdropPlacement | undefined;
2871
3497
  setViewport(viewport: ViewportState): void;
2872
3498
  readonly viewport: ViewportState;
2873
3499
  setGroup(input: GroupRenderInput): void;
@@ -2963,4 +3589,4 @@ declare const VITREA_CONTRACTS: {
2963
3589
  declare const RENDERER_TIERS: readonly ["webgpu", "css"];
2964
3590
  type RendererTier = (typeof RENDERER_TIERS)[number];
2965
3591
 
2966
- export { ACCESSIBILITY_BEHAVIOR_TABLE, ACCESSIBILITY_FLAGS, ACCESSIBILITY_PRECEDENCE, type AccessibilityConsequences, type AccessibilityFlag, type AccessibilityOverride, type AccessibilityOverrides, type ActiveRenderer, type AnalysisQuality, type BackdropEstimatorProvider, type BackdropHint, type BackdropHintRequest, type BackdropProvider, type BackdropRebuildRequest, type BackdropResolutionPolicy, type BackdropSourceDescriptor, type BackdropSourceRecord, type BackdropTone, type CapabilityInputs, type ConcentricParent, type ConfiguredSource, type CopyProviderOptions, type CornerProfile, type CornerRadii, type CornerReference, DEFAULT_BACKDROP_RESOLUTION, DEFAULT_CLEAR_DIMMING, DEFAULT_GROUP_SAMPLING, DEMOTION_REASONS, DEMOTION_RECOVERY, DIAGNOSTIC_CODES, type DemotionReason, type DescriptorPatch, type Diagnostic, type DiagnosticCode, type DiagnosticSeverity, type DiagnosticSink, type DiagnosticsChannel, type DiagnosticsChannelOptions, type DimmingPolicy, type DomBackdropSource, FOREGROUND_MODES, FRAME_PHASES, type ForegroundAdaptation, type ForegroundMode, type ForegroundResolutionOptions, type FrameContext, type FrameInfo, type FrameParticipant, type FramePhase, type FrameReport, type FrameScheduler, type FrameSchedulerOptions, GLASS_PLANES, GOVERNOR_PRESSURES, type GlassGroupDescriptor, type GlassGroupRecord, type GlassGroupState, type GlassNodeDescriptor, type GlassNodeRecord, type GlassPlane, type GlassRenderer, type GlassScene, GlassSceneError, type GlassSceneErrorCode, type GlassSceneOptions, type GlassTint, type GovernorPressure, type GroupHealth, type GroupSamplingGeometry, type GroupStateChange, HINT_AVAILABILITIES, type HintAvailability, type InteractionState, MATERIAL_VARIANTS$1 as MATERIAL_VARIANTS, type MaterialProfile$1 as MaterialProfile, type MaterialRequest, type MaterialVariant$1 as MaterialVariant, type MotionChannel, type MotionDriverKind, NOMINAL_ACCESSIBILITY_POLICY, OVERRIDABLE_ACCESSIBILITY_FLAGS, type OverridableAccessibilityFlag, type PlaneOverlap, type PlatformProbe, type ProxyOverlap, RENDERER_TIERS, type RecoveryContract, type RecoveryTrigger, type Rect, type RefractionQuality, type RendererTier, type ResolvedAccessibilityPolicy, type ResolvedBackdropHint, type ResolvedForegroundAdaptation, type ResolvedGroup, type ResolvedMaterial, type ResolvedMaterialPolicy, type ResolvedMotionPolicy, type ResolvedNode, SAMPLED_ASYNC_DEFAULTS, SAMPLED_ASYNC_RATE_LIMITS, type SamplingBackend, type SceneResolution, type ShapeChannels, type ShapeFamily, type SourceProbe, type StateChange, type SystemAccessibilityPreferences, type TextureBackdropSource, type TintColor, type TintMixingCheck, VITREA_CONTRACTS, type VariantMixingCheck, type Vec2, type VideoProviderOptions, WEBGPU_AVAILABILITIES, type WebGPUAvailability$1 as WebGPUAvailability, type WebGPURendererModule, type ZSlot, checkTintMixing, checkVariantMixing, classifyStateChange, clipRect, compareZSlot, createDiagnosticsChannel, createFrameScheduler, createGlassScene, defaultForegroundAdaptation, glassTint, inflateRect, isHealthy, loadWebGPURenderer, loadWebGPURendererModule, rectsOverlap, resolveAccessibilityPolicy, resolveBackdropHint, resolveForegroundAdaptation, resolveGlassGroupState, resolveMaterial, unionRect };
3592
+ export { ACCESSIBILITY_BEHAVIOR_TABLE, ACCESSIBILITY_FLAGS, ACCESSIBILITY_PRECEDENCE, type AccessibilityConsequences, type AccessibilityFlag, type AccessibilityOverride, type AccessibilityOverrides, type ActiveRenderer, type AnalysisQuality, type BackdropEstimatorProvider, type BackdropHint, type BackdropHintRequest, type BackdropProvider, type BackdropRebuildRequest, type BackdropResolutionPolicy, type BackdropSourceDescriptor, type BackdropSourceRecord, type BackdropTone, type CapabilityInputs, type ConcentricParent, type ConfiguredSource, type CopyProviderOptions, type CornerProfile, type CornerRadii, type CornerReference, DEFAULT_BACKDROP_RESOLUTION, DEFAULT_CLEAR_DIMMING, DEFAULT_GROUP_SAMPLING, DEMOTION_REASONS, DEMOTION_RECOVERY, DIAGNOSTIC_CODES, type DemotionReason, type DescriptorPatch, type Diagnostic, type DiagnosticCode, type DiagnosticSeverity, type DiagnosticSink, type DiagnosticsChannel, type DiagnosticsChannelOptions, type DimmingPolicy, type DomBackdropSource, FOREGROUND_MODES, FRAME_PHASES, type ForegroundAdaptation, type ForegroundMode, type ForegroundResolutionOptions, type FrameContext, type FrameInfo, type FrameParticipant, type FramePhase, type FrameReport, type FrameScheduler, type FrameSchedulerOptions, GLASS_PLANES, GOVERNOR_PRESSURES, type GlassGroupDescriptor, type GlassGroupRecord, type GlassGroupState, type GlassNodeDescriptor, type GlassNodeRecord, type GlassPlane, type GlassRenderer, type GlassScene, GlassSceneError, type GlassSceneErrorCode, type GlassSceneOptions, type GlassTint, type GovernorPressure, type GroupHealth, type GroupSamplingGeometry, type GroupStateChange, HINT_AVAILABILITIES, type HintAvailability, type InteractionState, MATERIAL_VARIANTS$1 as MATERIAL_VARIANTS, type MaterialProfile$1 as MaterialProfile, type MaterialRequest, type MaterialVariant$1 as MaterialVariant, type MotionChannel, type MotionDriverKind, NOMINAL_ACCESSIBILITY_POLICY, OVERRIDABLE_ACCESSIBILITY_FLAGS, type OverridableAccessibilityFlag, type PlaneOverlap, type PlatformProbe, type ProxyOverlap, RENDERER_TIERS, type RecoveryContract, type RecoveryTrigger, type Rect$1 as Rect, type RefractionQuality, type RendererTier, type ResolvedAccessibilityPolicy, type ResolvedBackdropHint, type ResolvedForegroundAdaptation, type ResolvedGroup, type ResolvedMaterial, type ResolvedMaterialPolicy, type ResolvedMotionPolicy, type ResolvedNode, SAMPLED_ASYNC_DEFAULTS, SAMPLED_ASYNC_RATE_LIMITS, type SamplingBackend, type SceneResolution, type ShapeChannels, type ShapeFamily, type SourceProbe, type StateChange, type SystemAccessibilityPreferences, type TextureBackdropSource, type TintColor, type TintMixingCheck, VITREA_CONTRACTS, type VariantMixingCheck, type Vec2, type VideoProviderOptions, WEBGPU_AVAILABILITIES, type WebGPUAvailability$1 as WebGPUAvailability, type WebGPURendererModule, type ZSlot, checkTintMixing, checkVariantMixing, classifyStateChange, clipRect, compareZSlot, createDiagnosticsChannel, createFrameScheduler, createGlassScene, defaultForegroundAdaptation, glassTint, inflateRect, isHealthy, loadWebGPURenderer, loadWebGPURendererModule, rectsOverlap, resolveAccessibilityPolicy, resolveBackdropHint, resolveForegroundAdaptation, resolveGlassGroupState, resolveMaterial, unionRect };