* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

:root {
    --accent: #3d2a5c;
    --accent-2: #2ba7a3;
    --accent-mid: #4f5a73;
    --panel-bg: rgba(255, 255, 255, 0.66);
    --panel-border: rgba(0, 0, 0, 0.12);
    --text-main: #262626;
    --text-dim: #5a5a5a;
}

body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
    color: var(--text-main);
    padding: 40px 20px;
    overflow-x: hidden;
    /* Not a mood gradient: an actual polarization-axis field, computed
       point by point from Malus's law itself. Each short mark is the
       transmission axis of a polarizer rotating smoothly left to right
       (0deg -> 180deg); its length is the real cos^2(theta) transmitted
       amplitude at that angle, so marks shrink to almost nothing near
       the crossed (90deg) angle and grow again as they realign — the
       same relationship the sliders and ladder compute live, just laid
       out once across the page instead of animated in the stage. */
    background-image:
        url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%221600%22%20height%3D%22900%22%20viewBox%3D%220%200%201600%20900%22%3E%3Cg%20stroke%3D%22%233d2a5c%22%20stroke-width%3D%225%22%20stroke-linecap%3D%22round%22%3E%3Cline%20x1%3D%220%22%20y1%3D%2233%22%20x2%3D%220%22%20y2%3D%2267%22%20stroke-opacity%3D%220.31%22/%3E%3Cline%20x1%3D%2296.8%22%20y1%3D%2233.8%22%20x2%3D%22103.2%22%20y2%3D%2266.2%22%20stroke-opacity%3D%220.30%22/%3E%3Cline%20x1%3D%22194.3%22%20y1%3D%2236.2%22%20x2%3D%22205.7%22%20y2%3D%2263.8%22%20stroke-opacity%3D%220.28%22/%3E%3Cline%20x1%3D%22293%22%20y1%3D%2239.5%22%20x2%3D%22307%22%20y2%3D%2260.5%22%20stroke-opacity%3D%220.24%22/%3E%3Cline%20x1%3D%22392.9%22%20y1%3D%2242.9%22%20x2%3D%22407.1%22%20y2%3D%2257.1%22%20stroke-opacity%3D%220.20%22/%3E%3Cline%20x1%3D%22493.9%22%20y1%3D%2245.9%22%20x2%3D%22506.1%22%20y2%3D%2254.1%22%20stroke-opacity%3D%220.16%22/%3E%3Cline%20x1%3D%22595.3%22%20y1%3D%2248.1%22%20x2%3D%22604.7%22%20y2%3D%2251.9%22%20stroke-opacity%3D%220.12%22/%3E%3Cline%20x1%3D%22696.5%22%20y1%3D%2249.3%22%20x2%3D%22703.5%22%20y2%3D%2250.7%22%20stroke-opacity%3D%220.10%22/%3E%3Cline%20x1%3D%22797%22%20y1%3D%2250%22%20x2%3D%22803%22%20y2%3D%2250%22%20stroke-opacity%3D%220.09%22/%3E%3Cline%20x1%3D%22896.5%22%20y1%3D%2250.7%22%20x2%3D%22903.5%22%20y2%3D%2249.3%22%20stroke-opacity%3D%220.10%22/%3E%3Cline%20x1%3D%22995.3%22%20y1%3D%2251.9%22%20x2%3D%221004.7%22%20y2%3D%2248.1%22%20stroke-opacity%3D%220.12%22/%3E%3Cline%20x1%3D%221093.9%22%20y1%3D%2254.1%22%20x2%3D%221106.1%22%20y2%3D%2245.9%22%20stroke-opacity%3D%220.16%22/%3E%3Cline%20x1%3D%221192.9%22%20y1%3D%2257.1%22%20x2%3D%221207.1%22%20y2%3D%2242.9%22%20stroke-opacity%3D%220.20%22/%3E%3Cline%20x1%3D%221293%22%20y1%3D%2260.5%22%20x2%3D%221307%22%20y2%3D%2239.5%22%20stroke-opacity%3D%220.24%22/%3E%3Cline%20x1%3D%221394.3%22%20y1%3D%2263.8%22%20x2%3D%221405.7%22%20y2%3D%2236.2%22%20stroke-opacity%3D%220.28%22/%3E%3Cline%20x1%3D%221496.8%22%20y1%3D%2266.2%22%20x2%3D%221503.2%22%20y2%3D%2233.8%22%20stroke-opacity%3D%220.30%22/%3E%3Cline%20x1%3D%221600%22%20y1%3D%2267%22%20x2%3D%221600%22%20y2%3D%2233%22%20stroke-opacity%3D%220.31%22/%3E%3Cline%20x1%3D%22-3.4%22%20y1%3D%22234%22%20x2%3D%223.4%22%20y2%3D%22266%22%20stroke-opacity%3D%220.30%22/%3E%3Cline%20x1%3D%2294.2%22%20y1%3D%22236.4%22%20x2%3D%22105.8%22%20y2%3D%22263.6%22%20stroke-opacity%3D%220.28%22/%3E%3Cline%20x1%3D%22192.9%22%20y1%3D%22239.7%22%20x2%3D%22207.1%22%20y2%3D%22260.3%22%20stroke-opacity%3D%220.24%22/%3E%3Cline%20x1%3D%22293%22%20y1%3D%22243.1%22%20x2%3D%22307%22%20y2%3D%22256.9%22%20stroke-opacity%3D%220.20%22/%3E%3Cline%20x1%3D%22394%22%20y1%3D%22246.1%22%20x2%3D%22406%22%20y2%3D%22253.9%22%20stroke-opacity%3D%220.16%22/%3E%3Cline%20x1%3D%22495.4%22%20y1%3D%22248.2%22%20x2%3D%22504.6%22%20y2%3D%22251.8%22%20stroke-opacity%3D%220.12%22/%3E%3Cline%20x1%3D%22596.6%22%20y1%3D%22249.4%22%20x2%3D%22603.4%22%20y2%3D%22250.6%22%20stroke-opacity%3D%220.10%22/%3E%3Cline%20x1%3D%22697%22%20y1%3D%22250%22%20x2%3D%22703%22%20y2%3D%22250%22%20stroke-opacity%3D%220.09%22/%3E%3Cline%20x1%3D%22796.5%22%20y1%3D%22250.7%22%20x2%3D%22803.5%22%20y2%3D%22249.3%22%20stroke-opacity%3D%220.10%22/%3E%3Cline%20x1%3D%22895.2%22%20y1%3D%22252%22%20x2%3D%22904.8%22%20y2%3D%22248%22%20stroke-opacity%3D%220.12%22/%3E%3Cline%20x1%3D%22993.8%22%20y1%3D%22254.2%22%20x2%3D%221006.2%22%20y2%3D%22245.8%22%20stroke-opacity%3D%220.16%22/%3E%3Cline%20x1%3D%221092.9%22%20y1%3D%22257.3%22%20x2%3D%221107.1%22%20y2%3D%22242.7%22%20stroke-opacity%3D%220.20%22/%3E%3Cline%20x1%3D%221193%22%20y1%3D%22260.8%22%20x2%3D%221207%22%20y2%3D%22239.2%22%20stroke-opacity%3D%220.24%22/%3E%3Cline%20x1%3D%221294.4%22%20y1%3D%22264%22%20x2%3D%221305.6%22%20y2%3D%22236%22%20stroke-opacity%3D%220.28%22/%3E%3Cline%20x1%3D%221397%22%20y1%3D%22266.3%22%20x2%3D%221403%22%20y2%3D%22233.7%22%20stroke-opacity%3D%220.30%22/%3E%3Cline%20x1%3D%221500.2%22%20y1%3D%22267%22%20x2%3D%221499.8%22%20y2%3D%22233%22%20stroke-opacity%3D%220.31%22/%3E%3Cline%20x1%3D%221603.4%22%20y1%3D%22266%22%20x2%3D%221596.6%22%20y2%3D%22234%22%20stroke-opacity%3D%220.30%22/%3E%3Cline%20x1%3D%22-6%22%20y1%3D%22436.6%22%20x2%3D%226%22%20y2%3D%22463.4%22%20stroke-opacity%3D%220.27%22/%3E%3Cline%20x1%3D%2292.9%22%20y1%3D%22439.9%22%20x2%3D%22107.1%22%20y2%3D%22460.1%22%20stroke-opacity%3D%220.24%22/%3E%3Cline%20x1%3D%22193%22%20y1%3D%22443.4%22%20x2%3D%22207%22%20y2%3D%22456.6%22%20stroke-opacity%3D%220.19%22/%3E%3Cline%20x1%3D%22294.1%22%20y1%3D%22446.3%22%20x2%3D%22305.9%22%20y2%3D%22453.7%22%20stroke-opacity%3D%220.15%22/%3E%3Cline%20x1%3D%22395.5%22%20y1%3D%22448.3%22%20x2%3D%22404.5%22%20y2%3D%22451.7%22%20stroke-opacity%3D%220.12%22/%3E%3Cline%20x1%3D%22496.6%22%20y1%3D%22449.4%22%20x2%3D%22503.4%22%20y2%3D%22450.6%22%20stroke-opacity%3D%220.10%22/%3E%3Cline%20x1%3D%22597%22%20y1%3D%22450.1%22%20x2%3D%22603%22%20y2%3D%22449.9%22%20stroke-opacity%3D%220.09%22/%3E%3Cline%20x1%3D%22696.4%22%20y1%3D%22450.8%22%20x2%3D%22703.6%22%20y2%3D%22449.2%22%20stroke-opacity%3D%220.10%22/%3E%3Cline%20x1%3D%22795.1%22%20y1%3D%22452.2%22%20x2%3D%22804.9%22%20y2%3D%22447.8%22%20stroke-opacity%3D%220.13%22/%3E%3Cline%20x1%3D%22893.7%22%20y1%3D%22454.4%22%20x2%3D%22906.3%22%20y2%3D%22445.6%22%20stroke-opacity%3D%220.16%22/%3E%3Cline%20x1%3D%22992.9%22%20y1%3D%22457.5%22%20x2%3D%221007.1%22%20y2%3D%22442.5%22%20stroke-opacity%3D%220.21%22/%3E%3Cline%20x1%3D%221093.1%22%20y1%3D%22461%22%20x2%3D%221106.9%22%20y2%3D%22439%22%20stroke-opacity%3D%220.25%22/%3E%3Cline%20x1%3D%221194.6%22%20y1%3D%22464.2%22%20x2%3D%221205.4%22%20y2%3D%22435.8%22%20stroke-opacity%3D%220.28%22/%3E%3Cline%20x1%3D%221297.2%22%20y1%3D%22466.4%22%20x2%3D%221302.8%22%20y2%3D%22433.6%22%20stroke-opacity%3D%220.30%22/%3E%3Cline%20x1%3D%221400.4%22%20y1%3D%22467%22%20x2%3D%221399.6%22%20y2%3D%22433%22%20stroke-opacity%3D%220.31%22/%3E%3Cline%20x1%3D%221503.6%22%20y1%3D%22465.9%22%20x2%3D%221496.4%22%20y2%3D%22434.1%22%20stroke-opacity%3D%220.30%22/%3E%3Cline%20x1%3D%221606%22%20y1%3D%22463.4%22%20x2%3D%221594%22%20y2%3D%22436.6%22%20stroke-opacity%3D%220.27%22/%3E%3Cline%20x1%3D%22-7.1%22%20y1%3D%22640.2%22%20x2%3D%227.1%22%20y2%3D%22659.8%22%20stroke-opacity%3D%220.23%22/%3E%3Cline%20x1%3D%2293.1%22%20y1%3D%22643.6%22%20x2%3D%22106.9%22%20y2%3D%22656.4%22%20stroke-opacity%3D%220.19%22/%3E%3Cline%20x1%3D%22194.2%22%20y1%3D%22646.4%22%20x2%3D%22205.8%22%20y2%3D%22653.6%22%20stroke-opacity%3D%220.15%22/%3E%3Cline%20x1%3D%22295.6%22%20y1%3D%22648.4%22%20x2%3D%22304.4%22%20y2%3D%22651.6%22%20stroke-opacity%3D%220.12%22/%3E%3Cline%20x1%3D%22396.7%22%20y1%3D%22649.5%22%20x2%3D%22403.3%22%20y2%3D%22650.5%22%20stroke-opacity%3D%220.10%22/%3E%3Cline%20x1%3D%22497%22%20y1%3D%22650.1%22%20x2%3D%22503%22%20y2%3D%22649.9%22%20stroke-opacity%3D%220.09%22/%3E%3Cline%20x1%3D%22596.3%22%20y1%3D%22650.9%22%20x2%3D%22603.7%22%20y2%3D%22649.1%22%20stroke-opacity%3D%220.10%22/%3E%3Cline%20x1%3D%22695%22%20y1%3D%22652.3%22%20x2%3D%22705%22%20y2%3D%22647.7%22%20stroke-opacity%3D%220.13%22/%3E%3Cline%20x1%3D%22793.7%22%20y1%3D%22654.6%22%20x2%3D%22806.3%22%20y2%3D%22645.4%22%20stroke-opacity%3D%220.17%22/%3E%3Cline%20x1%3D%22892.8%22%20y1%3D%22657.7%22%20x2%3D%22907.2%22%20y2%3D%22642.3%22%20stroke-opacity%3D%220.21%22/%3E%3Cline%20x1%3D%22993.1%22%20y1%3D%22661.2%22%20x2%3D%221006.9%22%20y2%3D%22638.8%22%20stroke-opacity%3D%220.25%22/%3E%3Cline%20x1%3D%221094.7%22%20y1%3D%22664.4%22%20x2%3D%221105.3%22%20y2%3D%22635.6%22%20stroke-opacity%3D%220.28%22/%3E%3Cline%20x1%3D%221197.4%22%20y1%3D%22666.5%22%20x2%3D%221202.6%22%20y2%3D%22633.5%22%20stroke-opacity%3D%220.30%22/%3E%3Cline%20x1%3D%221300.7%22%20y1%3D%22667%22%20x2%3D%221299.3%22%20y2%3D%22633%22%20stroke-opacity%3D%220.31%22/%3E%3Cline%20x1%3D%221403.8%22%20y1%3D%22665.8%22%20x2%3D%221396.2%22%20y2%3D%22634.2%22%20stroke-opacity%3D%220.30%22/%3E%3Cline%20x1%3D%221506.1%22%20y1%3D%22663.2%22%20x2%3D%221493.9%22%20y2%3D%22636.8%22%20stroke-opacity%3D%220.27%22/%3E%3Cline%20x1%3D%221607.1%22%20y1%3D%22659.8%22%20x2%3D%221592.9%22%20y2%3D%22640.2%22%20stroke-opacity%3D%220.23%22/%3E%3Cline%20x1%3D%22-6.9%22%20y1%3D%22843.8%22%20x2%3D%226.9%22%20y2%3D%22856.2%22%20stroke-opacity%3D%220.19%22/%3E%3Cline%20x1%3D%2294.3%22%20y1%3D%22846.6%22%20x2%3D%22105.7%22%20y2%3D%22853.4%22%20stroke-opacity%3D%220.15%22/%3E%3Cline%20x1%3D%22195.7%22%20y1%3D%22848.5%22%20x2%3D%22204.3%22%20y2%3D%22851.5%22%20stroke-opacity%3D%220.11%22/%3E%3Cline%20x1%3D%22296.7%22%20y1%3D%22849.5%22%20x2%3D%22303.3%22%20y2%3D%22850.5%22%20stroke-opacity%3D%220.09%22/%3E%3Cline%20x1%3D%22397%22%20y1%3D%22850.2%22%20x2%3D%22403%22%20y2%3D%22849.8%22%20stroke-opacity%3D%220.09%22/%3E%3Cline%20x1%3D%22496.3%22%20y1%3D%22850.9%22%20x2%3D%22503.7%22%20y2%3D%22849.1%22%20stroke-opacity%3D%220.10%22/%3E%3Cline%20x1%3D%22595%22%20y1%3D%22852.4%22%20x2%3D%22605%22%20y2%3D%22847.6%22%20stroke-opacity%3D%220.13%22/%3E%3Cline%20x1%3D%22693.6%22%20y1%3D%22854.8%22%20x2%3D%22706.4%22%20y2%3D%22845.2%22%20stroke-opacity%3D%220.17%22/%3E%3Cline%20x1%3D%22792.8%22%20y1%3D%22858%22%20x2%3D%22807.2%22%20y2%3D%22842%22%20stroke-opacity%3D%220.21%22/%3E%3Cline%20x1%3D%22893.2%22%20y1%3D%22861.5%22%20x2%3D%22906.8%22%20y2%3D%22838.5%22%20stroke-opacity%3D%220.25%22/%3E%3Cline%20x1%3D%22994.8%22%20y1%3D%22864.6%22%20x2%3D%221005.2%22%20y2%3D%22835.4%22%20stroke-opacity%3D%220.29%22/%3E%3Cline%20x1%3D%221097.6%22%20y1%3D%22866.5%22%20x2%3D%221102.4%22%20y2%3D%22833.5%22%20stroke-opacity%3D%220.31%22/%3E%3Cline%20x1%3D%221200.9%22%20y1%3D%22866.9%22%20x2%3D%221199.1%22%20y2%3D%22833.1%22%20stroke-opacity%3D%220.31%22/%3E%3Cline%20x1%3D%221304%22%20y1%3D%22865.7%22%20x2%3D%221296%22%20y2%3D%22834.3%22%20stroke-opacity%3D%220.30%22/%3E%3Cline%20x1%3D%221406.2%22%20y1%3D%22863%22%20x2%3D%221393.8%22%20y2%3D%22837%22%20stroke-opacity%3D%220.27%22/%3E%3Cline%20x1%3D%221507.2%22%20y1%3D%22859.6%22%20x2%3D%221492.8%22%20y2%3D%22840.4%22%20stroke-opacity%3D%220.23%22/%3E%3Cline%20x1%3D%221606.9%22%20y1%3D%22856.2%22%20x2%3D%221593.1%22%20y2%3D%22843.8%22%20stroke-opacity%3D%220.19%22/%3E%3C/g%3E%3Cg%20stroke%3D%22%232ba7a3%22%20stroke-width%3D%225%22%20stroke-linecap%3D%22round%22%3E%3Cline%20x1%3D%22-1.8%22%20y1%3D%22133.2%22%20x2%3D%221.8%22%20y2%3D%22166.8%22%20stroke-opacity%3D%220.31%22/%3E%3Cline%20x1%3D%2295.3%22%20y1%3D%22134.9%22%20x2%3D%22104.7%22%20y2%3D%22165.1%22%20stroke-opacity%3D%220.29%22/%3E%3Cline%20x1%3D%22193.4%22%20y1%3D%22137.9%22%20x2%3D%22206.6%22%20y2%3D%22162.1%22%20stroke-opacity%3D%220.26%22/%3E%3Cline%20x1%3D%22292.8%22%20y1%3D%22141.3%22%20x2%3D%22307.2%22%20y2%3D%22158.7%22%20stroke-opacity%3D%220.22%22/%3E%3Cline%20x1%3D%22393.4%22%20y1%3D%22144.6%22%20x2%3D%22406.6%22%20y2%3D%22155.4%22%20stroke-opacity%3D%220.18%22/%3E%3Cline%20x1%3D%22494.7%22%20y1%3D%22147.2%22%20x2%3D%22505.3%22%20y2%3D%22152.8%22%20stroke-opacity%3D%220.14%22/%3E%3Cline%20x1%3D%22596%22%20y1%3D%22148.8%22%20x2%3D%22604%22%20y2%3D%22151.2%22%20stroke-opacity%3D%220.11%22/%3E%3Cline%20x1%3D%22696.9%22%20y1%3D%22149.7%22%20x2%3D%22703.1%22%20y2%3D%22150.3%22%20stroke-opacity%3D%220.09%22/%3E%3Cline%20x1%3D%22796.9%22%20y1%3D%22150.3%22%20x2%3D%22803.1%22%20y2%3D%22149.7%22%20stroke-opacity%3D%220.09%22/%3E%3Cline%20x1%3D%22896%22%20y1%3D%22151.3%22%20x2%3D%22904%22%20y2%3D%22148.7%22%20stroke-opacity%3D%220.11%22/%3E%3Cline%20x1%3D%22994.6%22%20y1%3D%22153%22%20x2%3D%221005.4%22%20y2%3D%22147%22%20stroke-opacity%3D%220.14%22/%3E%3Cline%20x1%3D%221093.3%22%20y1%3D%22155.6%22%20x2%3D%221106.7%22%20y2%3D%22144.4%22%20stroke-opacity%3D%220.18%22/%3E%3Cline%20x1%3D%221192.8%22%20y1%3D%22158.9%22%20x2%3D%221207.2%22%20y2%3D%22141.1%22%20stroke-opacity%3D%220.22%22/%3E%3Cline%20x1%3D%221293.5%22%20y1%3D%22162.4%22%20x2%3D%221306.5%22%20y2%3D%22137.6%22%20stroke-opacity%3D%220.26%22/%3E%3Cline%20x1%3D%221395.5%22%20y1%3D%22165.2%22%20x2%3D%221404.5%22%20y2%3D%22134.8%22%20stroke-opacity%3D%220.29%22/%3E%3Cline%20x1%3D%221498.5%22%20y1%3D%22166.8%22%20x2%3D%221501.5%22%20y2%3D%22133.2%22%20stroke-opacity%3D%220.31%22/%3E%3Cline%20x1%3D%221601.8%22%20y1%3D%22166.8%22%20x2%3D%221598.2%22%20y2%3D%22133.2%22%20stroke-opacity%3D%220.31%22/%3E%3Cline%20x1%3D%22-4.8%22%20y1%3D%22335.1%22%20x2%3D%224.8%22%20y2%3D%22364.9%22%20stroke-opacity%3D%220.29%22/%3E%3Cline%20x1%3D%2293.3%22%20y1%3D%22338.1%22%20x2%3D%22106.7%22%20y2%3D%22361.9%22%20stroke-opacity%3D%220.26%22/%3E%3Cline%20x1%3D%22192.8%22%20y1%3D%22341.6%22%20x2%3D%22207.2%22%20y2%3D%22358.4%22%20stroke-opacity%3D%220.22%22/%3E%3Cline%20x1%3D%22293.4%22%20y1%3D%22344.8%22%20x2%3D%22306.6%22%20y2%3D%22355.2%22%20stroke-opacity%3D%220.17%22/%3E%3Cline%20x1%3D%22394.8%22%20y1%3D%22347.3%22%20x2%3D%22405.2%22%20y2%3D%22352.7%22%20stroke-opacity%3D%220.14%22/%3E%3Cline%20x1%3D%22496.1%22%20y1%3D%22348.9%22%20x2%3D%22503.9%22%20y2%3D%22351.1%22%20stroke-opacity%3D%220.11%22/%3E%3Cline%20x1%3D%22596.9%22%20y1%3D%22349.8%22%20x2%3D%22603.1%22%20y2%3D%22350.2%22%20stroke-opacity%3D%220.09%22/%3E%3Cline%20x1%3D%22696.8%22%20y1%3D%22350.4%22%20x2%3D%22703.2%22%20y2%3D%22349.6%22%20stroke-opacity%3D%220.09%22/%3E%3Cline%20x1%3D%22795.9%22%20y1%3D%22351.3%22%20x2%3D%22804.1%22%20y2%3D%22348.7%22%20stroke-opacity%3D%220.11%22/%3E%3Cline%20x1%3D%22894.5%22%20y1%3D%22353.1%22%20x2%3D%22905.5%22%20y2%3D%22346.9%22%20stroke-opacity%3D%220.14%22/%3E%3Cline%20x1%3D%22993.2%22%20y1%3D%22355.8%22%20x2%3D%221006.8%22%20y2%3D%22344.2%22%20stroke-opacity%3D%220.18%22/%3E%3Cline%20x1%3D%221092.8%22%20y1%3D%22359.1%22%20x2%3D%221107.2%22%20y2%3D%22340.9%22%20stroke-opacity%3D%220.23%22/%3E%3Cline%20x1%3D%221193.6%22%20y1%3D%22362.6%22%20x2%3D%221206.4%22%20y2%3D%22337.4%22%20stroke-opacity%3D%220.26%22/%3E%3Cline%20x1%3D%221295.7%22%20y1%3D%22365.4%22%20x2%3D%221304.3%22%20y2%3D%22334.6%22%20stroke-opacity%3D%220.29%22/%3E%3Cline%20x1%3D%221398.7%22%20y1%3D%22366.9%22%20x2%3D%221401.3%22%20y2%3D%22333.1%22%20stroke-opacity%3D%220.31%22/%3E%3Cline%20x1%3D%221502%22%20y1%3D%22366.7%22%20x2%3D%221498%22%20y2%3D%22333.3%22%20stroke-opacity%3D%220.31%22/%3E%3Cline%20x1%3D%221604.8%22%20y1%3D%22364.9%22%20x2%3D%221595.2%22%20y2%3D%22335.1%22%20stroke-opacity%3D%220.29%22/%3E%3Cline%20x1%3D%22-6.7%22%20y1%3D%22538.3%22%20x2%3D%226.8%22%20y2%3D%22561.7%22%20stroke-opacity%3D%220.26%22/%3E%3Cline%20x1%3D%2292.8%22%20y1%3D%22541.8%22%20x2%3D%22107.2%22%20y2%3D%22558.2%22%20stroke-opacity%3D%220.21%22/%3E%3Cline%20x1%3D%22193.5%22%20y1%3D%22545%22%20x2%3D%22206.5%22%20y2%3D%22555%22%20stroke-opacity%3D%220.17%22/%3E%3Cline%20x1%3D%22294.9%22%20y1%3D%22547.5%22%20x2%3D%22305.1%22%20y2%3D%22552.5%22%20stroke-opacity%3D%220.13%22/%3E%3Cline%20x1%3D%22396.2%22%20y1%3D%22549%22%20x2%3D%22403.8%22%20y2%3D%22551%22%20stroke-opacity%3D%220.10%22/%3E%3Cline%20x1%3D%22496.9%22%20y1%3D%22549.8%22%20x2%3D%22503.1%22%20y2%3D%22550.2%22%20stroke-opacity%3D%220.09%22/%3E%3Cline%20x1%3D%22596.8%22%20y1%3D%22550.4%22%20x2%3D%22603.2%22%20y2%3D%22549.6%22%20stroke-opacity%3D%220.09%22/%3E%3Cline%20x1%3D%22695.8%22%20y1%3D%22551.4%22%20x2%3D%22704.2%22%20y2%3D%22548.6%22%20stroke-opacity%3D%220.11%22/%3E%3Cline%20x1%3D%22794.4%22%20y1%3D%22553.3%22%20x2%3D%22805.6%22%20y2%3D%22546.8%22%20stroke-opacity%3D%220.14%22/%3E%3Cline%20x1%3D%22893.2%22%20y1%3D%22556%22%20x2%3D%22906.8%22%20y2%3D%22544%22%20stroke-opacity%3D%220.19%22/%3E%3Cline%20x1%3D%22992.8%22%20y1%3D%22559.4%22%20x2%3D%221007.2%22%20y2%3D%22540.6%22%20stroke-opacity%3D%220.23%22/%3E%3Cline%20x1%3D%221093.7%22%20y1%3D%22562.8%22%20x2%3D%221106.3%22%20y2%3D%22537.2%22%20stroke-opacity%3D%220.27%22/%3E%3Cline%20x1%3D%221195.8%22%20y1%3D%22565.5%22%20x2%3D%221204.2%22%20y2%3D%22534.5%22%20stroke-opacity%3D%220.30%22/%3E%3Cline%20x1%3D%221298.9%22%20y1%3D%22566.9%22%20x2%3D%221301.1%22%20y2%3D%22533.1%22%20stroke-opacity%3D%220.31%22/%3E%3Cline%20x1%3D%221402.2%22%20y1%3D%22566.6%22%20x2%3D%221397.8%22%20y2%3D%22533.4%22%20stroke-opacity%3D%220.31%22/%3E%3Cline%20x1%3D%221505%22%20y1%3D%22564.7%22%20x2%3D%221495%22%20y2%3D%22535.3%22%20stroke-opacity%3D%220.29%22/%3E%3Cline%20x1%3D%221606.8%22%20y1%3D%22561.7%22%20x2%3D%221593.3%22%20y2%3D%22538.3%22%20stroke-opacity%3D%220.26%22/%3E%3Cline%20x1%3D%22-7.2%22%20y1%3D%22742%22%20x2%3D%227.2%22%20y2%3D%22758%22%20stroke-opacity%3D%220.21%22/%3E%3Cline%20x1%3D%2293.6%22%20y1%3D%22745.2%22%20x2%3D%22106.4%22%20y2%3D%22754.8%22%20stroke-opacity%3D%220.17%22/%3E%3Cline%20x1%3D%22195%22%20y1%3D%22747.6%22%20x2%3D%22205%22%20y2%3D%22752.4%22%20stroke-opacity%3D%220.13%22/%3E%3Cline%20x1%3D%22296.3%22%20y1%3D%22749.1%22%20x2%3D%22303.7%22%20y2%3D%22750.9%22%20stroke-opacity%3D%220.10%22/%3E%3Cline%20x1%3D%22397%22%20y1%3D%22749.8%22%20x2%3D%22403%22%20y2%3D%22750.2%22%20stroke-opacity%3D%220.09%22/%3E%3Cline%20x1%3D%22496.7%22%20y1%3D%22750.5%22%20x2%3D%22503.3%22%20y2%3D%22749.5%22%20stroke-opacity%3D%220.09%22/%3E%3Cline%20x1%3D%22595.7%22%20y1%3D%22751.5%22%20x2%3D%22604.3%22%20y2%3D%22748.5%22%20stroke-opacity%3D%220.11%22/%3E%3Cline%20x1%3D%22694.3%22%20y1%3D%22753.4%22%20x2%3D%22705.7%22%20y2%3D%22746.6%22%20stroke-opacity%3D%220.15%22/%3E%3Cline%20x1%3D%22793.1%22%20y1%3D%22756.2%22%20x2%3D%22806.9%22%20y2%3D%22743.8%22%20stroke-opacity%3D%220.19%22/%3E%3Cline%20x1%3D%22892.8%22%20y1%3D%22759.6%22%20x2%3D%22907.2%22%20y2%3D%22740.4%22%20stroke-opacity%3D%220.23%22/%3E%3Cline%20x1%3D%22993.8%22%20y1%3D%22763%22%20x2%3D%221006.2%22%20y2%3D%22737%22%20stroke-opacity%3D%220.27%22/%3E%3Cline%20x1%3D%221096%22%20y1%3D%22765.7%22%20x2%3D%221104%22%20y2%3D%22734.3%22%20stroke-opacity%3D%220.30%22/%3E%3Cline%20x1%3D%221199.1%22%20y1%3D%22766.9%22%20x2%3D%221200.9%22%20y2%3D%22733.1%22%20stroke-opacity%3D%220.31%22/%3E%3Cline%20x1%3D%221302.4%22%20y1%3D%22766.5%22%20x2%3D%221297.6%22%20y2%3D%22733.5%22%20stroke-opacity%3D%220.31%22/%3E%3Cline%20x1%3D%221405.2%22%20y1%3D%22764.6%22%20x2%3D%221394.8%22%20y2%3D%22735.4%22%20stroke-opacity%3D%220.29%22/%3E%3Cline%20x1%3D%221506.8%22%20y1%3D%22761.5%22%20x2%3D%221493.2%22%20y2%3D%22738.5%22%20stroke-opacity%3D%220.25%22/%3E%3Cline%20x1%3D%221607.2%22%20y1%3D%22758%22%20x2%3D%221592.8%22%20y2%3D%22742%22%20stroke-opacity%3D%220.21%22/%3E%3C/g%3E%3C/svg%3E"),
        radial-gradient(ellipse at 50% 25%, #f8f6f4 0%, #eef0ef 48%, #dfe4e6 100%);
    background-repeat: no-repeat, no-repeat;
    background-position: center, center;
    background-size: cover, cover;
    background-attachment: fixed, fixed;
}

.container {
    max-width: 1200px;
    margin: 0 auto;
    position: relative;
}

.panel {
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    backdrop-filter: blur(14px);
    border-radius: 16px;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15);
}

.how-to-interpret {
    padding: 22px 24px;
    margin-bottom: 24px;
}

.how-to-interpret h2 {
    font-size: 1em;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--accent);
    margin-bottom: 10px;
    font-weight: 700;
}

.how-to-interpret p {
    color: var(--text-dim);
    line-height: 1.6;
    font-size: 0.95em;
}

.how-to-interpret p + p {
    margin-top: 10px;
}

.how-to-interpret p strong {
    color: var(--text-main);
}

header {
    text-align: center;
    margin-bottom: 36px;
    position: relative;
}

header h1 {
    font-size: 2.4em;
    font-weight: 800;
    background: linear-gradient(120deg, var(--accent) 0%, var(--accent-2) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    letter-spacing: 0.5px;
}

header p {
    color: var(--text-dim);
    margin-top: 8px;
    font-size: 1.05em;
}

.intro-wrap {
    position: relative;
    max-width: 760px;
    margin: 28px auto 0;
    padding-top: 22px;
}

.intro-wrap::before {
    content: '';
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 52px;
    height: 3px;
    border-radius: 2px;
    background: linear-gradient(120deg, var(--accent) 0%, var(--accent-2) 100%);
}

header p.intro {
    font-size: 1.08em;
    line-height: 1.7;
    color: var(--text-dim);
    margin: 0;
}

header p.intro strong {
    color: var(--text-main);
    font-weight: 600;
}

.main-grid {
    display: grid;
    grid-template-columns: 1.8fr 1fr;
    gap: 24px;
    margin-bottom: 24px;
    align-items: start;
}

.canvas-panel {
    padding: 22px 24px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.viz-root {
    color-scheme: light;
    --surface-1: #fffdf9;
    --ink-primary: #1a1a1a;
    --ink-secondary: #52514e;
    --ink-muted: #8c8a84;
}

@media (prefers-color-scheme: dark) {
    :root:where(:not([data-theme="light"])) .viz-root {
        color-scheme: dark;
        --surface-1: #1c1c1a;
        --ink-primary: #ffffff;
        --ink-secondary: #c3c2b7;
        --ink-muted: #8c8a84;
    }
}

:root[data-theme="dark"] .viz-root {
    color-scheme: dark;
    --surface-1: #1c1c1a;
    --ink-primary: #ffffff;
    --ink-secondary: #c3c2b7;
    --ink-muted: #8c8a84;
}

.legend-row {
    display: flex;
    justify-content: center;
    gap: 22px;
    font-size: 0.85em;
    font-weight: 700;
    color: var(--ink-secondary);
}

.legend-row strong {
    color: var(--accent);
    font-variant-numeric: tabular-nums;
}

.chart-stage {
    position: relative;
    width: 100%;
    aspect-ratio: 1 / 1;
    border-radius: 12px;
    overflow: hidden;
    background: var(--surface-1);
    box-shadow: inset 0 0 0 1px var(--panel-border);
}

/* The "light source" behind the filter stack: a radiating sunburst
   rather than a photo, since it's the incoming unpolarized light being
   demonstrated, not a picture — same conic-gradient technique as the
   page's decorative corner medallion, just vivid and full-bleed here. */
.photo-base {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    /* Equidistant concentric rings, each a distinct bright color (never
       black), rather than a flat fill — dimming a flat color by, say,
       12% just looks "very dark", easy to misread as fully blocked.
       Dimming a ring pattern keeps the *relative* contrast between
       neighboring bands intact, and the eye is far better at spotting
       that a boundary between two dark bands still exists than at
       judging one dark shade in isolation — so even a faint 12%
       transmission still visibly reads as "the rings are still there",
       not "it's just black". */
    background:
        radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0.9) 6%, rgba(255, 255, 255, 0) 10%),
        repeating-radial-gradient(circle at 50% 50%,
            #ff3d7f 0% 4%,
            #ff9f1c 4% 8%,
            #ffd60a 8% 12%,
            #2ec4b6 12% 16%,
            #3a86ff 16% 20%,
            #8338ec 20% 24%);
}

/* Holds each layer's darkening regions and its pane (border + axis-line)
   interleaved in stack order — background, filter 1's darkening,
   pane 1's border+axis, filter 2's darkening, pane 2's border+axis,
   and so on — so a given layer's own border/axis is affected only by
   the filters at or before it, not by anything stacked after it. The
   topmost (last) layer ends up fully bright, since nothing paints
   over it afterward — a real depth cue instead of an artificial one. */
.photo-stack {
    position: absolute;
    inset: 0;
    pointer-events: none;
}

.photo-badges {
    position: absolute;
    inset: 0;
    pointer-events: none;
}

/* A ghost duplicate of .polarizer-pane's own box/transform (no border,
   fill or shadow) purely to host that pane's badge above the darkening
   layer — otherwise a fully-blocked region (e.g. the Crossed preset,
   which is ~0% transmission across its whole shared area) would paint
   fully opaque black over the badge and make its label unreadable. */
.badge-holder {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 70.7107%;
    height: 70.7107%;
    transform: translate(-50%, -50%) translate(var(--pane-dx, 0px), var(--pane-dy, 0px)) rotate(var(--pane-angle, 0deg));
}

/* One flat div per region of the arrangement of filters *up through*
   a given depth (see renderPhotoStack/buildRegionSnapshots in app.js)
   — each already carries its own precomputed, correct darkening for
   exactly the subset of filters that geometrically covers it at that
   depth, so these sit as plain siblings rather than needing to be
   nested or composited. One such group is interleaved before each
   layer's own pane in .photo-stack. */
.darkening-level {
    position: absolute;
    inset: 0;
}

/* Each polarizing filter is a translucent square pane sized at
   1/sqrt(2) of the stage — the exact size whose own diagonal equals
   the stage's side, so however it's rotated, its corners sweep around
   but never leave the visible square. Panes sit slightly offset from
   each other (a small per-layer translate, applied before the
   rotation so the offset stays a consistent on-screen fan rather than
   spinning with each pane), stacked in viewing order, closest-to-
   viewer on top — matching the light path: layer 1 first, layer N last. */
.polarizer-pane {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 70.7107%;
    height: 70.7107%;
    /* Sharp corners, matching the actual (sharp) shape used for the
       darkening geometry in .photo-stack — a rounded border here
       would visually promise a shape this pane doesn't actually have. */
    border: 1px solid var(--pane-color, var(--accent));
    /* Purely decorative glass sheen. This pane is interleaved right
       after its own layer's darkening group in .photo-stack (see
       renderPhotoStack in app.js), so it's affected by that layer's
       own filter and every filter before it, but not by anything
       stacked after it — the last (topmost) layer's border ends up
       fully bright, a real depth cue instead of an artificial one. */
    background: linear-gradient(135deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.02) 45%, rgba(0, 0, 0, 0.05) 100%);
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.14);
    transform: translate(-50%, -50%) translate(var(--pane-dx, 0px), var(--pane-dy, 0px)) rotate(var(--pane-angle, 0deg));
}

.polarizer-pane .axis-line {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 100%;
    height: 2px;
    /* Full, unmodified layer color — same brightness as the border,
       not artificially dimmed. It's affected by the darkening the same
       way the border is (see .polarizer-pane above). */
    background: var(--pane-color, var(--accent));
    transform: translate(-50%, -50%);
}

.badge-holder .axis-badge {
    position: absolute;
    /* On the pane's own horizontal midline, near the left edge — lines
       up with the axis-line's height so the label reads as belonging
       to that angle line. */
    top: 50%;
    left: 10%;
    font-size: 0.68em;
    font-weight: 700;
    padding: 2px 7px;
    border-radius: 999px;
    color: #fff;
    background: var(--pane-color, var(--accent));
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
    white-space: nowrap;
    transform: translate(-50%, -50%) rotate(calc(-1 * var(--pane-angle, 0deg)));
}

.stage-ladder {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 6px;
    font-size: 0.78em;
}

.stage-chip {
    display: inline-flex;
    align-items: baseline;
    gap: 4px;
    background: rgba(0, 0, 0, 0.06);
    color: var(--ink-secondary);
    padding: 4px 10px;
    border-radius: 999px;
    font-weight: 700;
    white-space: nowrap;
}

.stage-chip .stage-chip-value {
    color: var(--ink-primary);
    font-variant-numeric: tabular-nums;
}

.stage-chip .stage-chip-delta {
    font-weight: 600;
    color: var(--ink-muted);
    font-size: 0.85em;
}

/* Color set inline per layer (see renderLadder) — same identity color
   as that layer's border/axis-line/badge elsewhere. */
.stage-chip-label {
    font-weight: 800;
}

.stage-arrow {
    color: var(--ink-muted);
    opacity: 0.7;
}

.controls-panel {
    padding: 24px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.field-group label {
    display: block;
    font-size: 0.85em;
    font-weight: 700;
    color: var(--text-main);
    margin-bottom: 8px;
}

.field-label-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
}

.field-label-row label {
    margin-bottom: 0;
    display: inline-flex;
    align-items: center;
    gap: 5px;
}

.field-icon {
    width: 15px;
    height: 15px;
    flex-shrink: 0;
    color: var(--accent-mid);
}

.layer-count-stepper {
    display: flex;
    align-items: center;
    gap: 8px;
}

.stepper-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    border: none;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--accent-2) 0%, var(--accent) 100%);
    color: #fff;
    font-size: 0.75em;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    transition: transform 0.15s ease, opacity 0.15s ease;
}

.stepper-btn:hover:not(:disabled) {
    transform: translateY(-1px);
}

.stepper-btn:active:not(:disabled) {
    transform: translateY(0);
}

.stepper-btn:disabled {
    opacity: 0.3;
    cursor: default;
}

.stepper-value {
    min-width: 1em;
    text-align: center;
    font-size: 0.85em;
    font-weight: 800;
    color: var(--accent);
    font-variant-numeric: tabular-nums;
}

.field-number {
    width: 84px;
    padding: 6px 8px;
    border: 1px solid var(--panel-border);
    border-radius: 8px;
    background: white;
    color: var(--accent);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    text-align: right;
    font-size: 0.95em;
}

.field-number:focus {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
}

input[type="range"] {
    -webkit-appearance: none;
    appearance: none;
    width: 100%;
    height: 6px;
    border-radius: 999px;
    background: #d9d9d9;
    outline: none;
    cursor: pointer;
}

input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--accent-2) 0%, var(--accent) 100%);
    border: none;
    cursor: pointer;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}

input[type="range"]::-moz-range-thumb {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--accent-2) 0%, var(--accent) 100%);
    border: none;
    cursor: pointer;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}

input[type="range"]::-moz-range-track {
    height: 6px;
    border-radius: 999px;
    background: transparent;
}

input[type="range"]:focus {
    outline: 2px solid var(--text-dim);
    outline-offset: 2px;
}

/* Custom always-visible angle reference marks, sitting right on the
   track — the native <datalist> ticks (via the slider's own `list`
   attribute) aren't rendered by every browser (Safari accepts it for
   snapping but never draws the ticks), so this is a custom overlay
   instead. Shared by every ticked slider (per-layer angle sliders and
   the layer-count slider, see buildTickedSlider in app.js). Must match
   the thumb's own width below (16px): the thumb's center can only
   travel from half its own width in from one edge to half its width in
   from the other, never reaching the true 0%/100% edges of the track,
   so each tick's left position — half the thumb width, plus that same
   fraction of the *remaining* travel distance — lines up with exactly
   where the thumb sits at that value, instead of drifting outward past
   it toward the ends.
   A fixed height matching the thumb diameter (16px), with the input
   flex-centered inside it, guarantees the ticks' own vertical center
   (from inset:0 on that same box) exactly coincides with the track's
   center — rather than relying on the input's own default box height,
   which isn't guaranteed to match. */
.ticked-slider-wrap {
    position: relative;
    /* Establishes its own stacking context (position + a real z-index,
       not "auto") so the ticks' negative z-index below is scoped to
       stacking *within this wrapper* — without this, a negative
       z-index climbs to the nearest ancestor that DOES establish one,
       which could be several parents up, hiding the ticks behind
       every ancestor's own background in between, not just the
       slider's track. */
    z-index: 0;
    display: flex;
    align-items: center;
    height: 16px;
}

.ticked-slider-wrap input[type="range"] {
    flex: 1;
    /* Translucent instead of solid, so the tick marks underneath (see
       z-index below) show through the track rather than being hidden
       by it — ticks behind, track over them, thumb on top of both. */
    background: rgba(217, 217, 217, 0.55);
}

.slider-ticks {
    position: absolute;
    inset: 0;
    pointer-events: none;
    /* Absolutely-positioned elements paint above static ones by
       default regardless of DOM order, so this needs an explicit
       negative z-index to actually sit behind the (static) input. */
    z-index: -1;
}

.slider-tick {
    position: absolute;
    top: 50%;
    left: calc(8px + var(--tick-fraction, 0) * (100% - 16px));
    width: 1px;
    height: 6px;
    background: var(--text-dim);
    opacity: 0.6;
    transform: translate(-50%, -50%);
}

/* A "major" mark (every 15 degrees on the angle sliders; every step on
   the layer-count slider, where all of them are major — see the
   majorStep argument to buildTickedSlider) reads as a stronger
   reference than an in-between minor one. */
.slider-tick-major {
    height: 10px;
}

/* --- Per-layer angle cards ------------------------------------------- */
.layer-controls {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.layer-card {
    padding: 12px 14px;
    border-radius: 12px;
    background: rgba(0, 0, 0, 0.035);
    border: 1px solid var(--panel-border);
    transition: opacity 0.15s ease, outline-color 0.15s ease;
}

.layer-card.dragging {
    opacity: 0.4;
}

.layer-card.drag-over {
    outline: 2px dashed var(--accent-mid);
    outline-offset: 2px;
}

.layer-card-header {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
}

.drag-handle {
    display: inline-flex;
    flex-shrink: 0;
    width: 16px;
    height: 16px;
    color: var(--text-dim);
    cursor: grab;
    touch-action: none;
    user-select: none;
}

.drag-handle:active {
    cursor: grabbing;
}

.layer-badge {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-weight: 700;
    font-size: 0.85em;
    color: var(--text-main);
    flex: 1;
    min-width: 0;
}

.layer-badge .dot {
    width: 11px;
    height: 11px;
    border-radius: 50%;
    flex-shrink: 0;
}

.visibility-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    padding: 0;
    border: none;
    background: none;
    color: inherit;
    cursor: pointer;
    opacity: 0.85;
}

.visibility-toggle:hover {
    opacity: 1;
}

.visibility-toggle svg {
    width: 20px;
    height: 20px;
}

/* A hidden layer is still fully editable (so it's ready to go once
   re-enabled), just visually muted apart from its own eye toggle. */
.layer-card.hidden-layer .layer-badge .dot,
.layer-card.hidden-layer .layer-badge span:last-child,
.layer-card.hidden-layer input {
    opacity: 0.4;
}

.layer-card-header .field-number {
    width: 62px;
    padding: 6px 6px;
    font-size: 0.88em;
}

.layer-delta {
    font-size: 0.72em;
    color: var(--text-dim);
    font-weight: 600;
    margin-top: 4px;
}

.preset-buttons {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 6px;
}

.preset-buttons button {
    min-width: 0;
    background: rgba(0, 0, 0, 0.06);
    border: none;
    color: var(--text-dim);
    font-size: 0.78em;
    font-weight: 700;
    padding: 8px 8px;
    border-radius: 999px;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: background 0.2s ease, color 0.2s ease;
}

.preset-buttons button:hover {
    background: rgba(0, 0, 0, 0.1);
    color: var(--text-main);
}

.preset-buttons button.active {
    background: var(--accent-mid);
    color: white;
}

.pill-toggle {
    display: inline-flex;
    background: rgba(0, 0, 0, 0.06);
    border-radius: 999px;
    padding: 3px;
    gap: 2px;
}

.pill-toggle button {
    background: transparent;
    border: none;
    color: var(--text-dim);
    font-size: 0.8em;
    font-weight: 700;
    padding: 6px 12px;
    border-radius: 999px;
    cursor: pointer;
    transition: background 0.2s ease, color 0.2s ease;
}

.pill-toggle button:hover {
    color: var(--text-main);
}

.pill-toggle button[aria-pressed="true"] {
    background: white;
    color: var(--accent-mid);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
}

footer {
    text-align: center;
    margin-top: 36px;
    padding-top: 22px;
    border-top: 1px solid var(--panel-border);
    color: var(--text-dim);
    font-size: 0.85em;
}

footer .pill-toggle {
    margin-bottom: 12px;
}

footer a {
    color: var(--accent);
    font-weight: 600;
    text-decoration: none;
}

footer a:hover {
    text-decoration: underline;
}

footer a.source-link svg {
    width: 14px;
    height: 14px;
    fill: currentColor;
    vertical-align: -2px;
    margin-right: 3px;
}

@media screen and (max-width: 860px) {
    .main-grid {
        grid-template-columns: 1fr;
    }
}

@media screen and (max-width: 768px) {
    header h1 {
        font-size: 1.8em;
    }
}
