@property --breath {
  syntax: '<number>';
  initial-value: 1;
  inherits: false;
}
@keyframes breathe {
  0%, 100% { --breath: 1; }
  38%      { --breath: 1.085; }
  71%      { --breath: .945; }
}

:root {
  /* ONE FIELD, NAMED ONCE. The aperture and the night sky are the same cosmos
     seen two ways -- through a hole in the weather, or with the weather gone --
     so carrying the 354 layers twice would be 56 KB of duplicate that could
     drift apart. A custom property holds a full background-image list fine. */
  --starfield:
    radial-gradient(circle 1.5px at 69.2% 8.0%,rgba(255,255,255,0.49) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 37.3% 7.0%,rgba(255,255,255,0.76) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 17.2% 77.5%,rgba(255,255,255,0.45) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 56.7% 48.2%,rgba(255,255,255,0.7) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 84.0% 10.4%,rgba(255,255,255,0.24) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 68.0% 48.8%,rgba(255,255,255,0.43) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 99.6% 86.8%,rgba(255,255,255,0.64) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 57.8% 84.1%,rgba(255,255,255,0.27) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 70.1% 82.5%,rgba(255,255,255,0.75) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 80.7% 34.8%,rgba(255,255,255,0.21) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 78.5% 4.0%,rgba(255,255,255,0.46) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 35.2% 96.3%,rgba(255,255,255,0.73) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 28.5% 66.6%,rgba(255,255,255,0.71) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 35.5% 1.6%,rgba(255,255,255,0.78) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 6.6% 51.8%,rgba(255,255,255,0.35) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 30.6% 58.8%,rgba(255,255,255,0.62) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 84.4% 25.6%,rgba(255,255,255,0.8) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 37.8% 86.9%,rgba(255,255,255,0.82) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 46.3% 54.9%,rgba(255,255,255,0.66) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 48.6% 29.9%,rgba(255,255,255,0.47) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 68.1% 79.7%,rgba(255,255,255,0.48) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 53.1% 91.1%,rgba(255,255,255,0.31) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 1.8% 69.8%,rgba(255,255,255,0.65) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 30.6% 81.3%,rgba(255,255,255,0.88) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 88.4% 66.1%,rgba(255,255,255,0.66) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 30.1% 0.4%,rgba(255,255,255,0.59) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 94.0% 16.1%,rgba(255,255,255,0.86) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 32.5% 83.9%,rgba(255,255,255,0.76) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 66.1% 89.4%,rgba(255,255,255,0.46) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 2.7% 50.0%,rgba(255,255,255,0.63) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 17.4% 84.0%,rgba(255,255,255,0.71) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 81.1% 75.3%,rgba(255,255,255,0.83) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 66.5% 70.6%,rgba(255,255,255,0.7) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 23.6% 1.5%,rgba(255,255,255,0.72) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 72.8% 54.0%,rgba(255,255,255,0.44) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 84.5% 90.7%,rgba(255,255,255,0.28) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 16.5% 39.0%,rgba(255,255,255,0.73) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 63.4% 5.2%,rgba(255,255,255,0.57) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 26.9% 82.6%,rgba(255,255,255,0.36) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 64.9% 2.6%,rgba(255,255,255,0.9) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 59.7% 3.3%,rgba(255,255,255,0.56) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 26.9% 77.2%,rgba(255,255,255,0.91) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 68.3% 22.1%,rgba(255,255,255,0.86) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 98.0% 86.8%,rgba(255,255,255,0.64) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 32.9% 58.3%,rgba(255,255,255,0.25) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 51.0% 79.1%,rgba(255,255,255,0.41) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 88.0% 6.7%,rgba(255,255,255,0.36) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 45.4% 55.0%,rgba(255,255,255,0.33) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 12.4% 26.6%,rgba(255,255,255,0.67) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 30.0% 1.9%,rgba(255,255,255,0.5) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 10.6% 38.7%,rgba(255,255,255,0.64) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 86.2% 42.0%,rgba(255,255,255,0.87) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 53.6% 20.2%,rgba(255,255,255,0.91) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 98.8% 38.0%,rgba(255,255,255,0.19) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 65.4% 91.2%,rgba(255,255,255,0.54) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 94.1% 24.7%,rgba(255,255,255,0.77) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 46.3% 62.1%,rgba(255,255,255,0.68) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 90.0% 89.4%,rgba(255,255,255,0.46) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 29.5% 73.8%,rgba(255,255,255,0.43) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 96.5% 60.4%,rgba(255,255,255,0.9) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 79.0% 21.5%,rgba(255,255,255,0.74) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 68.4% 47.9%,rgba(255,255,255,0.66) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 28.5% 77.2%,rgba(255,255,255,0.38) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 41.4% 63.6%,rgba(255,255,255,0.89) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 40.1% 17.8%,rgba(255,255,255,0.44) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 6.7% 62.7%,rgba(255,255,255,0.75) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 76.3% 89.3%,rgba(255,255,255,0.26) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 4.6% 50.1%,rgba(255,255,255,0.88) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 88.9% 49.2%,rgba(255,255,255,0.83) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 60.6% 79.3%,rgba(255,255,255,0.92) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 41.2% 52.2%,rgba(255,255,255,0.21) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 93.5% 60.5%,rgba(255,255,255,0.68) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 27.1% 97.6%,rgba(255,255,255,0.38) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 73.9% 69.4%,rgba(255,255,255,0.54) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 76.3% 38.6%,rgba(255,255,255,0.56) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 24.7% 89.1%,rgba(255,255,255,0.48) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 35.1% 8.2%,rgba(255,255,255,0.51) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 73.1% 44.9%,rgba(255,255,255,0.9) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 92.4% 46.0%,rgba(255,255,255,0.2) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 40.4% 86.8%,rgba(255,255,255,0.81) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 46.0% 63.6%,rgba(255,255,255,0.55) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 57.0% 54.1%,rgba(255,255,255,0.79) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 10.1% 76.0%,rgba(255,255,255,0.4) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 83.9% 80.8%,rgba(255,255,255,0.85) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 14.1% 47.2%,rgba(255,255,255,0.68) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 52.4% 9.8%,rgba(255,255,255,0.47) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 81.5% 27.8%,rgba(255,255,255,0.74) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 19.4% 20.8%,rgba(255,255,255,0.46) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 36.2% 12.9%,rgba(255,255,255,0.82) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 60.4% 38.7%,rgba(255,255,255,0.31) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 68.3% 40.5%,rgba(255,255,255,0.88) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 69.8% 50.9%,rgba(255,255,255,0.6) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 91.0% 51.9%,rgba(255,255,255,0.41) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 88.0% 30.6%,rgba(255,255,255,0.86) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 90.4% 13.0%,rgba(255,255,255,0.92) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 72.0% 49.0%,rgba(255,255,255,0.71) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 1.1% 97.0%,rgba(255,255,255,0.76) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 77.2% 56.5%,rgba(255,255,255,0.82) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 95.5% 6.7%,rgba(255,255,255,0.3) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 24.1% 21.9%,rgba(255,255,255,0.47) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 53.4% 21.2%,rgba(255,255,255,0.47) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 33.1% 75.5%,rgba(255,255,255,0.35) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 36.9% 25.7%,rgba(255,255,255,0.58) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 26.1% 32.3%,rgba(255,255,255,0.43) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 62.3% 33.3%,rgba(255,255,255,0.93) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 19.7% 87.1%,rgba(255,255,255,0.28) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 88.1% 77.7%,rgba(255,255,255,0.74) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 38.5% 77.4%,rgba(255,255,255,0.3) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 49.6% 85.0%,rgba(255,255,255,0.27) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 58.6% 64.5%,rgba(255,255,255,0.67) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 94.3% 1.1%,rgba(255,255,255,0.26) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 53.0% 97.2%,rgba(255,255,255,0.59) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 76.4% 23.4%,rgba(255,255,255,0.56) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 0.7% 71.7%,rgba(255,255,255,0.7) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 19.5% 72.5%,rgba(255,255,255,0.71) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 37.0% 59.7%,rgba(255,255,255,0.69) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 62.8% 64.5%,rgba(255,255,255,0.73) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 92.0% 64.8%,rgba(255,255,255,0.55) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 92.9% 3.7%,rgba(255,255,255,0.57) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 99.0% 1.2%,rgba(255,255,255,0.86) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 77.2% 20.5%,rgba(255,255,255,0.41) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 26.3% 54.1%,rgba(255,255,255,0.71) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 40.8% 98.4%,rgba(255,255,255,0.43) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 92.5% 17.9%,rgba(255,255,255,0.6) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 77.2% 94.2%,rgba(255,255,255,0.23) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 69.3% 76.8%,rgba(255,255,255,0.94) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 8.6% 63.0%,rgba(255,255,255,0.7) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 63.0% 52.4%,rgba(255,255,255,0.34) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 93.9% 43.0%,rgba(255,255,255,0.39) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 77.8% 99.7%,rgba(255,255,255,0.77) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 14.3% 16.2%,rgba(255,255,255,0.59) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 66.2% 32.8%,rgba(255,255,255,0.59) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 41.9% 8.8%,rgba(255,255,255,0.58) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 98.7% 98.4%,rgba(255,255,255,0.66) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 32.4% 5.9%,rgba(255,255,255,0.6) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 5.5% 44.4%,rgba(255,255,255,0.19) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 81.5% 50.6%,rgba(255,255,255,0.63) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 47.1% 82.6%,rgba(255,255,255,0.22) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 55.0% 70.5%,rgba(255,255,255,0.83) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 99.3% 93.6%,rgba(255,255,255,0.27) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 55.7% 20.7%,rgba(255,255,255,0.55) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 38.1% 57.0%,rgba(255,255,255,0.32) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 81.9% 94.0%,rgba(255,255,255,0.27) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 18.0% 95.3%,rgba(255,255,255,0.45) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 30.7% 14.0%,rgba(255,255,255,0.19) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 71.4% 98.8%,rgba(255,255,255,0.23) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 79.0% 84.3%,rgba(255,255,255,0.37) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 19.3% 27.4%,rgba(255,255,255,0.73) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 6.2% 56.7%,rgba(255,255,255,0.29) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 33.0% 67.6%,rgba(255,255,255,0.69) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 95.3% 71.4%,rgba(255,255,255,0.72) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 4.5% 80.7%,rgba(255,255,255,0.46) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 43.0% 41.5%,rgba(255,255,255,0.81) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 51.6% 33.4%,rgba(255,255,255,0.31) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 28.4% 47.8%,rgba(255,255,255,0.26) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 80.6% 64.9%,rgba(255,255,255,0.8) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 53.8% 85.8%,rgba(255,255,255,0.29) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 89.9% 32.0%,rgba(255,255,255,0.68) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 62.7% 26.3%,rgba(255,255,255,0.65) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 0.6% 95.1%,rgba(255,255,255,0.77) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 1.8% 26.5%,rgba(255,255,255,0.93) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 51.1% 85.9%,rgba(255,255,255,0.47) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 0.0% 27.3%,rgba(255,255,255,0.75) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 27.0% 35.6%,rgba(255,255,255,0.38) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 97.5% 73.9%,rgba(255,255,255,0.2) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 32.6% 5.2%,rgba(255,255,255,0.48) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 9.6% 6.1%,rgba(255,255,255,0.57) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 67.3% 85.6%,rgba(255,255,255,0.54) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 33.2% 36.2%,rgba(255,255,255,0.75) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 72.5% 43.7%,rgba(255,255,255,0.31) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 34.2% 88.0%,rgba(255,255,255,0.29) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 22.0% 42.5%,rgba(255,255,255,0.2) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 22.9% 48.6%,rgba(255,255,255,0.54) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 79.0% 15.6%,rgba(255,255,255,0.5) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 32.0% 27.7%,rgba(255,255,255,0.94) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 5.7% 57.1%,rgba(255,255,255,0.8) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 91.2% 4.4%,rgba(255,255,255,0.28) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 59.5% 76.1%,rgba(255,255,255,0.76) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 52.6% 4.6%,rgba(255,255,255,0.41) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 68.3% 46.7%,rgba(255,255,255,0.19) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 3.3% 32.6%,rgba(255,255,255,0.2) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 84.9% 91.9%,rgba(255,255,255,0.22) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 79.7% 77.1%,rgba(255,255,255,0.41) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 98.8% 74.3%,rgba(255,255,255,0.77) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 1.2% 45.4%,rgba(255,255,255,0.89) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 88.5% 27.2%,rgba(255,255,255,0.89) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 71.9% 68.4%,rgba(255,255,255,0.59) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 22.3% 24.6%,rgba(255,255,255,0.71) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 34.4% 50.4%,rgba(255,255,255,0.47) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 76.9% 27.7%,rgba(255,255,255,0.83) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 88.9% 20.4%,rgba(255,255,255,0.58) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 38.9% 43.7%,rgba(255,255,255,0.2) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 54.9% 46.3%,rgba(255,255,255,0.34) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 67.7% 44.3%,rgba(255,255,255,0.86) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 91.5% 24.1%,rgba(255,255,255,0.38) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 92.8% 22.5%,rgba(255,255,255,0.67) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 66.8% 84.2%,rgba(255,255,255,0.83) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 55.4% 42.9%,rgba(255,255,255,0.86) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 59.0% 53.5%,rgba(255,255,255,0.48) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 70.7% 83.0%,rgba(255,255,255,0.39) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 33.0% 12.2%,rgba(255,255,255,0.31) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 24.3% 84.2%,rgba(255,255,255,0.39) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 50.3% 38.9%,rgba(255,255,255,0.79) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 63.7% 22.0%,rgba(255,255,255,0.4) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 93.6% 37.0%,rgba(255,255,255,0.77) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 19.0% 94.4%,rgba(255,255,255,0.3) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 26.9% 30.8%,rgba(255,255,255,0.93) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 30.9% 79.0%,rgba(255,255,255,0.47) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 87.4% 99.1%,rgba(255,255,255,0.66) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 93.0% 34.7%,rgba(255,255,255,0.22) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 9.3% 62.7%,rgba(255,255,255,0.52) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 89.0% 70.6%,rgba(255,255,255,0.23) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 71.0% 62.9%,rgba(255,255,255,0.87) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 91.3% 96.7%,rgba(255,255,255,0.9) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 70.3% 75.8%,rgba(255,255,255,0.25) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 69.0% 7.6%,rgba(255,255,255,0.83) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 64.6% 59.2%,rgba(255,255,255,0.69) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 16.7% 79.9%,rgba(255,255,255,0.4) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 39.0% 82.4%,rgba(255,255,255,0.85) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 72.8% 46.3%,rgba(255,255,255,0.85) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 44.8% 11.1%,rgba(255,255,255,0.93) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 24.5% 94.5%,rgba(255,255,255,0.83) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 67.4% 75.1%,rgba(255,255,255,0.5) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 90.7% 90.3%,rgba(255,255,255,0.56) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 4.5% 99.6%,rgba(255,255,255,0.43) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 72.1% 52.6%,rgba(255,255,255,0.24) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 8.7% 93.4%,rgba(255,255,255,0.61) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 68.6% 75.3%,rgba(255,255,255,0.39) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 51.4% 85.0%,rgba(255,255,255,0.61) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 55.7% 58.4%,rgba(255,255,255,0.35) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 79.0% 47.0%,rgba(255,255,255,0.81) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 91.3% 70.2%,rgba(255,255,255,0.35) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 24.0% 53.7%,rgba(255,255,255,0.95) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 10.0% 63.0%,rgba(255,255,255,0.22) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 97.6% 65.6%,rgba(255,255,255,0.2) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 34.8% 90.3%,rgba(255,255,255,0.34) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 73.4% 9.5%,rgba(255,255,255,0.79) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 9.8% 3.2%,rgba(255,255,255,0.2) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 99.0% 0.1%,rgba(255,255,255,0.94) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 47.1% 68.4%,rgba(255,255,255,0.74) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 38.1% 23.8%,rgba(255,255,255,0.64) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 36.4% 79.1%,rgba(255,255,255,0.56) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 53.9% 13.3%,rgba(255,255,255,0.48) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 60.0% 92.4%,rgba(255,255,255,0.22) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 73.2% 19.7%,rgba(255,255,255,0.47) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 57.6% 26.3%,rgba(255,255,255,0.65) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 17.5% 75.5%,rgba(255,255,255,0.51) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 12.7% 59.3%,rgba(255,255,255,0.8) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 89.3% 22.3%,rgba(255,255,255,0.86) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 17.2% 35.8%,rgba(255,255,255,0.79) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 71.3% 49.0%,rgba(255,255,255,0.64) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 22.4% 65.5%,rgba(255,255,255,0.65) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 92.0% 83.4%,rgba(255,255,255,0.65) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 77.8% 97.3%,rgba(255,255,255,0.51) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 7.0% 26.8%,rgba(255,255,255,0.5) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 20.2% 78.8%,rgba(255,255,255,0.69) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 69.9% 78.3%,rgba(255,255,255,0.48) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 6.8% 50.5%,rgba(255,255,255,0.78) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 20.5% 89.1%,rgba(255,255,255,0.9) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 20.7% 13.3%,rgba(255,255,255,0.7) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 30.2% 57.4%,rgba(255,255,255,0.91) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 58.8% 95.2%,rgba(255,255,255,0.72) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 81.9% 36.2%,rgba(255,255,255,0.28) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 8.6% 41.9%,rgba(255,255,255,0.43) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 97.6% 42.6%,rgba(255,255,255,0.68) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 34.8% 40.7%,rgba(255,255,255,0.67) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 42.0% 52.6%,rgba(255,255,255,0.72) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 31.4% 44.6%,rgba(255,255,255,0.3) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 3.6% 82.3%,rgba(255,255,255,0.4) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 92.4% 37.4%,rgba(255,255,255,0.61) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 11.5% 10.9%,rgba(255,255,255,0.76) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 65.4% 72.9%,rgba(255,255,255,0.8) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 69.8% 9.4%,rgba(255,255,255,0.2) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 82.3% 32.6%,rgba(255,255,255,0.25) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 10.1% 75.1%,rgba(255,255,255,0.84) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 15.2% 95.9%,rgba(255,255,255,0.83) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 19.8% 84.8%,rgba(255,255,255,0.62) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 17.7% 98.3%,rgba(255,255,255,0.73) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 70.4% 59.3%,rgba(255,255,255,0.94) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 27.3% 25.1%,rgba(255,255,255,0.38) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 68.8% 71.9%,rgba(255,255,255,0.47) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 33.4% 23.0%,rgba(255,255,255,0.29) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 79.1% 58.5%,rgba(255,255,255,0.47) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 34.6% 10.2%,rgba(255,255,255,0.5) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 72.7% 57.7%,rgba(255,255,255,0.78) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 27.6% 34.9%,rgba(255,255,255,0.89) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 29.7% 50.9%,rgba(255,255,255,0.92) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 21.2% 62.9%,rgba(255,255,255,0.57) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 36.7% 90.0%,rgba(255,255,255,0.95) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 41.1% 85.6%,rgba(255,255,255,0.73) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 82.5% 72.5%,rgba(255,255,255,0.21) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 79.2% 11.7%,rgba(255,255,255,0.33) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 77.7% 9.4%,rgba(255,255,255,0.42) 0 100%,transparent 100%),
    radial-gradient(circle 1.2px at 55.9% 10.6%,rgba(255,255,255,0.63) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 85.7% 1.2%,rgba(255,255,255,0.7) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 75.2% 14.2%,rgba(255,255,255,0.87) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 54.5% 95.6%,rgba(255,255,255,0.7) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 27.4% 52.2%,rgba(255,255,255,0.83) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 23.8% 24.8%,rgba(255,255,255,0.2) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 25.6% 58.8%,rgba(255,255,255,0.76) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 1.4% 11.6%,rgba(255,255,255,0.82) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 57.9% 58.8%,rgba(255,255,255,0.76) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 10.8% 64.3%,rgba(255,255,255,0.2) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 35.2% 16.2%,rgba(255,255,255,0.58) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 62.5% 16.7%,rgba(255,255,255,0.54) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 55.4% 81.8%,rgba(255,255,255,0.95) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 49.9% 84.6%,rgba(255,255,255,0.55) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 82.9% 97.9%,rgba(255,255,255,0.77) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 81.3% 62.9%,rgba(255,255,255,0.77) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 44.9% 12.2%,rgba(255,255,255,0.88) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 54.5% 85.4%,rgba(255,255,255,0.88) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 48.4% 72.8%,rgba(255,255,255,0.76) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 0.6% 74.7%,rgba(255,255,255,0.19) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 21.4% 24.7%,rgba(255,255,255,0.57) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 17.4% 73.1%,rgba(255,255,255,0.31) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 4.1% 66.6%,rgba(255,255,255,0.9) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 17.0% 59.5%,rgba(255,255,255,0.82) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 94.3% 62.3%,rgba(255,255,255,0.26) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 89.2% 1.7%,rgba(255,255,255,0.56) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 27.9% 67.4%,rgba(255,255,255,0.39) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 57.0% 26.0%,rgba(255,255,255,0.31) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 89.3% 19.1%,rgba(255,255,255,0.82) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 43.2% 52.0%,rgba(255,255,255,0.76) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 13.4% 92.0%,rgba(255,255,255,0.4) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 54.3% 88.7%,rgba(255,255,255,0.7) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 51.4% 42.6%,rgba(255,255,255,0.65) 0 100%,transparent 100%),
    radial-gradient(circle 1.5px at 57.0% 12.0%,rgba(255,255,255,0.33) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 80.3% 75.3%,rgba(255,255,255,0.26) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 64.2% 38.8%,rgba(255,255,255,0.67) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 8.0% 27.6%,rgba(255,255,255,0.3) 0 100%,transparent 100%),
    radial-gradient(circle 0.9px at 3.2% 4.3%,rgba(255,255,255,0.27) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 66.3% 77.4%,rgba(255,255,255,0.84) 0 100%,transparent 100%),
    radial-gradient(circle 1.0px at 49.6% 35.7%,rgba(255,255,255,0.68) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 46.1% 63.0%,rgba(255,255,255,0.65) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 24.5% 67.3%,rgba(255,255,255,0.71) 0 100%,transparent 100%),
    radial-gradient(circle 0.8px at 48.7% 92.3%,rgba(255,255,255,0.51) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 86.6% 14.3%,rgba(255,255,255,0.57) 0 100%,transparent 100%),
    radial-gradient(circle 0.5px at 24.7% 10.3%,rgba(255,255,255,0.94) 0 100%,transparent 100%),
    radial-gradient(circle 0.7px at 11.8% 69.8%,rgba(255,255,255,0.64) 0 100%,transparent 100%),
    radial-gradient(circle 0.6px at 8.9% 30.0%,rgba(255,255,255,0.47) 0 100%,transparent 100%),
    radial-gradient(circle 2px at 5.2% 42.5%,rgba(214,228,206,.95) 0 55%,rgba(214,228,206,.16) 55% 100%,transparent 100%),
    radial-gradient(circle 2px at 47.7% 47.3%,rgba(228,214,190,.95) 0 55%,rgba(228,214,190,.16) 55% 100%,transparent 100%),
    radial-gradient(circle 2px at 56.8% 79.2%,rgba(228,214,190,.95) 0 55%,rgba(228,214,190,.16) 55% 100%,transparent 100%),
    radial-gradient(circle 2px at 3.7% 56.0%,rgba(214,228,206,.95) 0 55%,rgba(214,228,206,.16) 55% 100%,transparent 100%),
    radial-gradient(circle 2px at 53.5% 17.8%,rgba(214,228,206,.95) 0 55%,rgba(214,228,206,.16) 55% 100%,transparent 100%),
    radial-gradient(circle 2px at 99.4% 39.1%,rgba(228,214,190,.95) 0 55%,rgba(228,214,190,.16) 55% 100%,transparent 100%),
    radial-gradient(circle 2px at 27.6% 58.2%,rgba(214,228,206,.95) 0 55%,rgba(214,228,206,.16) 55% 100%,transparent 100%),
    radial-gradient(circle 2px at 60.0% 10.8%,rgba(214,228,206,.95) 0 55%,rgba(214,228,206,.16) 55% 100%,transparent 100%),
    radial-gradient(circle 2px at 58.4% 0.5%,rgba(228,214,190,.95) 0 55%,rgba(228,214,190,.16) 55% 100%,transparent 100%),
    radial-gradient(circle 2px at 97.1% 34.3%,rgba(228,214,190,.95) 0 55%,rgba(228,214,190,.16) 55% 100%,transparent 100%),
    radial-gradient(circle 2px at 92.1% 77.8%,rgba(214,228,206,.95) 0 55%,rgba(214,228,206,.16) 55% 100%,transparent 100%),
    radial-gradient(circle 2px at 69.1% 17.3%,rgba(190,214,228,.95) 0 55%,rgba(190,214,228,.16) 55% 100%,transparent 100%),
    radial-gradient(circle 2px at 53.0% 52.4%,rgba(190,214,228,.95) 0 55%,rgba(190,214,228,.16) 55% 100%,transparent 100%),
    radial-gradient(circle 2px at 13.5% 60.9%,rgba(228,214,190,.95) 0 55%,rgba(228,214,190,.16) 55% 100%,transparent 100%);
  --nebula:
    radial-gradient(70% 120% at 18% 120%,
      color-mix(in srgb, var(--teal) 42%, transparent) 0%, transparent 62%),
    radial-gradient(60% 140% at 86% -30%,
      color-mix(in srgb, var(--olive) 26%, transparent) 0%, transparent 58%);
  /* THE SCALE. 1 is overcast, .72 clear sun, .34 twilight, 0 full dark. Every
     layer below reads this one number; nothing else decides the time of day. */
  --day: .72;
}

/* The sky behind the nine, and the glass they are cut from.
 *
 * Victor, 4 Oct 2026: real space between the canvases, a slight shade behind
 * them, and a back canvas that is SKY -- morning through evening to twilight,
 * drifting. The greens live in the weather rather than being painted onto the
 * boxes.
 *
 * Every colour here comes from the pack, which publishes
 * --ink --muted --paper --card --rule --crimson --ochre --olive --teal.
 * Nothing invents a name: §5 records that an undefined var() is TRANSPARENT
 * rather than an error, so a mistyped colour does not fail loudly, it renders
 * an element invisible and reads as empty markup.
 *
 * THE DRIFT IS A CSS ANIMATION AND NEVER requestAnimationFrame. §5 again: rAF
 * does not fire in a hidden tab, so anything awaiting it deadlocks the moment
 * somebody switches away -- and a sky that stops when you look elsewhere and
 * lurches when you come back is worse than a still one. A CSS animation keeps
 * its own clock and resumes where the time says it should be.
 *
 * One cycle is four minutes. That is deliberately too slow to watch and just
 * fast enough to notice you missed it, which is what weather does.
 */

/* THE BASE IS DEEP SPACE, and it matches the canvas's own fill exactly so the
   two cannot disagree at any opacity in between. It was var(--ink), which is
   the LIGHT end of the pack in dark mode -- invisible while the vault was
   opaque, and a white bleed the moment the vault was allowed to fade. */
/* THREE GROUNDS, NOT TWO. Victor, 4 Oct: "we should have another screen
   behind it, which is completely clear. That is the one that the new AR
   technology will use, where we put on the glasses -- the empty space is
   essentially you are looking through the real world."

   So the sky dial does not stop at the cosmos. Below it the whole sky leaves,
   and what is left is the panels on nothing: no vault, no stars, no nebula.
   On a laptop that reads as an empty field, which is the honest mock. In an
   immersive AR session a transparent page composites over the camera, so the
   same state is literally the room -- the design is the same either way and
   only the compositor differs.

   --clear is a separate channel from --sky-layer on purpose. --sky-layer
   removes the WEATHER and leaves the cosmos; --clear removes the universe.
   One variable doing both would make "dark night" and "nothing" the same
   place on the travel, and they are the two different things this dial now
   has to be able to say. */
.sky {
  position: fixed; inset: 0; z-index: -2;
  background: #060a12;
  /* NO OPACITY HERE. Fading the whole element took the starfield out with the
     vault, so the bottom of the travel was black and empty -- "we go directly
     to dark". --clear is what REMOVES THE DAY SKY, not what removes the
     universe, and the two had been collapsed into one fade on the parent.
     The vault and the nebula carry it individually below; the cosmos does
     not, because at the dark end the cosmos IS the sky. */
}

/* THE COSMOS. Always running, always the ground. Everything else in this file
   is a layer laid ON it, and the sky dial decides how much of that layer there
   is -- so at dark night there is nothing on top and this is simply the sky.
   Denser than the aperture's field because it covers the whole window. */
.sky > .cosmos {
  position: absolute; inset: 0; width: 100%; height: 100%; display: block;
  /* Same two questions as before: --stars is how dark it is, --depth is how
     far through you are looking, and the cosmos answers to whichever asks
     harder. A bright sky at full depth still shows stars, which is what
     altitude looks like. */
  opacity: max(var(--stars, 0), var(--depth, 0));
  transition: opacity 1.4s ease;
}

/* Layer one: the vault. Four stops of the day, cross-faded. */
.sky::before {
  content: ''; position: absolute; inset: 0;
  /* A DAY SKY IS BLUE, AND THIS ONE WAS NOT.
     Victor, 4 Oct: "what I truly don't like is when the scale is 100... it's
     not a bright blue sky with clouds going around. It's dull."
     He is right and the cause is in the colours rather than the brightness:
     every stop was --teal or --olive mixed toward --ink, and --ink is the near
     white of the dark pack. Mixing a desaturated blue-green toward white gives
     exactly the overcast grey it gave. No amount of brightness() rescues that;
     a brighter grey is a brighter grey.

     So each stop now travels from its night colour to a real daylight one, led
     by --day. At 0 the gradient is the night sky it has always been, stop for
     stop; at 1 it is zenith blue falling to a pale horizon. The pack has no
     day-sky token and should not -- these are weather, not brand, and the
     deliberate literal keeps them out of the theming surface where a rename
     would silently turn the sky transparent (§5). */
  background:
    linear-gradient(to bottom,
      color-mix(in srgb, #1C6FD6 calc(var(--day, 0) * 100%),
                color-mix(in srgb, var(--teal) 70%, var(--ink))) 0%,
      color-mix(in srgb, #59A6E8 calc(var(--day, 0) * 100%),
                color-mix(in srgb, var(--teal) 34%, var(--ink))) 42%,
      color-mix(in srgb, #A5D1F2 calc(var(--day, 0) * 100%),
                color-mix(in srgb, var(--olive) 30%, var(--ink))) 78%,
      color-mix(in srgb, #DCEEFB calc(var(--day, 0) * 100%), var(--ink)) 100%);
  /* THE VAULT BREATHES AGAIN, and it multiplies the dial rather than replacing
     it. The scale sets the time of day; this is the sky being alive at
     whatever time that is. An auto-cycle that SET brightness would fight the
     hand on the dial -- a factor around 1 cannot.
     --breath needs @property or it is a string and will not animate: an
     unregistered custom property has no type, so the browser has nothing to
     interpolate between and the animation silently does nothing. */
  /* The ground is pulled down a little. Victor's own condition: the glass only
     reads if the background is duller than what is seen through it, so the
     vault gives up some saturation and light to make room for the panels to
     be the bright thing. */
  filter: hue-rotate(var(--vault-hue, 0deg))
          /* The .82 existed so the ground stayed duller than the glass --
             "the glass only reads if the background is duller than what is
             seen through it". The panels are opaque surfaces now, not glass,
             so the sky no longer has to give up colour to make room for them.
             It still does at night, where a saturated dark reads as a colour
             cast; it stops doing it as the day comes up. */
          saturate(calc(var(--vault-sat, 1) * (.82 + .34 * var(--day, 0))))
          /* THE MOON IS IN HERE NOW. A sky under a full moon and the same sky
             under a new moon are not the same sky, and before this the light
             dial moved the panels while the air behind them did not change --
             which is a lamp inside the cabin, not a moon outside it.
             It never reaches zero: a new moon is a darker night, not a
             switched-off sky, and the stars still have to sit on something. */
          brightness(calc(var(--vault-bright, 1.1) * var(--breath, 1) * .88
                          * (.34 + .66 * var(--moon, 1))));
  /* THE TWILIGHT LAYER LEAVES RATHER THAN GOING BLACK. Dimming it to 0.03
     still left an opaque near-black sheet over the cosmos -- which is a
     different thing from not being there, and it is what made the dark sky
     read as a dead backdrop. Now the dial removes the layer. */
  opacity: calc(var(--sky-layer, 1) * (1 - var(--clear, 0)));
  transition: filter 1.1s ease, opacity 1.1s ease;
  animation: breathe 190s ease-in-out infinite;
}

/* Layer two: the light. A soft low sun that drifts across and warms as it
   goes, so the horizon changes temperature rather than the whole field. */
.sky::after {
  content: ''; position: absolute; inset: -20%;
  background:
    /* THE SHINE. A tight bright core where the light source sits, over the
       broad warm wash. A sky without one reads as a painted gradient; the hard
       little centre is what says there is something up there. It is scaled by
       --day so it disappears at night rather than hanging in the dark. */
    /* A FAR LIGHT, NOT A NEAR ONE. This is the correction and it is about
       FALLOFF rather than position. A near source obeys inverse square, so one
       corner blows out and the rest drops away -- which is why the left was
       static and hot while the right had nothing left to blend with. A distant
       source arrives nearly parallel and lights the whole frame almost evenly,
       with only a gentle gradient across it.
       So the source moves to centre-top and OUTSIDE the frame at 50% -15%,
       the wash widens from roughly half the frame to one and a half times it,
       and the specular core shrinks -- a distant sun is a small bright point,
       not a large smear. The core also drops in strength, because at this
       extent it no longer has to carry the whole sky. */
    radial-gradient(3.5% 7% at 50% -15%,
      rgba(255,253,246, calc(var(--shine, .9) * .78)) 0%,
      rgba(255,250,238, calc(var(--shine, .9) * .30)) 46%,
      transparent 76%),
    /* the near field around the source, still soft */
    radial-gradient(44% 46% at 50% -15%,
      color-mix(in srgb,
        color-mix(in srgb, #fff var(--shine-white, 0%), var(--ochre))
        calc(26% * var(--shine, .9)), transparent) 0%,
      transparent 76%),
    /* the parallel wash: wide enough to cover the frame, so the gradient
       across it is gentle instead of a hotspot with darkness beside it */
    radial-gradient(150% 120% at 50% -15%,
      color-mix(in srgb,
        color-mix(in srgb, #fff var(--shine-white, 0%), var(--ochre))
        calc(22% * var(--shine, .9)), transparent) 0%,
      transparent 86%),
    /* THE HORIZON BAND. Twilight is brightest low, not overhead -- a wide band
       near the foot reads as dusk in a way a point never does, and it gives
       the lower half of the frame something to blend into. */
    linear-gradient(to top,
      color-mix(in srgb,
        color-mix(in srgb, #fff var(--shine-white, 0%), var(--ochre))
        calc(13% * var(--shine, .9)), transparent) 0%,
      transparent 42%),
    radial-gradient(34% 26% at 78% 18%,
      color-mix(in srgb, var(--teal) 34%, transparent) 0%,
      transparent 72%);
  animation: light 240s linear infinite;
  /* 18px of blur was smearing the whole daytime sky into a wash. 5px keeps
     the sun soft-edged -- which it is -- without taking the structure out of
     everything behind it. */
  /* The ground is softer than the glass on purpose. The contrast the effect
     needs is a difference in FOCUS, not only in brightness -- blurring the
     backdrop and sharpening the pane are the same gesture from two ends. */
  filter: blur(11px);
}

@keyframes vault {
  /* morning */ 0%   { filter: hue-rotate(-6deg)  saturate(.86) brightness(1.06); }
  /* day     */ 26%  { filter: hue-rotate(0deg)   saturate(1.00) brightness(1.14); }
  /* evening */ 58%  { filter: hue-rotate(12deg)  saturate(1.22) brightness(.96); }
  /* twilight*/ 82%  { filter: hue-rotate(-14deg) saturate(1.10) brightness(.74); }
                100% { filter: hue-rotate(-6deg)  saturate(.86) brightness(1.06); }
}
/* A far light barely moves. The excursion drops to a couple of percent --
   enough that the sky is alive, not enough to swing a distant source around
   the frame like a lamp on an arm. */
@keyframes light {
  0%   { transform: translate3d(-1.5%, 1%, 0) scale(1.01); opacity: .86; }
  34%  { transform: translate3d(1%, -1%, 0)   scale(1.05); opacity: .97; }
  67%  { transform: translate3d(2%, 1.5%, 0)  scale(1.02); opacity: .90; }
  100% { transform: translate3d(-1.5%, 1%, 0) scale(1.01); opacity: .86; }
}

/* Real space between them. The shell names --gap and defaults it to 8px, so
   this sets the published variable rather than overriding `gap` directly --
   shell.css records that declaring --gap in the wrong place once took it from
   17px to 8px with nothing else changed. */
/* REAL SPACE IS PAID FOR, and the first attempt took it from the content.
   20px of gap costs 40px per axis across three tracks, and the shallow rows are
   only ~76px to begin with -- six of nine canvases clipped, the worst by 66px.
   §5 says canvases clip and to measure scrollHeight against clientHeight rather
   than eyeball it, which is the only reason that was visible at all.
   So the gap is bought back out of the padding instead: 16px between the
   sheets, tighter inside them. The space between is what reads as depth; the
   space inside only reads as air. */
/* THE ASPECTS ARE THE SPECIFICATION, and the rows follow from them.
 * Victor, 4 Oct: top-left and top-right are 16:9, the vertical ones are 9:16,
 * the bottom row takes what is left, and the space between stays.
 *
 * Three aspects plus a 16:9 frame determine the whole grid. With the side
 * column at a fifth of the available width:
 *   16:9 on the top     -> r1 = c * 9/16
 *   9:16 in the middle  -> r2 = c * 16/9
 *   the bottom          -> whatever Ha - r1 - r2 leaves, 15.3% of the height
 * which gives columns 1 : 3 : 1 and rows .3164 : 1 : .2379. The columns coming
 * out at exactly 1 : 3 : 1 is the arithmetic agreeing with itself, not a
 * rounding.
 *
 * A FIXED PIXEL GAP WOULD MAKE THIS EXACT AT EXACTLY ONE FRAME SIZE, because
 * 16px is a different fraction of a 900px frame than of a 1400px one, and grid
 * distributes fr over what is left AFTER the gap. So the gap is a percentage.
 * column-gap% resolves against width and row-gap% against HEIGHT, so the two
 * percentages differ in order to be equal in pixels: 1.1% of width is 1.956%
 * of height at 16:9. */
.vista {
  --col-input: 1fr; --col-work: 3fr; --col-output: 1fr;
  --row-top: .3164fr; --row-mid: 1fr; --row-bot: .2379fr;
  column-gap: 1.1% !important;
  row-gap: 1.956% !important;
  /* THE FRAME'S OWN PADDING WAS THE 1.1% ERROR. shell.css insets the frame by
     `calc(--gap * 1.25) --gap --gap`, so the GRID lives in a content box of
     1449x806 -- aspect 1.7976 -- while the frame's border box is the 16:9 the
     arithmetic assumed. 1.7976 / 1.7778 = 1.0111, which is precisely the 1.1%
     every cell was out by. The aspects were not approximately right; they were
     exactly right for a box one layer in from the one I measured.
     Zeroing it makes content box = border box, so the grid is 16:9 at EVERY
     size rather than at none. The panels reaching the frame edge is also what
     a full-bleed painting wants: the frame is the viewport. */
  --frame-pad: 0;
  --canvas-pad: 10px 12px;
  background: transparent !important; border: 0 !important;
}
.vista > .canvas > h2 { margin: 0 0 4px !important; }
.vista > .canvas > p  { margin: 0 !important; }

/* The glass.
 *
 * THE SHADOW WAS DRAWN IN THE WRONG COLOUR, and that is why these read as
 * edged panels rather than as sheets in space. The pack's names are SEMANTIC
 * and they swap with the theme: light mode has --paper #EBF3E8 and --ink
 * #181E15, dark mode has --paper #131811 and --ink #EAEDE8. paper is always
 * the ground and ink is always the mark. The first version shadowed with
 * --ink, so in dark mode every panel cast a pale GLOW, and highlighted with
 * --paper, so the one lit edge was nearly black. Both exactly inverted, and
 * the result is the hard rim Victor saw.
 *
 * Shadows take --paper. Highlights take --ink. Never the other way, in either
 * theme -- this is the same family as §5's undefined var(): a name that
 * resolves to something plausible is worse than one that resolves to nothing,
 * because nothing disappears and plausible just looks like a choice.
 *
 * NO BORDER AT ALL. A 1px rule is what stops a sheet floating -- it draws the
 * panel's outline instead of letting the shadow imply its edge. The only line
 * is a hairline of light along the top, which is where a sheet catches a sky.
 */

.vista > .canvas {
  /* A LIGHT FILM, NOT A DARK ONE. This is the whole difference between frosted
     glass and tinted glass, and it is what the Apple look is actually doing:
     the sky seen THROUGH the panel is brighter and more saturated than the sky
     beside it, as though light were landing on the pane and scattering
     forward. Mixing --card (the dark ground) darkened the sky inside every
     panel, which is the opposite -- it read as a filter laid over the world
     rather than as a surface catching light.
     --ink is the light end of the pack in dark mode, so the film is now a
     brightening one, and the percentage drops because a light film at 18%
     would be a fog. */
  background: color-mix(in srgb, var(--panel) calc(var(--presence, 1) * 100%), transparent) !important;
  border: 0 !important;
  border-radius: 18px !important;
  position: relative;
  backdrop-filter: blur(26px) saturate(1.3) brightness(1.06);
  -webkit-backdrop-filter: blur(26px) saturate(1.3) brightness(1.06);
  /* THE SHADOW MUST NOT CROSS THE GAP.
     The gap is 16px. The previous cast was 52px of blur at 26px of offset with
     a third layer at 90px, so every panel darkened its neighbours and all four
     shadows pooled in each interior corner -- the frame read as grubby between
     the sheets rather than clean.
     So the cast is contained: 10px of blur at 4px of offset, which dies well
     inside the gap and never reaches the next panel. Nothing here is wider
     than the space it has.
     FLOAT NOW COMES FROM THE GLOSS, NOT FROM DARKENING ANYTHING. Glass reads
     as lifted because of its specular edge and its highlight, not because of
     what it does to the surface behind it -- which is also why a real pane in
     a window casts almost nothing and still obviously sits in front. */
  box-shadow:
    /* specular ring: the edge of the sheet catching light all the way round */
    0 0 0 1px color-mix(in srgb, var(--ink) 13%, transparent),
    /* the lit top edge */
    0 1px 0 color-mix(in srgb, var(--ink) 34%, transparent) inset,
    /* reflected light along the foot -- glass always has this and it is most
       of what makes a pane look like a pane rather than a hole */
    0 -1px 0 color-mix(in srgb, var(--ink) 12%, transparent) inset,
    /* A light film needs depth from somewhere, so the inner shade along the
       foot does the work the dark tint used to -- it is what stops the pane
       reading as a flat bright rectangle. */
    inset 0 -14px 20px -16px color-mix(in srgb, var(--paper) 70%, transparent),
    /* contact only, and short */
    0 4px 10px -6px color-mix(in srgb, var(--paper) 50%, transparent);
  transition: box-shadow .35s ease, transform .35s ease;
}

/* ONE SHEEN, BELONGING TO THE SKY.
 *
 * Victor, 4 Oct: the sheen looked like nine different skies. It was -- every
 * panel carried its own highlight positioned to ITSELF, so a gradient "at 12%
 * -10%" meant 12% of that panel, and the frame had nine little suns in it.
 * Glass does not work that way. There is one light, and a pane shows whatever
 * part of it falls where the pane is.
 *
 * background-attachment: fixed is what makes that true. It resolves the
 * gradient against the VIEWPORT rather than the element, so all nine panels
 * sample one continuous field and differ only by where they sit in it. The
 * top left catches the light; the bottom right barely does; moving a boundary
 * with the drag handles changes which part of the one sheen a panel shows.
 * Same mechanism as the cosmic aperture, for the same reason: a window shows
 * the thing behind it, not a copy of it.
 *
 * The highlight sits at 15% 14%, which is where the sky's own sun already is,
 * so the sheen and the light source agree instead of being two different
 * claims about where the light comes from.
 */
.vista > .canvas::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; z-index: 1;
  background:
    /* The sheen follows the source. It was anchored at 15% 14% while the sky's
       light moved to centre-top, and a glass highlight that disagrees with the
       sun is two claims about where the light comes from.
       Widened to match as well: a far light makes a broad even sheen, not a
       bright patch on one pane. */
    radial-gradient(70% 55% at 50% -18%,
      color-mix(in srgb, var(--ink) 22%, transparent) 0%,
      color-mix(in srgb, var(--ink) 7%, transparent) 52%,
      transparent 84%),
    /* the sheet, now falling from above rather than across a diagonal */
    linear-gradient(to bottom,
      color-mix(in srgb, var(--ink) 11%, transparent) 0%,
      color-mix(in srgb, var(--ink) 4%, transparent) 34%,
      transparent 68%),
    /* and the cool reflected wash from the floor */
    radial-gradient(90% 46% at 50% 104%,
      color-mix(in srgb, var(--teal) 14%, transparent) 0%, transparent 70%);
  background-attachment: fixed;
  background-repeat: no-repeat;
}

/* A screen sits further forward, and says so with a brighter edge rather than
   a longer shadow -- a longer shadow would cross the gap again. */
.vista > .canvas[data-screen] {
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--ink) 20%, transparent),
    0 1px 0 color-mix(in srgb, var(--ink) 44%, transparent) inset,
    0 -1px 0 color-mix(in srgb, var(--ink) 16%, transparent) inset,
    0 5px 12px -7px color-mix(in srgb, var(--paper) 55%, transparent);
}

/* At 28% the panel is a window, so the text carries itself. */
.vista > .canvas > h2 { color: color-mix(in srgb, var(--ink) 78%, transparent) !important;
  text-shadow: 0 0 3px color-mix(in srgb, var(--paper) 72%, transparent); }
/* A LIGHT FILM COSTS THE TEXT ITS CONTRAST, and the fix cannot be to darken
   the type: the light dial runs from overcast to full dark, so a colour that
   reads at one end is invisible at the other. The type stays --ink and takes a
   HALO instead -- a tight dark edge plus a soft bloom, which gives it an
   outline against a bright panel and disappears entirely against a dark one.
   One shadow at 55% was not enough once the panel became a brightener. */
.vista > .canvas > p,
.vista > .canvas .big,
.vista > .canvas .sub { color: var(--ink) !important;
  text-shadow:
    0 0 2px  color-mix(in srgb, var(--paper) 82%, transparent),
    0 1px 3px color-mix(in srgb, var(--paper) 78%, transparent),
    0 0 14px color-mix(in srgb, var(--paper) 58%, transparent); }

/* Anyone who has asked their system not to animate gets a still sky. The
   gradient stays; only the drift stops. */
@media (prefers-reduced-motion: reduce) {
  .sky::before, .sky::after { animation: none; }
}


/* FULL BLEED, STILL 16:9.
 *
 * The frame was capped at 60rem by the page, so it rendered at roughly half the
 * width a desktop offers and the sky did most of the work. The letterbox is the
 * point of `data-fit="frame"`, so the frame takes the whole viewport that 16:9
 * allows and nothing is cropped to get there: width is the smaller of what the
 * window is wide and what its height permits at 16:9, so the shape is the
 * constraint and the screen is the budget.
 *
 * `dvh` rather than `vh` because mobile browser chrome collapses on scroll and
 * `vh` would size the frame to a viewport that is not there.
 */
.gala-full .vista {
  /* One expression, declared on :root beside the gutter that is computed from
     it -- see the scale. --frame-pad stays 0: any padding here puts the
     content box at 1.7976 against a border box of 1.7778, which is exactly
     the 1.1% aspect error. */
  width: var(--frame-w);
  max-width: none;
  margin-inline: auto;
}
.gala-full { padding: 0 !important; max-width: none !important; }

/* At 55% the panel is genuinely transparent, so a label sitting directly on a
   bright patch of sky loses its edge. The text gets its own weight back rather
   than the panel getting its opacity back. */
.vista > .canvas > h2 { color: color-mix(in srgb, var(--ink) 72%, transparent) !important; }
.vista > .canvas > p  { color: var(--ink) !important; }


/* The clouds. feTurbulence gives real fractal texture rather than the smooth
   lobes a stack of radial gradients produces -- and it is generated in the
   page, so there is no image to fetch, no licence to carry, and it never
   repeats. Two layers at different speeds, because clouds at one speed read as
   a texture sliding rather than as weather.
   CSS keyframes again, never rAF: §5, a hidden tab stops firing it. */
.clouds { position: absolute; inset: 0; width: 100%; height: 100%;
          /* Looking deeper thins the weather: you are seeing past it, not
             waiting for it to clear. */
          opacity: calc(var(--cloud, .5) * (1 - var(--depth, 0) * .85));
          transition: opacity 1.1s ease;
          /* soft-light was too polite: at .9 opacity the turbulence read as
             film grain on a gradient rather than as weather. `screen` lets the
             bright lobes actually sit in front of the vault, which is what a
             cloud does. */
          /* `screen` at .5 was flattening the turbulence into haze. Raising the
             layer opacity and letting the filter's own alpha slope do the
             contrast keeps the cloud EDGES, which is the whole difference
             between weather and fog. */
          mix-blend-mode: screen; }
.clouds .layer-a { animation: cloud-a 420s linear infinite; opacity: .95; }
.clouds .layer-b { animation: cloud-b 680s linear infinite; opacity: .62; }
.clouds .layer-a { animation: cloud-a 420s linear infinite; opacity: .95; }
.clouds .layer-b { animation: cloud-b 680s linear infinite; opacity: .62; }
/* The weather travels as well: a scale alongside the lateral drift, so the
   clouds pass rather than slide. Different rates on the two layers is what
   makes it parallax instead of a single sheet moving. */
@keyframes cloud-a {
  from { transform: translateX(0) scale(1); }
  to   { transform: trans/* THE NEAR CLOUD LAYER IS GONE, AND THE ARITHMETIC IS WHY.
   It was a rect 260% x 180% of the viewport under a filter region of 220%,
   which is 28 megapixels of feTurbulence before it moves -- and it SCALED to
   2.6x, so by the end of its cycle the browser was asked for about 190
   megapixels of fractal noise, re-rasterised as it grew, inside a
   mix-blend-mode group, with a Gaussian blur on top.
   feTurbulence is the most expensive primitive in SVG and the one thing you
   must not animate the size of: §5 already records that the clouds animate
   TRANSFORM so the noise rasterises once. Scaling breaks exactly that, which
   is the trap the file warns about, entered by the person who wrote the
   warning. The depth cue was not worth a dropped frame. */
lateX(-28%) scale(1.14); } }
@keyframes cloud-b {
  from { transform: translateX(-10%) scale(1.06); }
  to   { transform: translateX(22%) scale(1); } }
@media (prefers-reduced-motion: reduce) {
  .clouds .layer-a, .clouds .layer-b { animation: none; }
}


/* ──────────────────────────────────────────────────────────────────────────
   THE SKY BEHIND THE SKY.
   Victor, 4 Oct: a cosmic sky under the weather, and the chat window cuts
   through the weather to show it. The user is asking the cosmic sky; the
   weather is what sits between; the panels are where the answer lands as
   quantity.

   Three layers, and in our own terms they are not decoration:
     the cosmos   what exists  -- every business there is, mostly unscanned
     the weather  what we have measured -- 143 businesses, 715 markets, moving
     the panels   what we can answer -- one question, condensed to a number
   Which keeps us the middle layer rather than the universe, and that is the
   honest position.

   THE ASK LOSES ITS backdrop-filter, and that is the whole trick. A pane that
   blurs what is behind it is a pane in front of the weather. A pane showing a
   DIFFERENT field is a hole through it, and a hole does not blur -- it reveals.
   So the ask stops sampling the backdrop and carries the cosmos as its own
   background instead.

   background-attachment: fixed locks the starfield to the viewport, so it
   reads as one continuous deep field seen through an aperture rather than as
   a texture that happens to be inside a box. Move the aperture and the stars
   stay put, which is what makes it a window.

   The field is written once with a fixed seed rather than randomised per load:
   a sky that is different on every visit is not a sky, it is noise.

   WHY THE STARFIELD CARRIES !important. The base glass rule sets `background:`
   as a SHORTHAND with !important, and a shorthand expands into every longhand
   it covers -- background-image among nine others -- each inheriting that
   priority. An !important declaration beats a later normal one regardless of
   order or specificity, so the field computed to `none` while its own rule sat
   in the stylesheet, parsed, 9,139 characters long, and matching the element.
   The CSSOM said the declaration was present; the cascade said it lost.
   READING A RULE IS NOT READING THE COMPUTED VALUE, and only the second one
   renders. */

.vista > .canvas[data-space="talk"] {
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  background: #060a12 !important;
  overflow: hidden;
}

/* THE VOID: the cosmos, on its own element.
   It lived on the canvas's background and could not move, because the base
   glass rule sets `background:` with !important and the cascade puts important
   author declarations ABOVE animation declarations -- so the keyframe was
   outranked and background-size never changed. An inner element that nothing
   else targets needs no !important and can therefore animate.
   It sits under the form and over nothing, so the ask's text reads on top of
   it. */
.vista > .canvas[data-space="talk"] .void {
  /* A canvas, so the CSS field is gone from here -- it is still used for the
     night sky, where one plane is correct because a sky overhead has no
     parallax to show. Travel needs depth; a backdrop does not. */
  position: absolute; inset: 0; z-index: 0; display: block;
  width: 100%; height: 100%; border-radius: inherit;
}
.vista > .canvas[data-space="talk"] .ask { z-index: 2; }
/* Centred, because the thing you type is the one thing on the screen with no
   fixed left edge to belong to -- it is addressed to the sky, not to a column. */
.vista > .canvas[data-space="talk"] .ask input { text-align: center; }

/* FLOATING THROUGH, NOT DRIFTING ACROSS. A position shift alone is a texture
   sliding. Travel is scale with a little lateral: the field grows as though
   you were moving into it, and alternates so it never snaps back. */
@keyframes cosmos {
  from { transform: scale(1)    translate3d(0, 0, 0); }
  to   { transform: scale(1.22) translate3d(-2.5%, 1.5%, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .vista > .canvas[data-space="talk"] .void { animation: none; }
}


/* ──────────────────────────────────────────────────────────────────────────
   THE NIGHT SIDE OF THE SCALE.
   Victor, 4 Oct: a pilot's view, with the sky running from cloudy through
   sunny and twilight to complete darkness, matching the cosmos behind.

   At the dark end the two layers stop being different things. In daylight the
   weather hides the cosmos and the aperture is the only way through; at night
   the weather is gone and the cosmos IS the sky. So this is the same
   --starfield the ask carries, at full screen, fading in as the scale falls.
   It sits above the clouds and below the panels, so the glass still catches
   it. */
.sky .night {
  position: absolute; inset: 0;
  /* THE BLACK AND THE STARS ARE DIFFERENT QUESTIONS, and the first version
     tied them together. The layer's opacity carries the STARS and answers to
     either dial; its base colour carries the DARK and answers only to the
     light dial. Bound together, clear light at full depth went entirely black
     -- an opaque night laid over a lit sky -- when what it should give is
     stars against blue, which is exactly what altitude looks like. */
  /* THE STARS LEFT THIS LAYER. They are a travelling canvas underneath now,
     and what stays here is the colour of deep space -- nebula only. A flat
     image of stars under a moving field of them was two skies disagreeing,
     and the still one won every argument about whether anything was moving.
     The black went too: the canvas fills its own ground. */
  background-image: var(--nebula);
  background-size: cover;
  background-repeat: no-repeat;
  /* TWO SKIES, TWO DIALS. --stars is how dark it is; --depth is how far
     through you are looking. They are different questions and the cosmos
     answers to whichever is asking harder, so a bright day at full depth shows
     stars -- which is what a pilot at altitude actually sees. */
  /* Moonlight washes the field. At full moon the nebula lifts and the deep
     sky is milkier; at new moon it falls away and the stars are alone on
     black -- which is exactly what a new moon looks like, and the reason the
     darkest setting reads as deep rather than merely unlit. */
  opacity: calc(max(var(--stars, 0), var(--depth, 0)) * (.45 + .55 * var(--moon, 1))
                 * (1 - var(--clear, 0)));
  transition: opacity 1.4s ease;
  animation: cosmos 900s linear infinite alternate;
}
@media (prefers-reduced-motion: reduce) { .sky .night { animation: none; } }

/* The pilot's scale. A slim track in its own lane to the right of the frame,
   quiet until wanted -- an instrument, not a toy. It is a real
   <input type=range> so it arrives keyboard-operable and screen-reader-
   labelled without being rebuilt.

   IT SITS IN THE MIDDLE OF ITS LANE, AND THE LANE IS REAL.
   Victor, 4 Oct: "it has to be a little centered between the extreme right
   and the end of the panel. It's too close to the border right now."
   It was not merely close to the border -- it was PAST it. The frame used the
   whole width bar 2.5rem, so the gutter was 20px and a 22px instrument at
   right:14px overlapped the panels by 16px. Centring alone could not fix that;
   there was nothing to centre it in.

   So the frame gives up --rail of its width and the instrument gets the lane.
   --frame-w is declared ONCE and read twice: the frame sizes from it and the
   gutter is computed from it. Two copies of that expression is a place for
   them to disagree about where the edge is, and then the instrument is
   centred in a lane that is not where the lane is.

   right: gutter/2 with translate: 50% puts the element's CENTRE at gutter/2
   from the window edge -- which is the middle of the lane, exactly. */
:root {
  --rail: 3.25rem;
  --frame-w: min(calc(100vw - 2.5rem - var(--rail)),
                 calc((100dvh - var(--chrome, 8.5rem)) * 16 / 9));
  --gutter: calc((100vw - var(--frame-w)) / 2);
}
.scale {
  position: fixed; right: calc(var(--gutter) / 2); top: 50%; translate: 50% -50%;
  z-index: 20; display: flex; flex-direction: column; align-items: center; gap: 14px;
  opacity: .42; transition: opacity .3s ease;
}
.scale:hover, .scale:focus-within { opacity: 1; }
/* THE TRACK IS SHORTER. Victor, same breath: "the slider should not have too
   much of the range." 150px of travel for a 0..100 value is 1.5px per unit,
   which is precision nobody asked for and a reach that crosses half the
   screen. 84px is still 1 unit per pixel at the step size. */
.scale input {
  writing-mode: vertical-lr; direction: rtl;
  width: 20px; height: 84px; accent-color: var(--ink); cursor: ns-resize;
}
/* The name beside the track rather than above it, so the pair is as tall as
   the LONGER of the two instead of the sum -- three stacked names above three
   stacked tracks did not fit a laptop. */
.scale .pair {
  display: grid; grid-template-columns: auto auto;
  grid-template-areas: "name track" "name value";
  align-items: center; justify-items: center; gap: 3px 2px;
}
.scale .name {
  grid-area: name;
  font: 600 9px/1 ui-monospace, monospace; letter-spacing: .12em;
  text-transform: uppercase; color: var(--ink); opacity: .62;
  writing-mode: vertical-rl; text-orientation: mixed;
}
/* The number is the only thing that moves. Tabular figures so 9 -> 10 -> 100
   does not shift the column, and a fixed min-width so the lane does not
   breathe as you drag. */
.scale output {
  grid-area: value;
  font: 600 9px/1 ui-monospace, monospace; font-variant-numeric: tabular-nums;
  color: var(--ink); opacity: .85; min-width: 20px; text-align: center;
}


/* ──────────────────────────────────────────────────────────────────────────
   ONE ACTIVE SCREEN.
   Victor, 4 Oct: the cursor lands on a panel and it becomes the active screen;
   the rest sit back and blend. The resting state is glassier than before so
   that lighting one up has somewhere to travel from.

   THE ASK IS EXEMPT. It is an aperture onto a different dimension, not a panel
   in the weather, so it neither lights up nor recedes -- every rule here
   excludes it by name.

   NOTHING MOVES AND NOTHING GROWS. The top corners are 16:9 and the side
   middles 9:16, exact to four decimals; a hover scale would make a panel
   briefly not those things. And the cast shadow is contained at 10px inside a
   16px gap so nothing pools in the corners -- so "forward" is carried by tint,
   rim and gloss, exactly as it is on the ask. The only properties that change
   are colour and light.

   hover: hover, or a touch screen has no cursor to leave and panels either
   never activate or stick activated. focus-within comes along so the keyboard
   reaches the same state. */
@media (hover: hover) {
  .vista > .canvas:not([data-space="talk"]) {
    transition: background-color .34s ease, box-shadow .34s ease,
                backdrop-filter .34s ease, opacity .34s ease;
  }

  /* The active screen. */
  /* THE ACTIVE SCREEN LIFTS ITS SURFACE, it no longer thins it.
     This rule used to say --tint: 9% and raise the backdrop-filter, and both
     died the moment the panel became opaque: nothing reads --tint any more,
     and a backdrop-filter behind an opaque surface is invisible work. The
     panel was still "active" in the stylesheet and flat on the screen, with
     only the rim left to say so.
     --lift adds ink to the surface itself, so a hovered panel is a LIGHTER
     panel at the same opacity. The backdrop-filter stays because it is still
     doing real work in the middle of the opacity travel, where the glass is
     genuinely see-through. */
  .vista > .canvas:not([data-space="talk"]):hover,
  .vista > .canvas:not([data-space="talk"]):focus-within {
    --lift: 8%;
    backdrop-filter: blur(3px) saturate(2.5) brightness(1.3) contrast(1.2);
    -webkit-backdrop-filter: blur(3px) saturate(2.5) brightness(1.3) contrast(1.2);
    box-shadow:
      0 0 0 1px color-mix(in srgb, var(--ink) 30%, transparent),
      0 1px 0 color-mix(in srgb, var(--ink) 62%, transparent) inset,
      0 -1px 0 color-mix(in srgb, var(--ink) 26%, transparent) inset,
      0 0 26px -6px color-mix(in srgb, var(--ink) 22%, transparent) inset,
      0 4px 10px -6px color-mix(in srgb, var(--paper) 58%, transparent);
  }
  .vista > .canvas:not([data-space="talk"]):hover::before,
  .vista > .canvas:not([data-space="talk"]):focus-within::before {
    background:
      radial-gradient(120% 70% at 12% -10%,
        color-mix(in srgb, var(--ink) 26%, transparent) 0%, transparent 58%),
      linear-gradient(to bottom,
        color-mix(in srgb, var(--ink) 16%, transparent) 0%,
        color-mix(in srgb, var(--ink) 4%, transparent) 30%,
        transparent 56%);
  }

  /* Everything that is not it. One :has() rule rather than nine, so the state
     belongs to the frame rather than to each panel. */
  .vista:has(> .canvas:not([data-space="talk"]):hover)
    > .canvas:not([data-space="talk"]):not(:hover),
  .vista:has(> .canvas:not([data-space="talk"]):focus-within)
    > .canvas:not([data-space="talk"]):not(:focus-within) {
    --tint: 2%;
    opacity: .82;
  }

  /* The ask holds its own state throughout: it is in a different dimension and
     nothing in the weather should dim it. */
  .vista:has(> .canvas:hover) > .canvas[data-space="talk"],
  .vista:has(> .canvas:focus-within) > .canvas[data-space="talk"] {
    opacity: 1;
  }
}

/* Without a cursor there is no active screen, so the resting tint is a little
   firmer -- nothing is ever going to light up to compensate for it. */
@media (hover: none) {
  .vista > .canvas { --tint: 7%; }
}


/* THE ACTIVE SCREEN SHOWS ITS CONTENT IN FULL.
   Resting, a label sits at 66% of ink and the media is slightly held back --
   which is right for eight panels you are not looking at, and wrong for the one
   you are. Active, everything comes up to full: the heading to near-solid, the
   prose to solid, and the media to its own luminosity rather than the frame's
   average. The ask is excluded here as everywhere. */
@media (hover: hover) {
  .vista > .canvas:not([data-space="talk"]):hover > h2,
  .vista > .canvas:not([data-space="talk"]):focus-within > h2 {
    color: color-mix(in srgb, var(--ink) 92%, transparent) !important;
  }
  .vista > .canvas:not([data-space="talk"]):hover .big,
  .vista > .canvas:not([data-space="talk"]):hover .sub,
  .vista > .canvas:not([data-space="talk"]):hover p,
  .vista > .canvas:not([data-space="talk"]):hover li,
  .vista > .canvas:not([data-space="talk"]):focus-within .big,
  .vista > .canvas:not([data-space="talk"]):focus-within .sub,
  .vista > .canvas:not([data-space="talk"]):focus-within p,
  .vista > .canvas:not([data-space="talk"]):focus-within li {
    color: var(--ink) !important;
    opacity: 1 !important;
    text-shadow:
      0 0 2px  color-mix(in srgb, var(--paper) 88%, transparent),
      0 1px 3px color-mix(in srgb, var(--paper) 82%, transparent),
      0 0 14px color-mix(in srgb, var(--paper) 62%, transparent);
  }
  /* Media at its own luminosity. The resting frame averages everything down;
     the active one lets the film be as bright as it was made. */
  .vista > .canvas:not([data-space="talk"]):hover video,
  .vista > .canvas:not([data-space="talk"]):hover img,
  .vista > .canvas:not([data-space="talk"]):focus-within video,
  .vista > .canvas:not([data-space="talk"]):focus-within img {
    filter: saturate(1.12) brightness(1.08) contrast(1.04);
    transition: filter .34s ease;
  }

  /* GLOSSIER WHEN ACTIVE: a second specular across the upper third on top of
     the bloom, so the active panel reads as a polished surface catching the
     sky rather than simply a brighter rectangle. */
  /* The active panel brightens ITS SHARE of the one sheen rather than
     acquiring a highlight of its own -- a second light would put the frame
     back to having nine suns, just one of them brighter. Filtering the same
     fixed field keeps the geometry of the light intact. */
  .vista > .canvas:not([data-space="talk"]):hover::before,
  .vista > .canvas:not([data-space="talk"]):focus-within::before {
    filter: brightness(1.45) saturate(1.1);
  }
}


/* ──────────────────────────────────────────────────────────────────────────
   PRESENCE: the screen dissolving into the sky.

   Victor, 4 Oct. On a laptop, opaque is free and transparent is a trick. On
   glasses it inverts: see-through is the ground state and every opaque pixel
   is stolen world. So a panel has to be able to go all the way to nothing --
   not hidden, which leaves a hole where it was, but DISSOLVED, which leaves
   sky.

   Three states were not enough. Active, resting and receded are all degrees of
   being present. This is the fourth, and it is the one the medium actually
   demands: zero.

   --presence multiplies everything that makes a panel visible: its tint, its
   rim, its blur and its shadow. At 1 the frame is what it was. At 0 the glass
   is gone, the backdrop is unfiltered, and what is left is the weather with
   some text floating in it -- which is the honest end state, because the words
   are the only part that was ever load-bearing.

   THE GEOMETRY NEVER MOVES. A dissolved panel keeps its cell, its aspect and
   its gap. A pilot's panel is constant across every aircraft they fly, and
   that constancy is what lets them be expert in an unfamiliar cockpit: the
   altimeter is where the altimeter is. If dissolving reflowed the grid, the
   nine would stop being a place and become a list. */
/* The default lives on the FRAME, not on each panel. Declaring --presence on
   .canvas shadowed the value the dial writes to .vista, so every panel read
   its own 1 and the control did nothing -- the variable was set, inherited,
   and immediately overridden one level down. A custom property is only a
   channel if nothing downstream redeclares it. */
/* THE PANEL IS A SURFACE, NOT A WINDOW — at full opacity.
   Victor, 4 Oct: "on my 100% opacity for the canvases I should have 100%
   opacity of the background screen... I do not want to see the star-like dots
   when the opacity is 100%."

   It was a 5% film over a blur, so at the top of the travel a panel was still
   a pane of glass with the cosmos legible through it. 100% that you can see
   stars through is not 100%. So the film now runs the WHOLE way: alpha is the
   opacity slider, flat, and at 1 the panel is opaque.

   It takes its colour from the sky rather than from the pack, because a solid
   panel in a twilight sky and the same panel at dark night should not be the
   same colour — "they should hold a particular hue that their background is
   taking". --t is the sky dial, so the surface walks with it.

   The two sliders split cleanly now, which they did not before:
     opacity     the ALPHA of this surface
     brightness  how light the surface IS
   Previously brightness also thinned the film, so turning it down made the
   panel more transparent as well as darker — two controls on one property. */
.vista {
  --presence: 1;
  --night-panel: #0a0f18;
  --sky-tint: color-mix(in srgb, var(--teal) calc(var(--t, 0) * 30%), var(--night-panel));
}
/* --panel is computed PER CANVAS, not on .vista, because the active state has
   to change it and a value declared upstream cannot be lifted downstream. The
   inputs it reads -- --sky-tint, --moon, --presence -- stay above it, which
   is the rule that matters: the channel a dial writes to must not be
   redeclared below it. Only the derived colour lives here. */
/* ── A PANEL GLOWS IN THE DARK ──────────────────────────────────────────
   Victor, 4 Oct: "in pure dark we want a 3D look for each of these panels by
   having a white shade behind them so that they look like they are glowing."

   It is a cast glow, not a border: a wide soft white spread BEHIND the panel,
   so the dark around each one is lifted and the panel reads as sitting in
   front of it. A rim would outline the shape; a halo separates it from the
   ground, which is what 3D means here.

   --dark is 1 when there is no day sky left, so the glow belongs to the night
   and is absent at noon -- a halo behind a panel on a bright sky is just fog.
   It also follows --presence: a panel fading out must not leave its own light
   hanging where it used to be, which is the empty-frame failure one layer
   further back.

   The shadow is contained rather than huge. §5 records a 52px blur pooling in
   the interior corners of a 16px gap; this is 26px of spread at low alpha,
   which lifts the seam without filling it. */
:root { --dark: 0; }   /* on :root, where the dial writes it */
.vista > .canvas:not([data-space="talk"]) {
  /* THE RIM IS REPEATED HERE ON PURPOSE, and leaving it out was the bug.
     box-shadow does not accumulate across rules -- the winning declaration
     REPLACES the whole list -- so a glow written in a later, more specific
     rule silently deleted the specular ring, the lit top edge and the
     reflected foot. Order carries the rest: the first shadow paints on top,
     so the rim comes first and the light goes last, behind everything.

     THE LIGHT AND THE SHADOW TRADE PLACES ACROSS THE DAY.
     Victor, 4 Oct: "as we scroll the sky from dark to light, the shade behind
     it should go from light to dark -- in the bright skies it should be the
     shadow, and in the darkest sky it should be the light."
     That is what actually happens to an object: a lit room casts a shadow
     under it, a dark room puts a light behind it. One crossfade on --dark
     rather than two effects that both try to be on at once.

     AND IT IS SMALL. The first attempt was 26px and 78px of spread, which at
     nine panels filled the 16px seams completely -- so the halo ate the stars
     in the only place the sky is visible at full opacity, which is why the
     night sky appeared to have gone. "It should not be that
     Gaussian-distributed. It should be small." 13px and 5px of contact: a
     bias light is a bright line around the bezel, not a fog bank.

     The white ring comes DOWN in the dark rather than up. The previous pass
     brightened it to 29% so the edge would read against the halo, and on a
     black ground that is simply a white outline -- "that white border is not
     helping". With a tight glow the edge no longer has to shout over it. */
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--ink)
      calc((15% - 6% * var(--dark)) * var(--presence)), transparent),
    0 1px 0 color-mix(in srgb, var(--ink) calc(30% * var(--presence)), transparent) inset,
    0 -1px 0 color-mix(in srgb, var(--ink) calc(12% * var(--presence)), transparent) inset,
    inset 0 -14px 20px -16px color-mix(in srgb, var(--paper) 70%, transparent),
    /* DAY: a cast shadow under the panel, which is what a lit room does. */
    0 5px 12px -7px color-mix(in srgb, var(--paper)
      calc(62% * (1 - var(--dark)) * var(--presence)), transparent),
    /* NIGHT: a bias light behind it, tight to the bezel. The negative spread
       pulls the shadow's edge inside the panel before the blur runs, so the
       brightest part is hidden behind an opaque surface and only the falloff
       escapes -- the screen is in front of the light. */
    0 0 13px -5px color-mix(in srgb, #cfe4ff
      calc(34% * var(--dark) * var(--presence)), transparent);
}

.vista > .canvas {
  --lift: 0%;
  --panel: color-mix(in srgb, var(--ink)
            calc(var(--moon, 1) * 10% + var(--lift)), var(--sky-tint));
}
@media (hover: hover) {
  .vista > .canvas:not([data-space="talk"]) {
    /* The same light film as the base rule. This one carries presence as well,
       and it is the LATER of the two !important declarations, so it is the one
       that actually paints -- leaving it on --card meant the base rule flipped
       to a light tint and nothing changed on screen. Two rules setting one
       property is a place for them to disagree, and they did. */
    background: color-mix(in srgb, var(--panel) calc(var(--presence, 1) * 100%), transparent) !important;
    /* THE PANE IS CLEARER THAN THE GROUND. This is the correction, and it is
       the opposite of what the last attempt did.
       A heavy blur plus a white film makes milk glass -- which is why the
       result went pale. Apple's pane does not fog what is behind it; it shows
       the same thing SHARPER and more colourful than the surround, so the
       panel reads as a lens rather than as frosting. The blur drops from 22px
       to 6, the film from 10% to 5, and saturation carries the difference.
       The sky behind stays soft; the sky through the glass is the crisp part. */
    /* NO BLUR. Victor, 4 Oct: "why is the image blurry... it's not giving the
       look of a person going through the clouds."
       That blur was mine and it peaked at exactly the wrong place: 32 x p x
       (1-p) is 8px at half opacity, which is the setting where you are
       LOOKING THROUGH the panel on purpose. Frosting the sky there is the
       opposite of the correction this file already records -- the pane is
       CLEARER than the ground, not milkier. Saturate and contrast stay,
       because those are what make a pane read as a lens; blur is what makes
       it read as frosted glass, and it also costs the most GPU of the four. */
    backdrop-filter: saturate(calc(1 + 1.1 * var(--presence)))
                     brightness(calc((1 + .22 * var(--presence)) * (.3 + .7 * var(--moon, 1))))
                     contrast(calc(1 + .14 * var(--presence)));
    -webkit-backdrop-filter: saturate(calc(1 + 1.1 * var(--presence)))
                     brightness(calc((1 + .22 * var(--presence)) * (.3 + .7 * var(--moon, 1))))
                     contrast(calc(1 + .14 * var(--presence)));
  }
}
/* The rim and the gloss fade with it, or a dissolved panel keeps a bright
   outline and reads as an empty frame rather than as open sky.

   IT REACHES ZERO NOW. Victor, 4 Oct: "the media displayed over there should
   go from opaque to transparent... the opacity, too, should be from 0 to 100."
   The old floor of .18 meant the bottom of the travel left nine faint ghosts
   on the sky -- which is the empty-frame failure this comment warns about,
   just dimmer. 0 is 0, media and words and rim together, and the panel's CELL
   is still there: the geometry never moves, so nothing reflows and the frame
   comes back exactly where it went.

   Safe to reach only because the ask is exempt and you can still talk. */
.vista > .canvas:not([data-space="talk"]) {
  opacity: var(--presence);
}

/* BRIGHTNESS: HOW LIT THE SCREEN IS WHEN IT IS THERE.
   Victor's third slider, and separate from opacity on purpose -- a dark panel
   at full opacity is a screen switched off and still in front of you, while a
   bright panel at low opacity is a screen getting out of the way.

   --moon runs 0..1, full moon to new, and 1 is the designed look, so 100 changes
   nothing and the whole travel is downward. It dims rather than boosts because
   above the designed value the film blows out and the glass stops reading as
   glass -- the headroom would be range nobody can use, which is the same
   mistake the sky dial just had removed from it.

   Two things carry it: the film and the backdrop (the glass's own light), and
   the media (what is being shown on it). A screen turned down shows a dimmer
   picture; that is what makes it read as brightness rather than as fog. */
/* THE MOON LIVES ON :root, NOT ON .vista, because it is no longer a panel
   setting. Victor, 4 Oct: "the brightness I am imagining is the moonlight...
   the sky is the sky that looks like the sky when the moon has that kind of
   lighting." A light source lights the SCENE -- the vault, the night air and
   the panels alike -- so it cannot live inside the thing it lights. */
:root { --moon: 1; }
.vista > .canvas:not([data-space="talk"]) > :is(img, video, canvas, .strip, .tick) {
  filter: brightness(calc(.3 + .7 * var(--moon, 1)));
  transition: filter .2s ease;
}
.vista > .canvas:not([data-space="talk"])::before {
  opacity: var(--presence);
}

/* A panel dissolved on its own, by double-click. The one you do not want is
   not always the same one, so this is per-panel rather than only global. */
.vista > .canvas.dissolved { --presence: 0 !important; }

/* THE ASK'S BOX ANSWERS TO THE OPACITY DIAL; ITS INSIDE DOES NOT.
   Victor, 4 Oct: "as we go to zero opacity the box should disappear, and as we
   up the opacity the box should appear -- except that this box is cut into the
   cosmos without opaquing."

   It used to force --presence: 1, which exempted it from the dial entirely so
   the frame could never be turned off. Two different things were being
   protected by one declaration: that you can always TALK, and that the aperture
   never becomes a solid panel. Only the first needs the exemption.

   So --presence is inherited now and the box follows it, while opacity: 1
   stays -- the element itself never fades, so the field you type in is there at
   every setting. The box around it is what comes and goes. */
.vista > .canvas[data-space="talk"] { opacity: 1 !important; }


/* Two canvases carry their name for the machine and not for the eye: the
   wordmark is its own heading, and a tagline with a label above it is a
   caption. nine.js REFUSES a contract with a missing label -- correctly, since
   a canvas without a name is unaddressable -- so they are hidden visually
   rather than omitted, and stay available to a screen reader. */
.vista > .canvas[data-space="ledger"] > h2,
.vista > .canvas[data-space="figure"] > h2 {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.vista > .canvas[data-space="ledger"],
.vista > .canvas[data-space="figure"] {
  display: flex; flex-direction: column; justify-content: center;
}


/* THE ASK KEEPS ITS OWN LIGHT, and it must: the sheen above belongs to the
   SKY, and the ask is a hole through the sky rather than a pane of it. A
   window onto the cosmos catching the weather's highlight would say the two
   layers are the same layer.
   So this overrides the shared field for one panel: a quiet travelling
   specular of its own, resting for most of the cycle and crossing in the
   remainder, so it is a glint rather than a loop. */
.vista > .canvas[data-space="talk"]::before {
  background:
    linear-gradient(104deg,
      transparent 26%,
      color-mix(in srgb, var(--ink) 7%, transparent) 44%,
      color-mix(in srgb, var(--ink) 14%, transparent) 50%,
      color-mix(in srgb, var(--ink) 7%, transparent) 56%,
      transparent 74%),
    radial-gradient(150% 220% at 8% -60%,
      color-mix(in srgb, var(--ink) 14%, transparent) 0%,
      color-mix(in srgb, var(--ink) 4%, transparent) 38%,
      transparent 70%);
  background-attachment: scroll;
  background-size: 260% 100%, 100% 100%;
  background-position: 160% 0, 0 0;
  background-repeat: no-repeat;
  animation: sheen 19s cubic-bezier(.45,0,.3,1) infinite;
  z-index: 1;
}
@keyframes sheen {
  0%, 78%  { background-position: 160% 0, 0 0; }
  100%     { background-position: -60% 0, 0 0; }
}
@media (prefers-reduced-motion: reduce) {
  .vista > .canvas[data-space="talk"]::before { animation: none; }
}


/* THE ASK AND THE COSMOS BECOME ONE FIELD, by EITHER route.
 *
 * Victor's model, and it is the right one: there are three layers. The cosmos
 * underneath, the nine canvases on top, and a LIGHT layer that slides in
 * between as the day dial rises -- weather laid over the deep field. The ask
 * is not part of that stack. It talks to the cosmos always, which is why the
 * light layer never applies to it.
 *
 * So the aperture stops being a cut whenever the thing it cuts through is
 * gone, and there are two ways for that to happen: pull the depth dial to the
 * bottom, or take the light away. --depth and --stars are the two measures,
 * and the ask answers to whichever is larger -- max(), not a sum, because
 * being at depth AND in the dark is not twice as dissolved as either.
 *
 * Its base, rim and gloss fade; the travelling starfield stays, so the frame
 * keeps moving through space and simply stops having a frame around that
 * movement. */
.vista > .canvas[data-space="talk"] {
  --merge: max(var(--depth, 0), var(--stars, 0));
  /* CUT INTO THE COSMOS WITHOUT OPAQUING. The fill is capped well below solid
     and scaled by the dial, so turning opacity up gives the box a body you can
     read text against and never a lid over the starfield, and turning it to
     zero leaves the cosmos alone. .62 at the top, not 1. */
  background-color: rgba(6, 10, 18,
    calc((1 - var(--merge) * .94) * var(--presence, 1) * .62)) !important;
  transition: background-color 1.4s ease, box-shadow 1.4s ease;
}
.vista > .canvas[data-space="talk"]::before {
  opacity: calc((1 - var(--merge)) * var(--presence, 1));
}
/* THE APERTURE HANDS OVER COMPLETELY. At .5 the ask kept half of its OWN
   field while the window behind it showed another, so the one place that is
   meant to be continuous sky had two independent star patterns in it and a
   visible rectangle where they met. At 0 the ask is a hole onto the same
   cosmos, which is what it always claimed to be. */
.vista > .canvas[data-space="talk"] .void {
  opacity: calc(1 - var(--merge));
  transition: opacity 1.4s ease;
}
/* The rim goes too, or a dissolved aperture keeps a bright outline and reads
   as an empty frame rather than as continuous sky. */
.vista > .canvas[data-space="talk"] {
  /* THE BOX IS THE DIAL'S, NOT THE SKY'S. Every line here used to be scaled by
     (1 - merge), so a dark sky took the frame to zero and the ask had no box at
     all at full opacity -- which is where it went. Merge still governs what the
     box CONTAINS: it stays a cut onto the cosmos either way. What the box IS
     answers to the opacity dial, like every other canvas. */
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--ink) calc(34% * var(--presence, 1)), transparent),
    0 1px 0 color-mix(in srgb, var(--ink) calc(62% * var(--presence, 1)), transparent) inset,
    0 -1px 0 color-mix(in srgb, var(--ink) calc(28% * var(--presence, 1)), transparent) inset,
    0 0 22px -6px color-mix(in srgb, var(--ink) calc(20% * var(--presence, 1)), transparent) inset,
    0 6px 14px -8px color-mix(in srgb, var(--paper) calc(52% * var(--presence, 1)), transparent);
}
