/* Poker Ledger — kosmetika-rinkiniai.css
   STEP 145 — moved out of index.html's one <style>, byte for byte and in its
   original place in the cascade: index.html links it exactly where this text
   used to sit, between the two halves of the stylesheet around it.
   This file: the sets — Kirmgrauža, Kvazaras, Runakmenis, Dzeusas, Egiptas, the common tier.
   Why: it is ~80 % of the stylesheet and changes far less often than the page.
   Inside index.html every release re-sent all of it; as its own file a phone
   keeps it and only asks whether it changed. And it no longer holds up the
   first paint: index.html loads it with media="print" and src/app.js switches
   it on when it has arrived, before any row is drawn (see cosmeticsReady). */
  /* ================= KIRMGRAUŽA — THE WORMHOLE SET =================
     Step 78, docs/SETS.md "Step 78". Three pieces that are one object seen
     three times: a frame that is a tunnel the row sits inside, a surface that
     is spacetime bent by the rank numeral, a nameplate whose letters carry the
     tunnel's light. Rarities as agreed 2026-09-03: frame mythic, surface rare,
     nameplate epic.

     THE FRAME IS THE FIRST COSMETIC THAT IS NOT A CLASS NAME. src/kirmgrauza.js
     puts four children into every .fr-kirmgrauza row after each paint — the
     painted haze, the tube's far wall, the slab, the tube's near wall — and
     these rules lay them out. The row's own band and fillet are switched off:
     the tunnel IS the frame. The row's cells are lifted above all four layers;
     the slab is the row's body, drawn as a child so the tube can pass behind
     it, and clipped by the script to the tube's profile so nothing of it
     shows outside the wall.

     THE COST, stated so it is not rediscovered: this frame OWNS THE ROW'S
     BACKGROUND. A surface worn with it must paint onto .slab, not the row —
     see the .sf-erdvelaikis rule below, which is the only surface that knows.
     Any other surface worn inside this frame paints under the slab and is not
     seen; docs/SETS.md lists that as open. And the tube reaches 10px above and
     below the row, which is exactly the gap between framed rows, so two
     adjacent wearers touch — the same standing question the dangles raised. */
  .fr-kirmgrauza{--int:#070B1C; background:none; box-shadow:none;}
  .fr-kirmgrauza::before,.fr-kirmgrauza::after{display:none;}
  .fr-kirmgrauza > .neb{position:absolute; left:-20px; top:-10px;
                        width:var(--worm-w,404px); height:var(--worm-h,69px);
                        pointer-events:none; z-index:0;}
  .fr-kirmgrauza > .worm{position:absolute; left:-20px; top:-10px;
                         width:var(--worm-w,404px); height:var(--worm-h,69px);
                         pointer-events:none; overflow:visible;}
  .fr-kirmgrauza > .worm.back{z-index:0;}
  .fr-kirmgrauza > .worm.front{z-index:2;}
  .fr-kirmgrauza > .slab{position:absolute; inset:0; border-radius:5px; z-index:1;
                         background:var(--int);
                         box-shadow:inset 0 0 0 1px rgba(127,212,255,.18), 0 2px 8px rgba(0,0,0,.5);}
  .fr-kirmgrauza > .cell-num,.fr-kirmgrauza > .cell-name,.fr-kirmgrauza > .cell-net,
  .fr-kirmgrauza > .eng{position:relative; z-index:3;}
  /* The row's hover lift paints a background; on this frame the slab is the
     background, so the lift lands on it. */
  .fr-kirmgrauza.clickable:hover > .slab{filter:brightness(1.12);}

  /* Erdvėlaikis — the surface. A rubber-sheet spacetime grid across the navy
     interior, sagging into a well exactly under the rank numeral: your place
     on the board is the mass that bends the sheet. It fades toward the right
     so the money sits on quiet ground. One SVG written straight into CSS — no
     asset, no request. Rare, not common, for one reason: it knows where the
     number is. */
  .sf-erdvelaikis{--int:#070B1C;
    background-image:
      linear-gradient(90deg, rgba(7,11,28,0) 0 460px, var(--int) 650px),
      url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 364 49' width='364' height='49' preserveAspectRatio='none'%3E%3Cdefs%3E%3CradialGradient id='w' cx='24' cy='24.5' r='34' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%237FD4FF' stop-opacity='.28'/%3E%3Cstop offset='.45' stop-color='%233A7BD5' stop-opacity='.10'/%3E%3Cstop offset='1' stop-color='%233A7BD5' stop-opacity='0'/%3E%3C/radialGradient%3E%3ClinearGradient id='fx' x1='0' x2='1'%3E%3Cstop offset='0' stop-color='%23fff' stop-opacity='.9'/%3E%3Cstop offset='.35' stop-color='%23fff' stop-opacity='.35'/%3E%3Cstop offset='1' stop-color='%23fff' stop-opacity='.18'/%3E%3C/linearGradient%3E%3Cmask id='mx'%3E%3Crect width='364' height='49' fill='url(%23fx)'/%3E%3C/mask%3E%3C/defs%3E%3Crect width='364' height='49' fill='url(%23w)'/%3E%3Cg fill='none' stroke='%237FD4FF' stroke-width='0.5' opacity='.38' mask='url(%23mx)'%3E%3Cpolyline points='0.9,-0.7 3.8,-0.3 6.6,0.1 9.4,0.5 12.0,0.9 14.6,1.3 17.0,1.6 19.4,1.8 21.8,1.9 24.1,2.0 26.4,1.9 28.8,1.8 31.2,1.5 33.6,1.2 36.2,0.9 38.9,0.5 41.6,0.1 44.4,-0.3 47.3,-0.7 50.3,-1.1 53.3,-1.4 56.4,-1.8 59.5,-2.1 62.7,-2.4 65.9,-2.7 69.1,-2.9 72.3,-3.1 75.5,-3.3 78.7,-3.5 81.9,-3.7 85.1,-3.8 88.4,-4.0 91.6,-4.1 94.8,-4.2 98.0,-4.3 101.3,-4.4 104.5,-4.5 107.7,-4.6 110.9,-4.7 114.1,-4.8 117.4,-4.8 120.6,-4.9 123.8,-5.0 127.0,-5.0 130.2,-5.1 133.4,-5.1 136.6,-5.1 139.8,-5.2 143.0,-5.2 146.1,-5.3 149.3,-5.3 152.5,-5.3 155.7,-5.4 158.9,-5.4 162.1,-5.4 165.2,-5.4 168.4,-5.4 171.6,-5.5 174.8,-5.5 177.9,-5.5 181.1,-5.5 184.3,-5.5 187.4,-5.6 190.6,-5.6 193.8,-5.6 196.9,-5.6 200.1,-5.6 203.2,-5.6 206.4,-5.6 209.6,-5.7 212.7,-5.7 215.9,-5.7 219.0,-5.7 222.2,-5.7 225.3,-5.7 228.5,-5.7 231.7,-5.7 234.8,-5.7 238.0,-5.7 241.1,-5.7 244.3,-5.7 247.4,-5.8 250.6,-5.8 253.7,-5.8 256.9,-5.8 260.0,-5.8 263.1,-5.8 266.3,-5.8 269.4,-5.8 272.6,-5.8 275.7,-5.8 278.9,-5.8 282.0,-5.8 285.2,-5.8 288.3,-5.8 291.5,-5.8 294.6,-5.8 297.7,-5.8 300.9,-5.8 304.0,-5.8 307.2,-5.8 310.3,-5.8 313.4,-5.9 316.6,-5.9 319.7,-5.9 322.9,-5.9 326.0,-5.9 329.1,-5.9 332.3,-5.9 335.4,-5.9 338.6,-5.9 341.7,-5.9 344.8,-5.9 348.0,-5.9 351.1,-5.9 354.2,-5.9 357.4,-5.9 360.5,-5.9 363.7,-5.9 366.8,-5.9'/%3E%3Cpolyline points='1.8,5.9 4.8,6.3 7.6,6.8 10.3,7.3 12.9,7.7 15.4,8.1 17.7,8.5 19.9,8.8 22.0,9.0 24.1,9.0 26.2,9.0 28.3,8.8 30.5,8.5 32.8,8.1 35.3,7.7 37.9,7.2 40.6,6.7 43.5,6.3 46.4,5.9 49.5,5.4 52.5,5.1 55.7,4.7 58.9,4.4 62.1,4.1 65.3,3.9 68.5,3.6 71.8,3.4 75.0,3.2 78.3,3.1 81.6,2.9 84.8,2.8 88.1,2.6 91.3,2.5 94.6,2.4 97.8,2.3 101.1,2.3 104.3,2.2 107.5,2.1 110.8,2.0 114.0,2.0 117.2,1.9 120.4,1.9 123.7,1.8 126.9,1.8 130.1,1.7 133.3,1.7 136.5,1.7 139.7,1.6 142.9,1.6 146.1,1.6 149.3,1.6 152.5,1.5 155.6,1.5 158.8,1.5 162.0,1.5 165.2,1.4 168.4,1.4 171.5,1.4 174.7,1.4 177.9,1.4 181.1,1.4 184.2,1.4 187.4,1.3 190.6,1.3 193.7,1.3 196.9,1.3 200.1,1.3 203.2,1.3 206.4,1.3 209.5,1.3 212.7,1.3 215.9,1.3 219.0,1.2 222.2,1.2 225.3,1.2 228.5,1.2 231.6,1.2 234.8,1.2 237.9,1.2 241.1,1.2 244.2,1.2 247.4,1.2 250.5,1.2 253.7,1.2 256.8,1.2 260.0,1.2 263.1,1.2 266.3,1.2 269.4,1.2 272.6,1.2 275.7,1.2 278.9,1.1 282.0,1.1 285.2,1.1 288.3,1.1 291.4,1.1 294.6,1.1 297.7,1.1 300.9,1.1 304.0,1.1 307.2,1.1 310.3,1.1 313.4,1.1 316.6,1.1 319.7,1.1 322.9,1.1 326.0,1.1 329.1,1.1 332.3,1.1 335.4,1.1 338.6,1.1 341.7,1.1 344.8,1.1 348.0,1.1 351.1,1.1 354.2,1.1 357.4,1.1 360.5,1.1 363.7,1.1 366.8,1.1'/%3E%3Cpolyline points='2.8,12.0 5.8,12.4 8.7,12.9 11.4,13.3 14.0,13.8 16.3,14.3 18.5,14.7 20.5,15.0 22.3,15.2 24.1,15.3 25.8,15.2 27.7,15.0 29.7,14.7 31.9,14.2 34.2,13.8 36.8,13.3 39.6,12.8 42.5,12.4 45.5,12.0 48.6,11.6 51.8,11.2 55.0,10.9 58.2,10.6 61.5,10.4 64.8,10.2 68.1,10.0 71.4,9.8 74.7,9.7 78.0,9.5 81.3,9.4 84.6,9.3 87.8,9.2 91.1,9.1 94.4,9.0 97.6,9.0 100.9,8.9 104.2,8.9 107.4,8.8 110.6,8.8 113.9,8.7 117.1,8.7 120.3,8.6 123.6,8.6 126.8,8.6 130.0,8.5 133.2,8.5 136.4,8.5 139.6,8.5 142.8,8.4 146.0,8.4 149.2,8.4 152.4,8.4 155.6,8.4 158.8,8.3 162.0,8.3 165.1,8.3 168.3,8.3 171.5,8.3 174.7,8.3 177.9,8.3 181.0,8.3 184.2,8.3 187.4,8.2 190.5,8.2 193.7,8.2 196.9,8.2 200.0,8.2 203.2,8.2 206.4,8.2 209.5,8.2 212.7,8.2 215.8,8.2 219.0,8.2 222.2,8.2 225.3,8.2 228.5,8.2 231.6,8.2 234.8,8.1 237.9,8.1 241.1,8.1 244.2,8.1 247.4,8.1 250.5,8.1 253.7,8.1 256.8,8.1 260.0,8.1 263.1,8.1 266.3,8.1 269.4,8.1 272.6,8.1 275.7,8.1 278.9,8.1 282.0,8.1 285.1,8.1 288.3,8.1 291.4,8.1 294.6,8.1 297.7,8.1 300.9,8.1 304.0,8.1 307.1,8.1 310.3,8.1 313.4,8.1 316.6,8.1 319.7,8.1 322.9,8.1 326.0,8.1 329.1,8.1 332.3,8.1 335.4,8.1 338.6,8.1 341.7,8.1 344.8,8.1 348.0,8.1 351.1,8.1 354.2,8.1 357.4,8.1 360.5,8.1 363.7,8.1 366.8,8.1'/%3E%3Cpolyline points='3.6,17.6 6.7,17.9 9.6,18.2 12.4,18.6 15.0,19.0 17.3,19.3 19.3,19.7 21.1,20.0 22.6,20.1 24.1,20.2 25.5,20.1 27.1,19.9 28.9,19.6 30.9,19.3 33.3,18.9 35.8,18.5 38.6,18.2 41.6,17.8 44.7,17.5 47.9,17.3 51.1,17.0 54.4,16.8 57.7,16.6 61.1,16.5 64.4,16.3 67.7,16.2 71.1,16.1 74.4,16.0 77.7,15.9 81.1,15.8 84.4,15.8 87.7,15.7 91.0,15.7 94.2,15.6 97.5,15.6 100.8,15.5 104.1,15.5 107.3,15.5 110.6,15.4 113.8,15.4 117.0,15.4 120.3,15.4 123.5,15.3 126.7,15.3 129.9,15.3 133.2,15.3 136.4,15.3 139.6,15.3 142.8,15.3 146.0,15.2 149.2,15.2 152.4,15.2 155.6,15.2 158.8,15.2 161.9,15.2 165.1,15.2 168.3,15.2 171.5,15.2 174.7,15.2 177.8,15.2 181.0,15.2 184.2,15.1 187.4,15.1 190.5,15.1 193.7,15.1 196.9,15.1 200.0,15.1 203.2,15.1 206.4,15.1 209.5,15.1 212.7,15.1 215.8,15.1 219.0,15.1 222.1,15.1 225.3,15.1 228.5,15.1 231.6,15.1 234.8,15.1 237.9,15.1 241.1,15.1 244.2,15.1 247.4,15.1 250.5,15.1 253.7,15.1 256.8,15.1 260.0,15.1 263.1,15.1 266.3,15.1 269.4,15.1 272.6,15.1 275.7,15.1 278.9,15.1 282.0,15.1 285.1,15.1 288.3,15.1 291.4,15.1 294.6,15.1 297.7,15.1 300.9,15.1 304.0,15.0 307.1,15.0 310.3,15.0 313.4,15.0 316.6,15.0 319.7,15.0 322.9,15.0 326.0,15.0 329.1,15.0 332.3,15.0 335.4,15.0 338.5,15.0 341.7,15.0 344.8,15.0 348.0,15.0 351.1,15.0 354.2,15.0 357.4,15.0 360.5,15.0 363.7,15.0 366.8,15.0'/%3E%3Cpolyline points='4.0,22.7 7.1,22.8 10.1,22.9 13.0,23.0 15.5,23.1 17.8,23.3 19.8,23.4 21.4,23.5 22.8,23.5 24.1,23.5 25.3,23.5 26.7,23.4 28.4,23.4 30.3,23.2 32.7,23.1 35.3,23.0 38.1,22.9 41.1,22.8 44.3,22.7 47.5,22.6 50.8,22.6 54.1,22.5 57.5,22.4 60.8,22.4 64.2,22.4 67.6,22.3 70.9,22.3 74.3,22.3 77.6,22.2 81.0,22.2 84.3,22.2 87.6,22.2 90.9,22.2 94.2,22.2 97.5,22.2 100.7,22.1 104.0,22.1 107.3,22.1 110.5,22.1 113.8,22.1 117.0,22.1 120.3,22.1 123.5,22.1 126.7,22.1 129.9,22.1 133.1,22.1 136.4,22.1 139.6,22.1 142.8,22.1 146.0,22.1 149.2,22.1 152.4,22.1 155.6,22.1 158.7,22.1 161.9,22.1 165.1,22.0 168.3,22.0 171.5,22.0 174.7,22.0 177.8,22.0 181.0,22.0 184.2,22.0 187.3,22.0 190.5,22.0 193.7,22.0 196.9,22.0 200.0,22.0 203.2,22.0 206.3,22.0 209.5,22.0 212.7,22.0 215.8,22.0 219.0,22.0 222.1,22.0 225.3,22.0 228.5,22.0 231.6,22.0 234.8,22.0 237.9,22.0 241.1,22.0 244.2,22.0 247.4,22.0 250.5,22.0 253.7,22.0 256.8,22.0 260.0,22.0 263.1,22.0 266.3,22.0 269.4,22.0 272.6,22.0 275.7,22.0 278.9,22.0 282.0,22.0 285.1,22.0 288.3,22.0 291.4,22.0 294.6,22.0 297.7,22.0 300.9,22.0 304.0,22.0 307.1,22.0 310.3,22.0 313.4,22.0 316.6,22.0 319.7,22.0 322.8,22.0 326.0,22.0 329.1,22.0 332.3,22.0 335.4,22.0 338.5,22.0 341.7,22.0 344.8,22.0 348.0,22.0 351.1,22.0 354.2,22.0 357.4,22.0 360.5,22.0 363.7,22.0 366.8,22.0'/%3E%3Cpolyline points='3.9,27.7 7.1,27.6 10.0,27.4 12.9,27.2 15.4,27.0 17.7,26.8 19.7,26.6 21.4,26.4 22.8,26.3 24.1,26.3 25.3,26.3 26.8,26.4 28.4,26.6 30.5,26.8 32.8,27.0 35.4,27.2 38.2,27.4 41.2,27.6 44.3,27.7 47.6,27.9 50.9,28.0 54.2,28.1 57.5,28.2 60.9,28.3 64.2,28.4 67.6,28.4 71.0,28.5 74.3,28.5 77.6,28.6 81.0,28.6 84.3,28.6 87.6,28.7 90.9,28.7 94.2,28.7 97.5,28.7 100.8,28.7 104.0,28.8 107.3,28.8 110.5,28.8 113.8,28.8 117.0,28.8 120.3,28.8 123.5,28.8 126.7,28.8 129.9,28.9 133.1,28.9 136.4,28.9 139.6,28.9 142.8,28.9 146.0,28.9 149.2,28.9 152.4,28.9 155.6,28.9 158.7,28.9 161.9,28.9 165.1,28.9 168.3,28.9 171.5,28.9 174.7,28.9 177.8,28.9 181.0,28.9 184.2,28.9 187.3,28.9 190.5,28.9 193.7,28.9 196.9,28.9 200.0,28.9 203.2,28.9 206.3,28.9 209.5,28.9 212.7,28.9 215.8,29.0 219.0,29.0 222.1,29.0 225.3,29.0 228.5,29.0 231.6,29.0 234.8,29.0 237.9,29.0 241.1,29.0 244.2,29.0 247.4,29.0 250.5,29.0 253.7,29.0 256.8,29.0 260.0,29.0 263.1,29.0 266.3,29.0 269.4,29.0 272.6,29.0 275.7,29.0 278.9,29.0 282.0,29.0 285.1,29.0 288.3,29.0 291.4,29.0 294.6,29.0 297.7,29.0 300.9,29.0 304.0,29.0 307.1,29.0 310.3,29.0 313.4,29.0 316.6,29.0 319.7,29.0 322.9,29.0 326.0,29.0 329.1,29.0 332.3,29.0 335.4,29.0 338.5,29.0 341.7,29.0 344.8,29.0 348.0,29.0 351.1,29.0 354.2,29.0 357.4,29.0 360.5,29.0 363.7,29.0 366.8,29.0'/%3E%3Cpolyline points='3.4,33.0 6.4,32.6 9.4,32.2 12.1,31.8 14.7,31.4 17.0,31.0 19.1,30.6 20.9,30.3 22.5,30.1 24.1,30.0 25.6,30.1 27.2,30.3 29.1,30.6 31.2,31.0 33.5,31.4 36.1,31.9 38.9,32.3 41.8,32.7 44.9,33.0 48.1,33.3 51.3,33.6 54.6,33.8 57.9,34.0 61.2,34.2 64.5,34.4 67.8,34.5 71.2,34.7 74.5,34.8 77.8,34.9 81.1,35.0 84.4,35.1 87.7,35.1 91.0,35.2 94.3,35.3 97.6,35.3 100.8,35.4 104.1,35.4 107.3,35.4 110.6,35.5 113.8,35.5 117.1,35.5 120.3,35.6 123.5,35.6 126.7,35.6 130.0,35.6 133.2,35.6 136.4,35.7 139.6,35.7 142.8,35.7 146.0,35.7 149.2,35.7 152.4,35.7 155.6,35.7 158.8,35.8 161.9,35.8 165.1,35.8 168.3,35.8 171.5,35.8 174.7,35.8 177.8,35.8 181.0,35.8 184.2,35.8 187.4,35.8 190.5,35.8 193.7,35.8 196.9,35.8 200.0,35.9 203.2,35.9 206.4,35.9 209.5,35.9 212.7,35.9 215.8,35.9 219.0,35.9 222.1,35.9 225.3,35.9 228.5,35.9 231.6,35.9 234.8,35.9 237.9,35.9 241.1,35.9 244.2,35.9 247.4,35.9 250.5,35.9 253.7,35.9 256.8,35.9 260.0,35.9 263.1,35.9 266.3,35.9 269.4,35.9 272.6,35.9 275.7,35.9 278.9,35.9 282.0,35.9 285.1,35.9 288.3,35.9 291.4,35.9 294.6,35.9 297.7,35.9 300.9,35.9 304.0,35.9 307.1,35.9 310.3,35.9 313.4,35.9 316.6,35.9 319.7,35.9 322.9,35.9 326.0,35.9 329.1,35.9 332.3,36.0 335.4,36.0 338.5,36.0 341.7,36.0 344.8,36.0 348.0,36.0 351.1,36.0 354.2,36.0 357.4,36.0 360.5,36.0 363.7,36.0 366.8,36.0'/%3E%3Cpolyline points='2.5,38.7 5.5,38.3 8.4,37.8 11.1,37.3 13.7,36.8 16.1,36.4 18.3,36.0 20.3,35.7 22.2,35.5 24.1,35.4 25.9,35.5 27.9,35.7 29.9,36.0 32.1,36.4 34.5,36.9 37.1,37.4 39.9,37.8 42.8,38.3 45.7,38.7 48.8,39.1 52.0,39.5 55.2,39.8 58.4,40.1 61.7,40.4 64.9,40.6 68.2,40.8 71.5,41.0 74.8,41.2 78.1,41.3 81.3,41.4 84.6,41.5 87.9,41.7 91.2,41.8 94.4,41.8 97.7,41.9 100.9,42.0 104.2,42.1 107.4,42.1 110.7,42.2 113.9,42.2 117.1,42.3 120.4,42.3 123.6,42.3 126.8,42.4 130.0,42.4 133.2,42.4 136.4,42.5 139.6,42.5 142.8,42.5 146.0,42.5 149.2,42.6 152.4,42.6 155.6,42.6 158.8,42.6 162.0,42.6 165.2,42.6 168.3,42.7 171.5,42.7 174.7,42.7 177.9,42.7 181.0,42.7 184.2,42.7 187.4,42.7 190.5,42.7 193.7,42.7 196.9,42.8 200.0,42.8 203.2,42.8 206.4,42.8 209.5,42.8 212.7,42.8 215.8,42.8 219.0,42.8 222.2,42.8 225.3,42.8 228.5,42.8 231.6,42.8 234.8,42.8 237.9,42.8 241.1,42.8 244.2,42.8 247.4,42.9 250.5,42.9 253.7,42.9 256.8,42.9 260.0,42.9 263.1,42.9 266.3,42.9 269.4,42.9 272.6,42.9 275.7,42.9 278.9,42.9 282.0,42.9 285.2,42.9 288.3,42.9 291.4,42.9 294.6,42.9 297.7,42.9 300.9,42.9 304.0,42.9 307.2,42.9 310.3,42.9 313.4,42.9 316.6,42.9 319.7,42.9 322.9,42.9 326.0,42.9 329.1,42.9 332.3,42.9 335.4,42.9 338.6,42.9 341.7,42.9 344.8,42.9 348.0,42.9 351.1,42.9 354.2,42.9 357.4,42.9 360.5,42.9 363.7,42.9 366.8,42.9'/%3E%3Cpolyline points='1.6,44.9 4.5,44.5 7.3,44.1 10.0,43.6 12.7,43.2 15.1,42.8 17.5,42.4 19.8,42.2 21.9,42.0 24.1,41.9 26.2,42.0 28.4,42.2 30.7,42.5 33.1,42.8 35.6,43.2 38.2,43.7 40.9,44.1 43.8,44.5 46.7,45.0 49.7,45.4 52.8,45.8 55.9,46.1 59.1,46.4 62.2,46.7 65.5,47.0 68.7,47.2 71.9,47.4 75.2,47.6 78.4,47.8 81.7,48.0 84.9,48.1 88.2,48.2 91.4,48.4 94.6,48.5 97.9,48.6 101.1,48.7 104.4,48.7 107.6,48.8 110.8,48.9 114.0,48.9 117.3,49.0 120.5,49.1 123.7,49.1 126.9,49.2 130.1,49.2 133.3,49.2 136.5,49.3 139.7,49.3 142.9,49.3 146.1,49.4 149.3,49.4 152.5,49.4 155.7,49.4 158.8,49.5 162.0,49.5 165.2,49.5 168.4,49.5 171.5,49.6 174.7,49.6 177.9,49.6 181.1,49.6 184.2,49.6 187.4,49.6 190.6,49.6 193.7,49.7 196.9,49.7 200.1,49.7 203.2,49.7 206.4,49.7 209.5,49.7 212.7,49.7 215.9,49.7 219.0,49.7 222.2,49.7 225.3,49.7 228.5,49.8 231.6,49.8 234.8,49.8 237.9,49.8 241.1,49.8 244.2,49.8 247.4,49.8 250.5,49.8 253.7,49.8 256.8,49.8 260.0,49.8 263.1,49.8 266.3,49.8 269.4,49.8 272.6,49.8 275.7,49.8 278.9,49.8 282.0,49.8 285.2,49.8 288.3,49.9 291.4,49.9 294.6,49.9 297.7,49.9 300.9,49.9 304.0,49.9 307.2,49.9 310.3,49.9 313.4,49.9 316.6,49.9 319.7,49.9 322.9,49.9 326.0,49.9 329.1,49.9 332.3,49.9 335.4,49.9 338.6,49.9 341.7,49.9 344.8,49.9 348.0,49.9 351.1,49.9 354.2,49.9 357.4,49.9 360.5,49.9 363.7,49.9 366.8,49.9'/%3E%3Cpolyline points='9.9,0.6 10.1,2.2 10.3,3.7 10.5,5.2 10.8,6.7 11.0,8.1 11.2,9.5 11.5,10.9 11.7,12.2 11.9,13.5 12.2,14.7 12.4,15.9 12.6,17.1 12.8,18.2 13.0,19.3 13.2,20.3 13.3,21.3 13.4,22.2 13.5,23.1 13.5,24.0 13.5,25.0 13.5,25.9 13.4,26.8 13.3,27.7 13.2,28.7 13.0,29.7 12.8,30.8 12.6,31.9 12.4,33.1 12.2,34.3 11.9,35.5 11.7,36.8 11.5,38.1 11.2,39.5 11.0,40.9 10.8,42.3 10.5,43.8 10.3,45.3 10.1,46.8 9.9,48.4'/%3E%3Cpolyline points='21.0,1.9 21.1,3.5 21.2,5.1 21.2,6.7 21.3,8.2 21.4,9.7 21.5,11.2 21.6,12.6 21.7,13.9 21.7,15.2 21.8,16.5 21.9,17.6 22.0,18.7 22.1,19.7 22.2,20.6 22.3,21.4 22.3,22.2 22.4,22.9 22.4,23.6 22.4,24.2 22.4,24.8 22.4,25.4 22.4,26.1 22.3,26.8 22.3,27.6 22.2,28.4 22.1,29.3 22.0,30.3 21.9,31.4 21.8,32.5 21.7,33.8 21.7,35.1 21.6,36.4 21.5,37.8 21.4,39.3 21.3,40.8 21.2,42.3 21.2,43.9 21.1,45.5 21.0,47.1'/%3E%3Cpolyline points='31.5,1.5 31.4,3.1 31.3,4.6 31.1,6.2 30.9,7.7 30.8,9.2 30.6,10.6 30.4,12.0 30.2,13.4 30.0,14.7 29.8,15.9 29.6,17.1 29.4,18.2 29.2,19.2 29.1,20.1 28.9,21.0 28.8,21.9 28.7,22.7 28.6,23.4 28.6,24.1 28.6,24.9 28.6,25.6 28.7,26.3 28.8,27.1 28.9,28.0 29.1,28.9 29.2,29.8 29.4,30.8 29.6,31.9 29.8,33.1 30.0,34.3 30.2,35.6 30.4,37.0 30.6,38.4 30.8,39.8 30.9,41.3 31.1,42.8 31.3,44.4 31.4,45.9 31.5,47.5'/%3E%3Cpolyline points='43.4,-0.1 43.2,1.4 43.0,2.9 42.8,4.3 42.5,5.8 42.3,7.2 42.1,8.6 41.8,10.0 41.6,11.3 41.4,12.6 41.2,13.9 41.0,15.1 40.8,16.3 40.6,17.5 40.4,18.6 40.3,19.7 40.2,20.8 40.1,21.9 40.0,22.9 40.0,24.0 40.0,25.0 40.0,26.1 40.1,27.1 40.2,28.2 40.3,29.3 40.4,30.4 40.6,31.5 40.8,32.7 41.0,33.9 41.2,35.1 41.4,36.4 41.6,37.7 41.8,39.0 42.1,40.4 42.3,41.8 42.5,43.2 42.8,44.7 43.0,46.1 43.2,47.6 43.4,49.1'/%3E%3Cpolyline points='56.8,-1.8 56.6,-0.3 56.4,1.1 56.3,2.6 56.1,4.0 56.0,5.4 55.8,6.8 55.6,8.2 55.5,9.6 55.3,11.0 55.2,12.3 55.1,13.6 54.9,14.9 54.8,16.2 54.7,17.5 54.7,18.8 54.6,20.1 54.5,21.4 54.5,22.6 54.5,23.9 54.5,25.1 54.5,26.4 54.5,27.6 54.6,28.9 54.7,30.2 54.7,31.5 54.8,32.8 54.9,34.1 55.1,35.4 55.2,36.7 55.3,38.0 55.5,39.4 55.6,40.8 55.8,42.2 56.0,43.6 56.1,45.0 56.3,46.4 56.4,47.9 56.6,49.3 56.8,50.8'/%3E%3Cpolyline points='70.9,-3.0 70.8,-1.6 70.7,-0.1 70.6,1.4 70.5,2.8 70.4,4.3 70.3,5.7 70.2,7.1 70.1,8.5 70.0,10.0 69.9,11.4 69.9,12.8 69.8,14.2 69.7,15.6 69.7,16.9 69.6,18.3 69.6,19.7 69.6,21.1 69.6,22.4 69.6,23.8 69.6,25.2 69.6,26.6 69.6,27.9 69.6,29.3 69.6,30.7 69.7,32.1 69.7,33.4 69.8,34.8 69.9,36.2 69.9,37.6 70.0,39.0 70.1,40.5 70.2,41.9 70.3,43.3 70.4,44.7 70.5,46.2 70.6,47.6 70.7,49.1 70.8,50.6 70.9,52.0'/%3E%3Cpolyline points='85.4,-3.9 85.3,-2.4 85.2,-0.9 85.1,0.6 85.1,2.1 85.0,3.5 85.0,5.0 84.9,6.5 84.8,7.9 84.8,9.4 84.7,10.8 84.7,12.3 84.6,13.7 84.6,15.2 84.6,16.6 84.6,18.0 84.5,19.5 84.5,20.9 84.5,22.3 84.5,23.8 84.5,25.2 84.5,26.7 84.5,28.1 84.5,29.5 84.6,31.0 84.6,32.4 84.6,33.8 84.6,35.3 84.7,36.7 84.7,38.2 84.8,39.6 84.8,41.1 84.9,42.5 85.0,44.0 85.0,45.5 85.1,46.9 85.1,48.4 85.2,49.9 85.3,51.4 85.4,52.9'/%3E%3Cpolyline points='99.8,-4.4 99.8,-2.9 99.7,-1.4 99.7,0.1 99.6,1.6 99.6,3.1 99.5,4.6 99.5,6.0 99.5,7.5 99.4,9.0 99.4,10.5 99.4,12.0 99.4,13.5 99.3,14.9 99.3,16.4 99.3,17.9 99.3,19.3 99.3,20.8 99.3,22.3 99.3,23.8 99.3,25.2 99.3,26.7 99.3,28.2 99.3,29.7 99.3,31.1 99.3,32.6 99.3,34.1 99.4,35.5 99.4,37.0 99.4,38.5 99.4,40.0 99.5,41.5 99.5,43.0 99.5,44.4 99.6,45.9 99.6,47.4 99.7,48.9 99.7,50.4 99.8,51.9 99.8,53.4'/%3E%3Cpolyline points='114.2,-4.8 114.2,-3.3 114.2,-1.8 114.1,-0.2 114.1,1.3 114.1,2.8 114.0,4.3 114.0,5.8 114.0,7.3 114.0,8.8 114.0,10.3 113.9,11.8 113.9,13.3 113.9,14.8 113.9,16.3 113.9,17.8 113.9,19.3 113.9,20.8 113.9,22.3 113.9,23.8 113.9,25.2 113.9,26.7 113.9,28.2 113.9,29.7 113.9,31.2 113.9,32.7 113.9,34.2 113.9,35.7 113.9,37.2 114.0,38.7 114.0,40.2 114.0,41.7 114.0,43.2 114.0,44.7 114.1,46.2 114.1,47.7 114.1,49.2 114.2,50.8 114.2,52.3 114.2,53.8'/%3E%3Cpolyline points='128.6,-5.0 128.6,-3.5 128.5,-2.0 128.5,-0.5 128.5,1.0 128.5,2.6 128.5,4.1 128.4,5.6 128.4,7.1 128.4,8.6 128.4,10.1 128.4,11.7 128.4,13.2 128.4,14.7 128.4,16.2 128.3,17.7 128.3,19.2 128.3,20.7 128.3,22.2 128.3,23.7 128.3,25.3 128.3,26.8 128.3,28.3 128.3,29.8 128.3,31.3 128.4,32.8 128.4,34.3 128.4,35.8 128.4,37.3 128.4,38.9 128.4,40.4 128.4,41.9 128.4,43.4 128.5,44.9 128.5,46.4 128.5,48.0 128.5,49.5 128.5,51.0 128.6,52.5 128.6,54.0'/%3E%3Cpolyline points='142.9,-5.2 142.9,-3.7 142.9,-2.2 142.8,-0.6 142.8,0.9 142.8,2.4 142.8,3.9 142.8,5.5 142.8,7.0 142.8,8.5 142.8,10.0 142.8,11.6 142.7,13.1 142.7,14.6 142.7,16.1 142.7,17.7 142.7,19.2 142.7,20.7 142.7,22.2 142.7,23.7 142.7,25.3 142.7,26.8 142.7,28.3 142.7,29.8 142.7,31.3 142.7,32.9 142.7,34.4 142.7,35.9 142.8,37.4 142.8,39.0 142.8,40.5 142.8,42.0 142.8,43.5 142.8,45.1 142.8,46.6 142.8,48.1 142.8,49.6 142.9,51.2 142.9,52.7 142.9,54.2'/%3E%3Cpolyline points='157.2,-5.4 157.2,-3.8 157.1,-2.3 157.1,-0.8 157.1,0.8 157.1,2.3 157.1,3.8 157.1,5.4 157.1,6.9 157.1,8.4 157.1,10.0 157.1,11.5 157.0,13.0 157.0,14.6 157.0,16.1 157.0,17.6 157.0,19.1 157.0,20.7 157.0,22.2 157.0,23.7 157.0,25.3 157.0,26.8 157.0,28.3 157.0,29.9 157.0,31.4 157.0,32.9 157.0,34.4 157.0,36.0 157.1,37.5 157.1,39.0 157.1,40.6 157.1,42.1 157.1,43.6 157.1,45.2 157.1,46.7 157.1,48.2 157.1,49.8 157.1,51.3 157.2,52.8 157.2,54.4'/%3E%3Cpolyline points='171.4,-5.5 171.4,-3.9 171.4,-2.4 171.4,-0.9 171.4,0.7 171.3,2.2 171.3,3.8 171.3,5.3 171.3,6.8 171.3,8.4 171.3,9.9 171.3,11.4 171.3,13.0 171.3,14.5 171.3,16.1 171.3,17.6 171.3,19.1 171.3,20.7 171.3,22.2 171.3,23.7 171.3,25.3 171.3,26.8 171.3,28.3 171.3,29.9 171.3,31.4 171.3,32.9 171.3,34.5 171.3,36.0 171.3,37.6 171.3,39.1 171.3,40.6 171.3,42.2 171.3,43.7 171.3,45.2 171.3,46.8 171.4,48.3 171.4,49.9 171.4,51.4 171.4,52.9 171.4,54.5'/%3E%3Cpolyline points='185.6,-5.6 185.6,-4.0 185.6,-2.5 185.6,-0.9 185.6,0.6 185.6,2.2 185.5,3.7 185.5,5.2 185.5,6.8 185.5,8.3 185.5,9.9 185.5,11.4 185.5,12.9 185.5,14.5 185.5,16.0 185.5,17.6 185.5,19.1 185.5,20.6 185.5,22.2 185.5,23.7 185.5,25.3 185.5,26.8 185.5,28.4 185.5,29.9 185.5,31.4 185.5,33.0 185.5,34.5 185.5,36.1 185.5,37.6 185.5,39.1 185.5,40.7 185.5,42.2 185.5,43.8 185.5,45.3 185.6,46.8 185.6,48.4 185.6,49.9 185.6,51.5 185.6,53.0 185.6,54.6'/%3E%3Cpolyline points='199.8,-5.6 199.8,-4.1 199.7,-2.5 199.7,-1.0 199.7,0.6 199.7,2.1 199.7,3.7 199.7,5.2 199.7,6.7 199.7,8.3 199.7,9.8 199.7,11.4 199.7,12.9 199.7,14.5 199.7,16.0 199.7,17.6 199.7,19.1 199.7,20.6 199.7,22.2 199.7,23.7 199.7,25.3 199.7,26.8 199.7,28.4 199.7,29.9 199.7,31.4 199.7,33.0 199.7,34.5 199.7,36.1 199.7,37.6 199.7,39.2 199.7,40.7 199.7,42.3 199.7,43.8 199.7,45.3 199.7,46.9 199.7,48.4 199.7,50.0 199.7,51.5 199.8,53.1 199.8,54.6'/%3E%3Cpolyline points='213.9,-5.7 213.9,-4.1 213.9,-2.6 213.9,-1.0 213.9,0.5 213.9,2.1 213.9,3.6 213.9,5.2 213.9,6.7 213.9,8.3 213.9,9.8 213.9,11.4 213.9,12.9 213.9,14.4 213.9,16.0 213.9,17.5 213.9,19.1 213.9,20.6 213.9,22.2 213.9,23.7 213.9,25.3 213.9,26.8 213.9,28.4 213.9,29.9 213.9,31.5 213.9,33.0 213.9,34.6 213.9,36.1 213.9,37.6 213.9,39.2 213.9,40.7 213.9,42.3 213.9,43.8 213.9,45.4 213.9,46.9 213.9,48.5 213.9,50.0 213.9,51.6 213.9,53.1 213.9,54.7'/%3E%3Cpolyline points='228.0,-5.7 228.0,-4.2 228.0,-2.6 228.0,-1.1 228.0,0.5 228.0,2.0 228.0,3.6 228.0,5.1 228.0,6.7 228.0,8.2 228.0,9.8 228.0,11.3 228.0,12.9 228.0,14.4 228.0,16.0 228.0,17.5 228.0,19.1 228.0,20.6 228.0,22.2 228.0,23.7 228.0,25.3 228.0,26.8 228.0,28.4 228.0,29.9 228.0,31.5 228.0,33.0 228.0,34.6 228.0,36.1 228.0,37.7 228.0,39.2 228.0,40.8 228.0,42.3 228.0,43.9 228.0,45.4 228.0,47.0 228.0,48.5 228.0,50.1 228.0,51.6 228.0,53.2 228.0,54.7'/%3E%3Cpolyline points='242.2,-5.7 242.2,-4.2 242.1,-2.6 242.1,-1.1 242.1,0.5 242.1,2.0 242.1,3.6 242.1,5.1 242.1,6.7 242.1,8.2 242.1,9.8 242.1,11.3 242.1,12.9 242.1,14.4 242.1,16.0 242.1,17.5 242.1,19.1 242.1,20.6 242.1,22.2 242.1,23.7 242.1,25.3 242.1,26.8 242.1,28.4 242.1,29.9 242.1,31.5 242.1,33.0 242.1,34.6 242.1,36.1 242.1,37.7 242.1,39.2 242.1,40.8 242.1,42.3 242.1,43.9 242.1,45.4 242.1,47.0 242.1,48.5 242.1,50.1 242.1,51.6 242.2,53.2 242.2,54.7'/%3E%3Cpolyline points='256.3,-5.8 256.3,-4.2 256.3,-2.7 256.3,-1.1 256.2,0.4 256.2,2.0 256.2,3.5 256.2,5.1 256.2,6.6 256.2,8.2 256.2,9.8 256.2,11.3 256.2,12.9 256.2,14.4 256.2,16.0 256.2,17.5 256.2,19.1 256.2,20.6 256.2,22.2 256.2,23.7 256.2,25.3 256.2,26.8 256.2,28.4 256.2,29.9 256.2,31.5 256.2,33.0 256.2,34.6 256.2,36.1 256.2,37.7 256.2,39.2 256.2,40.8 256.2,42.4 256.2,43.9 256.2,45.5 256.2,47.0 256.2,48.6 256.3,50.1 256.3,51.7 256.3,53.2 256.3,54.8'/%3E%3Cpolyline points='270.4,-5.8 270.4,-4.2 270.3,-2.7 270.3,-1.1 270.3,0.4 270.3,2.0 270.3,3.5 270.3,5.1 270.3,6.6 270.3,8.2 270.3,9.7 270.3,11.3 270.3,12.8 270.3,14.4 270.3,16.0 270.3,17.5 270.3,19.1 270.3,20.6 270.3,22.2 270.3,23.7 270.3,25.3 270.3,26.8 270.3,28.4 270.3,29.9 270.3,31.5 270.3,33.0 270.3,34.6 270.3,36.2 270.3,37.7 270.3,39.3 270.3,40.8 270.3,42.4 270.3,43.9 270.3,45.5 270.3,47.0 270.3,48.6 270.3,50.1 270.3,51.7 270.4,53.2 270.4,54.8'/%3E%3Cpolyline points='284.4,-5.8 284.4,-4.3 284.4,-2.7 284.4,-1.2 284.4,0.4 284.4,2.0 284.4,3.5 284.4,5.1 284.4,6.6 284.4,8.2 284.4,9.7 284.4,11.3 284.4,12.8 284.4,14.4 284.4,15.9 284.4,17.5 284.4,19.1 284.4,20.6 284.4,22.2 284.4,23.7 284.4,25.3 284.4,26.8 284.4,28.4 284.4,29.9 284.4,31.5 284.4,33.1 284.4,34.6 284.4,36.2 284.4,37.7 284.4,39.3 284.4,40.8 284.4,42.4 284.4,43.9 284.4,45.5 284.4,47.0 284.4,48.6 284.4,50.2 284.4,51.7 284.4,53.3 284.4,54.8'/%3E%3Cpolyline points='298.5,-5.8 298.5,-4.3 298.5,-2.7 298.5,-1.2 298.5,0.4 298.5,1.9 298.5,3.5 298.5,5.1 298.5,6.6 298.5,8.2 298.5,9.7 298.5,11.3 298.5,12.8 298.5,14.4 298.5,15.9 298.5,17.5 298.5,19.1 298.5,20.6 298.5,22.2 298.5,23.7 298.5,25.3 298.5,26.8 298.5,28.4 298.5,29.9 298.5,31.5 298.5,33.1 298.5,34.6 298.5,36.2 298.5,37.7 298.5,39.3 298.5,40.8 298.5,42.4 298.5,43.9 298.5,45.5 298.5,47.1 298.5,48.6 298.5,50.2 298.5,51.7 298.5,53.3 298.5,54.8'/%3E%3Cpolyline points='312.6,-5.9 312.6,-4.3 312.6,-2.7 312.6,-1.2 312.6,0.4 312.6,1.9 312.6,3.5 312.6,5.0 312.6,6.6 312.6,8.2 312.6,9.7 312.6,11.3 312.6,12.8 312.6,14.4 312.6,15.9 312.6,17.5 312.6,19.1 312.6,20.6 312.6,22.2 312.6,23.7 312.6,25.3 312.6,26.8 312.6,28.4 312.6,29.9 312.6,31.5 312.6,33.1 312.6,34.6 312.6,36.2 312.6,37.7 312.6,39.3 312.6,40.8 312.6,42.4 312.6,44.0 312.6,45.5 312.6,47.1 312.6,48.6 312.6,50.2 312.6,51.7 312.6,53.3 312.6,54.9'/%3E%3Cpolyline points='326.6,-5.9 326.6,-4.3 326.6,-2.7 326.6,-1.2 326.6,0.4 326.6,1.9 326.6,3.5 326.6,5.0 326.6,6.6 326.6,8.2 326.6,9.7 326.6,11.3 326.6,12.8 326.6,14.4 326.6,15.9 326.6,17.5 326.6,19.1 326.6,20.6 326.6,22.2 326.6,23.7 326.6,25.3 326.6,26.8 326.6,28.4 326.6,29.9 326.6,31.5 326.6,33.1 326.6,34.6 326.6,36.2 326.6,37.7 326.6,39.3 326.6,40.8 326.6,42.4 326.6,44.0 326.6,45.5 326.6,47.1 326.6,48.6 326.6,50.2 326.6,51.7 326.6,53.3 326.6,54.9'/%3E%3Cpolyline points='340.7,-5.9 340.7,-4.3 340.7,-2.8 340.7,-1.2 340.7,0.4 340.7,1.9 340.7,3.5 340.7,5.0 340.7,6.6 340.7,8.1 340.7,9.7 340.7,11.3 340.7,12.8 340.7,14.4 340.7,15.9 340.7,17.5 340.7,19.0 340.7,20.6 340.7,22.2 340.7,23.7 340.7,25.3 340.7,26.8 340.7,28.4 340.7,30.0 340.7,31.5 340.7,33.1 340.7,34.6 340.7,36.2 340.7,37.7 340.7,39.3 340.7,40.9 340.7,42.4 340.7,44.0 340.7,45.5 340.7,47.1 340.7,48.6 340.7,50.2 340.7,51.8 340.7,53.3 340.7,54.9'/%3E%3Cpolyline points='354.8,-5.9 354.8,-4.3 354.8,-2.8 354.8,-1.2 354.8,0.3 354.8,1.9 354.8,3.5 354.7,5.0 354.7,6.6 354.7,8.1 354.7,9.7 354.7,11.3 354.7,12.8 354.7,14.4 354.7,15.9 354.7,17.5 354.7,19.0 354.7,20.6 354.7,22.2 354.7,23.7 354.7,25.3 354.7,26.8 354.7,28.4 354.7,30.0 354.7,31.5 354.7,33.1 354.7,34.6 354.7,36.2 354.7,37.7 354.7,39.3 354.7,40.9 354.7,42.4 354.7,44.0 354.8,45.5 354.8,47.1 354.8,48.7 354.8,50.2 354.8,51.8 354.8,53.3 354.8,54.9'/%3E%3C/g%3E%3C/svg%3E");
    background-repeat:no-repeat, no-repeat;
    background-size:100% 100%, 720px 97px;
    background-position:0 0, -12px center;}
  /* Worn inside the wormhole the surface belongs on the slab. The row itself
     is transparent there, so the image moves; same picture, one layer down. */
  .fr-kirmgrauza.sf-erdvelaikis{background-image:none;}
  .fr-kirmgrauza.sf-erdvelaikis > .slab{
    background-image:
      linear-gradient(90deg, rgba(7,11,28,0) 0 460px, var(--int) 650px),
      url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 364 49' width='364' height='49' preserveAspectRatio='none'%3E%3Cdefs%3E%3CradialGradient id='w' cx='24' cy='24.5' r='34' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%237FD4FF' stop-opacity='.28'/%3E%3Cstop offset='.45' stop-color='%233A7BD5' stop-opacity='.10'/%3E%3Cstop offset='1' stop-color='%233A7BD5' stop-opacity='0'/%3E%3C/radialGradient%3E%3ClinearGradient id='fx' x1='0' x2='1'%3E%3Cstop offset='0' stop-color='%23fff' stop-opacity='.9'/%3E%3Cstop offset='.35' stop-color='%23fff' stop-opacity='.35'/%3E%3Cstop offset='1' stop-color='%23fff' stop-opacity='.18'/%3E%3C/linearGradient%3E%3Cmask id='mx'%3E%3Crect width='364' height='49' fill='url(%23fx)'/%3E%3C/mask%3E%3C/defs%3E%3Crect width='364' height='49' fill='url(%23w)'/%3E%3Cg fill='none' stroke='%237FD4FF' stroke-width='0.5' opacity='.38' mask='url(%23mx)'%3E%3Cpolyline points='0.9,-0.7 3.8,-0.3 6.6,0.1 9.4,0.5 12.0,0.9 14.6,1.3 17.0,1.6 19.4,1.8 21.8,1.9 24.1,2.0 26.4,1.9 28.8,1.8 31.2,1.5 33.6,1.2 36.2,0.9 38.9,0.5 41.6,0.1 44.4,-0.3 47.3,-0.7 50.3,-1.1 53.3,-1.4 56.4,-1.8 59.5,-2.1 62.7,-2.4 65.9,-2.7 69.1,-2.9 72.3,-3.1 75.5,-3.3 78.7,-3.5 81.9,-3.7 85.1,-3.8 88.4,-4.0 91.6,-4.1 94.8,-4.2 98.0,-4.3 101.3,-4.4 104.5,-4.5 107.7,-4.6 110.9,-4.7 114.1,-4.8 117.4,-4.8 120.6,-4.9 123.8,-5.0 127.0,-5.0 130.2,-5.1 133.4,-5.1 136.6,-5.1 139.8,-5.2 143.0,-5.2 146.1,-5.3 149.3,-5.3 152.5,-5.3 155.7,-5.4 158.9,-5.4 162.1,-5.4 165.2,-5.4 168.4,-5.4 171.6,-5.5 174.8,-5.5 177.9,-5.5 181.1,-5.5 184.3,-5.5 187.4,-5.6 190.6,-5.6 193.8,-5.6 196.9,-5.6 200.1,-5.6 203.2,-5.6 206.4,-5.6 209.6,-5.7 212.7,-5.7 215.9,-5.7 219.0,-5.7 222.2,-5.7 225.3,-5.7 228.5,-5.7 231.7,-5.7 234.8,-5.7 238.0,-5.7 241.1,-5.7 244.3,-5.7 247.4,-5.8 250.6,-5.8 253.7,-5.8 256.9,-5.8 260.0,-5.8 263.1,-5.8 266.3,-5.8 269.4,-5.8 272.6,-5.8 275.7,-5.8 278.9,-5.8 282.0,-5.8 285.2,-5.8 288.3,-5.8 291.5,-5.8 294.6,-5.8 297.7,-5.8 300.9,-5.8 304.0,-5.8 307.2,-5.8 310.3,-5.8 313.4,-5.9 316.6,-5.9 319.7,-5.9 322.9,-5.9 326.0,-5.9 329.1,-5.9 332.3,-5.9 335.4,-5.9 338.6,-5.9 341.7,-5.9 344.8,-5.9 348.0,-5.9 351.1,-5.9 354.2,-5.9 357.4,-5.9 360.5,-5.9 363.7,-5.9 366.8,-5.9'/%3E%3Cpolyline points='1.8,5.9 4.8,6.3 7.6,6.8 10.3,7.3 12.9,7.7 15.4,8.1 17.7,8.5 19.9,8.8 22.0,9.0 24.1,9.0 26.2,9.0 28.3,8.8 30.5,8.5 32.8,8.1 35.3,7.7 37.9,7.2 40.6,6.7 43.5,6.3 46.4,5.9 49.5,5.4 52.5,5.1 55.7,4.7 58.9,4.4 62.1,4.1 65.3,3.9 68.5,3.6 71.8,3.4 75.0,3.2 78.3,3.1 81.6,2.9 84.8,2.8 88.1,2.6 91.3,2.5 94.6,2.4 97.8,2.3 101.1,2.3 104.3,2.2 107.5,2.1 110.8,2.0 114.0,2.0 117.2,1.9 120.4,1.9 123.7,1.8 126.9,1.8 130.1,1.7 133.3,1.7 136.5,1.7 139.7,1.6 142.9,1.6 146.1,1.6 149.3,1.6 152.5,1.5 155.6,1.5 158.8,1.5 162.0,1.5 165.2,1.4 168.4,1.4 171.5,1.4 174.7,1.4 177.9,1.4 181.1,1.4 184.2,1.4 187.4,1.3 190.6,1.3 193.7,1.3 196.9,1.3 200.1,1.3 203.2,1.3 206.4,1.3 209.5,1.3 212.7,1.3 215.9,1.3 219.0,1.2 222.2,1.2 225.3,1.2 228.5,1.2 231.6,1.2 234.8,1.2 237.9,1.2 241.1,1.2 244.2,1.2 247.4,1.2 250.5,1.2 253.7,1.2 256.8,1.2 260.0,1.2 263.1,1.2 266.3,1.2 269.4,1.2 272.6,1.2 275.7,1.2 278.9,1.1 282.0,1.1 285.2,1.1 288.3,1.1 291.4,1.1 294.6,1.1 297.7,1.1 300.9,1.1 304.0,1.1 307.2,1.1 310.3,1.1 313.4,1.1 316.6,1.1 319.7,1.1 322.9,1.1 326.0,1.1 329.1,1.1 332.3,1.1 335.4,1.1 338.6,1.1 341.7,1.1 344.8,1.1 348.0,1.1 351.1,1.1 354.2,1.1 357.4,1.1 360.5,1.1 363.7,1.1 366.8,1.1'/%3E%3Cpolyline points='2.8,12.0 5.8,12.4 8.7,12.9 11.4,13.3 14.0,13.8 16.3,14.3 18.5,14.7 20.5,15.0 22.3,15.2 24.1,15.3 25.8,15.2 27.7,15.0 29.7,14.7 31.9,14.2 34.2,13.8 36.8,13.3 39.6,12.8 42.5,12.4 45.5,12.0 48.6,11.6 51.8,11.2 55.0,10.9 58.2,10.6 61.5,10.4 64.8,10.2 68.1,10.0 71.4,9.8 74.7,9.7 78.0,9.5 81.3,9.4 84.6,9.3 87.8,9.2 91.1,9.1 94.4,9.0 97.6,9.0 100.9,8.9 104.2,8.9 107.4,8.8 110.6,8.8 113.9,8.7 117.1,8.7 120.3,8.6 123.6,8.6 126.8,8.6 130.0,8.5 133.2,8.5 136.4,8.5 139.6,8.5 142.8,8.4 146.0,8.4 149.2,8.4 152.4,8.4 155.6,8.4 158.8,8.3 162.0,8.3 165.1,8.3 168.3,8.3 171.5,8.3 174.7,8.3 177.9,8.3 181.0,8.3 184.2,8.3 187.4,8.2 190.5,8.2 193.7,8.2 196.9,8.2 200.0,8.2 203.2,8.2 206.4,8.2 209.5,8.2 212.7,8.2 215.8,8.2 219.0,8.2 222.2,8.2 225.3,8.2 228.5,8.2 231.6,8.2 234.8,8.1 237.9,8.1 241.1,8.1 244.2,8.1 247.4,8.1 250.5,8.1 253.7,8.1 256.8,8.1 260.0,8.1 263.1,8.1 266.3,8.1 269.4,8.1 272.6,8.1 275.7,8.1 278.9,8.1 282.0,8.1 285.1,8.1 288.3,8.1 291.4,8.1 294.6,8.1 297.7,8.1 300.9,8.1 304.0,8.1 307.1,8.1 310.3,8.1 313.4,8.1 316.6,8.1 319.7,8.1 322.9,8.1 326.0,8.1 329.1,8.1 332.3,8.1 335.4,8.1 338.6,8.1 341.7,8.1 344.8,8.1 348.0,8.1 351.1,8.1 354.2,8.1 357.4,8.1 360.5,8.1 363.7,8.1 366.8,8.1'/%3E%3Cpolyline points='3.6,17.6 6.7,17.9 9.6,18.2 12.4,18.6 15.0,19.0 17.3,19.3 19.3,19.7 21.1,20.0 22.6,20.1 24.1,20.2 25.5,20.1 27.1,19.9 28.9,19.6 30.9,19.3 33.3,18.9 35.8,18.5 38.6,18.2 41.6,17.8 44.7,17.5 47.9,17.3 51.1,17.0 54.4,16.8 57.7,16.6 61.1,16.5 64.4,16.3 67.7,16.2 71.1,16.1 74.4,16.0 77.7,15.9 81.1,15.8 84.4,15.8 87.7,15.7 91.0,15.7 94.2,15.6 97.5,15.6 100.8,15.5 104.1,15.5 107.3,15.5 110.6,15.4 113.8,15.4 117.0,15.4 120.3,15.4 123.5,15.3 126.7,15.3 129.9,15.3 133.2,15.3 136.4,15.3 139.6,15.3 142.8,15.3 146.0,15.2 149.2,15.2 152.4,15.2 155.6,15.2 158.8,15.2 161.9,15.2 165.1,15.2 168.3,15.2 171.5,15.2 174.7,15.2 177.8,15.2 181.0,15.2 184.2,15.1 187.4,15.1 190.5,15.1 193.7,15.1 196.9,15.1 200.0,15.1 203.2,15.1 206.4,15.1 209.5,15.1 212.7,15.1 215.8,15.1 219.0,15.1 222.1,15.1 225.3,15.1 228.5,15.1 231.6,15.1 234.8,15.1 237.9,15.1 241.1,15.1 244.2,15.1 247.4,15.1 250.5,15.1 253.7,15.1 256.8,15.1 260.0,15.1 263.1,15.1 266.3,15.1 269.4,15.1 272.6,15.1 275.7,15.1 278.9,15.1 282.0,15.1 285.1,15.1 288.3,15.1 291.4,15.1 294.6,15.1 297.7,15.1 300.9,15.1 304.0,15.0 307.1,15.0 310.3,15.0 313.4,15.0 316.6,15.0 319.7,15.0 322.9,15.0 326.0,15.0 329.1,15.0 332.3,15.0 335.4,15.0 338.5,15.0 341.7,15.0 344.8,15.0 348.0,15.0 351.1,15.0 354.2,15.0 357.4,15.0 360.5,15.0 363.7,15.0 366.8,15.0'/%3E%3Cpolyline points='4.0,22.7 7.1,22.8 10.1,22.9 13.0,23.0 15.5,23.1 17.8,23.3 19.8,23.4 21.4,23.5 22.8,23.5 24.1,23.5 25.3,23.5 26.7,23.4 28.4,23.4 30.3,23.2 32.7,23.1 35.3,23.0 38.1,22.9 41.1,22.8 44.3,22.7 47.5,22.6 50.8,22.6 54.1,22.5 57.5,22.4 60.8,22.4 64.2,22.4 67.6,22.3 70.9,22.3 74.3,22.3 77.6,22.2 81.0,22.2 84.3,22.2 87.6,22.2 90.9,22.2 94.2,22.2 97.5,22.2 100.7,22.1 104.0,22.1 107.3,22.1 110.5,22.1 113.8,22.1 117.0,22.1 120.3,22.1 123.5,22.1 126.7,22.1 129.9,22.1 133.1,22.1 136.4,22.1 139.6,22.1 142.8,22.1 146.0,22.1 149.2,22.1 152.4,22.1 155.6,22.1 158.7,22.1 161.9,22.1 165.1,22.0 168.3,22.0 171.5,22.0 174.7,22.0 177.8,22.0 181.0,22.0 184.2,22.0 187.3,22.0 190.5,22.0 193.7,22.0 196.9,22.0 200.0,22.0 203.2,22.0 206.3,22.0 209.5,22.0 212.7,22.0 215.8,22.0 219.0,22.0 222.1,22.0 225.3,22.0 228.5,22.0 231.6,22.0 234.8,22.0 237.9,22.0 241.1,22.0 244.2,22.0 247.4,22.0 250.5,22.0 253.7,22.0 256.8,22.0 260.0,22.0 263.1,22.0 266.3,22.0 269.4,22.0 272.6,22.0 275.7,22.0 278.9,22.0 282.0,22.0 285.1,22.0 288.3,22.0 291.4,22.0 294.6,22.0 297.7,22.0 300.9,22.0 304.0,22.0 307.1,22.0 310.3,22.0 313.4,22.0 316.6,22.0 319.7,22.0 322.8,22.0 326.0,22.0 329.1,22.0 332.3,22.0 335.4,22.0 338.5,22.0 341.7,22.0 344.8,22.0 348.0,22.0 351.1,22.0 354.2,22.0 357.4,22.0 360.5,22.0 363.7,22.0 366.8,22.0'/%3E%3Cpolyline points='3.9,27.7 7.1,27.6 10.0,27.4 12.9,27.2 15.4,27.0 17.7,26.8 19.7,26.6 21.4,26.4 22.8,26.3 24.1,26.3 25.3,26.3 26.8,26.4 28.4,26.6 30.5,26.8 32.8,27.0 35.4,27.2 38.2,27.4 41.2,27.6 44.3,27.7 47.6,27.9 50.9,28.0 54.2,28.1 57.5,28.2 60.9,28.3 64.2,28.4 67.6,28.4 71.0,28.5 74.3,28.5 77.6,28.6 81.0,28.6 84.3,28.6 87.6,28.7 90.9,28.7 94.2,28.7 97.5,28.7 100.8,28.7 104.0,28.8 107.3,28.8 110.5,28.8 113.8,28.8 117.0,28.8 120.3,28.8 123.5,28.8 126.7,28.8 129.9,28.9 133.1,28.9 136.4,28.9 139.6,28.9 142.8,28.9 146.0,28.9 149.2,28.9 152.4,28.9 155.6,28.9 158.7,28.9 161.9,28.9 165.1,28.9 168.3,28.9 171.5,28.9 174.7,28.9 177.8,28.9 181.0,28.9 184.2,28.9 187.3,28.9 190.5,28.9 193.7,28.9 196.9,28.9 200.0,28.9 203.2,28.9 206.3,28.9 209.5,28.9 212.7,28.9 215.8,29.0 219.0,29.0 222.1,29.0 225.3,29.0 228.5,29.0 231.6,29.0 234.8,29.0 237.9,29.0 241.1,29.0 244.2,29.0 247.4,29.0 250.5,29.0 253.7,29.0 256.8,29.0 260.0,29.0 263.1,29.0 266.3,29.0 269.4,29.0 272.6,29.0 275.7,29.0 278.9,29.0 282.0,29.0 285.1,29.0 288.3,29.0 291.4,29.0 294.6,29.0 297.7,29.0 300.9,29.0 304.0,29.0 307.1,29.0 310.3,29.0 313.4,29.0 316.6,29.0 319.7,29.0 322.9,29.0 326.0,29.0 329.1,29.0 332.3,29.0 335.4,29.0 338.5,29.0 341.7,29.0 344.8,29.0 348.0,29.0 351.1,29.0 354.2,29.0 357.4,29.0 360.5,29.0 363.7,29.0 366.8,29.0'/%3E%3Cpolyline points='3.4,33.0 6.4,32.6 9.4,32.2 12.1,31.8 14.7,31.4 17.0,31.0 19.1,30.6 20.9,30.3 22.5,30.1 24.1,30.0 25.6,30.1 27.2,30.3 29.1,30.6 31.2,31.0 33.5,31.4 36.1,31.9 38.9,32.3 41.8,32.7 44.9,33.0 48.1,33.3 51.3,33.6 54.6,33.8 57.9,34.0 61.2,34.2 64.5,34.4 67.8,34.5 71.2,34.7 74.5,34.8 77.8,34.9 81.1,35.0 84.4,35.1 87.7,35.1 91.0,35.2 94.3,35.3 97.6,35.3 100.8,35.4 104.1,35.4 107.3,35.4 110.6,35.5 113.8,35.5 117.1,35.5 120.3,35.6 123.5,35.6 126.7,35.6 130.0,35.6 133.2,35.6 136.4,35.7 139.6,35.7 142.8,35.7 146.0,35.7 149.2,35.7 152.4,35.7 155.6,35.7 158.8,35.8 161.9,35.8 165.1,35.8 168.3,35.8 171.5,35.8 174.7,35.8 177.8,35.8 181.0,35.8 184.2,35.8 187.4,35.8 190.5,35.8 193.7,35.8 196.9,35.8 200.0,35.9 203.2,35.9 206.4,35.9 209.5,35.9 212.7,35.9 215.8,35.9 219.0,35.9 222.1,35.9 225.3,35.9 228.5,35.9 231.6,35.9 234.8,35.9 237.9,35.9 241.1,35.9 244.2,35.9 247.4,35.9 250.5,35.9 253.7,35.9 256.8,35.9 260.0,35.9 263.1,35.9 266.3,35.9 269.4,35.9 272.6,35.9 275.7,35.9 278.9,35.9 282.0,35.9 285.1,35.9 288.3,35.9 291.4,35.9 294.6,35.9 297.7,35.9 300.9,35.9 304.0,35.9 307.1,35.9 310.3,35.9 313.4,35.9 316.6,35.9 319.7,35.9 322.9,35.9 326.0,35.9 329.1,35.9 332.3,36.0 335.4,36.0 338.5,36.0 341.7,36.0 344.8,36.0 348.0,36.0 351.1,36.0 354.2,36.0 357.4,36.0 360.5,36.0 363.7,36.0 366.8,36.0'/%3E%3Cpolyline points='2.5,38.7 5.5,38.3 8.4,37.8 11.1,37.3 13.7,36.8 16.1,36.4 18.3,36.0 20.3,35.7 22.2,35.5 24.1,35.4 25.9,35.5 27.9,35.7 29.9,36.0 32.1,36.4 34.5,36.9 37.1,37.4 39.9,37.8 42.8,38.3 45.7,38.7 48.8,39.1 52.0,39.5 55.2,39.8 58.4,40.1 61.7,40.4 64.9,40.6 68.2,40.8 71.5,41.0 74.8,41.2 78.1,41.3 81.3,41.4 84.6,41.5 87.9,41.7 91.2,41.8 94.4,41.8 97.7,41.9 100.9,42.0 104.2,42.1 107.4,42.1 110.7,42.2 113.9,42.2 117.1,42.3 120.4,42.3 123.6,42.3 126.8,42.4 130.0,42.4 133.2,42.4 136.4,42.5 139.6,42.5 142.8,42.5 146.0,42.5 149.2,42.6 152.4,42.6 155.6,42.6 158.8,42.6 162.0,42.6 165.2,42.6 168.3,42.7 171.5,42.7 174.7,42.7 177.9,42.7 181.0,42.7 184.2,42.7 187.4,42.7 190.5,42.7 193.7,42.7 196.9,42.8 200.0,42.8 203.2,42.8 206.4,42.8 209.5,42.8 212.7,42.8 215.8,42.8 219.0,42.8 222.2,42.8 225.3,42.8 228.5,42.8 231.6,42.8 234.8,42.8 237.9,42.8 241.1,42.8 244.2,42.8 247.4,42.9 250.5,42.9 253.7,42.9 256.8,42.9 260.0,42.9 263.1,42.9 266.3,42.9 269.4,42.9 272.6,42.9 275.7,42.9 278.9,42.9 282.0,42.9 285.2,42.9 288.3,42.9 291.4,42.9 294.6,42.9 297.7,42.9 300.9,42.9 304.0,42.9 307.2,42.9 310.3,42.9 313.4,42.9 316.6,42.9 319.7,42.9 322.9,42.9 326.0,42.9 329.1,42.9 332.3,42.9 335.4,42.9 338.6,42.9 341.7,42.9 344.8,42.9 348.0,42.9 351.1,42.9 354.2,42.9 357.4,42.9 360.5,42.9 363.7,42.9 366.8,42.9'/%3E%3Cpolyline points='1.6,44.9 4.5,44.5 7.3,44.1 10.0,43.6 12.7,43.2 15.1,42.8 17.5,42.4 19.8,42.2 21.9,42.0 24.1,41.9 26.2,42.0 28.4,42.2 30.7,42.5 33.1,42.8 35.6,43.2 38.2,43.7 40.9,44.1 43.8,44.5 46.7,45.0 49.7,45.4 52.8,45.8 55.9,46.1 59.1,46.4 62.2,46.7 65.5,47.0 68.7,47.2 71.9,47.4 75.2,47.6 78.4,47.8 81.7,48.0 84.9,48.1 88.2,48.2 91.4,48.4 94.6,48.5 97.9,48.6 101.1,48.7 104.4,48.7 107.6,48.8 110.8,48.9 114.0,48.9 117.3,49.0 120.5,49.1 123.7,49.1 126.9,49.2 130.1,49.2 133.3,49.2 136.5,49.3 139.7,49.3 142.9,49.3 146.1,49.4 149.3,49.4 152.5,49.4 155.7,49.4 158.8,49.5 162.0,49.5 165.2,49.5 168.4,49.5 171.5,49.6 174.7,49.6 177.9,49.6 181.1,49.6 184.2,49.6 187.4,49.6 190.6,49.6 193.7,49.7 196.9,49.7 200.1,49.7 203.2,49.7 206.4,49.7 209.5,49.7 212.7,49.7 215.9,49.7 219.0,49.7 222.2,49.7 225.3,49.7 228.5,49.8 231.6,49.8 234.8,49.8 237.9,49.8 241.1,49.8 244.2,49.8 247.4,49.8 250.5,49.8 253.7,49.8 256.8,49.8 260.0,49.8 263.1,49.8 266.3,49.8 269.4,49.8 272.6,49.8 275.7,49.8 278.9,49.8 282.0,49.8 285.2,49.8 288.3,49.9 291.4,49.9 294.6,49.9 297.7,49.9 300.9,49.9 304.0,49.9 307.2,49.9 310.3,49.9 313.4,49.9 316.6,49.9 319.7,49.9 322.9,49.9 326.0,49.9 329.1,49.9 332.3,49.9 335.4,49.9 338.6,49.9 341.7,49.9 344.8,49.9 348.0,49.9 351.1,49.9 354.2,49.9 357.4,49.9 360.5,49.9 363.7,49.9 366.8,49.9'/%3E%3Cpolyline points='9.9,0.6 10.1,2.2 10.3,3.7 10.5,5.2 10.8,6.7 11.0,8.1 11.2,9.5 11.5,10.9 11.7,12.2 11.9,13.5 12.2,14.7 12.4,15.9 12.6,17.1 12.8,18.2 13.0,19.3 13.2,20.3 13.3,21.3 13.4,22.2 13.5,23.1 13.5,24.0 13.5,25.0 13.5,25.9 13.4,26.8 13.3,27.7 13.2,28.7 13.0,29.7 12.8,30.8 12.6,31.9 12.4,33.1 12.2,34.3 11.9,35.5 11.7,36.8 11.5,38.1 11.2,39.5 11.0,40.9 10.8,42.3 10.5,43.8 10.3,45.3 10.1,46.8 9.9,48.4'/%3E%3Cpolyline points='21.0,1.9 21.1,3.5 21.2,5.1 21.2,6.7 21.3,8.2 21.4,9.7 21.5,11.2 21.6,12.6 21.7,13.9 21.7,15.2 21.8,16.5 21.9,17.6 22.0,18.7 22.1,19.7 22.2,20.6 22.3,21.4 22.3,22.2 22.4,22.9 22.4,23.6 22.4,24.2 22.4,24.8 22.4,25.4 22.4,26.1 22.3,26.8 22.3,27.6 22.2,28.4 22.1,29.3 22.0,30.3 21.9,31.4 21.8,32.5 21.7,33.8 21.7,35.1 21.6,36.4 21.5,37.8 21.4,39.3 21.3,40.8 21.2,42.3 21.2,43.9 21.1,45.5 21.0,47.1'/%3E%3Cpolyline points='31.5,1.5 31.4,3.1 31.3,4.6 31.1,6.2 30.9,7.7 30.8,9.2 30.6,10.6 30.4,12.0 30.2,13.4 30.0,14.7 29.8,15.9 29.6,17.1 29.4,18.2 29.2,19.2 29.1,20.1 28.9,21.0 28.8,21.9 28.7,22.7 28.6,23.4 28.6,24.1 28.6,24.9 28.6,25.6 28.7,26.3 28.8,27.1 28.9,28.0 29.1,28.9 29.2,29.8 29.4,30.8 29.6,31.9 29.8,33.1 30.0,34.3 30.2,35.6 30.4,37.0 30.6,38.4 30.8,39.8 30.9,41.3 31.1,42.8 31.3,44.4 31.4,45.9 31.5,47.5'/%3E%3Cpolyline points='43.4,-0.1 43.2,1.4 43.0,2.9 42.8,4.3 42.5,5.8 42.3,7.2 42.1,8.6 41.8,10.0 41.6,11.3 41.4,12.6 41.2,13.9 41.0,15.1 40.8,16.3 40.6,17.5 40.4,18.6 40.3,19.7 40.2,20.8 40.1,21.9 40.0,22.9 40.0,24.0 40.0,25.0 40.0,26.1 40.1,27.1 40.2,28.2 40.3,29.3 40.4,30.4 40.6,31.5 40.8,32.7 41.0,33.9 41.2,35.1 41.4,36.4 41.6,37.7 41.8,39.0 42.1,40.4 42.3,41.8 42.5,43.2 42.8,44.7 43.0,46.1 43.2,47.6 43.4,49.1'/%3E%3Cpolyline points='56.8,-1.8 56.6,-0.3 56.4,1.1 56.3,2.6 56.1,4.0 56.0,5.4 55.8,6.8 55.6,8.2 55.5,9.6 55.3,11.0 55.2,12.3 55.1,13.6 54.9,14.9 54.8,16.2 54.7,17.5 54.7,18.8 54.6,20.1 54.5,21.4 54.5,22.6 54.5,23.9 54.5,25.1 54.5,26.4 54.5,27.6 54.6,28.9 54.7,30.2 54.7,31.5 54.8,32.8 54.9,34.1 55.1,35.4 55.2,36.7 55.3,38.0 55.5,39.4 55.6,40.8 55.8,42.2 56.0,43.6 56.1,45.0 56.3,46.4 56.4,47.9 56.6,49.3 56.8,50.8'/%3E%3Cpolyline points='70.9,-3.0 70.8,-1.6 70.7,-0.1 70.6,1.4 70.5,2.8 70.4,4.3 70.3,5.7 70.2,7.1 70.1,8.5 70.0,10.0 69.9,11.4 69.9,12.8 69.8,14.2 69.7,15.6 69.7,16.9 69.6,18.3 69.6,19.7 69.6,21.1 69.6,22.4 69.6,23.8 69.6,25.2 69.6,26.6 69.6,27.9 69.6,29.3 69.6,30.7 69.7,32.1 69.7,33.4 69.8,34.8 69.9,36.2 69.9,37.6 70.0,39.0 70.1,40.5 70.2,41.9 70.3,43.3 70.4,44.7 70.5,46.2 70.6,47.6 70.7,49.1 70.8,50.6 70.9,52.0'/%3E%3Cpolyline points='85.4,-3.9 85.3,-2.4 85.2,-0.9 85.1,0.6 85.1,2.1 85.0,3.5 85.0,5.0 84.9,6.5 84.8,7.9 84.8,9.4 84.7,10.8 84.7,12.3 84.6,13.7 84.6,15.2 84.6,16.6 84.6,18.0 84.5,19.5 84.5,20.9 84.5,22.3 84.5,23.8 84.5,25.2 84.5,26.7 84.5,28.1 84.5,29.5 84.6,31.0 84.6,32.4 84.6,33.8 84.6,35.3 84.7,36.7 84.7,38.2 84.8,39.6 84.8,41.1 84.9,42.5 85.0,44.0 85.0,45.5 85.1,46.9 85.1,48.4 85.2,49.9 85.3,51.4 85.4,52.9'/%3E%3Cpolyline points='99.8,-4.4 99.8,-2.9 99.7,-1.4 99.7,0.1 99.6,1.6 99.6,3.1 99.5,4.6 99.5,6.0 99.5,7.5 99.4,9.0 99.4,10.5 99.4,12.0 99.4,13.5 99.3,14.9 99.3,16.4 99.3,17.9 99.3,19.3 99.3,20.8 99.3,22.3 99.3,23.8 99.3,25.2 99.3,26.7 99.3,28.2 99.3,29.7 99.3,31.1 99.3,32.6 99.3,34.1 99.4,35.5 99.4,37.0 99.4,38.5 99.4,40.0 99.5,41.5 99.5,43.0 99.5,44.4 99.6,45.9 99.6,47.4 99.7,48.9 99.7,50.4 99.8,51.9 99.8,53.4'/%3E%3Cpolyline points='114.2,-4.8 114.2,-3.3 114.2,-1.8 114.1,-0.2 114.1,1.3 114.1,2.8 114.0,4.3 114.0,5.8 114.0,7.3 114.0,8.8 114.0,10.3 113.9,11.8 113.9,13.3 113.9,14.8 113.9,16.3 113.9,17.8 113.9,19.3 113.9,20.8 113.9,22.3 113.9,23.8 113.9,25.2 113.9,26.7 113.9,28.2 113.9,29.7 113.9,31.2 113.9,32.7 113.9,34.2 113.9,35.7 113.9,37.2 114.0,38.7 114.0,40.2 114.0,41.7 114.0,43.2 114.0,44.7 114.1,46.2 114.1,47.7 114.1,49.2 114.2,50.8 114.2,52.3 114.2,53.8'/%3E%3Cpolyline points='128.6,-5.0 128.6,-3.5 128.5,-2.0 128.5,-0.5 128.5,1.0 128.5,2.6 128.5,4.1 128.4,5.6 128.4,7.1 128.4,8.6 128.4,10.1 128.4,11.7 128.4,13.2 128.4,14.7 128.4,16.2 128.3,17.7 128.3,19.2 128.3,20.7 128.3,22.2 128.3,23.7 128.3,25.3 128.3,26.8 128.3,28.3 128.3,29.8 128.3,31.3 128.4,32.8 128.4,34.3 128.4,35.8 128.4,37.3 128.4,38.9 128.4,40.4 128.4,41.9 128.4,43.4 128.5,44.9 128.5,46.4 128.5,48.0 128.5,49.5 128.5,51.0 128.6,52.5 128.6,54.0'/%3E%3Cpolyline points='142.9,-5.2 142.9,-3.7 142.9,-2.2 142.8,-0.6 142.8,0.9 142.8,2.4 142.8,3.9 142.8,5.5 142.8,7.0 142.8,8.5 142.8,10.0 142.8,11.6 142.7,13.1 142.7,14.6 142.7,16.1 142.7,17.7 142.7,19.2 142.7,20.7 142.7,22.2 142.7,23.7 142.7,25.3 142.7,26.8 142.7,28.3 142.7,29.8 142.7,31.3 142.7,32.9 142.7,34.4 142.7,35.9 142.8,37.4 142.8,39.0 142.8,40.5 142.8,42.0 142.8,43.5 142.8,45.1 142.8,46.6 142.8,48.1 142.8,49.6 142.9,51.2 142.9,52.7 142.9,54.2'/%3E%3Cpolyline points='157.2,-5.4 157.2,-3.8 157.1,-2.3 157.1,-0.8 157.1,0.8 157.1,2.3 157.1,3.8 157.1,5.4 157.1,6.9 157.1,8.4 157.1,10.0 157.1,11.5 157.0,13.0 157.0,14.6 157.0,16.1 157.0,17.6 157.0,19.1 157.0,20.7 157.0,22.2 157.0,23.7 157.0,25.3 157.0,26.8 157.0,28.3 157.0,29.9 157.0,31.4 157.0,32.9 157.0,34.4 157.0,36.0 157.1,37.5 157.1,39.0 157.1,40.6 157.1,42.1 157.1,43.6 157.1,45.2 157.1,46.7 157.1,48.2 157.1,49.8 157.1,51.3 157.2,52.8 157.2,54.4'/%3E%3Cpolyline points='171.4,-5.5 171.4,-3.9 171.4,-2.4 171.4,-0.9 171.4,0.7 171.3,2.2 171.3,3.8 171.3,5.3 171.3,6.8 171.3,8.4 171.3,9.9 171.3,11.4 171.3,13.0 171.3,14.5 171.3,16.1 171.3,17.6 171.3,19.1 171.3,20.7 171.3,22.2 171.3,23.7 171.3,25.3 171.3,26.8 171.3,28.3 171.3,29.9 171.3,31.4 171.3,32.9 171.3,34.5 171.3,36.0 171.3,37.6 171.3,39.1 171.3,40.6 171.3,42.2 171.3,43.7 171.3,45.2 171.3,46.8 171.4,48.3 171.4,49.9 171.4,51.4 171.4,52.9 171.4,54.5'/%3E%3Cpolyline points='185.6,-5.6 185.6,-4.0 185.6,-2.5 185.6,-0.9 185.6,0.6 185.6,2.2 185.5,3.7 185.5,5.2 185.5,6.8 185.5,8.3 185.5,9.9 185.5,11.4 185.5,12.9 185.5,14.5 185.5,16.0 185.5,17.6 185.5,19.1 185.5,20.6 185.5,22.2 185.5,23.7 185.5,25.3 185.5,26.8 185.5,28.4 185.5,29.9 185.5,31.4 185.5,33.0 185.5,34.5 185.5,36.1 185.5,37.6 185.5,39.1 185.5,40.7 185.5,42.2 185.5,43.8 185.5,45.3 185.6,46.8 185.6,48.4 185.6,49.9 185.6,51.5 185.6,53.0 185.6,54.6'/%3E%3Cpolyline points='199.8,-5.6 199.8,-4.1 199.7,-2.5 199.7,-1.0 199.7,0.6 199.7,2.1 199.7,3.7 199.7,5.2 199.7,6.7 199.7,8.3 199.7,9.8 199.7,11.4 199.7,12.9 199.7,14.5 199.7,16.0 199.7,17.6 199.7,19.1 199.7,20.6 199.7,22.2 199.7,23.7 199.7,25.3 199.7,26.8 199.7,28.4 199.7,29.9 199.7,31.4 199.7,33.0 199.7,34.5 199.7,36.1 199.7,37.6 199.7,39.2 199.7,40.7 199.7,42.3 199.7,43.8 199.7,45.3 199.7,46.9 199.7,48.4 199.7,50.0 199.7,51.5 199.8,53.1 199.8,54.6'/%3E%3Cpolyline points='213.9,-5.7 213.9,-4.1 213.9,-2.6 213.9,-1.0 213.9,0.5 213.9,2.1 213.9,3.6 213.9,5.2 213.9,6.7 213.9,8.3 213.9,9.8 213.9,11.4 213.9,12.9 213.9,14.4 213.9,16.0 213.9,17.5 213.9,19.1 213.9,20.6 213.9,22.2 213.9,23.7 213.9,25.3 213.9,26.8 213.9,28.4 213.9,29.9 213.9,31.5 213.9,33.0 213.9,34.6 213.9,36.1 213.9,37.6 213.9,39.2 213.9,40.7 213.9,42.3 213.9,43.8 213.9,45.4 213.9,46.9 213.9,48.5 213.9,50.0 213.9,51.6 213.9,53.1 213.9,54.7'/%3E%3Cpolyline points='228.0,-5.7 228.0,-4.2 228.0,-2.6 228.0,-1.1 228.0,0.5 228.0,2.0 228.0,3.6 228.0,5.1 228.0,6.7 228.0,8.2 228.0,9.8 228.0,11.3 228.0,12.9 228.0,14.4 228.0,16.0 228.0,17.5 228.0,19.1 228.0,20.6 228.0,22.2 228.0,23.7 228.0,25.3 228.0,26.8 228.0,28.4 228.0,29.9 228.0,31.5 228.0,33.0 228.0,34.6 228.0,36.1 228.0,37.7 228.0,39.2 228.0,40.8 228.0,42.3 228.0,43.9 228.0,45.4 228.0,47.0 228.0,48.5 228.0,50.1 228.0,51.6 228.0,53.2 228.0,54.7'/%3E%3Cpolyline points='242.2,-5.7 242.2,-4.2 242.1,-2.6 242.1,-1.1 242.1,0.5 242.1,2.0 242.1,3.6 242.1,5.1 242.1,6.7 242.1,8.2 242.1,9.8 242.1,11.3 242.1,12.9 242.1,14.4 242.1,16.0 242.1,17.5 242.1,19.1 242.1,20.6 242.1,22.2 242.1,23.7 242.1,25.3 242.1,26.8 242.1,28.4 242.1,29.9 242.1,31.5 242.1,33.0 242.1,34.6 242.1,36.1 242.1,37.7 242.1,39.2 242.1,40.8 242.1,42.3 242.1,43.9 242.1,45.4 242.1,47.0 242.1,48.5 242.1,50.1 242.1,51.6 242.2,53.2 242.2,54.7'/%3E%3Cpolyline points='256.3,-5.8 256.3,-4.2 256.3,-2.7 256.3,-1.1 256.2,0.4 256.2,2.0 256.2,3.5 256.2,5.1 256.2,6.6 256.2,8.2 256.2,9.8 256.2,11.3 256.2,12.9 256.2,14.4 256.2,16.0 256.2,17.5 256.2,19.1 256.2,20.6 256.2,22.2 256.2,23.7 256.2,25.3 256.2,26.8 256.2,28.4 256.2,29.9 256.2,31.5 256.2,33.0 256.2,34.6 256.2,36.1 256.2,37.7 256.2,39.2 256.2,40.8 256.2,42.4 256.2,43.9 256.2,45.5 256.2,47.0 256.2,48.6 256.3,50.1 256.3,51.7 256.3,53.2 256.3,54.8'/%3E%3Cpolyline points='270.4,-5.8 270.4,-4.2 270.3,-2.7 270.3,-1.1 270.3,0.4 270.3,2.0 270.3,3.5 270.3,5.1 270.3,6.6 270.3,8.2 270.3,9.7 270.3,11.3 270.3,12.8 270.3,14.4 270.3,16.0 270.3,17.5 270.3,19.1 270.3,20.6 270.3,22.2 270.3,23.7 270.3,25.3 270.3,26.8 270.3,28.4 270.3,29.9 270.3,31.5 270.3,33.0 270.3,34.6 270.3,36.2 270.3,37.7 270.3,39.3 270.3,40.8 270.3,42.4 270.3,43.9 270.3,45.5 270.3,47.0 270.3,48.6 270.3,50.1 270.3,51.7 270.4,53.2 270.4,54.8'/%3E%3Cpolyline points='284.4,-5.8 284.4,-4.3 284.4,-2.7 284.4,-1.2 284.4,0.4 284.4,2.0 284.4,3.5 284.4,5.1 284.4,6.6 284.4,8.2 284.4,9.7 284.4,11.3 284.4,12.8 284.4,14.4 284.4,15.9 284.4,17.5 284.4,19.1 284.4,20.6 284.4,22.2 284.4,23.7 284.4,25.3 284.4,26.8 284.4,28.4 284.4,29.9 284.4,31.5 284.4,33.1 284.4,34.6 284.4,36.2 284.4,37.7 284.4,39.3 284.4,40.8 284.4,42.4 284.4,43.9 284.4,45.5 284.4,47.0 284.4,48.6 284.4,50.2 284.4,51.7 284.4,53.3 284.4,54.8'/%3E%3Cpolyline points='298.5,-5.8 298.5,-4.3 298.5,-2.7 298.5,-1.2 298.5,0.4 298.5,1.9 298.5,3.5 298.5,5.1 298.5,6.6 298.5,8.2 298.5,9.7 298.5,11.3 298.5,12.8 298.5,14.4 298.5,15.9 298.5,17.5 298.5,19.1 298.5,20.6 298.5,22.2 298.5,23.7 298.5,25.3 298.5,26.8 298.5,28.4 298.5,29.9 298.5,31.5 298.5,33.1 298.5,34.6 298.5,36.2 298.5,37.7 298.5,39.3 298.5,40.8 298.5,42.4 298.5,43.9 298.5,45.5 298.5,47.1 298.5,48.6 298.5,50.2 298.5,51.7 298.5,53.3 298.5,54.8'/%3E%3Cpolyline points='312.6,-5.9 312.6,-4.3 312.6,-2.7 312.6,-1.2 312.6,0.4 312.6,1.9 312.6,3.5 312.6,5.0 312.6,6.6 312.6,8.2 312.6,9.7 312.6,11.3 312.6,12.8 312.6,14.4 312.6,15.9 312.6,17.5 312.6,19.1 312.6,20.6 312.6,22.2 312.6,23.7 312.6,25.3 312.6,26.8 312.6,28.4 312.6,29.9 312.6,31.5 312.6,33.1 312.6,34.6 312.6,36.2 312.6,37.7 312.6,39.3 312.6,40.8 312.6,42.4 312.6,44.0 312.6,45.5 312.6,47.1 312.6,48.6 312.6,50.2 312.6,51.7 312.6,53.3 312.6,54.9'/%3E%3Cpolyline points='326.6,-5.9 326.6,-4.3 326.6,-2.7 326.6,-1.2 326.6,0.4 326.6,1.9 326.6,3.5 326.6,5.0 326.6,6.6 326.6,8.2 326.6,9.7 326.6,11.3 326.6,12.8 326.6,14.4 326.6,15.9 326.6,17.5 326.6,19.1 326.6,20.6 326.6,22.2 326.6,23.7 326.6,25.3 326.6,26.8 326.6,28.4 326.6,29.9 326.6,31.5 326.6,33.1 326.6,34.6 326.6,36.2 326.6,37.7 326.6,39.3 326.6,40.8 326.6,42.4 326.6,44.0 326.6,45.5 326.6,47.1 326.6,48.6 326.6,50.2 326.6,51.7 326.6,53.3 326.6,54.9'/%3E%3Cpolyline points='340.7,-5.9 340.7,-4.3 340.7,-2.8 340.7,-1.2 340.7,0.4 340.7,1.9 340.7,3.5 340.7,5.0 340.7,6.6 340.7,8.1 340.7,9.7 340.7,11.3 340.7,12.8 340.7,14.4 340.7,15.9 340.7,17.5 340.7,19.0 340.7,20.6 340.7,22.2 340.7,23.7 340.7,25.3 340.7,26.8 340.7,28.4 340.7,30.0 340.7,31.5 340.7,33.1 340.7,34.6 340.7,36.2 340.7,37.7 340.7,39.3 340.7,40.9 340.7,42.4 340.7,44.0 340.7,45.5 340.7,47.1 340.7,48.6 340.7,50.2 340.7,51.8 340.7,53.3 340.7,54.9'/%3E%3Cpolyline points='354.8,-5.9 354.8,-4.3 354.8,-2.8 354.8,-1.2 354.8,0.3 354.8,1.9 354.8,3.5 354.7,5.0 354.7,6.6 354.7,8.1 354.7,9.7 354.7,11.3 354.7,12.8 354.7,14.4 354.7,15.9 354.7,17.5 354.7,19.0 354.7,20.6 354.7,22.2 354.7,23.7 354.7,25.3 354.7,26.8 354.7,28.4 354.7,30.0 354.7,31.5 354.7,33.1 354.7,34.6 354.7,36.2 354.7,37.7 354.7,39.3 354.7,40.9 354.7,42.4 354.7,44.0 354.8,45.5 354.8,47.1 354.8,48.7 354.8,50.2 354.8,51.8 354.8,53.3 354.8,54.9'/%3E%3C/g%3E%3C/svg%3E");
    background-repeat:no-repeat, no-repeat;
    background-size:100% 100%, 720px 97px;
    background-position:0 0, -12px center;}

  /* Pluoštas — the nameplate, and Rapolas's own idea: "blue like the frame
     with bright lines going through the letters". The letters are filled with
     the tunnel's cyan and ONE thin beam sweeps through them, clipped to the
     glyphs, on the frame's nine-second period — a single repeating band, so
     nothing is timed by script. THIS IS THE FIRST NAMEPLATE THAT COLOURS THE
     LETTERS, the oldest rule the slot had; it breaks it on purpose, which is
     what makes it epic rather than a rich common. The global reduced-motion
     rule above stops the beam and leaves the blue. */
  .np-pluostas{font-weight:600; color:transparent; -webkit-text-fill-color:transparent;
    background-color:#7FD4FF;
    background-image:
      linear-gradient(97deg, transparent 0 48.8%, rgba(255,255,255,.9) 49.6%, transparent 50.4%, transparent 50.4% 100%),
      linear-gradient(#8AD6FF,#8AD6FF);
    background-size:230px 100%, 100% 100%;
    /* repeat-x on the BEAM layer, 2026-09-06. The beam sits at ~49% of a
       230px band, so about 113px in — further right than any name is wide.
       With no-repeat there was one band, its beam started to the right of
       the letters and the animation only carried it further right, so it
       never arrived: measured at 36 phases across the 9s loop, "Titas"
       had zero bright pixels at every one of them. Tiled, a beam enters
       from the left and the 230px translation is exactly one period, so
       the loop is seamless by construction. The comment above always said
       "a single repeating band" — the code was what disagreed. */
    background-repeat:repeat-x, no-repeat;
    background-position:0 0, 0 0;
    -webkit-background-clip:text; background-clip:text;
    filter:drop-shadow(0 0 4px rgba(127,212,255,.65));
    animation:pluostas 9s linear infinite;}
  @keyframes pluostas{to{background-position:230px 0, 0 0;}}


  /* ================= KVAZARAS — THE QUASAR SET =====================
     Step 79, docs/KVAZARAS.md. Three pieces that are one object seen three
     times: a frame that is an accretion disk seen face-on, a surface that is
     the nebula behind it, a nameplate lit by the disk's own core.
     Rarities: frame mythic, surface rare, nameplate epic.

     THE FRAME IS NO LONGER AN IMAGE. It was a resampled ray-traced render —
     18 KB of WebP wrapped onto the row by a signed distance field — and the
     diagnosis that replaced it is one line: NINE PIXELS CANNOT HOLD A
     PHOTOGRAPH. Resampling a render into a border keeps its noise and throws
     away its structure, and no amount of tuning fixes that.

     What is here instead is a conic-gradient, which index.html's own frame
     comments already argued for: "colour that varies by ANGLE around the row
     is how light plays around a frame." A black hole face-on is a function of
     exactly two things — distance from the shadow's edge, and angle — and a
     border has no room for the first, so the whole piece is the second. The
     stops are not picked by eye: they are the same Schwarzschild trace the
     image version used, sampled around the disk and integrated across the
     band, then mapped through Šerdis' own gradient so the frame and the
     nameplate are made of the same thing.

     WHAT MAKES IT MYTHIC IS DEPTH, NOT SIZE — the definition Kirmgrauža set
     and nobody wrote down at step 78. Its tube is mythic because `.worm.front`
     sits at z-index 2 over the row's body at 1, so part of the object passes
     IN FRONT of the row. The same move here is not a borrowing; it is what a
     disk at 62 degrees actually does:

       ::before      z0   the ring, whole — the far side and the two flanks
       ::after       z1   the SHADOW, opaque, occluding the ring's middle
       .sk-near      z2   the same ring, clipped to its lower half, in front
       .sk-jet/.sk-k z2   the jets and the knots leaving the poles
       .sk-flash     z2   the impact frames
       the cells     z3   always, and untouched

     AND IT FIRES. Every 5.2 seconds — four of the shock period, two of the
     knot period, so the burst lands on a beat the piece was already keeping —
     the frame charges, cuts to white for two frames, cuts to its own negative
     for one, and releases a shockwave. The cuts are hard: `steps(1,end)`, no
     interpolation, because an eased impact frame is just a pulse.

     THE COSTS, stated so they are not rediscovered:
       * this frame OWNS THE ROW'S INTERIOR, so a surface worn with it is
         hidden — the same bill Kirmgrauža pays, and the price of the tier.
         Migla is special-cased below and is the only surface that is;
       * the jets reach 10px past the row, which is exactly the gap between
         framed rows, so two adjacent wearers touch;
       * ONE white frame per 5.2s cycle, deliberately. White-black-white looks
         better and is two bright flashes 125ms apart — a local rate near 16Hz
         over an area a leaderboard row is just large enough to make count
         under the three-flashes-per-second guideline. One flash per 5.2s is
         0.19Hz. The negative frame carries the second beat instead.

     0 KB of asset, against 18. `src/kvazaras.js` still exists, but only to
     inject eight empty spans — every image is gone from it. */
  @property --sk{syntax:'<angle>'; inherits:false; initial-value:0deg;}

  .fr-sukurys{--int:#04010A; background:none;
    /* THE OBJECT ON THE FELT. Without this the row's ends sit in dead felt while
       its middle is lit, and the piece reads as two arcs rather than as one
       thing. */
    box-shadow:0 0 15px rgba(152,64,202,.34), 0 2px 5px rgba(0,0,0,.45);
    /* THE SHOT CLOCK. Every burst effect below runs 5.2s, and 5.2 is not a
       taste decision: it is 4 x 1.3 (the shock period) and 2 x 2.6 (the knot
       period), so the burst lands on a beat the piece was already keeping
       rather than sliding against it. The static box-shadow above is the 0%
       value, so reduced-motion leaves the frame exactly as it was. */
    /* the bloom belongs to the burst, so it moves to the set gate below */}

  /* THE RING. One ellipse, coloured by angle from the trace — the same measured
     conic the epic version uses — and masked to a ring rather than a disc. It
     reaches 20px past the ends and 10px past the top and bottom, which is
     exactly Kirmgrauža's reach and exactly the gap. */
  .fr-sukurys::before,
  .fr-sukurys > .sk-near{content:''; position:absolute; inset:-10px -20px;
    pointer-events:none; border-radius:50%;
    background:
      /* THE RINGS, and this is what the arcs were missing. Kirmgrauža's tube is
         not a glow — it is THIRTY FINE RINGS, and that high-frequency detail is
         most of why it reads as a made object rather than a light. Two smooth
         gradient arcs cannot compete with that however well coloured they are.
         So the disk gets its own banding: concentric ellipses in the same
         `closest-side` coordinates as the mask, so they are exactly concentric
         with the ring band. A bright line, a dark lane behind it, repeating —
         which is what a disk actually looks like edge-on.

         The PERIOD is the whole tuning, and it is set by the thin axis. A
         `closest-side` gradient scales with each radius, so a 2.1% period is
         8.8px apart at the ends and 0.8px apart at the top and bottom — under a
         pixel, which aliases into moire rather than reading as rings. 4.6% puts
         the tight axis at about 1.7px, which is the smallest spacing that
         survives. Fewer, bolder rings: the same call Kirmgrauža makes. */
      /* ===== TWO ZONES, which is the reference's real lesson =====
         A quasar's disk is not one texture. Close to the hole it is a smooth,
         pale, almost featureless sheet — hot, ionised, and moving too fast to
         hold structure. Out at the rim it breaks into the lumpy cloud the
         illustration labels the broad-line region. The version before this had
         one turbulence spread evenly across the whole band, which is why it read
         as weather rather than as a disk.

         This layer is the INNER SHEET, and it sits on top so it covers the cloud
         where the cloud should not be: a smooth pale band from the ring outward,
         gone by 84%, leaving the outer third to the turbulence. */
      radial-gradient(closest-side at 50% 50%,
        rgba(0,0,0,0)          0 56%,
        rgba(248,251,255,.62) 63%,
        rgba(236,226,255,.44) 69%,
        rgba(220,182,246,.20) 76%,
        rgba(0,0,0,0)         84%),
      /* THE CLOUD. Evenly spaced rings are an engineering drawing, not a
         quasar — a real disk is turbulent, and turbulence is fractal noise, so
         that is what this is: `feTurbulence type='fractalNoise'` with an
         ANISOTROPIC base frequency, low across the arc and high through it, so
         the cells come out sheared along the flow the way a differentially
         rotating disk shears everything in it. The feColorMatrix forces RGB to
         white and takes ALPHA from the noise, so it modulates the disk's own
         colour underneath instead of greying it — which is what a blend mode
         would have done, and `mix-blend-mode` has broken this project twice.

         THE OFFSET IN THAT MATRIX IS THE WHOLE TUNING. At -.18 mid-grey noise
         still carries 0.4 alpha of white, so the first cloud pass painted a veil
         over everything and the disk came back pale and desaturated. At -.9 only
         the bright cells clear zero — so the noise reads as WISPS in front of the
         colour rather than as fog on top of it. */
      url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='300' height='90'><filter id='t' x='0' y='0' width='100%25' height='100%25'><feTurbulence type='fractalNoise' baseFrequency='0.016 0.085' numOctaves='4' seed='11'/><feColorMatrix type='matrix' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 1.05 .72 .34 0 -.9'/></filter><rect width='300' height='90' filter='url(%23t)'/></svg>"),
      repeating-radial-gradient(closest-side at 50% 50%,
        rgba(0,0,0,0)        0 2.30%,
        rgba(255,240,255,.36) 2.70% 3.05%,
        rgba(0,0,0,.26)      3.45% 4.10%,
        rgba(0,0,0,0)        4.60%),
      /* a second set at a period that is NOT a multiple of the first, so the two
         beat against each other and the banding clumps instead of marching */
      repeating-radial-gradient(closest-side at 50% 50%,
        rgba(0,0,0,0)         0 3.10%,
        rgba(255,232,255,.17) 3.60% 4.15%,
        rgba(0,0,0,.14)       4.80% 5.90%,
        rgba(0,0,0,0)         6.70%),
      /* The rim goes COOL. In the reference the disk runs white-hot at the
         centre and slate blue at the edge, and that value structure is more of
         why it reads as a real object than any single colour is. Kvazaras stays
         violet — Migla and Šerdis are violet — but the outer edge picks up the
         cold blue, which also pushes the eye inward to the shadow. */
      radial-gradient(closest-side at 50% 50%,
        rgba(0,0,0,0)          0 78%,
        rgba(150,186,232,.40) 87%,
        rgba(112,146,204,.26) 94%,
        rgba(0,0,0,0)        100%),
      /* the striations, turning — the material flowing round the disk. The
         envelope below it does not move; only this does. */
      conic-gradient(from var(--sk) at 50% 50%,
        rgba(255,232,255,.16) 0deg, rgba(0,0,0,.16) 42deg,
        rgba(255,232,255,.13) 96deg, rgba(0,0,0,.14) 150deg,
        rgba(255,232,255,.16) 208deg, rgba(0,0,0,.15) 262deg,
        rgba(255,232,255,.12) 310deg, rgba(255,232,255,.16) 360deg),
  conic-gradient(from 0deg at 50% 50%,
    #8E45BB 0deg,
    #9346BA 15deg,
    #9948B9 30deg,
    #A04AB7 45deg,
    #8B44BC 60deg,
    #5A2B92 75deg,
    #743BB6 90deg,
    #7239B2 105deg,
    #602E9A 120deg,
    #6D37AC 135deg,
    #7B3FBF 150deg,
    #8943BC 165deg,
    #9146BA 180deg,
    #9A48B9 195deg,
    #A54CB6 210deg,
    #AF4FB4 225deg,
    #B651B3 240deg,
    #D162B7 255deg,
    #D363B7 270deg,
    #CA5BB3 285deg,
    #DB69BA 300deg,
    #CC5EB4 315deg,
    #AC4EB5 330deg,
    #9848B9 345deg,
    #8E45BB 360deg);

    /* THE ARCS HAVE TO MEET THE RING. The inner edge was at 79% of the vertical
       radius — 22.9px from centre against a row half-height of 19 — so there was
       a FOUR PIXEL DARK GAP between the hairline and the arc, and that gap is
       the whole reason the two read as separate systems: a neon outline with
       wings floating above it. 63% lands the arcs' inner edge inside the row's
       boundary, so they spring from the ring instead of hovering over it.

       Nothing is risked by reaching inside: ::before sits at z-index 0 under the
       opaque shadow, so it cannot paint on the row at all, and .sk-near is
       clipped to the bottom 12px whatever its mask says.

       TWO MASK LAYERS, INTERSECTED. The first is the ellipse ring. The second
       kills its horizontal extremes — and that one is not tidying, it is the
       whole legibility fix. An ellipse ring CONVERGES at x = ±rx, and it
       converges at y = 0, which is the row's vertical centre: the line the rank
       numeral and the money sit on. Measured, the arcs never actually enter the
       row's box — but they meet level with the text a few pixels past each end,
       and at reading size that is indistinguishable from crossing it. Fading the
       last 6% at each side removes the convergence point entirely, which is also
       what Kirmgrauža's tube does: it tapers and dies before the row's ends
       rather than wrapping round behind them. */
    -webkit-mask:
      radial-gradient(closest-side at 50% 50%,
        rgba(0,0,0,0) 0 63%, #000 70%, #000 93%, rgba(0,0,0,0) 100%),
      linear-gradient(90deg, rgba(0,0,0,0) 0, #000 6%, #000 94%, rgba(0,0,0,0) 100%);
            mask:
      radial-gradient(closest-side at 50% 50%,
        rgba(0,0,0,0) 0 63%, #000 70%, #000 93%, rgba(0,0,0,0) 100%),
      linear-gradient(90deg, rgba(0,0,0,0) 0, #000 6%, #000 94%, rgba(0,0,0,0) 100%);
    /* THE BASE RULE HAS TO BE UNDONE EXPLICITLY. `.framed::before` ships with a
       two-layer mask and `-webkit-mask-composite: xor` to cut the ring out of a
       solid block. Setting a new one-layer mask leaves that composite in place,
       and one layer XORed against nothing renders NOTHING — the first build of
       this piece came back as a completely blank row. The `mask` shorthand
       resets the standard property; the -webkit- one is separate and does not
       get reset with it. Padding too, or the content-box layer is still 7px in. */
    padding:0; -webkit-mask-composite:source-in; mask-composite:intersect;
    /* THE RING HAS TO START AT THE ROW'S EDGE, NOT INSIDE IT. `closest-side`
       makes ry the row's half-height plus the 10px overhang — 38.5px — and the
       first mask opened at 58% of that, which is 22px, four pixels INSIDE the
       row. The ring painted across the name's line and the first render washed
       the left half of it out. 74% lands the inner edge exactly on the row's
       boundary, so the disk only ever crosses the row's edges and the gap. */
    opacity:.95; filter:blur(.5px) saturate(1.18) contrast(1.1);}
  .fr-sukurys::before{z-index:0;
    animation:sk-turn 21s linear infinite;}

  /* THE SHADOW. Opaque, the row's own shape, and it is what makes the ring read
     as passing BEHIND at the top — without this the whole thing is a halo. */
  .fr-sukurys::after{content:''; position:absolute; inset:0; z-index:1;
    border-radius:5px; padding:0;
    -webkit-mask:none; mask:none;
    -webkit-mask-composite:source-over; mask-composite:add;
    background:
      radial-gradient(circle closest-side at 21% 33%, rgba(214,196,255,.5) 0 42%, rgba(0,0,0,0) 100%),
      radial-gradient(circle closest-side at 64% 70%, rgba(226,208,255,.38) 0 40%, rgba(0,0,0,0) 100%),
      radial-gradient(circle closest-side at 82% 27%, rgba(206,188,255,.34) 0 40%, rgba(0,0,0,0) 100%),
      radial-gradient(150% 200% at 50% 50%,
        #000 0%, #05020C 38%, #12061F 66%, #2A0C4A 88%, #4A1673 100%);
    background-size:2px 2px,1.6px 1.6px,1.4px 1.4px,100% 100%;
    background-position:21% 33%,64% 70%,82% 27%,0 0;
    background-repeat:no-repeat;
    /* THE PHOTON RING CLOSES THE FRAME, and it is the one part of the object
       entitled to be uniform. The arcs fade out before the row's ends — they
       have to, or they converge over the text — which left both ends dark and
       the piece looking unfinished. The ring is the fix, and it is not a
       compromise: it is fed by light that has ORBITED the hole and therefore
       sampled the whole disk, so it is far more even than the direct image. A
       1.2px hairline on `inset 0 0 0` follows the row's own rounded rectangle
       all the way round for nothing.

       The old rule had a BLACK hairline in this slot, which was actively
       darkening the very edge the arcs were failing to reach.

       A flat bright outline over a coloured, structured band reads as an added
       stroke rather than part of the object. So the hairline is pulled toward
       the arcs' own magenta and taken down in weight, and a second, wider and
       much softer ring sits just inside it — the gradient from ring to disk that
       a single hard line cannot give. */
    box-shadow:inset 0 0 0 1.1px rgba(250,198,246,.9),
               inset 0 0 0 2.6px rgba(214,112,222,.42),
               inset 0 0 14px -1px rgba(190,92,226,.5),
               inset 0 0 28px -7px rgba(214,120,236,.3),
               inset 0 3px 10px rgba(0,0,0,.78);}

  /* THE NEAR ARM, in front. Same ring, lower half only. */
  /* AN ELLIPSE RING ALWAYS CROSSES THE ROW'S CENTRE LINE AT ITS ENDS, and that
     is where the rank numeral and the money sit. Clipping the near arm to the
     ellipse's bottom HALF is not enough: the lower-left and lower-right of that
     half curve back up to y = 0 at the extremes, so the arc came out straight
     across the +38 on one side and the rank on the other.

     The fix is not to dim it, it is to make the geometry unable to reach the
     text: clip the near arm to the bottom 14px of its box. The box overhangs the
     row by 10px, so what is left is the whole gap plus FOUR PIXELS onto the row's
     bottom edge — enough to read as passing in front of it, and provably unable
     to touch a text cell, which begins about 20px higher.

     The far side needs no such clip: it is at z-index 0 and the opaque shadow at
     z-index 1 covers the row exactly, so it can only ever show outside it. */
  .fr-sukurys > .sk-near{z-index:2;
    clip-path:inset(calc(100% - 12px) 0 0 0);
    animation:sk-turn 21s linear infinite;}

  /* Differential rotation: the far arc and the near arm are one disk, so they
     share a period — but the striations are what move, not the beaming, so the
     colour is fixed and only a slow hue-rotate rides over it. A whole turn per
     loop, so it closes exactly. */
  /* THE TURN IS EASED, AND THE EASING IS DERIVED RATHER THAN TASTED.

     A conic-gradient advances by ANGLE. On a circle that is the same thing as a
     constant speed along the rim; on a ring eleven times wider than it is tall it
     is nothing like it. Measured on the board: a striation moves 3.5x faster
     across the middle of the row than round either end, and pointwise the ratio
     is nearly fifty to one. What you actually see is the arc BLINKING — the whole
     top lighting at once four times a turn, with the only visible travel in a
     narrow patch at the centre — and then the same at the bottom. That reads as a
     delay between the two, which is what it was reported as, and it is not a
     phase error: the halves cross-correlate at lag 0 to within 25ms. The motion
     is continuous. The SPEED is wrong.

     So the angle is scheduled by ARC LENGTH instead. For a point at ellipse
     parameter t, ds/dt = sqrt(a^2 sin^2 t + b^2 cos^2 t), and the conic angle
     painting that point is atan2(a cos t, -b sin t); invert one against the other
     and the angle advances slowly across the top and bottom and quickly round the
     ends, so the pattern travels the ring at one rate. The animation stays
     `linear` — for a registered custom property the easing has nowhere to live
     but the values.

     TWO THINGS THAT HAD TO BE RIGHT. The walk starts at the TOP of the ellipse,
     not at its right end: built from the end and shifted by subtracting the
     starting angle, the slow part lands ON the ends, which is the correction
     applied backwards and measures worse than none. And the unwrapped angle must
     not be taken modulo 360, or the last third of every turn flattens into a
     stall.

     ONE SET CANNOT SUIT EVERY WIDTH. The box runs about 4.3:1 on a phone row and
     11:1 on the desktop board; built at 7, near the geometric mean:
         aspect  4.3:1    50 : 1  ->  2.9 : 1
         aspect  7.0:1    19 : 1  ->  1.0 : 1
         aspect 11.2:1    49 : 1  ->  3.2 : 1  */
  @keyframes sk-turn{
    0%{--sk:0deg;}
    3.704%{--sk:47.2deg;}
    7.407%{--sk:65.95deg;}
    11.11%{--sk:74.46deg;}
    14.81%{--sk:79.46deg;}
    18.52%{--sk:83.03deg;}
    22.22%{--sk:86.24deg;}
    25.93%{--sk:91.73deg;}
    29.63%{--sk:95.38deg;}
    33.33%{--sk:98.65deg;}
    37.04%{--sk:102.8deg;}
    40.74%{--sk:109.1deg;}
    44.44%{--sk:121.3deg;}
    48.15%{--sk:151.8deg;}
    51.85%{--sk:208.2deg;}
    55.56%{--sk:238.7deg;}
    59.26%{--sk:250.9deg;}
    62.96%{--sk:257.2deg;}
    66.67%{--sk:261.3deg;}
    70.37%{--sk:264.6deg;}
    74.07%{--sk:268.3deg;}
    77.78%{--sk:273.8deg;}
    81.48%{--sk:277deg;}
    85.19%{--sk:280.5deg;}
    88.89%{--sk:285.5deg;}
    92.59%{--sk:294.1deg;}
    96.3%{--sk:312.8deg;}
    100%{--sk:360deg;}}

  /* THE JETS. Four travelling knots alone read as sparks; a jet is a BEAM with
     knots in it, and the beam is what was missing. Each is a tapering shaft at
     the pole — bright and narrow at the base, spreading and dying at the tip,
     which is what a collimated jet does — with the knots running up it. Static,
     so it costs nothing per frame; only the knots move. */
  .fr-sukurys > .sk-jet{position:absolute; left:50%; width:6px; height:14px;
    margin-left:-3px; z-index:2; pointer-events:none; border-radius:3px;
    /* 14px tall over a 4px overlap reaches exactly 10px past the row —
       the gap, and Kirmgrauža's own reach. At 17px it measured 13 and put
       three pixels onto the neighbour. */
    /* A HARD-EDGED BOX IS NOT A BEAM. The first version stacked a linear layer
       under a radial one and rendered as a pale rectangle: the linear painted
       full width and nothing softened the sides. A narrow element with a
       vertical gradient and a small blur gives the taper for free, and the
       box-shadow is the base glow where the beam leaves the pole. */
    /* In the reference the jet is the brightest thing in the frame by a
       distance — a hard white column, not a glow — and it is BEADED: the shaft
       carries bright knots and shocks all the way up. So the beam is two layers.

       THE SHOCKS TRAVEL. A repeating stripe up the shaft, moved by EXACTLY two
       periods per cycle, so the loop closes by arithmetic rather than by luck —
       12px against a 6px period. `.sk-jet.d` is flipped with scaleY(-1), so
       one keyframe set sends both beams OUTWARD.

       Both layers have to appear in the keyframes. One animation owns the whole
       `background-position` property, so a keyframe naming only the first layer
       silently resets the second — the trap this project has already hit once. */
    background:
      repeating-linear-gradient(to top,
        rgba(0,0,0,0) 0 2.9px, rgba(255,255,255,.5) 2.9px 4.2px,
        rgba(0,0,0,0) 4.2px 6px),
      /* THE TAPER IS IN PERCENTAGES, AND THAT IS A TRAP WHEN THE BEAM GROWS.
         The first version died to nothing by 58% of its length, which was fine
         at rest — the faint tip sat inside the disk's own glow and nobody could
         tell. On the burst the beam goes from 14px to 24px and the extra ten
         pixels are the ONLY part standing in clear felt, so all of the growth
         landed exactly where the gradient had already given up: the jet fired
         and what you saw was a round blob at the pole. Carry the brightness up
         the shaft and the burst reads as a beam punching out past the disk. */
      linear-gradient(to top,
        rgba(255,255,255,.98) 0, rgba(240,248,255,.93) 34%,
        rgba(208,232,255,.74) 62%, rgba(178,210,255,.4) 84%,
        rgba(150,190,255,0) 100%);
    background-size:100% 100%, 100% 100%;
    background-position:0 0, 0 0;
    box-shadow:0 0 10px 2px rgba(200,226,255,.5),
               0 0 22px 4px rgba(140,180,240,.22);
    /* The blur has to stay under the stripe. At 1.05px against a 0.9px bright
       band the shocks washed out entirely and the shaft was a smooth column
       again — the animation ran and could not be seen. 0.68px keeps the edges
       soft and the beading readable. */
    filter:blur(.68px);
    /* HEIGHT, NOT scaleY, and this is the one geometric decision in the burst.
       `.sk-jet.d` already carries `transform:scaleY(-1)` to mirror the beam
       downward, and one element cannot run two animations that both write
       `transform` — the later one silently wins and the lower jet flips back
       upright mid-burst. Growing `height` sidesteps it entirely: `.u` is
       anchored `bottom:100%` so it extends UP, `.d` is anchored `top:100%` so
       it extends DOWN, and one keyframe set drives both without knowing which
       is which. It is an out-of-flow 6px box, so the layout cost is nothing. */
    animation:sk-flow 1.3s linear infinite;}
  @keyframes sk-flow{to{background-position:0 -12px, 0 0;}}

  /* THE BASE FLARE. A jet does not pour, it FIRES — material is ejected in
     bursts, and the pole brightens as each one leaves. This is on its own
     pseudo-element so the pulse rides `opacity` and `transform` and stays off
     the paint path, and it shares the knots' 2.6s period so the flare and the
     knot that launches from it are the same event. */
  .fr-sukurys > .sk-jet::before{content:''; position:absolute; left:50%;
    /* FLATTER THAN IT WAS. A 15x9 ellipse scaled 2.6x on the burst is a 39x23
       ball, and a ball at the base of a 6px beam is the whole picture — the
       beam disappeared behind its own flare. Wide and low reads as the FOOT of
       something rather than as a sphere, which is what a jet base is. */
    bottom:-3px; width:19px; height:7px; margin-left:-9.5px; border-radius:50%;
    background:radial-gradient(closest-side,
      rgba(255,255,255,.95) 0 22%, rgba(206,230,255,.45) 55%,
      rgba(150,190,255,0) 100%);
    /* Now on the 5.2s shot clock rather than its own 2.6s one, because the pole
       has TWO different events to show and they are not the same size: an
       ordinary ejection on the first beat, and the burst on the second. Same
       period, one clock, two amplitudes. */
    animation:sk-fire-idle 2.6s ease-in-out infinite;}
  /* The pole's own beat, which is what it had before the burst folded a second
     amplitude into it: one ejection every 2.6s, no charge and no shot. The set
     version replaces this wholesale rather than layering on it, because two
     animations writing `transform` would leave the later one silently winning. */
  @keyframes sk-fire-idle{
    0%{transform:scale(.72); opacity:.34;}
    14%{transform:scale(1.12); opacity:1;}
    46%{transform:scale(.9); opacity:.55;}
    100%{transform:scale(.72); opacity:.34;}}

  @keyframes sk-fire{
    /* the ordinary beat — the old 2.6s shape, folded into the first half */
    0%  {transform:scale(.72); opacity:.34; animation-timing-function:ease-out;}
    7%  {transform:scale(1.12); opacity:1;  animation-timing-function:ease-in-out;}
    23% {transform:scale(.9);  opacity:.55; animation-timing-function:ease-in-out;}
    50% {transform:scale(.72); opacity:.34; animation-timing-function:linear;}
    /* the charge. Anticipation is the whole trick: the pole SUCKS IN and goes
       dark for half a second, and the hit lands on the contrast rather than on
       its own brightness. Take this out and the burst reads as a blink. */
    54% {transform:scale(.72); opacity:.34; animation-timing-function:ease-in;}
    66.4%{transform:scale(.42); opacity:.14; animation-timing-function:steps(1,end);}
    /* the shot */
    67.3%{transform:scale(1.85); opacity:1;  animation-timing-function:ease-out;}
    78% {transform:scale(1.2); opacity:.7; animation-timing-function:ease-in-out;}
    90% {transform:scale(.72); opacity:.34;}
    100%{transform:scale(.72); opacity:.34;}}

  .fr-sukurys > .sk-jet.u{bottom:100%; margin-bottom:-4px;}
  .fr-sukurys > .sk-jet.d{top:100%; margin-top:-4px; transform:scaleY(-1);}

  /* The knots, running up the beams. */
  .fr-sukurys > .sk-k{position:absolute; left:50%; width:11px; height:13px;
    margin-left:-5.5px; z-index:2; pointer-events:none; opacity:0;
    background:radial-gradient(closest-side,
      rgba(236,250,255,.99) 0%, rgba(170,210,255,.6) 42%,
      rgba(140,190,255,0) 100%);}
  /* The knots keep their own 2.6s clock — 5.2 is exactly two of them, so a knot
     already launches on the burst beat and nothing needs re-timing. What it
     needs is to be BRIGHTER on that launch, and brightness has to ride a second
     animation because `sk-up` already owns `transform` and `opacity`. `filter`
     is the only channel left, which is a constraint that happens to be correct:
     it is the same knot, lit harder. */
  .fr-sukurys > .sk-k.u{top:-3px;
    animation:sk-up 2.6s linear infinite;}
  .fr-sukurys > .sk-k.d{bottom:-3px;
    animation:sk-dn 2.6s linear infinite;}
  /* TWO DELAYS, NOT ONE. A bare `animation-delay:-1.3s` delays BOTH animations,
     which would slide this knot's flare a quarter-cycle off the burst and leave
     it lighting up in the quiet. The list has to name a delay per animation. */
  .fr-sukurys > .sk-k.b{animation-delay:-1.3s;}
  @keyframes sk-up{0%{transform:translateY(1px) scale(.4); opacity:0;}
    22%{opacity:1;} 62%{opacity:.6;}
    100%{transform:translateY(-9px) scale(1.05); opacity:0;}}
  @keyframes sk-dn{0%{transform:translateY(-1px) scale(.4); opacity:0;}
    22%{opacity:1;} 62%{opacity:.6;}
    100%{transform:translateY(9px) scale(1.05); opacity:0;}}

  .fr-sukurys > .cell-num,.fr-sukurys > .cell-name,
  .fr-sukurys > .cell-net,.fr-sukurys > .eng{position:relative; z-index:3;
    filter:none;                       /* the 0% value, so stillness is normal */
    }


  /* ==================== THE BURST, AND ITS IMPACT FRAMES ====================

     AN IMPACT FRAME IS A HARD CUT. That is the entire definition and it is the
     only thing that separates one from a glow: for one or two frames the picture
     is REPLACED — blown to white, then to its own negative — and then the shot
     comes back. Nothing eases. Everything below that belongs to the impact runs
     on `animation-timing-function:steps(1,end)` per keyframe, which holds a value
     flat and swaps it at the end of the interval. Ease any of it and the whole
     effect collapses into a pulse, which is what the frame already had.

     THE SHAPE OF A HIT, in the order it has to happen:

       0 - 54%      quiet. The frame is the frame.
       54 - 66.4%   CHARGE. Everything dims and pulls in over 0.65s. This is the
                    expensive part and the one people skip: a hit is read against
                    what came immediately before it, so the anticipation buys
                    more than the flash does. Removing it and keeping everything
                    else made the burst read as a dropped frame.
       67.3%        WHITE. Two frames at 24fps — 83ms, 1.6% of the cycle.
       68.9%        NEGATIVE. One frame — 42ms. Dark field, blazing rim, and the
                    speedlines only here.
       69.7 - 90%   RELEASE, and this part DOES ease: the shockwave expands, the
                    jets overshoot and fall back, the disk cools. An expansion is
                    a motion, not a cut.

     ONE WHITE FRAME PER CYCLE, DELIBERATELY. The obvious version of this is
     white -> black -> white, and it looks better. It is also two bright flashes
     125ms apart, which is a local rate near 16Hz over an area a leaderboard row
     is just big enough to make count under the three-flashes-per-second rule.
     One white frame every 5.2s is 0.19Hz and cannot trip it. The negative frame
     carries the second beat instead, which is where sakuga puts it anyway.

     THE TEXT DOES NOT DISAPPEAR. The flash sits at z-index 2, under the cells at
     3, and the cells invert for exactly the white frame — so the name and the
     money go DARK ON WHITE and stay readable rather than being covered. That is
     also the correct look: an impact frame silhouettes what is in front of it.
     `filter:invert(1)` does it for all three cells with one keyframe set,
     whatever colour each one normally is, which animating `color` could not:
     the three cells have three different rest colours and would have needed
     three sets. */

  /* THE FRAME FILL. One span, appended after the cells like everything else this
     frame injects, so the row's :nth-child phone layout is untouched. */
  .fr-sukurys > .sk-flash{position:absolute; inset:0; z-index:2;
    pointer-events:none; border-radius:5px;
    background-color:transparent; background-image:none; box-shadow:none;
    }
  @keyframes sk-frames{
    0%,66.4%{background-color:transparent; background-image:none; box-shadow:none;}
    /* WHITE. Not #FFF — a hair of the set's violet in it, so the blowout still
       belongs to Kvazaras and not to a browser default. The box-shadow is how
       the flash gets past the row's own edges without a second element. */
    67.3%{background-color:#FBF6FF; background-image:none;
          box-shadow:0 0 30px 12px rgba(252,244,255,.9);}
    /* NEGATIVE. The classic second beat: the field drops out and only the rim
       survives, in the set's magenta. */
    68.9%{background-color:#05020B;
          background-image:radial-gradient(125% 260% at 50% 50%,
            rgba(5,2,11,1) 0 52%, rgba(180,87,232,.85) 80%,
            rgba(255,217,247,.95) 100%);
          box-shadow:0 0 22px 4px rgba(190,100,236,.55);}
    69.7%{background-color:transparent; background-image:none; box-shadow:none;}
    100%{background-color:transparent; background-image:none; box-shadow:none;}}

  /* SPEEDLINES, on the negative frame and for two frames after it while they
     scale out. A repeating conic is exactly the right primitive — radial spokes
     are a function of angle and nothing else — and it is the same call the frame
     made for the disk.

     THEY HAVE TO DIE FAST AND SMALL. The first pass ran them to scale 1.9 over
     250ms and they left the row entirely: long grey streaks drawn across the
     names in the rows above and below, which read as scratches on the screen
     rather than as anything belonging to the frame. Dense and brief is the whole
     look — out by 71% of the cycle, 110ms after they appear, and never past
     1.25x. Speedlines are punctuation. Held longer than a breath they become an
     effect somebody applied. */
  .fr-sukurys > .sk-flash::before{content:''; position:absolute;
    inset:-30px -30px; pointer-events:none;
    background:repeating-conic-gradient(from 4deg at 50% 50%,
      rgba(255,255,255,0) 0 2.2deg, rgba(255,240,255,.95) 2.2deg 3.2deg,
      rgba(255,255,255,0) 3.2deg 8deg);
    -webkit-mask:radial-gradient(closest-side at 50% 50%,
      rgba(0,0,0,0) 0 58%, #000 76%, #000 88%, rgba(0,0,0,0) 100%);
            mask:radial-gradient(closest-side at 50% 50%,
      rgba(0,0,0,0) 0 58%, #000 76%, #000 88%, rgba(0,0,0,0) 100%);
    opacity:0; transform:scale(.6);
    }
  @keyframes sk-lines{
    0%,68.8%{opacity:0; transform:scale(.6);
             animation-timing-function:steps(1,end);}
    68.9%{opacity:1; transform:scale(.82);
          animation-timing-function:cubic-bezier(.1,.85,.3,1);}
    70.3%{opacity:.55; transform:scale(1.12);}
    71%{opacity:0; transform:scale(1.25);}
    100%{opacity:0; transform:scale(.6);}}

  /* THE SHOCKWAVE. This one is a motion and eases: born at the negative frame,
     out past the ends of the row and gone by 82%. An ELLIPSE, not a circle — a
     circle scaled to clear a 364px row would reach 180px above and below it and
     wash two neighbours. Sized `inset:0` with a 50% radius, it inherits the
     row's own aspect and stays in its lane. */
  .fr-sukurys > .sk-flash::after{content:''; position:absolute; inset:0;
    pointer-events:none; border-radius:50%;
    background:radial-gradient(closest-side at 50% 50%,
      rgba(0,0,0,0) 0 74%, rgba(255,236,252,.85) 86%,
      rgba(196,112,238,.4) 95%, rgba(0,0,0,0) 100%);
    opacity:0; transform:scale(.15);
    }
  @keyframes sk-wave{
    0%,68.8%{opacity:0; transform:scale(.15);
             animation-timing-function:steps(1,end);}
    68.9%{opacity:1; transform:scale(.28);
          animation-timing-function:cubic-bezier(.12,.85,.25,1);}
    82%{opacity:0; transform:scale(2.1);}
    100%{opacity:0; transform:scale(.15);}}

  /* The cells' one frame of inversion, and one frame blown out over the
     negative. Both are hard cuts; `filter:none` at rest means reduced motion
     leaves them exactly as the app drew them. */
  @keyframes sk-cell{
    0%,66.4%{filter:none;}
    /* INVERT ALONE TURNS SERDIS GREEN. The nameplate is a violet-to-cream
       gradient clipped to the glyphs, and inverting a violet gives a green —
       so on the white frame the name came back the one colour this set does not
       contain. `hue-rotate(180deg)` after the invert puts the hue back where it
       was while keeping the inverted lightness, which is the whole point: a
       dark violet name on white. It does the same favour to the money, whose
       --win green would otherwise have flashed magenta. */
    67.3%{filter:invert(1) hue-rotate(180deg) contrast(1.35);}
    68.9%{filter:brightness(2.1) saturate(.35);}
    69.7%{filter:none;}
    100%{filter:none;}}

  /* THE JETS FIRE. Rest 14px; charge down to 9; snap to 24 on the white frame;
     fall back over 0.9s.

     24px is not the biggest number that looked good, it is the biggest number
     that stays inside its lane. The jet overlaps the row by 4px, so reach is
     height minus 4, and the gap between framed rows is 10px: at rest 14px
     reaches exactly 10 and touches nothing. At 24 it reaches 20 and enters the
     neighbour by 10px — which on a 65px row is its top border and dead space,
     still well clear of the neighbour's glyphs, and only for about a third of a
     second. A jet that cannot leave its own row is not a jet; one that draws on
     somebody else's name is a bug. This is the line between them.

     The beam also BLOOMS, on `box-shadow` rather than on width. Widening it
     would mean animating `width` against a fixed `margin-left:-3px` and the beam
     would walk off centre, or moving the centring into `transform` — which
     `.sk-jet.d` has already spent on its mirror. A shadow that grows from 10px
     to 30px does the same job on the paint path and cannot move anything. */
  @keyframes sk-punch{
    0%,54%{height:14px; filter:blur(.68px) brightness(1);
           box-shadow:0 0 10px 2px rgba(200,226,255,.5),
                      0 0 22px 4px rgba(140,180,240,.22);
           animation-timing-function:ease-in;}
    66.4%{height:9px; filter:blur(1.1px) brightness(.45);
          box-shadow:0 0 5px 1px rgba(200,226,255,.24),
                     0 0 12px 2px rgba(140,180,240,.1);
          animation-timing-function:steps(1,end);}
    67.3%{height:24px; filter:blur(.5px) brightness(2.5);
          box-shadow:0 0 16px 3px rgba(232,244,255,.95),
                     0 0 44px 9px rgba(170,200,255,.45);
          animation-timing-function:ease-out;}
    72%{height:21px; filter:blur(.55px) brightness(1.8);
        box-shadow:0 0 13px 2px rgba(216,236,255,.7),
                   0 0 32px 6px rgba(150,190,245,.32);
        animation-timing-function:ease-in-out;}
    90%{height:14px; filter:blur(.68px) brightness(1);
        box-shadow:0 0 10px 2px rgba(200,226,255,.5),
                   0 0 22px 4px rgba(140,180,240,.22);}
    100%{height:14px; filter:blur(.68px) brightness(1);
         box-shadow:0 0 10px 2px rgba(200,226,255,.5),
                    0 0 22px 4px rgba(140,180,240,.22);}}

  /* The disk answers. Same charge, same snap — the whole object is one event, so
     nothing is allowed to sit the burst out. This rides `filter` because the
     ring's `--sk` rotation already owns its own animation and the two must not
     share a property. */
  @keyframes sk-glare{
    0%,54%{filter:blur(.5px) saturate(1.18) contrast(1.1) brightness(1);
           animation-timing-function:ease-in;}
    66.4%{filter:blur(1px) saturate(.62) contrast(1) brightness(.5);
          animation-timing-function:steps(1,end);}
    67.3%{filter:blur(.4px) saturate(1.5) contrast(1.2) brightness(2.4);
          animation-timing-function:ease-out;}
    78%{filter:blur(.45px) saturate(1.3) contrast(1.15) brightness(1.35);
        animation-timing-function:ease-in-out;}
    90%{filter:blur(.5px) saturate(1.18) contrast(1.1) brightness(1);}
    100%{filter:blur(.5px) saturate(1.18) contrast(1.1) brightness(1);}}

  /* And the felt. The glow on the row is what carries the hit OFF the row —
     without it the burst stops dead at the border and reads as something
     happening inside a box rather than to the table. */
  @keyframes sk-kflare{
    0%,66.4%{filter:none;}
    67.3%{filter:brightness(2.6) blur(.5px);
          animation-timing-function:ease-out;}
    80%{filter:brightness(1); }
    100%{filter:none;}}

  @keyframes sk-bloom{
    0%,54%{box-shadow:0 0 15px 0 rgba(152,64,202,.34), 0 2px 5px rgba(0,0,0,.45);
           animation-timing-function:ease-in;}
    66.4%{box-shadow:0 0 7px 0 rgba(152,64,202,.16), 0 2px 5px rgba(0,0,0,.45);
          animation-timing-function:steps(1,end);}
    67.3%{box-shadow:0 0 46px 8px rgba(238,196,255,.72), 0 2px 5px rgba(0,0,0,.45);
          animation-timing-function:ease-out;}
    80%{box-shadow:0 0 24px 2px rgba(178,88,224,.42), 0 2px 5px rgba(0,0,0,.45);
        animation-timing-function:ease-in-out;}
    90%{box-shadow:0 0 15px 0 rgba(152,64,202,.34), 0 2px 5px rgba(0,0,0,.45);}
    100%{box-shadow:0 0 15px 0 rgba(152,64,202,.34), 0 2px 5px rgba(0,0,0,.45);}}

  /* ================= THE SET BONUS — KVAZARAS COMPLETE =================

     Step 149 (docs/SETS.md §Step 149), replacing the step-79 burst. Worn
     together, the three pieces run one crescendo every 11 seconds — the same
     lap as Kometa's Perihelis and Hipertunelis' Kilpa — and its one hit lands
     on the same frame as theirs, 25.5%, so every set effect on a board hits
     together. The stages are written out in kvazaras.js, which builds the
     layers (only on rows wearing all three, never under reduced motion) and
     adds `kq-on`, the switch every rule below hangs from:
       .kq-fx     an SVG 26px/14px round the row: stars, glows, starburst,
                  rings, shocks, stardust, the core and the white frame;
       .kq-spot   three hot spots riding a path round the row;
       .kq-jet    the two big beams, 120px past the row each way, with
       .kq-knot / .kq-pole / .kq-head   their knots, charging poles and the
                  bright heads fired out ahead of them;
       .kq-ghost  the lensed image: each cell turned half round the centre.

     ONE WHITE FRAME per cycle (25.5%-26.26%, 83ms), the cells inverted on it.
     Transforms and opacity only otherwise — no animated filter, blend mode or
     shadow. The beams cross the neighbouring rows ON PURPOSE, so the row's
     leaderboard wrapper (a stacking context of its own) is lifted over its
     neighbours while it wears the set. */
  .pz-lbwrap:has(> .row.kq-on){position:relative; z-index:6;}
  .row.kq-on{z-index:6;}
  .row.kq-on .kq-fx{position:absolute; left:-26px; top:-14px; overflow:visible; pointer-events:none; z-index:2;}
  .kq-fx > *{opacity:0;}
  .kq-fx > .kq-dust{opacity:1;}
  .kq-fx .kq-dust .d{opacity:0;}

  .kq-fx .kq-white{animation:kq-white 11s steps(1,end) infinite;}
  @keyframes kq-white{0%{opacity:0} 25.5%{opacity:1} 26.26%{opacity:0} 100%{opacity:0}}

  /* the lens: stars drift in, the image shows on the far side */
  .kq-fx .kq-stars{animation:kq-stars 11s linear infinite;}
  @keyframes kq-stars{0%{opacity:0; transform:scale(1.35); animation-timing-function:ease-out} 6%{opacity:1} 25.4%{opacity:1; transform:scale(1); animation-timing-function:steps(1,end)}
    26.26%{opacity:1; transform:scale(1); animation-timing-function:cubic-bezier(.1,.75,.3,1)} 40%,100%{opacity:0; transform:scale(1.7,2.2)}}
  .row.kq-on > .kq-ghost{opacity:0; pointer-events:none; transform-origin:calc(50% + var(--kq-dx)) calc(50% + var(--kq-dy));
    animation:kq-ghost 11s linear infinite;}
  .row.kq-on > .kq-ghost, .row.kq-on > .kq-ghost *{color:#C9A2FF !important; -webkit-text-fill-color:#C9A2FF !important; background:none !important; text-shadow:0 0 6px rgba(180,108,255,.6) !important;}
  @keyframes kq-ghost{0%{opacity:0; transform:rotate(180deg) scale(.85,.7); animation-timing-function:ease-in-out}
    10%{opacity:.3; transform:rotate(180deg) scale(1.08,.85); animation-timing-function:ease-in} 16%,100%{opacity:0; transform:rotate(186deg) scale(.9,.6)}}

  /* the spin: hot spots round the row, faster and faster */
  .row.kq-on > .kq-spot{position:absolute; left:0; top:0; width:36px; height:4px; margin:0; border-radius:3px; z-index:2; pointer-events:none;
    background:radial-gradient(5px 4px at 92% 50%, #FFFFFF 40%, rgba(255,255,255,0)), linear-gradient(to left, rgba(247,214,255,.95) 6%, rgba(236,156,255,.55) 35%, rgba(152,64,202,0));
    offset-rotate:auto; offset-anchor:85% 50%; opacity:0; animation:kq-spot 11s linear infinite;}
  @keyframes kq-spot{0%,9%{opacity:0; offset-distance:var(--o); animation-timing-function:cubic-bezier(.45,0,.95,.55)}
    13%{opacity:1} 25.4%{opacity:1; offset-distance:calc(var(--o) + 500%); animation-timing-function:steps(1,end)} 25.5%,100%{opacity:0; offset-distance:var(--o)}}
  .kq-fx .kq-dlit{animation:kq-dlit 11s linear infinite;}
  @keyframes kq-dlit{0%,14%{opacity:0; animation-timing-function:ease-in} 25.4%{opacity:.55; animation-timing-function:steps(1,end)} 25.5%,100%{opacity:0}}

  /* the poles charge in pulses and flash */
  .row.kq-on > .kq-pole{position:absolute; left:50%; width:30px; height:18px; margin:0 0 0 -15px; z-index:4; pointer-events:none; opacity:0; border-radius:50%;
    background:radial-gradient(closest-side, #FFFFFF 0 25%, rgba(247,214,255,.85) 45%, rgba(180,108,255,.35) 70%, rgba(152,64,202,0)); animation:kq-pole 11s linear infinite;}
  .row.kq-on > .kq-pole.u{top:-9px;}
  .row.kq-on > .kq-pole.d{bottom:-9px;}
  @keyframes kq-pole{0%,7.5%{opacity:0; transform:scale(.4); animation-timing-function:ease-in}
    9%{opacity:.55; transform:scale(.8); animation-timing-function:ease-out} 9.8%{opacity:.25; transform:scale(.6); animation-timing-function:ease-in}
    10.8%{opacity:.8; transform:scale(1); animation-timing-function:ease-out} 11.4%{opacity:.4; transform:scale(.75); animation-timing-function:ease-in}
    11.95%{opacity:1; transform:scale(1.1); animation-timing-function:steps(1,end)}
    12%{opacity:1; transform:scale(1.9,1.5); animation-timing-function:ease-out} 15%{opacity:.5; transform:scale(1.1)} 18%{opacity:.3; transform:scale(.9); animation-timing-function:ease-in} 25.4%{opacity:.6; transform:scale(1); animation-timing-function:steps(1,end)}
    25.5%,48%{opacity:0; transform:scale(.4); animation-timing-function:ease-out} 53%{opacity:.5; transform:scale(.9)} 62%{opacity:.35; transform:scale(.8); animation-timing-function:ease-in-out} 67%{opacity:.6; transform:scale(1)} 75%,100%{opacity:0; transform:scale(.5)}}

  /* the beams: fired out of the poles, precessing at once, turning to face
     you; later swinging back and drawing into the poles */
  .row.kq-on > .kq-jet{position:absolute; left:50%; width:12px; height:var(--kq-reach,120px); margin:0 0 0 -6px; border-radius:5px; z-index:4; pointer-events:none; opacity:0;
    animation:kq-jet 11s linear infinite;}
  .row.kq-on > .kq-jet::before{content:''; position:absolute; left:50%; top:0; bottom:0; width:22px; margin-left:-11px; border-radius:11px; opacity:.4;}
  .row.kq-on > .kq-jet::after{content:''; position:absolute; left:50%; top:0; bottom:0; width:3px; margin-left:-1.5px; border-radius:2px; opacity:.95;}
  .row.kq-on > .kq-jet.u{bottom:calc(100% - 6px); transform-origin:50% 100%;
    background:linear-gradient(to top, #FFFFFF, #F7E9FF 12%, #EC9CFF 40%, rgba(152,64,202,.55) 75%, rgba(152,64,202,0));}
  .row.kq-on > .kq-jet.d{top:calc(100% - 6px); transform-origin:50% 0;
    background:linear-gradient(to bottom, #FFFFFF, #F7E9FF 12%, #EC9CFF 40%, rgba(152,64,202,.55) 75%, rgba(152,64,202,0));}
  .row.kq-on > .kq-jet.u, .row.kq-on > .kq-jet.u::before{clip-path:polygon(40% 0, 60% 0, 100% 100%, 0 100%);}
  .row.kq-on > .kq-jet.d, .row.kq-on > .kq-jet.d::before{clip-path:polygon(0 0, 100% 0, 60% 100%, 40% 100%);}
  .row.kq-on > .kq-jet.u::before{background:linear-gradient(to top, rgba(236,156,255,.8), rgba(152,64,202,.3) 50%, rgba(152,64,202,0));}
  .row.kq-on > .kq-jet.d::before{background:linear-gradient(to bottom, rgba(236,156,255,.8), rgba(152,64,202,.3) 50%, rgba(152,64,202,0));}
  .row.kq-on > .kq-jet.u::after{background:linear-gradient(to top, #FFFFFF, #FFFFFF 30%, rgba(255,255,255,.4) 70%, rgba(255,255,255,0));}
  .row.kq-on > .kq-jet.d::after{background:linear-gradient(to bottom, #FFFFFF, #FFFFFF 30%, rgba(255,255,255,.4) 70%, rgba(255,255,255,0));}
  @keyframes kq-jet{0%,11.99%{opacity:0; transform:scale(.5,0); animation-timing-function:steps(1,end)}
    12%{opacity:1; transform:scale(.5,0); animation-timing-function:cubic-bezier(.12,.75,.3,1)}
    15%{transform:rotate(0deg) scale(1,1); animation-timing-function:ease-in-out}
    16.1%{transform:rotate(3deg) scale(1,1)} 17.2%{transform:rotate(-5deg) scale(1,1)} 18.3%{transform:rotate(8deg) scale(1,1)}
    19.4%{transform:rotate(-11deg) scale(1,1)} 20.5%{transform:rotate(14deg) scale(1,1)} 21.6%{transform:rotate(-18deg) scale(1,1)}
    22.8%{opacity:1; transform:rotate(-6deg) scale(1.25,.62); animation-timing-function:cubic-bezier(.5,0,.9,.5)}
    25.4%{opacity:.35; transform:rotate(0deg) scale(1.7,.05); animation-timing-function:steps(1,end)}
    25.5%,47%{opacity:0; transform:rotate(0deg) scale(1.7,.05); animation-timing-function:cubic-bezier(.3,0,.3,1)}
    52%{opacity:.8; transform:rotate(-12deg) scale(1.1,.55); animation-timing-function:ease-in-out}
    55.5%{opacity:.85; transform:rotate(8deg) scale(1,.62)} 59%{transform:rotate(-4deg) scale(1,.6); animation-timing-function:ease-in-out}
    62%{opacity:.8; transform:rotate(0deg) scale(.9,.5); animation-timing-function:cubic-bezier(.5,0,.6,1)}
    69%{opacity:0; transform:rotate(0deg) scale(.5,.12)} 100%{opacity:0; transform:scale(.5,0)}}
  .row.kq-on > .kq-head{position:absolute; left:50%; width:12px; height:18px; margin:0 0 0 -6px; z-index:5; pointer-events:none; opacity:0; border-radius:50%;
    background:radial-gradient(closest-side, #FFFFFF 0 45%, rgba(247,214,255,.9) 65%, rgba(236,156,255,0));}
  .row.kq-on > .kq-head.u{bottom:calc(100% - 15px); animation:kq-head-u 11s linear infinite;}
  .row.kq-on > .kq-head.d{top:calc(100% - 15px); animation:kq-head-d 11s linear infinite;}
  @keyframes kq-head-u{0%,11.99%{opacity:0; transform:translateY(0) scale(.6); animation-timing-function:steps(1,end)}
    12%{opacity:1; transform:translateY(0) scale(1.3); animation-timing-function:cubic-bezier(.12,.75,.3,1)} 15%{opacity:.9; transform:translateY(calc(var(--kq-reach,120px) * -1)) scale(1); animation-timing-function:ease-out} 15.8%,100%{opacity:0; transform:translateY(calc(var(--kq-reach,120px) * -1 - 3px)) scale(1.4,.6)}}
  @keyframes kq-head-d{0%,11.99%{opacity:0; transform:translateY(0) scale(.6); animation-timing-function:steps(1,end)}
    12%{opacity:1; transform:translateY(0) scale(1.3); animation-timing-function:cubic-bezier(.12,.75,.3,1)} 15%{opacity:.9; transform:translateY(var(--kq-reach,120px)) scale(1); animation-timing-function:ease-out} 15.8%,100%{opacity:0; transform:translateY(calc(var(--kq-reach,120px) + 3px)) scale(1.4,.6)}}
  /* knots stream out along the beams while the swing is still small: a short
     loop for the travel, the 11s envelope for when */
  .row.kq-on > .kq-knot{position:absolute; left:50%; width:8px; height:13px; margin:0 0 0 -4px; border-radius:50%; z-index:5; pointer-events:none; opacity:0;
    background:radial-gradient(closest-side, #FFFFFF 0 40%, rgba(247,214,255,.9) 62%, rgba(236,156,255,0));}
  .row.kq-on > .kq-knot.u{bottom:100%; animation:kq-kup .9s linear infinite, kq-kenv 11s linear infinite;}
  .row.kq-on > .kq-knot.d{top:100%; animation:kq-kdn .9s linear infinite, kq-kenv 11s linear infinite;}
  @keyframes kq-kup{0%{transform:translateY(0)} 100%{transform:translateY(calc(var(--kq-reach,120px) * -1))}}
  @keyframes kq-kdn{0%{transform:translateY(0)} 100%{transform:translateY(var(--kq-reach,120px))}}
  @keyframes kq-kenv{0%,13.5%{opacity:0} 14.5%{opacity:1} 16%{opacity:.8} 17%,100%{opacity:0}}
  /* the frame's own jets: out on the flash, back as the beams draw in */
  .row.kq-on.fr-sukurys.sf-migla > .sk-jet{animation:sk-flow 1.3s linear infinite, kq-hide 11s linear infinite;}
  @keyframes kq-hide{0%,11.95%{opacity:1; animation-timing-function:steps(1,end)} 12%,62%{opacity:0; animation-timing-function:ease-in-out} 69%,100%{opacity:1}}

  /* the blazar: the core swells, draws in for a beat, and blinds */
  .kq-fx .kq-coreg{animation:kq-coreg 11s linear infinite;}
  @keyframes kq-coreg{0%,45%{opacity:1; transform:none; animation-timing-function:cubic-bezier(.5,0,.8,.6)} 57%,100%{opacity:0; transform:translateX(70px) scale(.5,.7)}}
  .kq-fx .kq-core{animation:kq-core 11s linear infinite;}
  @keyframes kq-core{0%,19%{opacity:0; transform:scale(.05); animation-timing-function:cubic-bezier(.55,0,.9,.6)}
    24.6%{opacity:1; transform:scale(.62); animation-timing-function:cubic-bezier(.6,0,1,.5)} 25.4%{opacity:.85; transform:scale(.32); animation-timing-function:steps(1,end)}
    26.26%{opacity:1; transform:scale(1.35); animation-timing-function:ease-out} 30%{opacity:.7; transform:scale(1); animation-timing-function:steps(1,end)}
    30.5%{opacity:1; transform:scale(1.2)} 31.1%{opacity:.55; transform:scale(.95)} 34.3%{opacity:.6} 34.7%{opacity:1; transform:scale(1.15)} 35.4%{opacity:.5; transform:scale(.9)}
    39.3%{opacity:.5} 39.7%{opacity:.95; transform:scale(1.1); animation-timing-function:ease-in} 45%{opacity:.6; transform:scale(.85)} 100%{opacity:.6; transform:scale(.85)}}
  .kq-fx .kq-lit{animation:kq-lit 11s linear infinite;}
  @keyframes kq-lit{0%,19%{opacity:0; animation-timing-function:ease-in} 24.6%{opacity:.5; animation-timing-function:ease-in} 25.4%{opacity:.2; animation-timing-function:steps(1,end)} 26.26%{opacity:1; animation-timing-function:ease-out}
    30.5%{opacity:.75} 34.7%{opacity:.9} 39.7%{opacity:.8; animation-timing-function:ease-in} 56%,100%{opacity:0}}
  .kq-fx .kq-rays{animation:kq-rays 11s linear infinite;}
  @keyframes kq-rays{0%,26.25%{opacity:0; transform:scale(.5) rotate(0deg); animation-timing-function:steps(1,end)}
    26.26%{opacity:1; transform:scale(.6) rotate(0deg); animation-timing-function:cubic-bezier(.12,.8,.3,1)} 32%{opacity:.8} 46%,100%{opacity:0; transform:scale(1.35) rotate(14deg)}}
  .kq-fx .kq-ring{animation:kq-ring 11s linear infinite;}
  @keyframes kq-ring{0%,26.25%{opacity:0; transform:scale(.3); animation-timing-function:steps(1,end)} 26.26%{opacity:1; transform:scale(.3); animation-timing-function:cubic-bezier(.2,.6,.4,1)} 40%,100%{opacity:0; transform:scale(9,5)}}
  /* the shocks leave the core and run outward — never on the row's edge,
     where they would read as a second frame */
  .kq-fx .kq-shock{animation:kq-shock 11s linear infinite;}
  .kq-fx .kq-shock.b{animation-delay:.08s;}
  @keyframes kq-shock{0%,26.25%{opacity:0; transform:scale(.2); animation-timing-function:steps(1,end)} 26.26%{opacity:1; transform:scale(.2); animation-timing-function:cubic-bezier(.15,.7,.3,1)} 38%,100%{opacity:0; transform:scale(1.3,2.1)}}
  .kq-fx .kq-shock2{animation:kq-shock2 11s linear infinite;}
  @keyframes kq-shock2{0%,26.25%{opacity:0; transform:scale(.15); animation-timing-function:steps(1,end)} 26.9%{opacity:.9; transform:scale(.15); animation-timing-function:cubic-bezier(.15,.7,.3,1)} 40%,100%{opacity:0; transform:scale(1.25,2)}}
  .kq-fx .kq-dust .d{animation:kq-dust 11s linear infinite;}
  @keyframes kq-dust{0%,26.25%{opacity:0; transform:translate(0,0) scale(.4); animation-timing-function:steps(1,end)} 26.26%{opacity:1; transform:translate(0,0) scale(1.2); animation-timing-function:cubic-bezier(.1,.75,.3,1)} 42%,100%{opacity:0; transform:translate(var(--dx),var(--dy)) scale(.5)}}

  /* the row: magnified by the lens, dimmed and drawn in as the disk spins
     up, drawn in harder for the beat before, silhouetted on the white,
     pushed out by the burst */
  .row.kq-on.fr-sukurys.sf-migla > :is(.cell-num,.cell-name,.cell-net,.eng):not(.kq-ghost){animation:kq-cells 11s linear infinite;}
  @keyframes kq-cells{0%{opacity:1; filter:none; transform:none; animation-timing-function:ease-in-out}
    10%{opacity:1; filter:none; transform:scale(1.07,1.03); animation-timing-function:ease-in-out}
    24.6%{opacity:.55; filter:none; transform:translate(calc(var(--kq-dx) * .05),calc(var(--kq-dy) * .15)) scale(.975); animation-timing-function:cubic-bezier(.6,0,1,.5)}
    25.4%{opacity:.4; filter:none; transform:translate(calc(var(--kq-dx) * .12),calc(var(--kq-dy) * .3)) scale(.94); animation-timing-function:steps(1,end)}
    25.5%{opacity:1; filter:invert(1) hue-rotate(180deg) contrast(1.35); transform:none}
    26.26%{filter:none; transform:scale(1.05); animation-timing-function:cubic-bezier(.2,.7,.3,1)} 31%,100%{opacity:1; filter:none; transform:none}}

  /* The beams' reach, 120px on the board. Anywhere the row sits inside a
     card of its own (the set-effect card on Traukimas) it is shortened so the
     jets stay inside the card instead of running over its text. */
  .item2 .row.kq-on{--kq-reach:40px;}

  /* worn together but not yet dressed (or dressed for a reader who asked for
     stillness): the frame's own motion, and nothing of the old burst */
  .fr-sukurys.sf-migla:has(.np-serdis) > .sk-flash{display:none;}

  /* ============ REDUCED MOTION, AND WHY IT NEEDS ITS OWN BLOCK ============

     index.html ends with `@media (prefers-reduced-motion:reduce){*{animation:
     none !important}}` and that rule has been enough for every frame so far.
     It is not enough for this one, because THE UNIVERSAL SELECTOR DOES NOT MATCH
     PSEUDO-ELEMENTS. `*` matches elements; `::before` and `::after` are not
     elements, so nothing in that rule ever reaches them.

     Measured, with the shipped rule applied and reduce on: six animations still
     running, every one of them on a pseudo — the disk still turning, the base
     flares still pulsing, and, worst of it, the speedlines and the shockwave
     still firing. Somebody who asked their operating system for stillness would
     have got a still row that detonates every 5.2 seconds.

     The app already knew this once: the one animated pseudo-element it ships,
     `.nitem.unwrap .gift .tile::after`, is switched off by a rule that names it
     explicitly rather than by the universal one. This is the same rule for this
     frame, and every pseudo it animates is listed. What is left is the 0% of
     every keyframe set — a still quasar, which is a perfectly good picture. */
  @media (prefers-reduced-motion:reduce){
    .fr-sukurys,
    .fr-sukurys::before,
    .fr-sukurys::after,
    .fr-sukurys > .sk-near,
    .fr-sukurys > .sk-flash,
    .fr-sukurys > .sk-flash::before,
    .fr-sukurys > .sk-flash::after,
    .fr-sukurys > .sk-jet,
    .fr-sukurys > .sk-jet::before,
    .fr-sukurys > .sk-k,
    .fr-sukurys > .cell-num,
    .fr-sukurys > .cell-name,
    .fr-sukurys > .cell-net{animation:none !important;}
    .row.kq-on *, .row.kq-on *::before, .row.kq-on *::after{animation:none !important;}
  }

  /* OFF-SCREEN AND HIDDEN-TAB ROWS STOP. kvazaras.js toggles .kv-idle from an
     IntersectionObserver and from visibilitychange; these are the rules it
     drives. Every selector is written to OUT-SPECIFY the rule it is pausing —
     `.fr-sukurys.kv-idle > .sk-k.u` is (0,4,0) against the (0,3,0) that set
     the animation. Step 79 shipped this as `.kv-k{animation:none}` at (0,2,0)
     against a (0,3,0) and it silently did nothing, which is the same trap the
     reduced-motion query fell into that day. */
  .fr-sukurys.kv-idle,
  .fr-sukurys.kv-idle::before,
  .fr-sukurys.kv-idle > .sk-near,
  .fr-sukurys.kv-idle > .sk-flash,
  .fr-sukurys.kv-idle > .sk-flash::before,
  .fr-sukurys.kv-idle > .sk-flash::after,
  .fr-sukurys.kv-idle > .sk-jet.u,
  .fr-sukurys.kv-idle > .sk-jet.d,
  .fr-sukurys.kv-idle > .sk-jet::before,
  .fr-sukurys.kv-idle > .sk-k.u,
  .fr-sukurys.kv-idle > .sk-k.d,
  .fr-sukurys.kv-idle > .cell-num,
  .fr-sukurys.kv-idle > .cell-name,
  .fr-sukurys.kv-idle > .cell-net,
  .row.kq-on.kv-idle *,
  .row.kq-on.kv-idle *::before,
  .row.kq-on.kv-idle *::after{animation-play-state:paused !important;}

  /* Migla — the surface. Worn alone it is the row's background; worn
     inside Sūkurys the frame reaches it through the custom properties below,
     because that frame owns the row's interior.

     REMADE 2026-09-06, AND THE REASON IS A MEASUREMENT. The old Migla was a
     2 KB WebP of smooth fog and the note here said it was "capped at the
     felt's own luminance (0.0198)". It was not at that cap. Measured under
     each cell on a real board row it peaked at 0.0073 — 0.37x the felt — so it
     was spending barely a third of the budget it was allowed, and the row read
     as a dark bar. The ceiling was never the problem; under-using it was.

     THE CAP IS PER CELL, NOT PER ROW. What sets a figure's contrast is the
     brightest pixel under THAT figure, and the cells do not fill the row: the
     rank is 19px of a 69px board row and the name 35, so there are bands top
     and bottom carrying no glyphs at all, which may go brighter than the felt
     without costing any figure a thing. The vertical ramp below is what holds
     the text band down, and its 16%/74% stops are the NAME CELL's measured
     edges — it is not centred, because the `.sub` line under the name pushes
     its box to 19%-70%, and every ramp built on the symmetric assumption left
     the peak sitting exactly on the cell's top edge.

     AND IT IS BUILT OUT OF STRUCTURE, NOT BRIGHTNESS. Under a hard brightness
     cap smooth fog is nothing — there is no brightness left to make a gradient
     out of. What reads down here is LOCAL contrast: a point at twice the felt
     on a ground at a fifth of it is a bright star that costs the money
     nothing. So the budget goes on a star field (three tiles at 67, 89 and
     113px — none divides another, so the field does not repeat until their
     product and there is no lattice to see), filaments from anisotropic
     turbulence, a dust lane, and a low-frequency clumping layer that eats
     irregular holes in the lit bands. Without that last one the lit band was
     uniform across 972px and read as a stripe: nothing else in the piece
     varies slowly across the row.

     THE COLOURS ARE AUTHORED DOWN HERE RATHER THAN SCALED DOWN. The first
     remake picked a nebula palette normally and divided every alpha to fit; it
     measured 27x over, and dividing by 27 is a grey mush. At this ceiling
     "bright" means rgb around 55, not 220.

     WHAT IT IS A PICTURE OF: the gas this object is lighting. A quasar ionises
     its host galaxy in two cones along the jet axis — the axis Sūkurys' jets
     leave the row on — so worn together the surface is the gas the frame is
     ionising, and the object's own dust lane is the dark band the name sits
     on. The physics and the legibility budget ask for the same picture, which
     is the only reason this works at all. A CONE DOES NOT SURVIVE A 14:1 ROW,
     stated rather than pretended: at the board's real width a 21-degree wedge
     off the vertical is 13px in 972, so the conic below is a lift toward the
     top and bottom rather than a shape anyone will identify. What the row
     honestly shows is the same object edge-on and very close.

     MEASURED, on views.js's own board row, against a plain row:
       the money      5.42:1   (plain row 5.00:1, old Migla 6.34:1)
       the name      13.68:1   (plain row 12.47:1)
       the rank       6.98:1   (plain row 5.93:1)
     Every figure still lands better than the felt gives it, which is the rule:
     a surface may not be the remedy for --loss, and may not be its cause.

     0 KB of asset, against 2. Both of Kvazaras' images are now gone. */
  .sf-migla{--migla:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='67' height='100' viewBox='0 0 67 100' preserveAspectRatio='none'><circle cx='11' cy='9%25' r='1.25' fill='%237B4FAE'/><circle cx='48' cy='88%25' r='1.05' fill='%236A4198'/><circle cx='27' cy='14%25' r='0.85' fill='%235A3684'/><circle cx='60' cy='93%25' r='0.75' fill='%234A2C6E'/></svg>"),
              url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='89' height='100' viewBox='0 0 89 100' preserveAspectRatio='none'><circle cx='19' cy='91%25' r='1.1' fill='%2374499F'/><circle cx='71' cy='7%25' r='0.9' fill='%23633D8C'/><circle cx='44' cy='86%25' r='0.7' fill='%23523073'/></svg>"),
              url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='113' height='100' viewBox='0 0 113 100' preserveAspectRatio='none'><circle cx='31' cy='6%25' r='0.95' fill='%236E4499'/><circle cx='88' cy='94%25' r='0.8' fill='%235C3780'/><circle cx='63' cy='11%25' r='0.6' fill='%234A2C6E'/></svg>"),
              linear-gradient(to bottom, rgba(6,3,12,0) 0%, rgba(6,3,12,0.68) 16%, rgba(6,3,12,0.74) 45%, rgba(6,3,12,0.68) 74%, rgba(6,3,12,0) 100%),
              radial-gradient(42% 48% at 50% 50%, rgba(6,3,12,.97) 0%, rgba(6,3,12,.95) 58%, rgba(6,3,12,.62) 82%, rgba(6,3,12,0) 100%),
              url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='364' height='69' viewBox='0 0 364 69' preserveAspectRatio='none'><filter id='f' x='0' y='0' width='100%25' height='100%25'><feTurbulence type='fractalNoise' baseFrequency='0.0026 0.018' numOctaves='4' seed='21'/><feColorMatrix type='matrix' values='0 0 0 0 0.03 0 0 0 0 0.02 0 0 0 0 0.06 1.05 .72 .34 0 -0.5'/></filter><rect width='364' height='69' filter='url(%23f)'/></svg>"),
              url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='364' height='69' viewBox='0 0 364 69' preserveAspectRatio='none'><filter id='f' x='0' y='0' width='100%25' height='100%25'><feTurbulence type='fractalNoise' baseFrequency='0.024 0.140' numOctaves='4' seed='11'/><feColorMatrix type='matrix' values='0 0 0 0 0.4 0 0 0 0 0.25 0 0 0 0 0.58 1.05 .72 .34 0 -0.68'/></filter><rect width='364' height='69' filter='url(%23f)'/></svg>"),
              url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='364' height='69' viewBox='0 0 364 69' preserveAspectRatio='none'><filter id='f' x='0' y='0' width='100%25' height='100%25'><feTurbulence type='fractalNoise' baseFrequency='0.009 0.075' numOctaves='4' seed='5'/><feColorMatrix type='matrix' values='0 0 0 0 0.34 0 0 0 0 0.19 0 0 0 0 0.52 1.05 .72 .34 0 -0.55'/></filter><rect width='364' height='69' filter='url(%23f)'/></svg>"),
              linear-gradient(97deg, rgba(0,0,0,0) 16%, rgba(0,0,0,.5) 33%, rgba(0,0,0,.58) 43%, rgba(0,0,0,0) 60%),
              conic-gradient(from 0deg at 50% 50%, rgba(150,92,214,.30) 0deg, rgba(120,70,176,.19) 26deg, rgba(88,50,130,.08) 46deg, rgba(0,0,0,0) 66deg, rgba(0,0,0,0) 114deg, rgba(88,50,130,.08) 134deg, rgba(120,70,176,.19) 154deg, rgba(150,92,214,.30) 180deg, rgba(120,70,176,.19) 206deg, rgba(88,50,130,.08) 226deg, rgba(0,0,0,0) 246deg, rgba(0,0,0,0) 294deg, rgba(88,50,130,.08) 314deg, rgba(120,70,176,.19) 334deg, rgba(150,92,214,.30) 360deg),
              linear-gradient(90deg, rgba(26,13,46,.9) 0%, rgba(21,10,38,.9) 34%, rgba(15,7,28,.9) 68%, rgba(10,5,18,.9) 100%),
              linear-gradient(#08050F,#08050F);
            --migla-size:67px 100%,89px 100%,113px 100%,100% 100%,100% 100%,100% 100%,100% 100%,100% 100%,100% 100%,100% 100%,100% 100%,100% 100%;
            --migla-repeat:repeat-x,repeat-x,repeat-x,no-repeat,no-repeat,no-repeat,no-repeat,no-repeat,no-repeat,no-repeat,no-repeat,no-repeat;
            background-image:var(--migla);
            background-size:var(--migla-size);
            background-repeat:var(--migla-repeat);
            background-position:0 0;}
  .fr-sukurys.sf-migla{background-image:none;}
  /* THE SET BOND. The frame's shadow is not painted flat black — it carries a
     violet vignette that was always standing in for the sky behind the hole,
     and Migla IS that sky. So worn together the surface is painted into the
     frame's own shadow with the vignette over it: dead black through the
     middle where the hole is, the real nebula at the rim.

     The three custom properties are what make this possible without repeating
     anything: custom properties inherit into pseudo-elements, and a shorter
     background-size list repeats to cover the extra layer. */
  .fr-sukurys.sf-migla::after{
    background-image:radial-gradient(150% 200% at 50% 50%,
      #000 0%, rgba(5,2,12,.97) 34%, rgba(18,6,31,.86) 62%,
      rgba(42,12,74,.52) 85%, rgba(74,22,115,.24) 100%), var(--migla);
    background-size:100% 100%, var(--migla-size);
    background-repeat:no-repeat, var(--migla-repeat);
    background-position:0 0;}

  /* ================= THE SET BONUS — HIPERTUNELIS COMPLETE: KILPA ==========

     Step 148 (docs/SETS.md). Worn together, the three pieces send the row
     round the wormhole once a lap: pulled into the right-hand mouth, through
     a tunnel full of space, and back out of the left. It replaced the old
     burst (white, negative, a shockwave; 9s) when Kometa's Perihelis raised
     the bar — every set effect is now one 11-second sequence, the hit about
     3s in and the row settled by about 8s.

     kirmgrauza.js builds the layers, and only on rows wearing all three, so
     the class `kl-on` it adds is the whole switch:
       .kl-back   space and the grid, straight after the slab, clipped as it
                  is, so the tube's near wall still paints over the space;
       .kl-fx     rings, mouths, the white frame and the dust, over the tube;
       .kl-clone  two echoes and two colour-split copies of each cell.

     ONE WHITE FRAME per cycle (25.5%-26.26%, 83ms — the same frame as
     Kometa's impact, so every set effect on a board hits together), the cells inverted on it —
     dark on white — with `hue-rotate(180deg)` so Pluoštas' cyan does not turn
     orange. Everything else is transform and opacity: the mock-ups lagged
     with animated filters, blend modes, box-shadow blooms and 110 separately
     twinkling stars, so none of those are here. */
  .row.kl-on .kl-fx{position:absolute; left:-26px; top:-14px; overflow:visible; pointer-events:none; z-index:2;}
  .row.kl-on .kl-back{position:absolute; inset:0; z-index:1; pointer-events:none;}
  .row.kl-on .kl-back > .kl-fx{z-index:auto;}
  .row.kl-on > .kl-clone{opacity:0; pointer-events:none;}
  .kl-fx > *{opacity:0;}
  .kl-fx > .kl-dust, .kl-fx > .kl-rings{opacity:1;}
  .kl-fx .kl-dust .d{opacity:0;}

  .kl-fx .kl-white{animation:kl-white 11s steps(1,end) infinite;}
  @keyframes kl-white{0%{opacity:0} 25.5%{opacity:1} 26.26%{opacity:0} 100%{opacity:0}}

  /* the tunnel wakes: two waves along its rings, left to right, and a third
     at the pull; then one running back while the row is inside */
  .kl-fx .kl-ring{opacity:0; animation:kl-ring 11s linear infinite; animation-delay:calc(var(--u) * .7s - .165s);}
  @keyframes kl-ring{0%{opacity:0; stroke-width:1} .8%{opacity:.8; stroke-width:2} 3.5%{opacity:0; stroke-width:1}
    6%{opacity:0; stroke-width:1} 6.8%{opacity:.9; stroke-width:2.2} 9.5%{opacity:0; stroke-width:1}
    20%{opacity:0; stroke-width:1} 21%{opacity:1; stroke-width:2.6} 24%,100%{opacity:0; stroke-width:1}}
  .kl-fx .kl-ringb{display:none;}   /* the wave back along the tube: there is no tube then */
  @keyframes kl-ringb{0%,26.5%{opacity:0; stroke-width:1} 27.3%{opacity:1; stroke-width:2.8} 30%,100%{opacity:0; stroke-width:1}}

  /* the mouths: the right one swells as the row goes in, the left one opens
     as it comes out */
  .kl-fx .kl-mouth.r{animation:kl-mouth-r 11s linear infinite;}
  .kl-fx .kl-mouth.l{animation:kl-mouth-l 11s linear infinite;}
  @keyframes kl-mouth-r{0%,12.5%{opacity:0; transform:scale(.5); animation-timing-function:ease-in} 25.4%{opacity:1; transform:scale(1.15); animation-timing-function:steps(1,end)} 25.5%{opacity:0} 100%{opacity:0}}
  @keyframes kl-mouth-l{0%,26.5%{opacity:0; transform:scale(.5); animation-timing-function:ease-in} 31.4%{opacity:.9; transform:scale(1); animation-timing-function:steps(1,end)} 31.5%{opacity:1; transform:scale(1.25); animation-timing-function:ease-out} 42.5%,100%{opacity:0; transform:scale(.7)}}
  .kl-fx .kl-dust .d{animation:kl-dust 11s linear infinite;}
  @keyframes kl-dust{0%,31.4%{opacity:0; transform:translate(0,0) scale(.4); animation-timing-function:steps(1,end)}
    31.5%{opacity:1; transform:translate(0,0) scale(1.2); animation-timing-function:cubic-bezier(.1,.75,.3,1)} 48.5%,100%{opacity:0; transform:translate(var(--dx),var(--dy)) scale(.5)}}

  /* the space inside the tunnel: opens behind the row as it is pulled out,
     streams past while it is inside, stays under it as it comes back */
  .kl-back .kl-space{animation:kl-space 11s linear infinite;}
  @keyframes kl-space{0%,3.5%{opacity:0; animation-timing-function:ease-in} 20.5%{opacity:1} 56.5%{opacity:1; animation-timing-function:ease-in} 76.5%,100%{opacity:0}}
  .kl-back .kl-streaks{opacity:0; animation:kl-streak 11s linear infinite;}
  @keyframes kl-streak{0%,25.4%{opacity:0; transform:translateX(40px); animation-timing-function:steps(1,end)}
    25.5%{opacity:1; transform:translateX(40px); animation-timing-function:cubic-bezier(.3,0,.7,1)} 31.5%{opacity:.9; transform:translateX(-90px)} 33.5%,100%{opacity:0; transform:translateX(-120px)}}
  .kl-back .kl-stars{animation:kl-settle 11s linear infinite;}
  @keyframes kl-settle{0%,3.5%{transform:scale(1.25)} 25.5%{transform:scale(1.08); animation-timing-function:cubic-bezier(.4,0,.2,1)} 31.5%{transform:scale(1.22); animation-timing-function:ease-out} 76.5%,100%{transform:scale(1)}}
  .kl-back .kl-tw{animation:kl-twinkle 3s ease-in-out infinite;}
  .kl-back .kl-tw.t1{animation-delay:-1s; --tw:.35;}
  .kl-back .kl-tw.t2{animation-delay:-2s; --tw:.55;}
  @keyframes kl-twinkle{0%,100%{opacity:1} 50%{opacity:var(--tw,.5)}}
  .kl-back .kl-gal{animation:kl-gal 11s linear infinite;}
  @keyframes kl-gal{0%,3.5%{transform:rotate(-14deg) scale(.75)} 25.5%{transform:rotate(-4deg) scale(.95)} 31.5%{transform:rotate(4deg) scale(1.12); animation-timing-function:ease-out} 76.5%,100%{transform:rotate(14deg) scale(1.05)}}
  .kl-back .kl-nebula .n1{animation:kl-n1 11s linear infinite;}
  .kl-back .kl-nebula .n2{animation:kl-n2 11s linear infinite;}
  @keyframes kl-n1{0%,11.34%{transform:translate(6px,0)} 52.5%,100%{transform:translate(-8px,1px)}}
  @keyframes kl-n2{0%,11.34%{transform:translate(-6px,0)} 52.5%,100%{transform:translate(9px,-1px)}}
  /* the fly-through: nearer stars rush out past the viewer while the row is
     inside the tunnel, and glints flash as it goes in and comes out */
  .kl-back .kl-near{opacity:0; animation:kl-near 11s linear infinite;}
  @keyframes kl-near{0%,25.4%{opacity:0; transform:scale(.6); animation-timing-function:steps(1,end)}
    25.5%{opacity:1; transform:scale(.6); animation-timing-function:cubic-bezier(.5,0,.9,.6)} 32.5%{opacity:.9; transform:scale(2.4)} 34.5%,100%{opacity:0; transform:scale(2.6)}}
  .kl-back .kl-glint{opacity:0; transform:scale(0); animation:kl-glint 11s linear infinite;}
  @keyframes kl-glint{0%,18.4%{opacity:0; transform:scale(0) rotate(0deg)} 19.5%{opacity:1; transform:scale(1.2)} 22%{opacity:0; transform:scale(.3) rotate(45deg)}
    31.5%{opacity:0; transform:scale(0) rotate(0deg)} 32.5%{opacity:1; transform:scale(1.4)} 35.5%{opacity:.2; transform:scale(.5) rotate(45deg)}
    46.5%{opacity:0; transform:scale(0)} 48%{opacity:.9; transform:scale(1)} 50.5%,100%{opacity:0; transform:scale(.3) rotate(45deg)}}
  /* the spacetime grid, dragged into the right mouth and unrolled out of the left */
  .kl-back .kl-grid{animation:kl-grid 11s linear infinite;}
  @keyframes kl-grid{0%,0.5%{opacity:0; transform:scaleX(1); transform-origin:100% 50%; animation-timing-function:ease-in}
    8.5%{opacity:.6; transform:scaleX(.97); transform-origin:100% 50%; animation-timing-function:cubic-bezier(.6,0,.95,.5)}
    25.5%{opacity:.35; transform:scaleX(.04); transform-origin:100% 50%; animation-timing-function:steps(1,end)}
    31.5%{opacity:.35; transform:scaleX(.04); transform-origin:0% 50%; animation-timing-function:cubic-bezier(.12,.7,.25,1)}
    44.5%{opacity:.4; transform:scaleX(1); transform-origin:0% 50%; animation-timing-function:ease-in} 62.5%,100%{opacity:0; transform:scaleX(1); transform-origin:0% 50%}}

  /* the row itself, and its echoes a beat behind */
  .row.kl-on > :is(.cell-num,.cell-name,.cell-net):not(.kl-clone){transform-origin:100% 50%; animation:kl-cells 11s linear infinite;}
  .row.kl-on > .kl-clone{transform-origin:100% 50%;}
  .row.kl-on > .kl-clone.kl-e1{animation:kl-echo 11s linear infinite; animation-delay:.1s; --eo:.45;}
  .row.kl-on > .kl-clone.kl-e2{animation:kl-echo 11s linear infinite; animation-delay:.22s; --eo:.22;}
  @keyframes kl-cells{
    0%,2.5%{opacity:1; transform:none; filter:none; animation-timing-function:ease-in-out}
    10.5%{opacity:1; transform:translateX(5px) scaleX(.97); animation-timing-function:cubic-bezier(.6,0,.95,.5)}
    25.4%{opacity:.35; transform:translateX(var(--kl-to)) scaleX(.2); filter:none; animation-timing-function:steps(1,end)}
    /* the white frame: the cells stay where they stood, inverted, as the silhouette */
    25.5%{opacity:1; transform:none; filter:invert(1) hue-rotate(180deg) contrast(1.35); animation-timing-function:steps(1,end)}
    26.26%{opacity:0; transform:translateX(var(--kl-to)) scaleX(.2); filter:none}
    31.5%{opacity:1; transform:translateX(var(--kl-from)) scaleX(.2); transform-origin:0% 50%; animation-timing-function:cubic-bezier(.12,.7,.25,1)}
    44.5%,100%{opacity:1; transform:none; filter:none; transform-origin:0% 50%}}
  @keyframes kl-echo{
    0%,9.5%{opacity:0; transform:translateX(5px) scaleX(.97); animation-timing-function:cubic-bezier(.6,0,.95,.5)}
    11.5%{opacity:var(--eo)}
    25.4%{opacity:calc(var(--eo) * .5); transform:translateX(var(--kl-to)) scaleX(.2); animation-timing-function:steps(1,end)}
    25.5%{opacity:0; transform:translateX(var(--kl-to)) scaleX(.2)}
    31.5%{opacity:var(--eo); transform:translateX(var(--kl-from)) scaleX(.2); transform-origin:0% 50%; animation-timing-function:cubic-bezier(.12,.7,.25,1)}
    44.5%{opacity:calc(var(--eo) * .7); transform:none; transform-origin:0% 50%; animation-timing-function:ease-in}
    62.5%,100%{opacity:0; transform:none; transform-origin:0% 50%}}
  /* the tear: two frames of the row split into its colours where it stood —
     plain colours, not filters or blend modes */
  .row.kl-on > .kl-clone.kl-cr{animation:kl-split 11s steps(1,end) infinite; --sx:-4px;}
  .row.kl-on > .kl-clone.kl-cb{animation:kl-split 11s steps(1,end) infinite; --sx:4px;}
  .row.kl-on > .kl-clone.kl-cr, .row.kl-on > .kl-clone.kl-cr *{color:#FF8FB0 !important; -webkit-text-fill-color:#FF8FB0 !important; background:none !important;}
  .row.kl-on > .kl-clone.kl-cb, .row.kl-on > .kl-clone.kl-cb *{color:#8FD8FF !important; -webkit-text-fill-color:#8FD8FF !important; background:none !important;}
  @keyframes kl-split{0%{opacity:0; transform:none} 26.26%{opacity:.95; transform:translateX(var(--sx))} 26.64%{opacity:.6; transform:translateX(calc(var(--sx) * 2))} 27.02%,100%{opacity:0; transform:none}}
  /* the wormhole itself gives way to the space: it thins out as the row is
     pulled in, is gone while the row is out in the open, and forms again
     round the row as the space drains away */
  .row.kl-on > :is(.worm,.neb){animation:kl-tube 11s linear infinite;}
  @keyframes kl-tube{0%,8.5%{opacity:1; transform:none; animation-timing-function:ease-in}
    25.4%{opacity:.18; transform:scaleX(1.02); animation-timing-function:steps(1,end)}
    26.26%{opacity:0; transform:none} 54.5%{opacity:0; transform:scaleY(.9); animation-timing-function:cubic-bezier(.3,0,.3,1)}
    72.5%,100%{opacity:1; transform:none}}
  .row.kl-on > .eng{animation:none;}

  /* The module never builds the layers for a reader who asked for stillness;
     this is the belt to that. */
  @media (prefers-reduced-motion:reduce){
    .row.kl-on > *, .row.kl-on .kl-fx *{animation:none !important;}
  }

  /* Šerdis — the nameplate. The name lit by the disk it sits in: violet at the
     ends, white-hot through the middle, which is the reference's one gesture.
     Static, and pure CSS — the second nameplate to colour the letters, after
     Pluoštas broke that rule first. */
  .np-serdis{font-weight:600; color:transparent;
    -webkit-text-fill-color:transparent;
    background-image:linear-gradient(100deg,#7B3FBF 0%,#C255B0 22%,
      #FFE9C8 48%,#F58BA6 70%,#8B46C6 100%);
    -webkit-background-clip:text; background-clip:text;
    filter:drop-shadow(0 0 5px rgba(214,110,190,.5));}

  /* ================= RUNAKMENIS — THE RUNE STONE SET =================
     Ported 2026-09-13 from Claude outputs/runakmenis-3.css, the newest of the
     four copies (runakmenis.css, -1, -2, -3), verbatim. Frame `runu-ratas`,
     surface `raiziniai`, nameplate `pasvaiste` — the catalogue's codes, which
     are the class names below. src/runakmenis.js adds `rn ends` to the row
     and injects the layers; the stylesheet is written against `.rn`.
     THE ROW CLASS IS A GATE, NOT A CANVAS: `.sf-raiziniai` is
     position:relative and the paint lives on the injected `.rk-plait` child.
     ==================================================================== */
  /* ==== CORRECTED 2026-09-11 · THE ROW-CLASS TRAP, TWICE ====================
     Two app-breaking faults found by putting this file on the SHIPPING row next
     to Egiptas and Dzeusas. Both have the same root cause: the file assumed the
     surface class lands on a CHILD SPAN. `cosmeticClasses()` writes it ON THE
     ROW.

     1 · `.sf-raiziniai{position:absolute; inset:0}` therefore made THE ROW
         absolutely positioned — it left the flow, stretched to its container and
         every row after it piled up underneath. Measured on a nine-row board:
         the wearer rendered 900px tall. The paint now lives on an injected
         `.rk-plait` child and the row class is only a gate, exactly as
         `.dz-aegis` does it in Dzeusas.

     2 · Every set-bonus rule was gated `.rn:has(.sf-raiziniai)`, which asks
         whether the row CONTAINS that class. The row IS that class, so it
         matched nothing and Raštas silently did not exist. AN ELEMENT CANNOT
         `:has()` ITS OWN CLASS. Now `.rn.sf-raiziniai:has(.np-pasvaiste)` — a
         compound for the two that are on the row, `:has()` only for the
         nameplate, which really is on the span inside.

     THE MARKUP CHANGES BY ONE LINE. What was
         <span class="sf-raiziniai"><i class="lo"></i><i class="hi"></i></span>
     is now
         <span class="rk-plait"><i class="lo"></i><i class="hi"></i></span>
     and the `sf-raiziniai` class stays where views.js puts it, on the row.

     3 · And the money keeps its own colour. This file forced the figure to
         #6FE0A8 / #E58060 against the board's #5FD39B / #E07B52. Green for up
         and orange for down is the one thing on this board that carries meaning
         rather than decoration; a frame may light the money, shade behind it or
         recess it, but not recolour it.
  ========================================================================= */

  /* ---- THE RUNE FRAME, built to your reference ------------------------------
     Everything here is CSS and inline SVG: no images, no build step.
     Four parts, in the order they were hard:

     1. STONE       a slate gradient + a crack layer drawn as SVG strokes,
                    tiled at 160×48 so the cracks don't repeat visibly
     2. RUNE BANDS  runes as SVG line paths, NOT as text. Unicode runic glyphs
                    depend on a font being installed; a path is a path.
     3. GEMS        a 45°-rotated square, faceted with two gradients and a
                    clipped highlight, glowing on a dark bezel
     4. WHEEL       an SVG medallion, absolutely centred, exactly one row tall
                    so that its pole diamonds land on the bands, not past them

     --h is the row height. Everything else is derived from it, so the same
     markup renders at board scale and at your reference's scale.
  --------------------------------------------------------------------------- */

  .rn{
    --h: 57px;                    /* the board's row height, MEASURED */
    /* THE BAND'S OWN HEIGHT, SEPARATE FROM --band SINCE 2026-09-13. --band is
       the SPACING figure the panel, the glass and the light container all inset
       themselves by, and it must stay at .14 for the reason written below. But
       .14 of 57.8 is an 8px content box, and the inscription's ink is 10px tall
       in its 264x16 tile — so at the drawn size every glyph lost a pixel off its
       head and a pixel off its feet. The band alone grows to 10px and takes those
       two pixels from the BARE STONE ABOVE AND BELOW IT, where nothing lives,
       rather than from the interior, where the name does. Nothing else moves. */
    --bandh: calc(var(--h) * .175);
    --band: calc(var(--h) * .14); /* rune band, top and bottom. WAS .17, which
                                     is what it wants to be at 65px. The board's
                                     row is 57.8, and .17 of that put the top
                                     band's lower edge at 12.4 while the name's
                                     cap-height starts at 11.5 — the inscription
                                     ran through the letters. THE BANDS ARE SIZED
                                     BY WHAT IS LEFT FOR THE NAME, not by a ratio
                                     that looked right on a taller row. */
    --gem:  calc(var(--h) * .215);
    --wheel: var(--h);

    /* THE BOARD'S OWN ROW METRICS. These four are not the frame's to choose —
       they are copied from a plain row so the columns line up down the board.
       --ext is the only one that belongs to the frame: how far its chrome may
       reach into the board's side margin. */
    --c-rank: 34px;   /* MEASURED OFF THE SHIPPING APP, not off a demo page. The */
    --c-gap:  10px;   /* first draft used 30/8/12/65 taken from egiptas.html and  */
    --c-pad:  14px;   /* every one of them was wrong: .brow is `34px 1fr 88px 76px
                         100px` with .row's 10px gap and 11px 14px padding, and a
                         board row renders 57px tall, not 65. Below 700px the rank
                         column narrows to 30px and the two money columns are
                         hidden — see the media query at the foot of this file. */
    --c-money: 284px; /* the three money columns and the two gaps between them:
                         88 + 10 + 76 + 10 + 100. On a phone only the net
                         survives and this becomes 92. */
    /* THE FRAME IS EXACTLY AS WIDE AS EVERY OTHER ROW. It used to reach 13px
       into the board's side margin; --ext is now 0 and nothing leaves the row
       in any direction. The cost is paid by the gem — see .rn-capgem. */
    --ext:    0px;

    /* A ROTATED SQUARE IS BIGGER THAN ITS BOX. Rotate a square of side w by 45°
       and its bounding box is w×1.414 wide, centred on the same point — so it
       sticks out by .207w on every side. That is why the gems overhung: they
       were positioned as if `width` were what they occupied. --gemout is that
       overhang, and every gem is inset by it. */
    --gemout: calc(var(--gem) * .21);

    /* THE CORNER IS CUT AWAY AND THE GEM IS WHAT CLOSES IT. A diamond parked
       near a square corner is a jewel lying on the frame; a diamond whose outer
       facet IS the frame's edge is a corner. So the slab is chamfered at 45° and
       the gem is seated in the cut, flush.

       The arithmetic: a diamond of side w has half-diagonal d = .7071w, and its
       outer facet is the line x+y = (cx+cy) − d. Put the centre on the diagonal
       at (t,t) and that facet is x+y = 2t − d, so it is parallel to a chamfer
       x+y = c for any t — and flush when 2t − d = c. Taking c = .9d puts the
       gem's facet just inside the cut, which is where the 1px rim goes.
       The facet is w long and the cut is 1.414c ≈ .9w, so the diamond spans the
       whole cut and its own corners are trimmed by the two straight edges. */
    --cut: calc(var(--gem) * .636);

    /* THE FRAME NO LONGER OWNS THE LAYOUT, and this is the house rule rather
       than a tweak: paint() owns the cells, a cosmetic is a class on the row.
       So .rn IS the row — same grid, same padding, same column gaps as a plain
       row — and every part of the frame is decoration positioned around the
       cells. A framed name now starts at the same x as an unframed one.

       The chrome has to go somewhere, and it goes OUTWARD: --ext of board
       margin on each side, which is empty, instead of into the row's content,
       which is not. Same answer as Smėlis — put the material where there is
       room for it, not where the idea says it belongs. */
    position:relative;
    isolation:isolate;
    background:transparent;

    /* NO CLIP-PATH ON THE ROW, and this is the single biggest frame-rate fix on
       the idle frame. A clip-path on an element makes the browser re-composite
       the whole clipped subtree whenever anything inside it moves — and the
       rune lights move inside it every twelve seconds, on every wearer.
       Measured at 8× CPU throttle with nine wearers: removing it was worth as
       much as removing the animation itself.

       THE CHAMFER MOVED DOWN TO .rn-stone, which is a static leaf. The shape is
       identical; the difference is that nothing animates inside the clipped
       element any more. The rule generalises: PUT THE CLIP ON A LEAF, NEVER ON
       THE CONTAINER THE ANIMATIONS LIVE IN. */
    /* NO FILTER ON THE ROW, and this is a performance decision that costs a
       little polish. A clip-path eats box-shadow, so the row's drop shadow had
       to be `filter: drop-shadow()` — and a filter, even a STATIC one, makes the
       browser render the element and everything inside it into a separate
       buffer for as long as it exists. Nine wearers meant nine permanent
       buffers before a single animation had started.

       The slab is chamfered and sits on a dark board; the shadow was doing
       almost nothing. It is gone, and a 1px dark rim carries the separation. */
  }

  /* THE SET-BONUS LAYERS ARE DECLARED HERE, NOT IN THE BONUS STYLESHEET.
     They were `display:none` in setbonus.css only — so on any page that did not
     load that file, three plain divs sat in the row's GRID as real items, took
     the first three cells, and pushed the rank, the name and the figure into an
     implicit second row. That is what was dropping the name block below the
     glass and running the sub-line into the bottom band. A hidden thing has to
     be hidden by the stylesheet that always ships. */
  .rn-carry, .rn-wash, .rn-flash{display:none}

  /* THE CELLS SIT ABOVE EVERY PAINTED LAYER, AND THIS FILE MUST SAY SO.
     The demo page gave its own cells a z-index and this file carried a comment
     claiming the app did too. It does not: `.brow`'s cells have no `position`
     and no `z-index` anywhere in index.html, so against the shipping row the
     stone (z 0), the bands (2), the panel (3) and the slot (5) all painted OVER
     the name and the figure and the framed rows rendered EMPTY. Stated as a
     rule: a cosmetic that paints layers into a row owns the stacking of that
     row's cells, because the row itself has never needed one. */
  .rn > .cell-num, .rn > .cell-name, .rn > .cell-net, .rn > .eng{
    position:relative; z-index:6;
  }

  /* the slab: the chamfered silhouette, the rim and the stone, all on one
     static layer that nothing animates inside */
  .rn-stone{
    position:absolute; inset:0; z-index:0; pointer-events:none;
    clip-path:polygon(
      var(--cut) 0, calc(100% - var(--cut)) 0,
      100% var(--cut), 100% calc(100% - var(--cut)),
      calc(100% - var(--cut)) 100%, var(--cut) 100%,
      0 calc(100% - var(--cut)), 0 var(--cut));
    background:
      /* the light falls from top-left, once, across the whole slab */
      linear-gradient(112deg,rgba(255,255,255,.13) 0%,rgba(255,255,255,.03) 26%,
                             rgba(0,0,0,0) 55%,rgba(0,0,0,.30) 100%),
      linear-gradient(180deg,#43678A 0%,#2A455F 17%,#1B2F44 54%,#122036 100%),
      #1B2F44;
    box-shadow:
      inset 0 0 0 1px #070D15,              /* the rim, now an inset ring */
      inset 0 2px 0 -1px rgba(190,230,255,.34),  /* top bevel, lit */
      inset 0 -2px 0 -1px rgba(0,0,0,.65),       /* bottom bevel, shadowed */
      inset 2px 0 0 -1px rgba(150,200,235,.14);
  }

  /* cracks, over the whole stone */
  .rn::before{
    content:'';position:absolute;inset:0;pointer-events:none;z-index:1;
    opacity:.5;
    background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='48' viewBox='0 0 160 48'%3E%3Cg fill='none' stroke='%23000' stroke-opacity='.55' stroke-width='1'%3E%3Cpath d='M0 12 L18 16 L31 9 L52 14 L70 8 L96 15 L118 10 L141 17 L160 12'/%3E%3Cpath d='M0 34 L22 30 L44 37 L61 31 L88 36 L110 29 L133 35 L160 30'/%3E%3Cpath d='M31 9 L34 0 M70 8 L66 0 M118 10 L122 0 M44 37 L41 48 M88 36 L92 48 M133 35 L130 48'/%3E%3C/g%3E%3Cg fill='none' stroke='%23A8CDE8' stroke-opacity='.16' stroke-width='.8'%3E%3Cpath d='M0 13 L18 17 L31 10 L52 15 L70 9 L96 16 L118 11 L141 18 L160 13'/%3E%3Cpath d='M0 35 L22 31 L44 38 L61 32 L88 37 L110 30 L133 36 L160 31'/%3E%3C/g%3E%3C/svg%3E") repeat;
    background-size:160px 48px;
  }

  /* the two rune bands */
  .rn-band{
    position:absolute; left:calc(var(--gem) * 1.45); right:calc(var(--gem) * 1.45);
    /* z 5, ABOVE THE GLASS. At 65px the bands sat outside the panel and the
       order never mattered. At the app's 57.8 the name needs so much of the
       interior that the glass has to reach under them — and at z 2 the glass
       was painted OVER the inscription and washed the runes out. The stone's
       carving is on its surface and the glass is recessed into it, so the
       bands go on top and the cells go above both. */
    height:var(--bandh); z-index:5; pointer-events:none;
    background:
      linear-gradient(180deg,rgba(9,20,32,.80),rgba(9,20,32,.30)),
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='264' height='16' viewBox='0 0 264 16'%3E%3Cg fill='none' stroke='%239FEBFF' stroke-width='1.5' stroke-linecap='square'%3E%3Cpath d='M3%203%20V13%20M3%204%20L8%206.5%20M3%209%20L8%206.5'/%3E%3Cpath d='M14%2013%20V3%20L19%206%20L14%208.5'/%3E%3Cpath d='M25%2013%20V3%20M25%203%20L30%206%20L25%209%20M25%208%20L30%2012'/%3E%3Cpath d='M36%203%20V13%20M42%203%20V13%20M36%205%20L42%2011'/%3E%3Cpath d='M47%2013%20V3%20L53%208%20L47%208'/%3E%3Cpath d='M58%2013%20V3%20L64%2013%20M59.5%208.5%20L62.5%208.5'/%3E%3Cpath d='M69%203%20L74%208%20L69%2013%20M74%208%20L79%203'/%3E%3Cpath d='M84%203%20V13%20M90%203%20V13%20M84%208%20L90%208'/%3E%3Cpath d='M95%208%20L100%203%20L105%208%20L100%2013%20Z'/%3E%3Cpath d='M110%2013%20V3%20M110%203%20L115%208%20L110%2013'/%3E%3Cpath d='M121%203%20V13%20M118%203%20L126%203%20M118%2013%20L126%2013'/%3E%3Cpath d='M132%2013%20V3%20M132%208%20L137%203%20M132%208%20L137%2013'/%3E%3Cpath d='M143%203%20V13%20L149%2013'/%3E%3Cpath d='M154%2013%20V3%20L160%203%20M154%208%20L159%208'/%3E%3Cpath d='M165%208%20L170%203%20L175%208%20M170%203%20V13'/%3E%3Cpath d='M180%203%20V13%20M186%203%20V13%20M180%203%20L186%2013'/%3E%3Cpath d='M191%2013%20L196%203%20L201%2013%20M193%209%20H199'/%3E%3Cpath d='M206%203%20V13%20M206%203%20L212%208%20M212%208%20L206%2013%20M212%208%20V13'/%3E%3Cpath d='M217%203%20L223%203%20M220%203%20V13%20M217%2013%20L223%2013'/%3E%3Cpath d='M228%2013%20V3%20M228%203%20L233%208%20L228%2013%20M233%208%20L238%208'/%3E%3Cpath d='M243%203%20V13%20M243%208%20L249%203%20M243%208%20L249%2013'/%3E%3Cpath d='M254%203%20L259%208%20L254%2013%20M259%208%20V3'/%3E%3C/g%3E%3C/svg%3E") repeat-x center;
    background-size:100% 100%, 264px 16px;
    border-top:1px solid rgba(140,205,240,.20);
    border-bottom:1px solid rgba(0,0,0,.5);
    box-shadow:0 0 8px rgba(90,190,240,.18);
    /* THE BAND ENDS RATHER THAN STOPPING. This was briefly replaced by a fade
       painted in the stone's own colour, to save two masked layers per wearer —
       and it looked wrong, because the stone is cross-lit and a flat fill is
       not. The mask is back: it was not where the frames were going. */
    -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 5%,#000 95%,transparent 100%);
            mask-image:linear-gradient(90deg,transparent 0,#000 5%,#000 95%,transparent 100%);
  }
  /* FLUSH TO THE EDGE, NOT INSET. The band used to start 2.2px down and end at
     12.2; it now starts at 0 and ends at 12 — the same inner edge to the tenth
     of a pixel, so the clearance to the name's cap-height (11.5) is unchanged
     and the .17 fault the comment above records cannot come back. The two pixels
     come off the top, which is why this is a MOVE and not just a resize. */
  .rn-band.t{top:0}
  .rn-band.b{bottom:0}

  /* the glass the row appears to sit on. It is a PAINTED LAYER now — nothing
     lives inside it — so it can be inset as far as the chrome needs without
     moving a single cell. */
  .rn-panel{
    position:absolute; z-index:3;
    /* WAS --band * 1.45. The name block is 34.8px tall (13px name, 11px sub,
       2px between) and that inset left it 29.7 to sit in, so the name broke out
       of the glass top and bottom. THE PANEL MUST CONTAIN THE NAME BLOCK — it is
       the thing the name sits on, and a panel the name overflows is not a panel.
       Measured rather than derived: .9 puts the glass at 10.8-46.1, which contains
       the name block at 11.0-45.7 with room, and the bands sit just outside it. */
    inset:calc(var(--band) * .9) calc(var(--gem) * 1.52);
    border-radius:calc(var(--h) * .12) / 50%;
    background:linear-gradient(180deg,rgba(10,22,34,.72) 0%,rgba(5,12,20,.88) 100%);
    border:1px solid rgba(120,225,255,.55);
    overflow:hidden;
    box-shadow:
      inset 0 0 14px rgba(0,0,0,.9),
      inset 0 1px 0 rgba(150,225,255,.22),
      0 0 9px rgba(90,200,245,.30);
  }

  /* the sheen: a wide, very soft ellipse of light lying across the top of the
     glass. This is the nearest CSS gets to the painted specular in your render —
     it is not the same thing, but it stops the panel reading as flat paint. */
  .rn-panel::before{
    content:'';position:absolute;inset:0;pointer-events:none;
    background:radial-gradient(120% 150% at 22% -40%,rgba(160,225,255,.16) 0%,
               rgba(160,225,255,.05) 42%,transparent 68%);
  }

  /* the wheel. It is now exactly one row tall — the pole diamonds land ON the
     bands instead of past them, which is the whole of the fit. */
  /* ---- THE WHEEL · REMOVED 2026-09-10 --------------------------------------
     Kept as a record because the reasoning is worth more than the object was.

     It was the frame's signature: an SVG medallion, one row tall, a stone ring
     with eight runes set into it, turning once every two minutes. It failed on
     arithmetic rather than on looks. A medallion wants the middle of the row;
     at 850px there is a middle, and at the board's real 390px there is not —
     the name reaches the money, and measured at 416px the wheel was sitting on
     top of a figure.

     Three fixes were drawn and all three cost more than the wheel was worth.
     Behind the glass: safe at every width, but a ghost. In front, parked left
     of the figure: it fits the 82px of clearance the longest roster name
     leaves, but only if the name track is shortened by 64px for every wearer —
     nearly twice what Egypt rejected a nameplate for costing. A container
     query: one frame that looks like two.

     So it is gone, and the bands now run unbroken end to end — which is what a
     rune stone actually looks like. The `.rn-wheel` rules below are dead code
     left deliberately; delete them when this ships.
  -------------------------------------------------------------------------- */
  /* THE WHEEL SITS UNDER THE GLASS, and this is a fix rather than a taste.
     At the width these were being drawn at — 850px — the middle of the row was
     empty and a medallion could live there. THE REAL BOARD IS 390px, and at
     390px there is no middle: the name reaches the money. Measured at 416px,
     the wheel landed directly on €55.00.

     So the wheel is no longer over the row, it is behind it: below the glass,
     above the stone. The glass is translucent rather than opaque, so the wheel
     reads as something carved into the slab and seen through the panel — and
     nothing it does can ever touch a figure, at any width. */
  .rn-wheel{
    position:absolute; z-index:1; left:50%; top:50%;
    opacity:.85;
    width:var(--wheel); height:var(--wheel);
    transform:translate(-50%,-50%); pointer-events:none;
    filter:drop-shadow(0 0 7px rgba(120,215,255,.55)) drop-shadow(0 2px 4px rgba(0,0,0,.8));
    /* IT TURNS, ONCE EVERY TWO MINUTES. Slow enough that you never catch it
       moving and only notice the pole diamonds have changed places. One
       transform on one element, composited — it costs nothing per row.
       Delete this block and the two below to have it stand still. */
    animation:rn-turn 120s linear infinite;
    background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' width='100' height='100'%3E%3Cdefs%3E%3ClinearGradient id='st' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%234E7595'/%3E%3Cstop offset='.5' stop-color='%232B4864'/%3E%3Cstop offset='1' stop-color='%23172B40'/%3E%3C/linearGradient%3E%3C/defs%3E%3Ccircle cx='50' cy='50' r='33.5' fill='none' stroke='url(%23st)' stroke-width='11'/%3E%3Ccircle cx='50' cy='50' r='39' fill='none' stroke='%230C1622' stroke-width='1.5'/%3E%3Ccircle cx='50' cy='50' r='28' fill='none' stroke='%230C1622' stroke-width='1.5'/%3E%3Cg stroke='%239FEBFF' stroke-width='1.4' stroke-opacity='.9' fill='none'%3E%3Cpath d='M50 29 V38 M47 30 L53 30'/%3E%3Cpath d='M64.8 34.2 L58.4 40.6 M67 37 L63 41'/%3E%3Cpath d='M71 50 H62 M69 47 L65 51'/%3E%3Cpath d='M64.8 65.8 L58.4 59.4 M62 68 L62 63'/%3E%3Cpath d='M50 71 V62 M47 69 L53 65'/%3E%3Cpath d='M35.2 65.8 L41.6 59.4 M33 63 L37 67'/%3E%3Cpath d='M29 50 H38 M31 47 L35 51'/%3E%3Cpath d='M35.2 34.2 L41.6 40.6 M38 32 L38 37'/%3E%3C/g%3E%3Cg stroke='%23BFF0FF' stroke-width='2.4' fill='none'%3E%3Cpath d='M50 14 V86 M14 50 H86'/%3E%3C/g%3E%3Cg stroke='%237FD3F0' stroke-width='1.6' stroke-opacity='.75' fill='none'%3E%3Cpath d='M26 26 L74 74 M74 26 L26 74'/%3E%3C/g%3E%3Ccircle cx='50' cy='50' r='13' fill='%230B1A28' stroke='%23BFF0FF' stroke-width='1.8'/%3E%3Cpath d='M50 41 L57 50 L50 59 L43 50 Z' fill='%2395E1FA' stroke='%23E4FAFF' stroke-width='1.4'/%3E%3Cg fill='%2395E1FA' stroke='%23E4FAFF' stroke-width='1.6'%3E%3Cpath d='M50 0.5 L57 8 L50 15.5 L43 8 Z'/%3E%3Cpath d='M50 84.5 L57 92 L50 99.5 L43 92 Z'/%3E%3C/g%3E%3C/svg%3E") center/contain no-repeat;
  }

  /* gems */
  .rn-gem{
    position:absolute; z-index:5;
    width:var(--gem); height:var(--gem);
    border-radius:calc(var(--gem) * .18);
    background:
      linear-gradient(150deg,#DFFBFF 0%,#7FD9F5 34%,#2E86B8 68%,#12405E 100%);
    border:1px solid rgba(215,248,255,.85);
    box-shadow:
      0 0 0 3px #2E4C68,           /* the stone bezel the gem is set into */
      0 0 0 4.5px #0B1622,
      0 0 12px rgba(120,215,255,.60),
      inset 0 0 6px rgba(255,255,255,.5),
      0 2px 4px rgba(0,0,0,.7);
    transform:rotate(45deg);
  }
  /* seated in the cut: .172w puts the outer facet a rim's width inside the
     chamfer, and the extra 1px is the rim itself showing round the gem. */
  .rn{--gemseat:calc(var(--gem) * .172 + 1px)}
  .rn-gem::after{                     /* the facet split */
    content:'';position:absolute;inset:0;border-radius:inherit;
    background:linear-gradient(45deg,transparent 48%,rgba(255,255,255,.75) 50%,transparent 52%),
               linear-gradient(-45deg,transparent 46%,rgba(10,50,75,.55) 50%,transparent 54%);
  }
  /* the glint — a hard four-point star at the lit facet, drawn as two crossed
     bars rather than a blurred blob, because a blur at this size is a smudge */
  .rn-gem::before{
    content:'';position:absolute; left:26%; top:26%;
    width:48%; height:48%; transform:rotate(-45deg);
    background:
      linear-gradient(90deg,transparent 43%,rgba(255,255,255,.95) 50%,transparent 57%),
      linear-gradient(0deg, transparent 43%,rgba(255,255,255,.95) 50%,transparent 57%),
      radial-gradient(closest-side,rgba(255,255,255,.9),transparent 70%);
    background-size:100% 26%,26% 100%,100% 100%;
    background-position:center,center,center;
    background-repeat:no-repeat;
  }
  .rn-gem.tl{top:var(--gemseat);    left:var(--gemseat)}
  .rn-gem.tr{top:var(--gemseat);    right:var(--gemseat)}
  .rn-gem.bl{bottom:var(--gemseat); left:var(--gemseat)}
  .rn-gem.br{bottom:var(--gemseat); right:var(--gemseat)}

  /* row content */

  /* THE VERTICAL GAP, and it was a real bug rather than the board's layout.
     The nameplate needs the <b> to shrink-wrap its text — a frost bank or an
     aurora sized to the whole column is wrong — so it is `inline-block`. But an
     inline-block sits on a text baseline, and a baseline reserves room BELOW it
     for descenders. That reserved strip is empty, it is part of `.who`, and
     `align-items:center` then centres the block PLUS the strip — which pushes
     the visible text up and leaves the gap under `9 vakarai`.

     Making `.who` a column flexbox removes the inline formatting context
     entirely: no baseline, no descender strip, and the two lines are centred on
     what you can actually see. `align-items:flex-start` keeps the shrink-wrap. */
  .rn .cell-name{
    min-width:0;
    display:flex; flex-direction:column; justify-content:center;
    align-items:flex-start;
    align-self:center;          /* say it rather than inherit it */
  }
  .rn .cell-name .np{display:block; color:#EAF4FA;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
  .rn .cell-name .sub{
    display:block; color:#7FA0B4;
    /* NO font-size AND NO line-height HERE, deliberately. The demo set 10px/1.2
       to cure a gap between the name and the figure — but the gap was the
       BASELINE, not the leading: an inline-block sits on a baseline that
       reserves a descender strip, and `align-items:center` centred block plus
       strip. The column flexbox above is the whole fix. Overriding the type as
       well made a framed row 53px against a plain row's 58 — A FRAMED ROW MUST
       BE EXACTLY AS TALL AS AN UNFRAMED ONE or the board steps at every wearer.
       The type is the app's; this file only positions it. */
  }
  /* the money keeps --win and --loss */
  .rn > .cell-num:not(:first-child){color:#9FBACB}


  /* the name no longer reserves room for the wheel — there is nothing in front
     of it to dodge, and at 390px that reservation was pure lost name track. */

  @keyframes rn-turn{
    from{transform:translate(-50%,-50%) rotate(0)}
    to  {transform:translate(-50%,-50%) rotate(360deg)}
  }

  /* `*` does not match pseudo-elements, so reduced motion is written out. */
  @media (prefers-reduced-motion:reduce){
    .rn-wheel{animation:none}
  }

  /* ---- VARIANT: ends instead of four corners --------------------------------
     The honest problem with four corners on this frame is its aspect ratio.
     Your reference is 819×219, about 3.7:1, and four corners on a 219px edge
     have room to be four separate things. A board row is 800×65 — 12:1 — and
     the two corners on a 65px edge are 65px apart whatever size the gem is.
     Shrinking them buys air but also makes them rivets.

     So: one gem per end, centred on a stone end-block that runs the full height
     of the row. The block is what makes the corner read; the gem is set in it.
     The frame keeps its four chamfers, so the corners are still cut — they are
     just cut in a piece of stone heavy enough to be seen.
  -------------------------------------------------------------------------- */
  .rn.ends .rn-gem{display:none}
  .rn.ends .rn-cap{display:block}
  .rn .rn-cap{display:none}

  .rn-cap{
    position:absolute; top:0; bottom:0; z-index:5;
    /* The block is the row's own side padding and nothing more, so the frame
       is exactly as wide as a plain row. 18px of strap holding a 13px stone. */
    width:var(--capw);
    background:
      linear-gradient(112deg,rgba(255,255,255,.16) 0%,rgba(255,255,255,.04) 30%,
                             rgba(0,0,0,.10) 60%,rgba(0,0,0,.34) 100%),
      linear-gradient(180deg,#4E7397 0%,#31506D 20%,#20374E 60%,#152640 100%);
    box-shadow:
      inset 0 1px 0 rgba(200,235,255,.40),
      inset 0 -1px 0 rgba(0,0,0,.7);
  }
  .rn-cap.l{left:0;  border-right:1px solid #070D15;
    clip-path:polygon(var(--cut) 0,100% 0,100% 100%,var(--cut) 100%,0 calc(100% - var(--cut)),0 var(--cut))}
  .rn-cap.r{right:0; border-left:1px solid #070D15;
    clip-path:polygon(0 0,calc(100% - var(--cut)) 0,100% var(--cut),100% calc(100% - var(--cut)),calc(100% - var(--cut)) 100%,0 100%)}

  /* THE GEM IS NOT A CHILD OF THE BLOCK ANY MORE, and that is the fix rather
     than a tidy-up. It was .rn-cap::after, so the block's own clip-path — the
     one that cuts its two chamfers — was also cutting the gem, and what it cut
     first was not the gem but its bezel: two rings at 2px and 3px sit OUTSIDE
     the element, and on a rotated element they rotate with it, so the bezel is
     a diamond 6px larger across than the gem. Measuring the gem alone was
     measuring the wrong thing twice in a row.

     The gem is now a sibling, centred on the block. It is still inside the
     frame's own clip, but the frame is only cut at its corners and the gem sits
     at half-height, where the edge is straight — so nothing clips it at all.

     The fit, with the bezel counted: across, it occupies (gem + 2×bez) × 1.414.
     At --gem .25h and 3px of bezel that is 31.5px inside a 36.4px block, so a
     little under two and a half pixels of stone show on each side. */
  /* THE GEM IS NOW A TALL CUT STONE, and that is what pulling the chrome
     inside the row costs. The end block can only be as wide as the row's own
     padding — 18px — and a diamond that fits 18px across is a 10px rivet,
     because a diamond spends its size sideways. A lozenge spends it the other
     way: 13px across and 30px tall, which the block has to spare, so the stone
     keeps its presence without asking for a single pixel of width.

     Bezel by nesting rather than by box-shadow: spread paints outside the
     element and the clip-path would eat it, which has now cost time three
     times. The outer element IS the bezel; the gem is the same shape inset
     1.5px inside it. */
  .rn-capgem{
    position:absolute; top:50%; z-index:6; pointer-events:none;
    width:calc(var(--h) * .20); height:calc(var(--h) * .46);
    transform:translate(-50%,-50%);
    clip-path:polygon(50% 0, 100% 26%, 100% 74%, 50% 100%, 0 74%, 0 26%);
    background:#0A1826;
    /* the gems' drop-shadows were two more permanent filter buffers per row.
       The bezel is a nested shape rather than a shadow, so it needs neither. */
  }
  .rn-capgem::after{
    content:''; position:absolute; inset:1.5px;
    clip-path:polygon(50% 0, 100% 26%, 100% 74%, 50% 100%, 0 74%, 0 26%);
    background:
      /* the glint: one hard vertical bar down the lit facet */
      linear-gradient(90deg,transparent 26%,rgba(255,255,255,.85) 34%,
                      rgba(255,255,255,0) 44%),
      /* the facet break */
      linear-gradient(90deg,rgba(255,255,255,.30) 0%,rgba(255,255,255,0) 48%,
                      rgba(8,44,66,.55) 52%,rgba(8,44,66,.75) 100%),
      linear-gradient(180deg,#E4FCFF 0%,#8CDFF7 30%,#2E86B8 70%,#0F3A56 100%);
  }
  .rn-capgem.l{left:calc(var(--capw) / 2)}
  .rn-capgem.r{left:auto; right:calc(var(--capw) / 2); transform:translate(50%,-50%)}
  .rn .rn-capgem{display:none}
  .rn.ends .rn-capgem{display:block}

  .rn.ends{
    /* THE GEM IS SIZED BY WHAT IT MUST CLEAR, not by what looks generous.
       The block now ends exactly where the row's own content begins, so the
       gem's outer point has to stop short of the rank. At --gem .215h the
       footprint is (14 + 2×3) × 1.414 = 28.3px inside a 31px block, and the
       point lands 1.4px clear of the rank's first pixel. */
    --gem:  calc(var(--h) * .215);
  }
  .rn.ends .rn-band{left:calc(var(--capw) + 3px); right:calc(var(--capw) + 3px)}
  .rn.ends .rn-panel{
    /* THE GLASS HAS TO REACH PAST THE FIGURES, and it was not: its inner edge
       sat 23px from the row's edge while the last figure ends at 18px, so the
       money was overhanging onto bare stone. It now runs to 9px and tucks its
       rounded ends UNDER the blocks — which reads better than a pill floating
       between them anyway. */
    /* .9, NOT 1.45. This is the rule that was actually in play — the `.ends`
       override, not the base `.rn-panel` — and finding that took a measurement
       rather than a read: the base rule was corrected first and the glass did
       not move a pixel. When a value will not change, check what is overriding
       it before changing it again. At 1.45 the glass was 11.6-45.3 on a 57.8
       row and the name block, 11.0-45.7, broke out of it top and bottom. */
    inset:calc(var(--band) * .9) calc(var(--capw) - 9px);
  }
  .rn.ends{--capw:var(--c-pad)}   /* the block is the row's own padding, no more */

  /* the surface, when it is worn inside this frame, takes the glass's shape */
  .rn .rk-plait{
    inset:calc(var(--band) * .9) calc(var(--capw) - 9px);   /* follows the glass */
    border-radius:calc(var(--h) * .12) / 50%;
    z-index:3;                      /* after .rn-panel in the markup, so above it */
  }

  /* ---- THE FRAME MAKING ROOM FOR THE ROW ------------------------------------
     Alignment got the cells into the right columns. This is the other half:
     the ornament arranged around what the row has to say, instead of the row
     being dropped onto an ornament that was already finished.

     Three things, and each one is the frame giving something up.
  -------------------------------------------------------------------------- */

  /* 1. THE RANK GETS A SOCKET. The left block ends exactly where the rank
     begins, so the number was sitting on the seam with nothing under it. A
     small well sunk into the stone gives it somewhere to be — and it is drawn
     INSIDE the rank's own box, so the cell does not move a pixel. */
  .rn > .cell-num:first-child{position:relative; z-index:4; color:#F0CE76;
    justify-self:start}   /* shrink to the digit so the socket is a socket, not an oval */
  .rn > .cell-num:first-child::before{
    content:''; position:absolute; inset:-7px; z-index:-1;
    border-radius:50%;
    background:radial-gradient(closest-side,rgba(4,10,16,.92),rgba(4,10,16,.55) 70%,transparent);
    box-shadow:inset 0 1px 1px rgba(0,0,0,.9), inset 0 -1px 0 rgba(150,210,240,.16);
  }

  /* 2. THE FIGURES GET A LEDGER SLOT — one recess under all three money
     columns rather than three, because they are read as one group. Its right
     edge is the row's own padding, so it tracks the columns exactly, and it is
     a painted layer: no cell is nudged by it. */
  .rn .rn-slot{
    position:absolute; z-index:3; pointer-events:none;
    top:50%; height:calc(var(--h) * .42); transform:translateY(-50%);
    right:calc(var(--c-pad) + var(--ext) - 8px);
    /* --c-money IS THE WHOLE MONEY GROUP, and it is not one number. The comment
       above says "under all three money columns" and the width said 92px + 14 —
       the PHONE figure, where two of the three are hidden. On the 1000px board
       the group is 88 + 76 + 100 with two 10px gaps = 284, and the recess ran
       under the net alone while In and ROI sat on bare stone. */
    width:calc(var(--c-money) + 14px);
    border-radius:3px;
    background:linear-gradient(180deg,rgba(0,0,0,.46),rgba(0,0,0,.20));
    box-shadow:
      inset 0 1px 2px rgba(0,0,0,.75),
      inset 0 -1px 0 rgba(150,210,240,.13),
      0 0 0 1px rgba(0,0,0,.35);
    /* the slot fades in from the left rather than starting with a cut edge —
       a recess in stone has a lip, not a wall */
    -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 14%,#000 100%);
            mask-image:linear-gradient(90deg,transparent 0,#000 14%,#000 100%);
  }

  /* 3. THE ORNAMENT STANDS BACK WHERE THE TEXT IS. The plait is at full
     strength across the middle of the row, which is the one stretch that
     carries nothing, and drops to a quarter under the name and under the
     figures. This is not the Egyptian veil — that dimmed a whole half and the
     art was loudest where nobody needed to read. Here it is symmetrical, and
     the ornament is loudest exactly where there is nothing to read. */
  /* THE MASK IS GONE, for the same reason the wheel moved. It held the plait
     back at 30–74% of the row because that was where the text was at 850px. At
     390px the text is everywhere and those percentages point at the money. A
     percentage cannot stand back from content whose position it does not know,
     so the ornament is uniformly quieter instead — which is worth less than the
     composition was, and is at least true at every width. */

  /* ---- THE WHEEL IN FRONT, as a variant ------------------------------------
     The wheel went behind the glass because at 390px a centred medallion sits
     on the money. But the phone layout shows ONE figure, not three, and that
     changed the sums: measured on the nine-player board, the free space between
     the END of the longest roster name and the figure is 82px. A 56px wheel
     fits in that, clearing the name by 13px and the figure by 14.

     The catch, and it is the whole trade: 82px is the clearance for THAT name.
     A longer one truncates at the column edge and leaves 20px. So the wheel can
     only come forward if the name track is shortened by the width it occupies —
     64px, for wearers only. Egypt rejected a nameplate that cost 34px of name
     track, so this is not a small ask; it is just an honest one.
  -------------------------------------------------------------------------- */
  .rn.wf{--wheel:calc(var(--h) * .86)}  /* dead: the wheel is removed */
  .rn.wf .rn-wheel{
    z-index:4; opacity:1;
    left:auto; right:calc(var(--c-pad) + 52px + 14px);
    transform:translate(0,-50%);
    animation-name:rn-turn-r;
  }
  @keyframes rn-turn-r{
    from{transform:translate(0,-50%) rotate(0)}
    to  {transform:translate(0,-50%) rotate(360deg)}
  }


  /* ---- THE QUIRK · THE STONE IS READ ---------------------------------------
     Every twelve seconds a light runs out along the top band and back along the
     bottom — boustrophedon, the way a rune stone's inscription actually snakes.

     MOVED BY `transform`, NOT `background-position`. This is the whole of the
     performance story on this frame. A moving background repaints the element
     every frame on the main thread; a transform on a fixed layer is handed to
     the compositor and costs almost nothing. Nine wearers on a board means
     eighteen of these running at once, so the difference is not academic.
  -------------------------------------------------------------------------- */
  /* THE LIGHT IS NOT A CHILD OF THE BAND, and this is the fix for the skipping.

     The band carries a `mask-image` for its faded ends. A MASKED ELEMENT CANNOT
     HAND ITS CHILDREN'S TRANSFORMS TO THE COMPOSITOR — the masked layer has to
     be re-rendered every time anything inside it moves. That is why the glide
     was stepped in the first place: at `steps(8)` it repainted eight times in
     twelve seconds instead of sixty times a second, which bought back the frame
     rate and paid for it in a stutter that read as lag.

     So the light moved out of the band and into its own layer, a sibling with
     no mask above it. Nothing is clipped over it, so the transform composites,
     and it can glide at sixty frames for free. Measured: linear inside the band
     cost 11.5 fps of a nine-wearer board; linear outside it costs nothing.

     The rule, and it is the one I got wrong twice today: DO NOT ANIMATE INSIDE
     A MASKED OR CLIPPED ELEMENT. Move the moving thing out. */
  .rn-lite{
    position:absolute; z-index:2; pointer-events:none; overflow:hidden;
    left:calc(var(--gem) * 1.45); right:calc(var(--gem) * 1.45);
    /* THE CONTAINER SPANS BOTH BANDS, not one. It is `overflow:hidden`, so when
       the light dropped 47.8px to the lower band it was simply clipped away —
       visible on the way out and gone on the way back. Tall enough now that the
       drop stays inside it; the light is only ever at one of the two bands,
       because the Y move happens in a single frame. */
    /* follows the bands: they are flush to the row's edges now, so this spans
       the whole row and the drop is measured band-top to band-top. */
    top:0;
    height:var(--h);
    --drop:calc(var(--h) - var(--bandh) - 2px);   /* top band to bottom band */
  }
  .rn-lite::after{
    content:''; position:absolute; top:0; left:0; width:46%; height:var(--bandh);
    background:linear-gradient(90deg,
      rgba(150,225,255,0) 0%, rgba(170,235,255,.28) 38%,
      rgba(230,250,255,.62) 50%, rgba(170,235,255,.28) 62%,
      rgba(150,225,255,0) 100%);
    transform:translate(-140%,0);
    animation:rk-read 9s linear infinite;
  }

  /* ONE LIGHT, NOT TWO. It used to be a light per band, both running all the
     time and one of them always off-screen — eighteen animated layers on a full
     board to show at most nine. Now a single light goes out along the top,
     DROPS to the bottom band in one frame, and comes back. The drop is a step
     in Y inside the same transform, so it is still one composited animation,
     and it is the boustrophedon read written literally: out, down, back. */
  /* NINE SECONDS, WHICH IS EGYPT'S NUMBER. Sparnuotas diskas' burst runs on a
     9s period, and matching it means the two sets tick at the same rate on the
     same board rather than drifting against each other. Out along the top in
     1.8s, back along the bottom in 1.8s, then 5.4s of stillness. */
  @keyframes rk-read{
    0%          {transform:translate(-110%, 0)}
    20%         {transform:translate( 230%, 0)}
    20.001%     {transform:translate( 230%, var(--drop))}
    40%         {transform:translate(-110%, var(--drop))}
    40.001%,100%{transform:translate(-140%, 0)}
  }

  @media (prefers-reduced-motion:reduce){
    .rn-lite{display:none}
  }
  /* ---- RUNAKMENIS · the remaining two pieces --------------------------------
     Set: the rune stone. Frame RUNŲ RATAS (built and approved).
     Surface RAIŽINIAI. Nameplate ĮRAŠAS.

     THE SHARED VARIABLE IS A CLOCK, NOT A STATE, and that choice is the whole
     architecture of this set. Ódinas' old pair — a vessel lit by its own
     contents — could not be worn apart, which was flagged as a genuine first
     and never resolved. Here all three pieces run the SAME 120-second period,
     read from the document timeline rather than from each other. Worn alone
     each is complete; worn together they agree, because they are counting the
     same seconds, not asking each other questions. Nothing needs to know what
     else the player owns, so `player_may_wear()` stays what it is and a
     cosmetic stays a string.

     The 120s is the frame's wheel. One turn of the wheel is the set's day.
  -------------------------------------------------------------------------- */

  /* ==== SURFACE · RAIŽINIAI (the carvings) =================================
     The interior is the stone's face, carved with a two-strand plait — the
     commonest ornament on the stones themselves, and the one that survives
     being small, because it is a rhythm rather than a picture.

     WHAT MAKES IT THE SET'S MYTHIC: the carving is LIT FROM A DIRECTION, and
     the direction travels. Every groove has a bright lip and a dark one, and
     which side is which goes round once per turn of the wheel. The app has
     never had a surface with a relief, let alone a moving light on it.

     How, without animating anything expensive: the plait is drawn twice, once
     in light and once in shadow, and each copy is offset a pixel from centre.
     Circling those two offsets in opposite phase IS the moving light. Two
     transforms, composited, no repaint.
  ========================================================================= */
  .rk-plait{display:none}
  .sf-raiziniai .rk-plait{
    display:block;
    position:absolute; inset:0; z-index:0; pointer-events:none;
    overflow:hidden; border-radius:inherit;
  }
  .rk-plait i{                       /* one of the two lit copies */
    position:absolute; inset:-2px; display:block;
    background:var(--plait) repeat left center;
    background-size:34px 17px;
    animation:rk-light 120s linear infinite;
  }
  .rk-plait i.hi{opacity:.10}
  .rk-plait i.lo{
    opacity:.30;
    /* THE SHADOW COPY DOES NOT MOVE ANY MORE. Both copies used to circle in
       opposite phase, which is two animated layers per wearer — eighteen on a
       full board — to produce a one-pixel effect. Moving only the LIT copy
       against a fixed shadow reads the same: what your eye follows is the
       bright lip changing sides, not the dark one. */
    animation:none;
    transform:translate(0,1px);
  }

  /* the plait. Two strands, each a wave, with the under-strand casing knocked
     out where the over-strand crosses it — that knockout is the only reason a
     braid reads as woven rather than as two wavy lines. */
  .rk-plait i.hi{--plait:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='44' height='22' viewBox='0 0 44 22'%3E%3Cg fill='none' stroke='%23BFE9FF' stroke-width='1.7' stroke-linecap='round'%3E%3Cpath d='M-2 11 C 3 1, 8 1, 13 11 S 23 21, 28 11 S 38 1, 43 11'/%3E%3Cpath d='M-2 11 C 3 21, 8 21, 13 11 S 23 1, 28 11 S 38 21, 43 11'/%3E%3C/g%3E%3C/svg%3E")}
  .rk-plait i.lo{--plait:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='44' height='22' viewBox='0 0 44 22'%3E%3Cg fill='none' stroke='%23000A12' stroke-width='1.7' stroke-linecap='round'%3E%3Cpath d='M-2 11 C 3 1, 8 1, 13 11 S 23 21, 28 11 S 38 1, 43 11'/%3E%3Cpath d='M-2 11 C 3 21, 8 21, 13 11 S 23 1, 28 11 S 38 21, 43 11'/%3E%3C/g%3E%3C/svg%3E")}

  /* the light goes round: a 1px circle, once per wheel-turn */
  @keyframes rk-light{
    0%  {transform:translate( 0px,-1px)}
    25% {transform:translate( 1px, 0px)}
    50% {transform:translate( 0px, 1px)}
    75% {transform:translate(-1px, 0px)}
    100%{transform:translate( 0px,-1px)}
  }

  /* the field the carving sits on, so the plait is IN the stone and not on the
     glass — a touch lighter than the empty panel, with the panel's own vignette
     still on top of it */
  .rk-plait::after{
    content:'';position:absolute;inset:0;
    background:linear-gradient(180deg,rgba(70,120,160,.07),rgba(0,0,0,.34));
  }

  /* ==== NAMEPLATE · ĮRAŠAS  [RETIRED 2026-09-09 — replaced by PAŠVAISTĖ,
     which lives in names2.css. Kept as the record of what the cut letter was.] (the inscription) ===============================
     A rune stone's whole purpose is a name — *X raised this stone in memory of
     Y* — so the nameplate is not decoration here, it is the object's function.
     The name is cut into the same stone as the band, in the same hand.

     SUNK, NOT RAISED, and the shadow proves it: on a cut letter the light
     catches the LOWER inner edge and the shadow sits along the TOP, which is
     the exact reverse of an embossed one. That single inversion is the whole
     difference between carved and stuck on.

     And once per turn of the wheel the cut takes the light — a two-second
     flare, on the same 120s clock, so a player who never notices the wheel
     still sees the name answer something.
  ========================================================================= */
  .np-irasas{
    color:#B9CEDC;
    letter-spacing:.015em;
    text-shadow:
      0 -1px 0 rgba(0,0,0,.92),            /* the shadow ALONG THE TOP: cut */
      0  1px 0 rgba(196,236,255,.42),      /* the light on the lower lip */
      0  0   7px rgba(110,205,250,.22);    /* the paint in the groove */
    animation:rk-take 120s linear infinite;
  }
  .np-irasas small{
    color:#7C97A8;
    text-shadow:0 -1px 0 rgba(0,0,0,.8), 0 1px 0 rgba(180,225,250,.22);
  }
  @keyframes rk-take{
    0%,   48%{filter:brightness(1)}
    50%     {filter:brightness(1.55)}
    52%     {filter:brightness(1.18)}
    54%     {filter:brightness(1.42)}
    58%     {filter:brightness(1)}
    100%    {filter:brightness(1)}
  }

  @media (prefers-reduced-motion:reduce){
    .rk-plait i, .np-irasas{animation:none}
  }
  /* ==== FOUR ANIMATED NAMEPLATES · epic ======================================
     An epic has to have an EVENT. A rare can be a look; an epic is a thing that
     happens and that you can wait for. All four below run on the set's clock —
     the same 120 seconds the wheel turns in — except the aurora, which is
     weather and keeps its own time.

     Four house rules are load-bearing here:
       · a solid object never animates its own opacity — brightness or a halo
       · a gradient survives a 2px stroke; a PATTERN does not (Runų aidas)
       · `*` does not match pseudo-elements, so reduced motion is written out
       · the name must be at least as legible at every frame as a plain row's
  ========================================================================= */

  /* --- 1. PAŠVAISTĖ · the aurora ------------------------------------------
     DECIDED: this is Runakmenis' nameplate.

     TWO CLOCKS, because an epic is a mechanism and one clock running for ever
     is the ladder's definition of a rare. The first is the quiet arc — hues
     walking through the letters over 18 seconds, its own time, because weather
     does not take orders from a wheel. The second is the SUBSTORM: once per
     turn of the wheel the aurora breaks up, brightens hard, flickers three
     times and settles. That is not invented for the tier — it is what an
     aurora actually does: a still green arc for most of a night, then a few
     minutes where it moves faster than you expect.

     THE TWO ANIMATIONS WRITE DIFFERENT PROPERTIES ON PURPOSE. Two animations
     both writing `filter`, or both writing `background-position`, do not
     compose — the later one simply wins, which this project has been bitten by
     before. So the arc owns `background-position` and the substorm owns
     `filter`, and they never meet.

     And it works at 13px for the one reason Runų aidas did not: it is a
     GRADIENT, not a pattern. A rune inside a two-pixel stroke is grey; a slow
     colour field inside a two-pixel stroke is still a colour field. */
  .rn .cell-name .np.np-pasvaiste{
    display:inline-block; max-width:100%; vertical-align:top;
    color:transparent;
    -webkit-background-clip:text; background-clip:text;
    background-image:linear-gradient(100deg,
      #CFE6F2 0%, #9FE9C8 14%, #7CE0E8 26%, #BFD8F6 38%,
      #C6A8F0 50%, #7CE0E8 62%, #A8ECD2 74%, #CFE6F2 88%, #9FE9C8 100%);
    background-size:280% 100%;
    animation:
      np-aurora 18s linear infinite,          /* the arc */
      np-substorm 120s linear infinite;       /* the breakup */
  }
  @keyframes np-aurora{from{background-position:0% 50%} to{background-position:-280% 50%}}

  /* the substorm. Brightness and saturation only — never opacity, because the
     letters are a solid object and a solid object that fades shows what is
     behind it. Four seconds of the hundred and twenty. */
  @keyframes np-substorm{
    0%,   48%{filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) drop-shadow(0 0 6px rgba(120,225,210,.30)) brightness(1) saturate(1)}
    49%     {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) drop-shadow(0 0 10px rgba(150,240,220,.55)) brightness(1.35) saturate(1.5)}
    49.6%   {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) drop-shadow(0 0 16px rgba(170,255,230,.75)) brightness(1.75) saturate(1.9)}
    50.1%   {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) drop-shadow(0 0 9px  rgba(150,240,220,.45)) brightness(1.20) saturate(1.4)}
    50.6%   {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) drop-shadow(0 0 15px rgba(170,255,230,.70)) brightness(1.62) saturate(1.8)}
    51.2%   {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) drop-shadow(0 0 8px  rgba(150,240,220,.40)) brightness(1.14) saturate(1.3)}
    51.8%   {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) drop-shadow(0 0 13px rgba(170,255,230,.62)) brightness(1.46) saturate(1.6)}
    53%     {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) drop-shadow(0 0 8px  rgba(140,235,215,.38)) brightness(1.16) saturate(1.25)}
    55.5%   {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) drop-shadow(0 0 6px  rgba(120,225,210,.30)) brightness(1) saturate(1)}
    100%    {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) drop-shadow(0 0 6px  rgba(120,225,210,.30)) brightness(1) saturate(1)}
  }

  /* --- 2. KALVĖ · the strike ------------------------------------------------
     Once per turn of the wheel the name is struck: a white blow crosses it in
     240ms and the metal cools behind it through white, cyan, stone. One
     gradient band moving through the letters, then a slow cool.
     The blow is `steps(6)` on purpose — a hammer lands, it does not sweep. */
  .rn .cell-name .np.np-kalve{
    display:inline-block; max-width:100%; vertical-align:top;
    color:transparent;
    -webkit-background-clip:text; background-clip:text;
    background-image:linear-gradient(96deg,
      #9FB6C4 0%, #9FB6C4 34%, #FFFFFF 43%, #EAFBFF 47%, #7FD8F2 53%,
      #9FB6C4 64%, #9FB6C4 100%);
    background-size:340% 100%;
    background-position:120% 50%;
    filter:drop-shadow(0 1px 0 rgba(0,0,0,.9));
    animation:np-strike 120s linear infinite;
  }
  @keyframes np-strike{
    0%,   49.6%{background-position:118% 50%; filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) brightness(1)}
    49.8%      {background-position:118% 50%; filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) brightness(1.9)}
    50.0%      {background-position: 60% 50%; filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) brightness(1.6)}
    50.4%      {background-position:  0% 50%; filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) brightness(1.25)}
    56%        {background-position:-40% 50%; filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) brightness(1)}
    100%       {background-position:-40% 50%; filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) brightness(1)}
  }

  /* --- 3. ŠALNA · frost that forms and thaws --------------------------------
     Šerkšnas with a life. The rime creeps along the name over most of the
     turn, reaching the last letter just before the wheel completes — then a
     thaw crosses it in two seconds and it starts again from the first letter.
     The name underneath never changes; only how far the frost has got. */
  .rn .cell-name .np.np-salna{
    position:relative; display:inline-block; max-width:100%; vertical-align:top;
    color:#D5E9F5;
    text-shadow:0 -1px 0 rgba(0,0,0,.9), 0 1px 0 rgba(226,247,255,.5),
                0 0 6px rgba(150,225,255,.26);
  }
  .rn .cell-name .np.np-salna::before{
    content:''; position:absolute; left:-6px; right:-10px; bottom:-2px; height:11px;
    background:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='11' viewBox='0 0 160 11'><circle cx='26.4' cy='7.6' r='0.61' fill='%23E8F7FF' opacity='0.28'/><circle cx='34.6' cy='8.7' r='0.62' fill='%23E8F7FF' opacity='0.22'/><circle cx='80.8' cy='2.6' r='0.38' fill='%23E8F7FF' opacity='0.47'/><circle cx='93.7' cy='0.8' r='1.18' fill='%23E8F7FF' opacity='0.47'/><circle cx='37.2' cy='0.5' r='1.40' fill='%23E8F7FF' opacity='0.80'/><circle cx='140.0' cy='6.8' r='0.29' fill='%23E8F7FF' opacity='0.27'/><circle cx='79.6' cy='1.3' r='1.29' fill='%23E8F7FF' opacity='0.53'/><circle cx='24.8' cy='9.0' r='0.27' fill='%23E8F7FF' opacity='0.29'/><circle cx='72.5' cy='6.1' r='0.51' fill='%23E8F7FF' opacity='0.35'/><circle cx='29.9' cy='0.4' r='1.27' fill='%23E8F7FF' opacity='0.49'/><circle cx='124.8' cy='2.3' r='1.22' fill='%23E8F7FF' opacity='0.77'/><circle cx='120.8' cy='8.4' r='0.53' fill='%23E8F7FF' opacity='0.29'/><circle cx='19.6' cy='5.2' r='0.89' fill='%23E8F7FF' opacity='0.29'/><circle cx='147.7' cy='9.8' r='0.37' fill='%23E8F7FF' opacity='0.15'/><circle cx='72.2' cy='4.2' r='1.09' fill='%23E8F7FF' opacity='0.41'/><circle cx='4.3' cy='1.0' r='1.09' fill='%23E8F7FF' opacity='0.92'/><circle cx='79.4' cy='5.4' r='0.68' fill='%23E8F7FF' opacity='0.49'/><circle cx='35.5' cy='6.7' r='0.61' fill='%23E8F7FF' opacity='0.37'/><circle cx='28.9' cy='1.9' r='0.70' fill='%23E8F7FF' opacity='0.82'/><circle cx='55.5' cy='6.6' r='0.46' fill='%23E8F7FF' opacity='0.21'/><circle cx='10.5' cy='9.0' r='0.59' fill='%23E8F7FF' opacity='0.18'/><circle cx='109.3' cy='7.4' r='0.77' fill='%23E8F7FF' opacity='0.42'/><circle cx='65.1' cy='10.9' r='0.53' fill='%23E8F7FF' opacity='0.12'/><circle cx='141.3' cy='5.4' r='0.56' fill='%23E8F7FF' opacity='0.30'/><circle cx='140.2' cy='1.8' r='0.46' fill='%23E8F7FF' opacity='0.75'/><circle cx='123.8' cy='5.3' r='0.89' fill='%23E8F7FF' opacity='0.23'/><circle cx='41.3' cy='3.2' r='0.70' fill='%23E8F7FF' opacity='0.35'/><circle cx='11.1' cy='3.7' r='1.05' fill='%23E8F7FF' opacity='0.71'/><circle cx='119.3' cy='5.3' r='0.48' fill='%23E8F7FF' opacity='0.58'/><circle cx='84.1' cy='8.0' r='0.25' fill='%23E8F7FF' opacity='0.19'/><circle cx='134.1' cy='8.7' r='0.66' fill='%23E8F7FF' opacity='0.24'/><circle cx='68.2' cy='6.4' r='0.82' fill='%23E8F7FF' opacity='0.28'/><circle cx='85.5' cy='3.0' r='1.00' fill='%23E8F7FF' opacity='0.27'/><circle cx='109.6' cy='10.5' r='0.18' fill='%23E8F7FF' opacity='0.14'/><circle cx='103.0' cy='9.4' r='0.47' fill='%23E8F7FF' opacity='0.14'/><circle cx='64.9' cy='10.5' r='0.53' fill='%23E8F7FF' opacity='0.08'/><circle cx='15.2' cy='1.0' r='0.44' fill='%23E8F7FF' opacity='0.59'/><circle cx='22.5' cy='9.5' r='0.50' fill='%23E8F7FF' opacity='0.12'/><circle cx='86.2' cy='3.6' r='0.74' fill='%23E8F7FF' opacity='0.36'/><circle cx='26.6' cy='2.0' r='0.72' fill='%23E8F7FF' opacity='0.69'/><circle cx='88.0' cy='0.5' r='1.12' fill='%23E8F7FF' opacity='0.88'/><circle cx='123.9' cy='8.7' r='0.22' fill='%23E8F7FF' opacity='0.22'/><circle cx='10.2' cy='8.4' r='0.32' fill='%23E8F7FF' opacity='0.29'/><circle cx='40.5' cy='7.7' r='0.42' fill='%23E8F7FF' opacity='0.15'/><circle cx='62.2' cy='3.4' r='1.08' fill='%23E8F7FF' opacity='0.40'/><circle cx='80.5' cy='6.0' r='0.91' fill='%23E8F7FF' opacity='0.22'/><circle cx='96.2' cy='5.6' r='0.80' fill='%23E8F7FF' opacity='0.56'/><circle cx='49.6' cy='7.7' r='0.54' fill='%23E8F7FF' opacity='0.29'/><circle cx='10.2' cy='9.0' r='0.69' fill='%23E8F7FF' opacity='0.18'/><circle cx='50.9' cy='10.9' r='0.20' fill='%23E8F7FF' opacity='0.06'/><circle cx='11.7' cy='9.0' r='0.58' fill='%23E8F7FF' opacity='0.20'/><circle cx='99.4' cy='0.2' r='1.07' fill='%23E8F7FF' opacity='0.63'/><circle cx='82.8' cy='4.3' r='0.63' fill='%23E8F7FF' opacity='0.33'/><circle cx='7.8' cy='4.8' r='0.50' fill='%23E8F7FF' opacity='0.51'/><circle cx='130.8' cy='8.0' r='0.49' fill='%23E8F7FF' opacity='0.20'/><circle cx='61.7' cy='5.4' r='0.74' fill='%23E8F7FF' opacity='0.57'/><circle cx='13.7' cy='5.3' r='0.65' fill='%23E8F7FF' opacity='0.48'/><circle cx='142.5' cy='8.6' r='0.54' fill='%23E8F7FF' opacity='0.29'/><circle cx='106.9' cy='9.4' r='0.52' fill='%23E8F7FF' opacity='0.22'/><circle cx='39.2' cy='10.1' r='0.35' fill='%23E8F7FF' opacity='0.17'/><circle cx='132.0' cy='10.6' r='0.56' fill='%23E8F7FF' opacity='0.07'/><circle cx='50.0' cy='3.4' r='0.67' fill='%23E8F7FF' opacity='0.33'/><circle cx='88.5' cy='0.9' r='0.70' fill='%23E8F7FF' opacity='0.90'/><circle cx='118.8' cy='5.1' r='0.39' fill='%23E8F7FF' opacity='0.59'/><circle cx='112.6' cy='2.3' r='0.67' fill='%23E8F7FF' opacity='0.63'/><circle cx='109.1' cy='2.9' r='1.16' fill='%23E8F7FF' opacity='0.44'/><circle cx='40.7' cy='9.3' r='0.28' fill='%23E8F7FF' opacity='0.23'/><circle cx='32.0' cy='6.6' r='0.45' fill='%23E8F7FF' opacity='0.29'/><circle cx='150.5' cy='5.1' r='0.62' fill='%23E8F7FF' opacity='0.45'/><circle cx='44.9' cy='1.9' r='0.73' fill='%23E8F7FF' opacity='0.45'/><circle cx='30.2' cy='10.6' r='0.19' fill='%23E8F7FF' opacity='0.16'/><circle cx='149.6' cy='7.8' r='0.25' fill='%23E8F7FF' opacity='0.27'/><circle cx='6.3' cy='6.7' r='0.70' fill='%23E8F7FF' opacity='0.25'/><circle cx='1.2' cy='6.0' r='0.35' fill='%23E8F7FF' opacity='0.30'/><circle cx='72.7' cy='9.8' r='0.35' fill='%23E8F7FF' opacity='0.11'/><circle cx='126.7' cy='9.0' r='0.47' fill='%23E8F7FF' opacity='0.12'/><circle cx='30.0' cy='4.4' r='0.74' fill='%23E8F7FF' opacity='0.33'/><circle cx='128.4' cy='9.3' r='0.64' fill='%23E8F7FF' opacity='0.26'/><circle cx='2.8' cy='6.4' r='0.33' fill='%23E8F7FF' opacity='0.47'/><circle cx='119.5' cy='8.4' r='0.33' fill='%23E8F7FF' opacity='0.14'/><circle cx='130.4' cy='6.7' r='0.65' fill='%23E8F7FF' opacity='0.32'/><circle cx='128.0' cy='3.7' r='0.56' fill='%23E8F7FF' opacity='0.41'/><circle cx='47.7' cy='6.9' r='0.80' fill='%23E8F7FF' opacity='0.19'/><circle cx='10.8' cy='5.6' r='0.76' fill='%23E8F7FF' opacity='0.27'/><circle cx='43.2' cy='0.6' r='0.46' fill='%23E8F7FF' opacity='0.64'/><circle cx='108.9' cy='7.2' r='0.35' fill='%23E8F7FF' opacity='0.19'/><circle cx='148.9' cy='5.9' r='0.56' fill='%23E8F7FF' opacity='0.43'/><circle cx='116.5' cy='5.8' r='0.35' fill='%23E8F7FF' opacity='0.49'/><circle cx='34.2' cy='0.4' r='0.77' fill='%23E8F7FF' opacity='0.67'/><circle cx='100.5' cy='1.9' r='1.02' fill='%23E8F7FF' opacity='0.57'/><circle cx='25.9' cy='9.4' r='0.58' fill='%23E8F7FF' opacity='0.26'/><circle cx='108.7' cy='2.4' r='1.05' fill='%23E8F7FF' opacity='0.76'/><circle cx='85.3' cy='10.0' r='0.60' fill='%23E8F7FF' opacity='0.14'/><circle cx='150.7' cy='10.3' r='0.51' fill='%23E8F7FF' opacity='0.07'/><circle cx='56.3' cy='6.7' r='0.64' fill='%23E8F7FF' opacity='0.40'/><circle cx='103.5' cy='1.8' r='1.23' fill='%23E8F7FF' opacity='0.60'/><circle cx='141.1' cy='2.3' r='1.25' fill='%23E8F7FF' opacity='0.59'/><circle cx='124.1' cy='8.1' r='0.71' fill='%23E8F7FF' opacity='0.22'/><circle cx='13.3' cy='4.5' r='0.46' fill='%23E8F7FF' opacity='0.46'/><circle cx='130.4' cy='4.0' r='0.44' fill='%23E8F7FF' opacity='0.25'/><circle cx='67.7' cy='6.4' r='0.29' fill='%23E8F7FF' opacity='0.40'/><circle cx='33.7' cy='1.2' r='1.27' fill='%23E8F7FF' opacity='0.63'/><circle cx='143.2' cy='5.7' r='0.38' fill='%23E8F7FF' opacity='0.29'/><circle cx='67.9' cy='7.0' r='0.72' fill='%23E8F7FF' opacity='0.38'/><circle cx='104.1' cy='2.8' r='0.73' fill='%23E8F7FF' opacity='0.47'/><circle cx='78.3' cy='2.9' r='0.81' fill='%23E8F7FF' opacity='0.50'/><circle cx='5.7' cy='9.1' r='0.49' fill='%23E8F7FF' opacity='0.26'/><circle cx='117.8' cy='8.0' r='0.77' fill='%23E8F7FF' opacity='0.23'/><circle cx='63.0' cy='0.0' r='1.10' fill='%23E8F7FF' opacity='0.73'/><circle cx='92.2' cy='11.0' r='0.24' fill='%23E8F7FF' opacity='0.08'/><circle cx='117.5' cy='8.9' r='0.45' fill='%23E8F7FF' opacity='0.12'/><circle cx='59.3' cy='9.1' r='0.45' fill='%23E8F7FF' opacity='0.20'/><circle cx='62.3' cy='6.9' r='0.63' fill='%23E8F7FF' opacity='0.37'/><circle cx='138.4' cy='8.3' r='0.43' fill='%23E8F7FF' opacity='0.19'/><circle cx='125.1' cy='8.7' r='0.69' fill='%23E8F7FF' opacity='0.16'/><circle cx='135.6' cy='9.8' r='0.23' fill='%23E8F7FF' opacity='0.14'/><circle cx='101.4' cy='1.6' r='1.15' fill='%23E8F7FF' opacity='0.46'/><circle cx='109.2' cy='3.3' r='0.53' fill='%23E8F7FF' opacity='0.36'/><circle cx='79.6' cy='7.8' r='0.36' fill='%23E8F7FF' opacity='0.32'/><circle cx='53.6' cy='7.1' r='0.48' fill='%23E8F7FF' opacity='0.21'/><g stroke='%23DFF4FF' stroke-width='.45' opacity='0.67'><path d='M23.2 0.8H27.7M25.4 -1.5V3.0M23.9 -0.8L27.0 2.3M27.0 -0.8L23.9 2.3'/></g><g stroke='%23DFF4FF' stroke-width='.45' opacity='0.51'><path d='M20.5 4.5H24.9M22.7 2.3V6.6M21.2 2.9L24.3 6.0M24.3 2.9L21.2 6.0'/></g><g stroke='%23DFF4FF' stroke-width='.45' opacity='0.70'><path d='M112.2 3.2H116.1M114.2 1.2V5.1M112.8 1.8L115.5 4.5M115.5 1.8L112.8 4.5'/></g><g stroke='%23DFF4FF' stroke-width='.45' opacity='0.75'><path d='M148.1 2.2H152.4M150.3 0.0V4.3M148.7 0.7L151.8 3.7M151.8 0.7L148.7 3.7'/></g><g stroke='%23DFF4FF' stroke-width='.45' opacity='0.75'><path d='M57.3 2.1H61.9M59.6 -0.2V4.4M58.0 0.4L61.2 3.7M61.2 0.4L58.0 3.7'/></g><g stroke='%23DFF4FF' stroke-width='.45' opacity='0.82'><path d='M71.8 2.8H75.1M73.5 1.1V4.5M72.3 1.6L74.6 4.0M74.6 1.6L72.3 4.0'/></g><g stroke='%23DFF4FF' stroke-width='.45' opacity='0.59'><path d='M5.1 3.4H9.0M7.0 1.4V5.3M5.7 2.0L8.4 4.8M8.4 2.0L5.7 4.8'/></g><g stroke='%23DFF4FF' stroke-width='.45' opacity='0.70'><path d='M91.7 3.1H94.7M93.2 1.6V4.6M92.1 2.1L94.2 4.2M94.2 2.1L92.1 4.2'/></g><g stroke='%23DFF4FF' stroke-width='.45' opacity='0.63'><path d='M27.3 4.1H30.9M29.1 2.3V5.9M27.8 2.8L30.3 5.4M30.3 2.8L27.8 5.4'/></g></svg>") repeat-x left bottom;
    background-size:160px 11px;
    animation:np-rime 120s linear infinite;
    pointer-events:none;
  }
  @keyframes np-rime{        /* the mask IS the growth; nothing else moves */
    0%  {-webkit-mask-image:linear-gradient(90deg,#000 0%,transparent 2%);
                 mask-image:linear-gradient(90deg,#000 0%,transparent 2%)}
    92% {-webkit-mask-image:linear-gradient(90deg,#000 96%,transparent 100%);
                 mask-image:linear-gradient(90deg,#000 96%,transparent 100%)}
    98% {-webkit-mask-image:linear-gradient(90deg,transparent 96%,transparent 100%);
                 mask-image:linear-gradient(90deg,transparent 96%,transparent 100%)}
    100%{-webkit-mask-image:linear-gradient(90deg,#000 0%,transparent 2%);
                 mask-image:linear-gradient(90deg,#000 0%,transparent 2%)}
  }

  /* --- 4. SKAITYMAS · the reading ------------------------------------------
     A rune stone is read aloud, left to right, one word at a time — the same
     direction the board reads. So the light does not sweep across the name, it
     LANDS on it in twelve steps and moves on, and each step holds long enough
     to be a syllable rather than a smear. `steps(12,end)`, which is the same
     grammar as the impact frames: cuts, not fades. */
  .rn .cell-name .np.np-skaitymas{
    display:inline-block; max-width:100%; vertical-align:top;
    color:transparent;
    -webkit-background-clip:text; background-clip:text;
    background-image:linear-gradient(90deg,
      #A9C2D2 0%, #A9C2D2 30%, #EAF9FF 42%, #FFFFFF 50%, #EAF9FF 58%,
      #A9C2D2 70%, #A9C2D2 100%);
    background-size:400% 100%;
    filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) drop-shadow(0 0 5px rgba(140,225,255,.28));
    animation:np-read 12s steps(12,end) infinite;
  }
  @keyframes np-read{from{background-position:130% 50%} to{background-position:-170% 50%}}

  @media (prefers-reduced-motion:reduce){
    .rn .cell-name .np.np-pasvaiste,
    .rn .cell-name .np.np-kalve,
    .rn .cell-name .np.np-skaitymas,
    .rn .cell-name .np.np-salna::before{animation:none}
    .rn .cell-name .np.np-salna::before{-webkit-mask-image:none; mask-image:none}
  }
  /* ==== SET BONUS · RAŠTAS ("the writing") ===================================
     Runakmenis complete. Gated with :has() on DISPLAY, so an incomplete set does
     not paint any of this — and does not run any of it either.

     FOURTH VERSION, and the arc of the three before it is the useful part.
     (1) Too subtle: a brighter light and a flare in the letters, a detail
     rather than an event. (2) Loud enough and it dropped frames: four filter
     animations per wearer, white frames, a whole-row invert. (3) Cheap enough
     but still shouting three times a minute.

     THIS ONE IS QUIET AND CONSTANT, on Egypt's clock. Sparnuotas diskas runs a
     9-second period; the frame's reading now runs 9s too, so the bonus happens
     on EVERY read rather than every third, and the two sets tick together on a
     shared board instead of drifting against each other.

     What happens: the light reaches the end of the top band and, instead of
     dropping straight to the lower one, it slips through the player's name —
     the aurora answers with a single swell, the inscription lifts a little, and
     the light carries on. **No white frames, no negative frame, no curtain.**
     The event is that the reading passes through the name, which is the whole
     idea; the fireworks around it were the part that was wrong twice.

     Cost: two moving gradients and two opacity fades, all composited. The one
     filter is the nameplate's own, because Pašvaistė is a filter effect.
  ========================================================================= */

  /* ---- 1 · THE READING WAITS ----------------------------------------------
     THE TWO EVENTS DO NOT OVERLAP. They take turns.

     The aurora goes first: it gathers in the player's name, lifts out of the
     letters and crosses the row, and dies. Only when it has gone does the
     frame's own reading start — out along the top band, down, back along the
     bottom, exactly as it runs when the frame is worn alone. Nothing is
     rerouted and nothing is suppressed; the reading is simply HELD until the
     set has finished speaking.

     That is why there is no middle beam. There never needed to be one: the
     thing crossing the middle is the aurora, and the thing reading the bands is
     the frame, and they are not on screen at the same time.

     0.0 – 4.2s  the aurora
     4.6 – 8.2s  the reading
     8.2 – 9.0s  still
  -------------------------------------------------------------------------- */
  .rn.sf-raiziniai:has(.np-pasvaiste) .rn-lite::after{
    animation:rk-read-late 9s linear infinite;
  }
  @keyframes rk-read-late{
    0%,     51%{transform:translate(-110%, 0)}            /* waiting, off-screen */
    71%       {transform:translate( 230%, 0)}             /* out along the top */
    71.001%   {transform:translate( 230%, var(--drop))}   /* down */
    91%       {transform:translate(-110%, var(--drop))}   /* back along the bottom */
    91.001%,100%{transform:translate(-140%, 0)}
  }

  /* ---- 1b · THE CURTAIN ---------------------------------------------------
     FOUR THINGS MAKE AN AURORA LOOK LIKE ONE, and the first version had two of
     them. Rays and colour order were right; motion and depth were not, which is
     why it read as a coloured rectangle sliding sideways.

     · IT IS MADE OF VERTICAL RAYS, unevenly spaced, and they LEAN. Rays follow
       the field lines, so a curtain is skewed rather than upright.
     · IT IS BRIGHTEST AT ITS FOOT — green low, cyan through the middle, violet
       at the top: oxygen at about 100km, oxygen higher, nitrogen above it.
     · IT IS NOT ONE SHEET. **Two curtains, at different ray pitches, different
       leans and different speeds.** The parallax between them is what makes it
       read as folds seen edge-on rather than as a picture of an aurora. This is
       the change that did most of the work.
     · THE LEAN AND THE HEIGHT ARE CONSTANT PER CURTAIN. An earlier pass had
       both animating — the curtains stretched and the skew rocked — and it
       looked good and cost eight frames a second on a nine-wearer board. **Only
       `translate` is free: a skew or a scale that CHANGES makes the browser
       re-rasterise the layer every frame**, where a fixed one is baked in once.
       So each curtain keeps its own lean and its own height, and all the life
       comes from the parallax between them.

     Both are translate + opacity. Nothing repaints, nothing re-rasterises.
  -------------------------------------------------------------------------- */
  .rn.sf-raiziniai:has(.np-pasvaiste) .rn-wash{
    display:block; position:absolute; z-index:3; pointer-events:none;
    overflow:hidden;
    left:var(--c-pad); right:var(--c-pad);
    top:calc(var(--band) * 1.45); bottom:calc(var(--band) * 1.45);
    border-radius:calc(var(--h) * .12) / 50%;
  }

  /* the near curtain — wider rays, a shallow lean, the brighter one */
  .rn.sf-raiziniai:has(.np-pasvaiste) .rn-wash::before{
    content:''; position:absolute; top:-20%; bottom:-20%; left:0; width:86%;
    transform-origin:50% 100%;
    background:
      repeating-linear-gradient(90deg,
        rgba(232,255,246,0)    0px,  rgba(232,255,246,0)    3px,
        rgba(232,255,246,.055) 3px,  rgba(232,255,246,.055) 4px,
        rgba(232,255,246,0)    4px,  rgba(232,255,246,0)    9px,
        rgba(232,255,246,.035) 9px,  rgba(232,255,246,.035) 10.5px,
        rgba(232,255,246,0)   10.5px,rgba(232,255,246,0)    17px,
        rgba(232,255,246,.07) 17px,  rgba(232,255,246,.07) 18px,
        rgba(232,255,246,0)   18px,  rgba(232,255,246,0)    26px),
      radial-gradient(50% 165% at 50% 108%,
        rgba(124,232,176,.34)  0%,
        rgba(118,226,206,.26) 26%,
        rgba(116,214,236,.19) 46%,
        rgba(158,178,246,.13) 66%,
        rgba(186,142,238,.07) 84%,
        rgba(186,142,238,0)  100%);
    transform:translateX(-44%) skewX(-9deg) scaleY(.98);
    animation:rk-aur-near 9s cubic-bezier(.34,.42,.4,1) infinite;
  }
  @keyframes rk-aur-near{
    0%,     4%{transform:translateX(-44%) skewX(-9deg)  scaleY(.98); opacity:0}
    11%      {transform:translateX(-28%) skewX(-11deg) scaleY(1.06); opacity:.9}
    21%      {transform:translateX(  6%) skewX(-7deg)  scaleY(.96); opacity:1}
    31%      {transform:translateX( 42%) skewX(-12deg) scaleY(1.10); opacity:.86}
    40%      {transform:translateX( 76%) skewX(-8deg)  scaleY(.94); opacity:.45}
    47%      {transform:translateX(105%) skewX(-10deg) scaleY(1.02); opacity:0}
    47.001%,100%{transform:translateX(-44%) skewX(-9deg) scaleY(.90); opacity:0}
  }

  /* the far curtain — finer rays, a steeper lean, slower, dimmer, out of phase */
  .rn.sf-raiziniai:has(.np-pasvaiste) .rn-wash::after{
    content:''; position:absolute; top:-14%; bottom:-14%; left:0; width:64%;
    transform-origin:50% 100%;
    background:
      repeating-linear-gradient(90deg,
        rgba(226,246,255,0)    0px,  rgba(226,246,255,0)    2px,
        rgba(226,246,255,.05)  2px,  rgba(226,246,255,.05)  2.8px,
        rgba(226,246,255,0)    2.8px,rgba(226,246,255,0)    7px,
        rgba(226,246,255,.028) 7px,  rgba(226,246,255,.028) 8px,
        rgba(226,246,255,0)    8px,  rgba(226,246,255,0)    13px,
        rgba(226,246,255,.045)13px,  rgba(226,246,255,.045)13.8px,
        rgba(226,246,255,0)  13.8px, rgba(226,246,255,0)    19px),
      radial-gradient(50% 150% at 50% 106%,
        rgba(116,222,190,.20)  0%,
        rgba(124,206,238,.16) 32%,
        rgba(168,170,246,.12) 60%,
        rgba(196,146,240,.08) 82%,
        rgba(196,146,240,0)  100%);
    transform:translateX(-58%) skewX(-16deg) scaleY(1.02);
    animation:rk-aur-far 9s cubic-bezier(.4,.35,.45,1) infinite;
  }
  @keyframes rk-aur-far{
    0%,     6%{transform:translateX(-58%) skewX(-16deg) scaleY(1.02); opacity:0}
    14%      {transform:translateX(-40%) skewX(-13deg) scaleY(.92); opacity:.75}
    26%      {transform:translateX( -4%) skewX(-18deg) scaleY(1.08); opacity:.9}
    36%      {transform:translateX( 34%) skewX(-14deg) scaleY(.94); opacity:.7}
    45%      {transform:translateX( 74%) skewX(-17deg) scaleY(1.05); opacity:.3}
    52%      {transform:translateX(112%) skewX(-15deg) scaleY(.98); opacity:0}
    52.001%,100%{transform:translateX(-58%) skewX(-16deg) scaleY(1.06); opacity:0}
  }

  /* ---- 2 · THE INSCRIPTION LIFTS ------------------------------------------
     A second copy of the band's own runes in white-cyan, fading up and down
     rather than the four-step charge ladder version three had. Peak .38, where
     that one went to 1. */
  .rn.sf-raiziniai:has(.np-pasvaiste) .rn-band::before{
    content:''; position:absolute; inset:0; z-index:1; pointer-events:none;
    background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='264' height='16' viewBox='0 0 264 16'%3E%3Cg fill='none' stroke='%23EAFCFF' stroke-width='1.8' stroke-linecap='square'%3E%3Cpath d='M3%203%20V13%20M3%204%20L8%206.5%20M3%209%20L8%206.5'/%3E%3Cpath d='M14%2013%20V3%20L19%206%20L14%208.5'/%3E%3Cpath d='M25%2013%20V3%20M25%203%20L30%206%20L25%209%20M25%208%20L30%2012'/%3E%3Cpath d='M36%203%20V13%20M42%203%20V13%20M36%205%20L42%2011'/%3E%3Cpath d='M47%2013%20V3%20L53%208%20L47%208'/%3E%3Cpath d='M58%2013%20V3%20L64%2013%20M59.5%208.5%20L62.5%208.5'/%3E%3Cpath d='M69%203%20L74%208%20L69%2013%20M74%208%20L79%203'/%3E%3Cpath d='M84%203%20V13%20M90%203%20V13%20M84%208%20L90%208'/%3E%3Cpath d='M95%208%20L100%203%20L105%208%20L100%2013%20Z'/%3E%3Cpath d='M110%2013%20V3%20M110%203%20L115%208%20L110%2013'/%3E%3Cpath d='M121%203%20V13%20M118%203%20L126%203%20M118%2013%20L126%2013'/%3E%3Cpath d='M132%2013%20V3%20M132%208%20L137%203%20M132%208%20L137%2013'/%3E%3Cpath d='M143%203%20V13%20L149%2013'/%3E%3Cpath d='M154%2013%20V3%20L160%203%20M154%208%20L159%208'/%3E%3Cpath d='M165%208%20L170%203%20L175%208%20M170%203%20V13'/%3E%3Cpath d='M180%203%20V13%20M186%203%20V13%20M180%203%20L186%2013'/%3E%3Cpath d='M191%2013%20L196%203%20L201%2013%20M193%209%20H199'/%3E%3Cpath d='M206%203%20V13%20M206%203%20L212%208%20M212%208%20L206%2013%20M212%208%20V13'/%3E%3Cpath d='M217%203%20L223%203%20M220%203%20V13%20M217%2013%20L223%2013'/%3E%3Cpath d='M228%2013%20V3%20M228%203%20L233%208%20L228%2013%20M233%208%20L238%208'/%3E%3Cpath d='M243%203%20V13%20M243%208%20L249%203%20M243%208%20L249%2013'/%3E%3Cpath d='M254%203%20L259%208%20L254%2013%20M259%208%20V3'/%3E%3C/g%3E%3C/svg%3E") repeat-x center;
    background-size:264px 16px;
    opacity:0;
    animation:rk-catch 9s ease-in-out infinite;
  }
  /* the bands answer the aurora, not the reading */
  @keyframes rk-catch{
    0%,    6%{opacity:0}
    20%     {opacity:.34}
    34%     {opacity:.20}
    50%,100%{opacity:0}
  }

  /* ---- 3 · THE NAME ANSWERS -----------------------------------------------
     ONE swell, not two flares, and it peaks at 1.5 where version three peaked
     at 2.5. Pašvaistė's own substorm is folded into the same animation because
     two animations writing `filter` do not compose — the later one wins. */
  .rn.sf-raiziniai .cell-name .np.np-pasvaiste{
    animation:np-aurora 18s steps(120,end) infinite,
              rk-name 36s linear infinite;
  }
  @keyframes rk-name{
    /* four readings per 36s cycle: the swell at each, the substorm once */
    /* the swell is the aurora gathering, so it LEADS the curtain */
    0%,     0.5%{filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) brightness(1) saturate(1)}
    2.4%       {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) brightness(1.52) saturate(1.45)}
    6.5%       {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) brightness(1) saturate(1)}
    28.5%      {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) brightness(1) saturate(1)}
    30.5%      {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) brightness(1.50) saturate(1.45)}
    34.0%      {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) brightness(1) saturate(1)}
    53.5%      {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) brightness(1) saturate(1)}
    55.5%      {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) brightness(1.72) saturate(1.7)}   /* the substorm */
    57.0%      {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) brightness(1.28) saturate(1.35)}
    58.5%      {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) brightness(1.55) saturate(1.55)}
    62.0%      {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) brightness(1) saturate(1)}
    78.5%      {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) brightness(1) saturate(1)}
    80.5%      {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) brightness(1.50) saturate(1.45)}
    84.0%,100% {filter:drop-shadow(0 1px 0 rgba(0,0,0,.9)) brightness(1) saturate(1)}
  }

  @media (prefers-reduced-motion:reduce){
    .rn-wash{display:none !important}
    .rn.sf-raiziniai:has(.np-pasvaiste) .rn-band::before{animation:none; opacity:0}
    .rn.sf-raiziniai .cell-name .np.np-pasvaiste{animation:none}
  }

  /* ==== THE APP, NOT THE DEMO ==============================================
     Everything below exists because this frame was designed on a stand-alone
     page and then measured against the shipping row. Each block is a
     correction, and each one would have shown up as "there's the gap again".
  ========================================================================= */

  /* 1 · THE ROW IS A <button>, AND cosmeticClasses() ALWAYS EMITS `framed`.
     `.framed` paints its own fillet on ::before and ::after — a 7px inset
     border and a 1px liner. On a rune stone that is a second frame drawn on
     top of the first. The rune frame supplies its own edge, so both are
     turned off, and `--int` is set because `.framed` colours the row with it. */
  .rn.framed{--int:transparent; background-color:transparent}
  .rn.framed::before, .rn.framed::after, .fr-runu-ratas.framed::before, .fr-runu-ratas.framed::after{display:none}

  /* 2 · THE DATABASE NAME IS THE MARKUP NAME, AND JS JOINS THEM, NOT CSS.
     Migration 017 stores a string; `cosmeticClasses()` writes `fr-` + that
     string, so the row arrives as `fr-runu-ratas`. Everything in this file is
     written against `.rn`. Aliasing every selector was tried and doubled the
     stylesheet for nothing: `dressRunes()` already walks these rows to inject
     the layers, so it adds `rn ends` at the same time — ONE LINE INSTEAD OF
     THIRTY-EIGHT DUPLICATED SELECTORS. `.ends` is not a cosmetic; it is this
     frame's only variant and comes with it. */


  /* 3 · THE PHONE COLUMN CHANGE. Below 700px `.brow` becomes `30px 1fr 92px`
     and children 3 and 4 are hidden. The frame reads the rank column out of
     --c-rank, so it only needs the one number — but it must be here, because
     a frame that keeps a 34px rank column on a phone puts its own light four
     pixels off the numeral for the entire width of the board. */
  @media (max-width:700px){
    .rn{--c-rank:30px; --c-money:92px}
  }

  /* 4 · THE NAME TRACK IS NOT 220px. On a phone the name cell is 183px; on a
     1000px board it is 596px. Nothing in this frame may assume a width for
     it — the panel, the slot and the wash are all anchored to --c-pad and
     --c-rank from the left and to .cell-net from the right, never sized. */

  /* Same fault as Aigidė's, found the same way: `.rk-plait` is
     `position:absolute; inset:0` and a plain row wearing the surface alone has
     nothing positioned in its chain. `position:relative` on the gate does not
     take the row out of the flow — that was the `absolute` trap, and this is
     not it. */
  .sf-raiziniai{position:relative}

  /* THE POSITIVE SAFETY NET, said once about everything this frame injects.
     The row is a grid, so an injected element with no rule of its own is a
     grid ITEM: it takes a cell, pushes the real cells onto a second line and
     makes the wearer taller than its neighbours — the `.rn-wash` fault, and
     `.zs-arch` and `.zs-shock` after it. A blocklist only catches what it was
     told about. This is the other way round: anything in the row that is not
     one of the four cells is absolute, and a layer without a rule is a
     zero-size box instead of a structural one. */
  .rn > :not(.cell-num):not(.cell-name):not(.cell-net):not(.eng){position:absolute;}

  /* ================= DZEUSAS — THE THUNDERER SET =================
     Ported 2026-09-13 from Claude outputs/zeus.css, aigide-1.css (the newer
     of the two copies), names-kapitales.css and dz-set.css, verbatim and in
     that order. Frame `perkunsvaidis`, surface `aigide`, nameplate
     `kapitales`. src/perkunas.js adds `zs` to the row, injects the layers and
     aims the bolts; the stylesheet is written against `.zs`. The positive
     safety net is the frame's own: `.zs > div[class*="zs-"], .zs >
     span[class*="dz-"]{position:absolute}`.
     ==================================================================== */
  /* ==== DZEUSAS · FRAME · PERKŪNSVAIDIS ("the thunderbolt-hurler") ===========
     Two marble piers carrying an arch, a gilded meander running between them on
     dark stone — and a bolt through the middle of it every nine seconds.

     THE ONE IDEA: YOU CAN SEE THE STORM COMING. Two masses drift across the
     tablet and thicken for five and a half seconds, the bolt tears them open,
     the gilding catches the flash, and the weather clears.

     IT USED TO BE "THE MEANDER IS THE CIRCUIT" — a charge running along the
     Greek key from both ends, converging where the bolt would land. The sentence
     is better than the picture. It is an abstract conceit nobody watching a row
     would ever name, and this batch's own standing rule is that THE SYMBOL IS
     CHOSEN FOR HOW WELL IT IS KNOWN, NOT FOR HOW INTERESTING IT IS. Clouds
     gathering before lightning is a thing every person alive has seen. The
     cleverness was mine; the recognition is the player's, and the player wins.

     HOW MUCH MARBLE THIS PIECE CAN HOLD, which is the constraint everything else
     bent around. The row is 57.8px, the name block takes 34.8 of it and the two
     bands take 20 — so there is no field left over to be stone, and the interior
     has to be dark anyway because views.js writes the rank numeral's colour
     INLINE and those four colours need a dark ground. The resolution is
     structural rather than decorative: THE MARBLE IS THE PIERS AND THE BANDS,
     the interior is a bronze tablet let into them, and the ground behind is dark
     stone. The reference's cracked marble field has nowhere to live here and
     belongs to the SURFACE, which has a whole interior.

     The corollary, learned by drawing it wrong first: marble piers standing on a
     marble ground under marble bands are one pale smear. AN OBJECT HAS TO BE A
     DIFFERENT VALUE FROM ITS BACKGROUND BEFORE ANY OF ITS DETAIL MATTERS.

     WHY THE ENDS FIRST LOOKED BORROWED FROM ANOTHER OBJECT, diagnosed by putting
     a pier next to the band and comparing rather than by guessing. (1) The pier's
     marble peaked at #F5F0E3 and the band's at #EDE7DA, so the ends read as a
     different, brighter stone. (2) The ends carried NO GOLD AT ALL, while
     everything else on the frame is marble and gilding together. (3) Seven
     horizontal seams inside a 13px width is noise, not detail. Fixed by matching
     the stone exactly, giving the cornice, impost and base fillets the key's own
     gold, and cutting the seams to three. THE MATERIAL PALETTE HAS TO BE THE
     SAME EVERYWHERE OR THE PARTS READ AS BORROWED FROM DIFFERENT PIECES.
     (The archivolt was gilded too at this stage, which turned out to be the
     line too many — see below.)

     THE PIERS ARE THE ROW'S EDGES, top to bottom. They used to start 2px down
     and stop 3px short, which left a sliver of dark ground above the cornice and
     below the plinth and made the end read as a short column standing inside the
     row rather than as the row's own side. A frame's side member IS the edge;
     anything showing past it is a gap, not a margin. The meander now runs into
     the pier rather than fading before it, the way a real course dies into the
     stone that stops it.

     WHAT "NOT CONNECTED" TURNED OUT TO BE, after five attempts at this one
     corner. Three of them were joins rather than drawing: the piers were painted
     AFTER the bands at the same z-index, so the archivolt landed ON TOP of the
     meander and stopped there (piers are at z 4 now); the spandrel had its own
     gradient while the pier had another, so the corner read as two pieces of
     marble touching rather than one with a curve cut out of it; and the bronze
     was inset 3px past the pier, leaving a strip of dark ground between the
     stone and the plate. "IT LOOKS DISCONNECTED" IS USUALLY PAINT ORDER,
     MATERIAL AND CONTACT, NOT SHAPE.

     But the fourth and real fault was a CONSTRUCTION error the first four
     attempts all shared: THE ARCH WAS DRAWN AS ITS OWN GOLD LINE, which put a
     second moulding running parallel to the meander with a sliver of marble
     between them. Two parallel gold lines a few pixels apart is what kept
     reading as wrong, and no adjustment to either one fixes a construction with
     one line too many. THE ARCH IS THE SHAPE OF THE OPENING, NOT A LINE DRAWN
     NEAR IT: the bronze tablet's top corners are rounded and its own gilt rim
     follows them, so the arch is the edge of the hole. The spandrel is now plain
     marble filling the corner between the straight band above and the curved
     opening below, carrying no gold at all.

     AND THE TABLET'S GOLD IS ON ITS TOP AND BOTTOM EDGES ONLY, never a ring. A
     full inset ring put a vertical gold line down each side — between the rank
     numeral and the pier at one end, between the money and the pier at the other
     — and those read as the frame having an extra edge where it already had one:
     THE PIER IS THE SIDE. Nothing else should draw one. An inset shadow with a
     vertical offset and no spread follows the border-radius, so the gold runs
     the arched top and thins away exactly where the curve turns vertical, which
     is where the stone takes over.

     THE ARCH IS THE HAUNCH, NOT THE SPAN, and that is geometry rather than
     taste: across a 327px opening with 16px of rise the curve is flatter than
     the text it crosses, and a full arch rendered as a white scratch through the
     name. An arch needs a span-to-rise ratio a person can see; a board row is
     12:1. So each end carries the arch springing off its impost and turning
     horizontal where it meets the band — what it would do if the rest of it
     existed — running UP INTO the band rather than tapering to a point, which is
     what made the first attempt read as a corbel.

     Built on the SHIPPING row, measured, not on a demo: .brow is
     `34px 1fr 88px 76px 100px` with .row's 10px gap and 11px 14px padding, and
     a board row renders 57.8px tall. Below 700px the rank narrows to 30 and the
     two middle money columns are hidden. Runakmenis was drawn against a demo's
     numbers and had to be rebuilt; this one starts where the app is.
  ========================================================================= */

  .zs{
    --h: 57.8px;
    --key: 10px;                 /* THE MEANDER BAND. It went 10 → 8 to keep the
                                    key clear of the name, and at 8 the key was
                                    unreadable — three stroke levels in 8px leave
                                    under a pixel of clear space between them and
                                    the ornament merges into a gold smear. Back to
                                    10, and the 1px it now overlaps the name's
                                    cap-height costs nothing, because the cells
                                    are at z-index 6 and paint over the band.
                                    OCCLUSION AND CLUTTER ARE DIFFERENT PROBLEMS
                                    and the first fix confused them. */
    --cap: 13px;                 /* THE PIER. A pier, not a column: a column
                                    carries a beam and a pier carries an arch,
                                    and the arch is what he asked for. It is
                                    squarer and heavier than the Doric column it
                                    replaces, and it has an IMPOST — the
                                    projecting block the arch lands on, which is
                                    the piece that says an arch springs here. */

    /* the board's own metrics — not the frame's to choose */
    --c-rank: 34px;
    --c-gap:  10px;
    --c-pad:  14px;
    --c-money: 284px;            /* 88 + 10 + 76 + 10 + 100 */

    position:relative;
    isolation:isolate;
    background:transparent;
    /* NO clip-path and NO filter on the row. A clip forces the whole subtree to
       re-composite whenever anything inside it moves, and a filter — even a
       static one — is a permanent buffer per wearer. Both lessons are paid for;
       see BRIEF-85. The chamfer, such as it is, lives on .zs-slab, a leaf. */
  }
  .zs.framed{--int:transparent; background-color:transparent}
  .zs.framed::before, .zs.framed::after{display:none}   /* .framed's own fillet */

  /* EVERY LAYER THIS FRAME INJECTS IS ABSOLUTE, AND THIS RULE IS THE SAFETY NET.
     The row is a GRID, so any injected div that is not positioned becomes a grid
     ITEM: it takes a cell, pushes the real cells into an implicit second row and
     makes the wearer ten pixels taller than its neighbours. That is exactly what
     happened when an `.zs-arch` layer was tried and then removed from the CSS
     while the div was left in the markup — no error, just a board that steps at
     every wearer. Declared here, in the stylesheet that always ships, so a layer
     with no rule of its own is invisible rather than structural. */
  .zs > div:not([class*="zs-"]){display:none}
  .zs-arch{display:none}
  /* AND THE POSITIVE VERSION, which is the one that actually holds. The rule
     above is a blocklist and a blocklist only catches what it was told about:
     `.zs-shock` was a set-bonus layer that got deleted from the CSS while its
     div stayed in the markup, it matched `[class*="zs-"]`, so the blocklist
     waved it through and every wearer went to 68px against a plain row's 58 —
     the same failure as `.zs-arch`, second time. Every layer this frame paints
     is absolutely positioned, so SAY THAT ONCE about all of them: a layer with
     no rule of its own is then a zero-size absolute box instead of a grid item
     that pushes the cells onto a second line. */
  .zs > div[class*="zs-"], .zs > span[class*="dz-"]{position:absolute}

  /* the cells sit above every painted layer — the app gives them no z-index */
  .zs > .cell-num, .zs > .cell-name, .zs > .cell-net, .zs > .eng{
    position:relative; z-index:6;
  }
  .zs .cell-name{
    min-width:0; display:flex; flex-direction:column;
    justify-content:center; align-items:flex-start; align-self:center;
  }
  .zs .cell-name .np{display:block; white-space:nowrap; overflow:hidden;
    text-overflow:ellipsis; color:#F6EEDC}
  .zs .cell-name .sub{display:block; color:#A99977}
  /* THE MONEY KEEPS ITS OWN COLOUR. This used to force the figure to cream on
     the bronze, which quietly took `--win` and `--loss` off the row — and green
     for up and orange for down is the one thing on this board that carries
     MEANING rather than decoration. A frame does not get to overrule it. The
     plate is near-black, so both read: #5FD39B lands at 8.1:1 on it and #E07B52
     at 4.9:1, against the 4.5:1 floor. A cosmetic may light the money, shade
     behind it or recess it — it may not recolour it. */
  .zs > .cell-num:not(:first-child){color:#A99977}

  /* ---- 1 · THE SLAB --------------------------------------------------------
     Pentelic marble is warm white with a grey-green vein, not blue-white. Two
     gradients for the block and one repeating skew for the vein; the crack layer
     is separate because it has to be lit on its own later. */
  .zs-slab{
    /* THE SLAB IS NOT MARBLE ANY MORE, and this is what made the columns read.
       With a marble slab behind them, the columns, the bands and the ground were
       all the same cream value and the whole frame merged into one pale smear —
       a column cannot read as a support if it is the same colour as what it is
       standing on. Now the only marble on the piece is the two bands and the two
       columns, and they stand against a dark stone ground. THE OBJECT HAS TO BE
       A DIFFERENT VALUE FROM ITS BACKGROUND BEFORE ANY OF ITS DETAIL MATTERS. */
    position:absolute; inset:0; z-index:0; pointer-events:none;
    border-radius:4px;
    background:
      linear-gradient(180deg, rgba(255,255,255,.07) 0%, rgba(255,255,255,0) 30%),
      linear-gradient(180deg, #2E2A22 0%, #211E18 52%, #2A2620 100%);
    box-shadow: inset 0 0 0 1px rgba(20,17,12,.85),
                inset 0 1px 0 rgba(255,250,236,.16);
  }
  .zs-slab::after{                    /* the vein, now in the shadow tone */
    content:''; position:absolute; inset:0; border-radius:inherit;
    background:repeating-linear-gradient(101deg,
      rgba(210,200,176,0) 0 17px, rgba(210,200,176,.05) 17px 19px,
      rgba(210,200,176,0) 19px 44px);
  }
  .zs-crack{
    position:absolute; inset:0; z-index:1; pointer-events:none;
    background:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27216%27%20height%3D%2758%27%20viewBox%3D%270%200%20216%2058%27%3E%3Cg%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%3E%3Cpath%20d%3D%27M12%2C0%20L20%2C9%20L14%2C18%20L23%2C31%20L18%2C44%20L27%2C58%20M58%2C2%20L52%2C13%20L61%2C22%20L55%2C35%20L64%2C47%20L59%2C58%20M104%2C0%20L112%2C14%20L106%2C24%20L115%2C38%20L109%2C52%20M148%2C4%20L141%2C16%20L150%2C28%20L144%2C41%20L152%2C55%20M190%2C0%20L197%2C11%20L191%2C25%20L200%2C36%20L194%2C50%20L203%2C58%20M31%2C20%20L44%2C26%20M120%2C30%20L133%2C25%20M166%2C36%20L179%2C31%20M74%2C40%20L86%2C36%27%20stroke%3D%27%23FFFFFF%27%20stroke-width%3D%271.6%27%20opacity%3D%27.30%27%20transform%3D%27translate%280%2C1%29%27%2F%3E%3Cpath%20d%3D%27M12%2C0%20L20%2C9%20L14%2C18%20L23%2C31%20L18%2C44%20L27%2C58%20M58%2C2%20L52%2C13%20L61%2C22%20L55%2C35%20L64%2C47%20L59%2C58%20M104%2C0%20L112%2C14%20L106%2C24%20L115%2C38%20L109%2C52%20M148%2C4%20L141%2C16%20L150%2C28%20L144%2C41%20L152%2C55%20M190%2C0%20L197%2C11%20L191%2C25%20L200%2C36%20L194%2C50%20L203%2C58%20M31%2C20%20L44%2C26%20M120%2C30%20L133%2C25%20M166%2C36%20L179%2C31%20M74%2C40%20L86%2C36%27%20stroke%3D%27%23473C2E%27%20stroke-width%3D%271.05%27%20opacity%3D%27.42%27%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") repeat left top;
    background-size:216px 58px;
    opacity:.85;
  }

  /* ---- 2 · THE MEANDER, WHICH IS THE CIRCUIT -------------------------------
     Drawn as a PATH, not typed. U+2E3F and the box-drawing characters both
     depend on a font being installed; a path is a path. 19 units in a 266px
     tile so the repeat never lands twice in one row — the same reason the runes
     were cut at 22 glyphs rather than 11.

     z-index 5, ABOVE the glass: at 57.8px the name needs so much of the
     interior that the panel has to reach under the bands, and a band painted
     over is a band you cannot read. */
  .zs-key{
    position:absolute; left:var(--cap); right:var(--cap);
    height:var(--key); z-index:5; pointer-events:none;
    /* overflow, NOT a mask. The end mask used to be doing two jobs without
       saying so: fading the band's ends AND clipping the travelling charge to
       the band. Removing it for the first job let the charge sail out of the row
       and paint across the board. A mask also forces a repaint on every frame of
       a child's transform, which is a cost this project has already paid once —
       overflow clips for free. */
    overflow:hidden;
    background:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27288%27%20height%3D%2710%27%20viewBox%3D%270%200%20288%2010%27%3E%3Cg%20fill%3D%27none%27%20stroke-linecap%3D%27square%27%3E%3Cpath%20d%3D%27M0%2C8.6%20H288%27%20stroke%3D%27%233B3022%27%20stroke-width%3D%272.6%27%2F%3E%3Cpath%20d%3D%27M2.4%2C8.6%20V2%20H13%20V5.6%20H6.6%20M18.4%2C8.6%20V2%20H29%20V5.6%20H22.6%20M34.4%2C8.6%20V2%20H45%20V5.6%20H38.6%20M50.4%2C8.6%20V2%20H61%20V5.6%20H54.6%20M66.4%2C8.6%20V2%20H77%20V5.6%20H70.6%20M82.4%2C8.6%20V2%20H93%20V5.6%20H86.6%20M98.4%2C8.6%20V2%20H109%20V5.6%20H102.6%20M114.4%2C8.6%20V2%20H125%20V5.6%20H118.6%20M130.4%2C8.6%20V2%20H141%20V5.6%20H134.6%20M146.4%2C8.6%20V2%20H157%20V5.6%20H150.6%20M162.4%2C8.6%20V2%20H173%20V5.6%20H166.6%20M178.4%2C8.6%20V2%20H189%20V5.6%20H182.6%20M194.4%2C8.6%20V2%20H205%20V5.6%20H198.6%20M210.4%2C8.6%20V2%20H221%20V5.6%20H214.6%20M226.4%2C8.6%20V2%20H237%20V5.6%20H230.6%20M242.4%2C8.6%20V2%20H253%20V5.6%20H246.6%20M258.4%2C8.6%20V2%20H269%20V5.6%20H262.6%20M274.4%2C8.6%20V2%20H285%20V5.6%20H278.6%27%20stroke%3D%27%233B3022%27%20stroke-width%3D%272.6%27%2F%3E%3Cpath%20d%3D%27M0%2C8.6%20H288%27%20stroke%3D%27%23FFFBEE%27%20stroke-width%3D%272.6%27%20opacity%3D%27.5%27%20transform%3D%27translate%280%2C.9%29%27%2F%3E%3Cpath%20d%3D%27M2.4%2C8.6%20V2%20H13%20V5.6%20H6.6%20M18.4%2C8.6%20V2%20H29%20V5.6%20H22.6%20M34.4%2C8.6%20V2%20H45%20V5.6%20H38.6%20M50.4%2C8.6%20V2%20H61%20V5.6%20H54.6%20M66.4%2C8.6%20V2%20H77%20V5.6%20H70.6%20M82.4%2C8.6%20V2%20H93%20V5.6%20H86.6%20M98.4%2C8.6%20V2%20H109%20V5.6%20H102.6%20M114.4%2C8.6%20V2%20H125%20V5.6%20H118.6%20M130.4%2C8.6%20V2%20H141%20V5.6%20H134.6%20M146.4%2C8.6%20V2%20H157%20V5.6%20H150.6%20M162.4%2C8.6%20V2%20H173%20V5.6%20H166.6%20M178.4%2C8.6%20V2%20H189%20V5.6%20H182.6%20M194.4%2C8.6%20V2%20H205%20V5.6%20H198.6%20M210.4%2C8.6%20V2%20H221%20V5.6%20H214.6%20M226.4%2C8.6%20V2%20H237%20V5.6%20H230.6%20M242.4%2C8.6%20V2%20H253%20V5.6%20H246.6%20M258.4%2C8.6%20V2%20H269%20V5.6%20H262.6%20M274.4%2C8.6%20V2%20H285%20V5.6%20H278.6%27%20stroke%3D%27%23FFFBEE%27%20stroke-width%3D%272.6%27%20opacity%3D%27.5%27%20transform%3D%27translate%280%2C.9%29%27%2F%3E%3Cpath%20d%3D%27M0%2C8.6%20H288%27%20stroke%3D%27%23D4A93A%27%20stroke-width%3D%271.4%27%2F%3E%3Cpath%20d%3D%27M2.4%2C8.6%20V2%20H13%20V5.6%20H6.6%20M18.4%2C8.6%20V2%20H29%20V5.6%20H22.6%20M34.4%2C8.6%20V2%20H45%20V5.6%20H38.6%20M50.4%2C8.6%20V2%20H61%20V5.6%20H54.6%20M66.4%2C8.6%20V2%20H77%20V5.6%20H70.6%20M82.4%2C8.6%20V2%20H93%20V5.6%20H86.6%20M98.4%2C8.6%20V2%20H109%20V5.6%20H102.6%20M114.4%2C8.6%20V2%20H125%20V5.6%20H118.6%20M130.4%2C8.6%20V2%20H141%20V5.6%20H134.6%20M146.4%2C8.6%20V2%20H157%20V5.6%20H150.6%20M162.4%2C8.6%20V2%20H173%20V5.6%20H166.6%20M178.4%2C8.6%20V2%20H189%20V5.6%20H182.6%20M194.4%2C8.6%20V2%20H205%20V5.6%20H198.6%20M210.4%2C8.6%20V2%20H221%20V5.6%20H214.6%20M226.4%2C8.6%20V2%20H237%20V5.6%20H230.6%20M242.4%2C8.6%20V2%20H253%20V5.6%20H246.6%20M258.4%2C8.6%20V2%20H269%20V5.6%20H262.6%20M274.4%2C8.6%20V2%20H285%20V5.6%20H278.6%27%20stroke%3D%27%23D4A93A%27%20stroke-width%3D%271.4%27%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") repeat-x left center,
      linear-gradient(180deg,#EDE7DA 0%,#DCD4C1 55%,#C9BFA8 100%);
    background-size:288px var(--key), 100% 100%;
    /* THE CHANNEL, as a second background layer under the gilding: a sunk
       dark ground with a bright lower lip. The key used to be gilded straight
       onto white marble — light on light, the worst contrast pair on the
       piece, and no amount of enlarging fixes a contrast problem. */
    /* THE BAND IS MARBLE AND THE KEY IS CUT INTO IT. A dark channel was tried
       first and it read well — but it turned the whole frame gold-and-black and
       took the marble out of a piece whose reference is mostly marble. On a
       57.8px row the name needs 34.8 and the two bands take 20, so there is no
       field left to be marble: THE BANDS THEMSELVES HAVE TO BE THE STONE.
       Legibility comes from the cut instead — a dark groove and a bright lower
       lip under the gilding — so the contrast is carried by the outline, not by
       the gold. That is also what the reference actually shows. */
    box-shadow: inset 0 0 0 1px rgba(74,62,46,.30);
    border-radius:1px;
    /* NO END MASK. The band used to fade out at 4% and 96% because its ends were
       open and a cut-off key looked like a mistake. Now the piers terminate it,
       so the band should die INTO the stone the way a real course does — and the
       fade was actively wrong: it dissolved the last key unit mid-pattern and
       left a dark gap between the band and the pier, which is what made the
       sides look like they did not reach the row's edges. */
  }
  .zs-key.t{top:1.5px}
  .zs-key.b{bottom:1.5px}


  /* THE BAND IS LIT BY THE STRIKE, NOT A WIRE THAT FEEDS IT.
     The first version ran a charge along each meander from opposite ends,
     converging on the strike point — "the Greek key is the circuit", which is a
     good sentence and a weak picture. It is an abstract conceit: nobody watching
     a row names it, and the batch's own standing rule is that THE SYMBOL IS
     CHOSEN FOR HOW WELL IT IS KNOWN, NOT FOR HOW INTERESTING IT IS. Clouds
     gathering before a bolt is a thing every person alive has seen.
     So the gilding now simply CATCHES the flash — one brightening of the whole
     key at the instant of the strike, no travel. It is also cheaper: two
     travelling gradients became two opacity fades. */
  .zs-key::before{
    content:''; position:absolute; inset:0;
    background:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27288%27%20height%3D%2710%27%20viewBox%3D%270%200%20288%2010%27%3E%3Cg%20fill%3D%27none%27%20stroke-linecap%3D%27square%27%3E%3Cpath%20d%3D%27M0%2C8.6%20H288%27%20stroke%3D%27%233B3022%27%20stroke-width%3D%272.6%27%2F%3E%3Cpath%20d%3D%27M2.4%2C8.6%20V2%20H13%20V5.6%20H6.6%20M18.4%2C8.6%20V2%20H29%20V5.6%20H22.6%20M34.4%2C8.6%20V2%20H45%20V5.6%20H38.6%20M50.4%2C8.6%20V2%20H61%20V5.6%20H54.6%20M66.4%2C8.6%20V2%20H77%20V5.6%20H70.6%20M82.4%2C8.6%20V2%20H93%20V5.6%20H86.6%20M98.4%2C8.6%20V2%20H109%20V5.6%20H102.6%20M114.4%2C8.6%20V2%20H125%20V5.6%20H118.6%20M130.4%2C8.6%20V2%20H141%20V5.6%20H134.6%20M146.4%2C8.6%20V2%20H157%20V5.6%20H150.6%20M162.4%2C8.6%20V2%20H173%20V5.6%20H166.6%20M178.4%2C8.6%20V2%20H189%20V5.6%20H182.6%20M194.4%2C8.6%20V2%20H205%20V5.6%20H198.6%20M210.4%2C8.6%20V2%20H221%20V5.6%20H214.6%20M226.4%2C8.6%20V2%20H237%20V5.6%20H230.6%20M242.4%2C8.6%20V2%20H253%20V5.6%20H246.6%20M258.4%2C8.6%20V2%20H269%20V5.6%20H262.6%20M274.4%2C8.6%20V2%20H285%20V5.6%20H278.6%27%20stroke%3D%27%233B3022%27%20stroke-width%3D%272.6%27%2F%3E%3Cpath%20d%3D%27M0%2C8.6%20H288%27%20stroke%3D%27%23FFFBEE%27%20stroke-width%3D%272.6%27%20opacity%3D%27.5%27%20transform%3D%27translate%280%2C.9%29%27%2F%3E%3Cpath%20d%3D%27M2.4%2C8.6%20V2%20H13%20V5.6%20H6.6%20M18.4%2C8.6%20V2%20H29%20V5.6%20H22.6%20M34.4%2C8.6%20V2%20H45%20V5.6%20H38.6%20M50.4%2C8.6%20V2%20H61%20V5.6%20H54.6%20M66.4%2C8.6%20V2%20H77%20V5.6%20H70.6%20M82.4%2C8.6%20V2%20H93%20V5.6%20H86.6%20M98.4%2C8.6%20V2%20H109%20V5.6%20H102.6%20M114.4%2C8.6%20V2%20H125%20V5.6%20H118.6%20M130.4%2C8.6%20V2%20H141%20V5.6%20H134.6%20M146.4%2C8.6%20V2%20H157%20V5.6%20H150.6%20M162.4%2C8.6%20V2%20H173%20V5.6%20H166.6%20M178.4%2C8.6%20V2%20H189%20V5.6%20H182.6%20M194.4%2C8.6%20V2%20H205%20V5.6%20H198.6%20M210.4%2C8.6%20V2%20H221%20V5.6%20H214.6%20M226.4%2C8.6%20V2%20H237%20V5.6%20H230.6%20M242.4%2C8.6%20V2%20H253%20V5.6%20H246.6%20M258.4%2C8.6%20V2%20H269%20V5.6%20H262.6%20M274.4%2C8.6%20V2%20H285%20V5.6%20H278.6%27%20stroke%3D%27%23FFFBEE%27%20stroke-width%3D%272.6%27%20opacity%3D%27.5%27%20transform%3D%27translate%280%2C.9%29%27%2F%3E%3Cpath%20d%3D%27M0%2C8.6%20H288%27%20stroke%3D%27%23FFF8D8%27%20stroke-width%3D%271.4%27%2F%3E%3Cpath%20d%3D%27M2.4%2C8.6%20V2%20H13%20V5.6%20H6.6%20M18.4%2C8.6%20V2%20H29%20V5.6%20H22.6%20M34.4%2C8.6%20V2%20H45%20V5.6%20H38.6%20M50.4%2C8.6%20V2%20H61%20V5.6%20H54.6%20M66.4%2C8.6%20V2%20H77%20V5.6%20H70.6%20M82.4%2C8.6%20V2%20H93%20V5.6%20H86.6%20M98.4%2C8.6%20V2%20H109%20V5.6%20H102.6%20M114.4%2C8.6%20V2%20H125%20V5.6%20H118.6%20M130.4%2C8.6%20V2%20H141%20V5.6%20H134.6%20M146.4%2C8.6%20V2%20H157%20V5.6%20H150.6%20M162.4%2C8.6%20V2%20H173%20V5.6%20H166.6%20M178.4%2C8.6%20V2%20H189%20V5.6%20H182.6%20M194.4%2C8.6%20V2%20H205%20V5.6%20H198.6%20M210.4%2C8.6%20V2%20H221%20V5.6%20H214.6%20M226.4%2C8.6%20V2%20H237%20V5.6%20H230.6%20M242.4%2C8.6%20V2%20H253%20V5.6%20H246.6%20M258.4%2C8.6%20V2%20H269%20V5.6%20H262.6%20M274.4%2C8.6%20V2%20H285%20V5.6%20H278.6%27%20stroke%3D%27%23FFF8D8%27%20stroke-width%3D%271.4%27%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") repeat-x left center;
    background-size:288px var(--key);
    opacity:0;
    animation:zs-keyflash 9s ease-out infinite;
  }
  @keyframes zs-keyflash{
    0%,61.9%{opacity:0}
    62%     {opacity:1}
    64%     {opacity:.45}
    72%     {opacity:.08}
    80%,100%{opacity:0}
  }



  /* ---- THE STORM ----------------------------------------------------------
     A CLOUD IS LUMPS ON A FLAT BOTTOM. One soft radial was a spotlight, not a
     cloud — a single smooth ellipse is a light pool whatever colour it is, and
     that is what it read as. What identifies a cloud in a strip 18px tall is the
     SILHOUETTE: a bumpy top and a flat, darker underside. So this is five
     overlapping ellipses of different sizes along one line, sitting on a base
     that is deliberately straighter than they are.

     AND IT DOES NOT DRIFT ACROSS THE ROW ANY MORE. A mass sliding past while the
     bolt fires somewhere else is two events, not one — the drift is what made it
     read as a light sweeping through. It now FORMS IN PLACE over the strike
     point and the bolt drops out of its underside, so the storm and the strike
     are the same object. The only motion is internal: two layers easing a few
     pixels against each other, which is what a building cloud actually does.

     IT IS A CEILING, NOT AN OBJECT IN THE ROOM, and that is forced by the row
     rather than chosen. A 148px cloud parked at the strike point was completely
     hidden behind a long name — "Marcinkevičius Patrikas" is 173px and starts at
     x 54, so it covered the whole thing; only the short names showed any weather
     at all. The same fault that moved Runakmenis' wheel: A CENTRED OBJECT NEEDS A
     MIDDLE AND A BOARD ROW DOES NOT HAVE ONE. The clear space here is not in the
     middle, it is the 6px strip along the TOP of the tablet above the letters —
     so the storm is a low ceiling across the whole row with a lumpy underside,
     and the underside is the whole read.

     Ellipse radii are in PIXELS, not percentages, so the lumps keep their size
     whether the row is 353px wide or 962. */
  .zs-cloud{
    position:absolute; z-index:3; pointer-events:none;
    left:var(--cap); right:var(--cap);
    top:calc(var(--key) * .72); height:13px;
    opacity:0;
    animation:zs-gather 9s ease-in-out infinite;
  }
  .zs-cloud::before, .zs-cloud::after{
    content:''; position:absolute; inset:0;
  }
  .zs-cloud::before{
    /* the lit top of the cloud, tiled so the ceiling runs the row's whole width
       at any width: four lumps of different sizes in a 96px tile, which is wide
       enough that the repeat does not read at a glance */
    background:
      radial-gradient(13px 8px at 14px 5px, rgba(206,217,233,.50) 0 58%, transparent 76%),
      radial-gradient(18px 10px at 40px 3px, rgba(217,227,240,.56) 0 56%, transparent 76%),
      radial-gradient(11px 7px at 63px 6px, rgba(198,210,228,.46) 0 58%, transparent 78%),
      radial-gradient(15px 9px at 84px 4px, rgba(188,201,221,.42) 0 58%, transparent 78%);
    background-size:96px 13px;
    animation:zs-roll-a 9s ease-in-out infinite;
  }
  /* the shadowed underside — a cloud that is about to strike is dark where the
     light is not getting through, and that dark edge is most of the read */
  .zs-cloud::after{
    /* THE UNDERSIDE IS THE READ. A cloud about to strike is dark where the light
       is not getting through, and at this size that hanging, uneven dark edge is
       what says "cloud" rather than any lump above it. Offset half a tile from
       the lit layer so the two do not line up. */
    background:
      radial-gradient(16px 7px at 26px 12px, rgba(22,28,38,.72) 0 58%, transparent 80%),
      radial-gradient(12px 6px at 52px 13px, rgba(28,35,46,.62) 0 60%, transparent 82%),
      radial-gradient(19px 8px at 76px 11px, rgba(22,28,38,.66) 0 58%, transparent 80%);
    background-size:96px 13px;
    animation:zs-roll-b 9s ease-in-out infinite;
  }
  @keyframes zs-gather{
    0%      {opacity:0}
    30%     {opacity:.45}
    56%     {opacity:1}
    62%     {opacity:.85}
    76%     {opacity:.35}
    92%,100%{opacity:0}
  }
  @keyframes zs-roll-a{
    0%,100%{transform:translateX(-3px)}
    56%    {transform:translateX(3px)}
  }
  @keyframes zs-roll-b{
    0%,100%{transform:translateX(2px)}
    56%    {transform:translateX(-2px)}
  }

  /* ---- 3 · THE STRIKE ------------------------------------------------------
     Two strokes, the second 40ms after the first. That is the whole difference
     between lightning and a flashing shape: a real flash is a leader followed by
     a return stroke, and the eye reads the pair as alive. `steps(1,end)` because
     this IS an event with a before and an after — the impact-frame grammar,
     which belongs to the sets that fire and not to the sets that pass.

     The bolt ENTERS THE ROW'S OWN TOP EDGE and stops at its bottom. It never
     reaches a neighbour: that ruling came with dropping the Anapus tier and it
     still holds. */
  .zs-bolt{
    /* THE BOLT LEAVES THE CLOUD. It used to span the row's full height from the
       top edge down, which put its head above the cloud rather than inside it —
       the strike and the storm were two things happening at the same moment
       instead of one thing causing another. Its box now starts at the cloud's
       underside and ends at the tablet's floor. */
    /* THE X IS A VARIABLE SO IT CAN MOVE. `--zs-x` is set by perkunas.js once
       per cycle to a fresh random position; the fallback is the old fixed 38%,
       so the frame still works with the module absent or JS off — it just always
       strikes the same place, which is what it did before. */
    position:absolute; left:var(--zs-x, calc(38% - 55px)); width:110px;
    /* the box starts at the cloud's underside and STOPS AT THE TABLET'S FLOOR.
       At 36px tall it ran out through the bottom band and past the frame — a
       bolt that leaves the row is a claim on the neighbour below, which this set
       does not have. 13 + 30 lands exactly on the plate's lower edge. */
    top:calc(var(--key) * .72 + 13px); height:30px;
    z-index:4; pointer-events:none; opacity:0;
    background:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27110%27%20height%3D%2736%27%20viewBox%3D%270%200%20110%2036%27%3E%3Cg%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M58%2C0%20L41%2C15%20L54%2C18%20L34%2C36%27%20stroke%3D%27%23FFFFFF%27%20stroke-width%3D%275.5%27%20opacity%3D%27.30%27%2F%3E%3Cpath%20d%3D%27M58%2C0%20L41%2C15%20L54%2C18%20L34%2C36%27%20stroke%3D%27%23FFF8E0%27%20stroke-width%3D%272.1%27%2F%3E%3Cpath%20d%3D%27M47%2C8%20L30%2C14%20M50%2C18%20L68%2C24%27%20stroke%3D%27%23FFF8E0%27%20stroke-width%3D%271.4%27%20opacity%3D%27.85%27%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") no-repeat center/contain;
    animation:zs-strike 9s steps(1,end) infinite;
  }
  /* the volley's second and third bolts. They are injected always and shown
     only by the set bonus, so a lone frame carries two hidden divs and no
     compositor layers — display, not opacity, the standing rule. */
  .zs-bolt.b2, .zs-bolt.b3{display:none}
  .zs-bolt.b2{left:var(--zs-x2, calc(22% - 55px))}
  .zs-bolt.b3{left:var(--zs-x3, calc(62% - 55px))}
  .zs-idle *{animation-play-state:paused}

  .zs-bolt.two{
    background-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27110%27%20height%3D%2736%27%20viewBox%3D%270%200%20110%2036%27%3E%3Cg%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M58%2C0%20L43%2C14%20L55%2C18%20L37%2C36%27%20stroke%3D%27%23FFFFFF%27%20stroke-width%3D%274%27%20opacity%3D%27.22%27%2F%3E%3Cpath%20d%3D%27M58%2C0%20L43%2C14%20L55%2C18%20L37%2C36%27%20stroke%3D%27%23FFFDF2%27%20stroke-width%3D%271.5%27%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
    animation:zs-strike2 9s steps(1,end) infinite;
  }
  @keyframes zs-strike{
    0%,61.9%{opacity:0}
    62%     {opacity:1}     /* the leader, ~90ms */
    63%,100%{opacity:0}
  }
  @keyframes zs-strike2{
    0%,62.4%{opacity:0}
    62.5%   {opacity:1}     /* the return stroke, 40ms behind */
    63.4%,100%{opacity:0}
  }

  /* THE CRACKS LIGHT FROM THE INSIDE. This is the layer that makes the marble
     and the lightning one object instead of two. It fades rather than cuts,
     because a discharge is instant and cooling is not. */
  /* The bloom sits INSIDE the tablet's rectangle, not the row's, so nothing it
     does can reach a neighbour or wash the money: its right edge stops well
     short of the figure column. */
  .zs-lit{
    position:absolute; z-index:4; pointer-events:none; opacity:0;
    top:calc(var(--key) * .72); bottom:calc(var(--key) * .72);
    left:calc(var(--cap) + 3px); right:calc(var(--cap) + 3px);
    /* THE FALLOFF PROTECTS THE MONEY, NOT THE BOX. The first version ended the
       element at 38% so the bloom could not reach the figures — but a radial
       centred on its own right edge is at full strength when the box stops, and
       it left a hard vertical cut down the row. The same fault the aurora had.
       Now the layer spans the whole tablet and the light is contained by its
       RADIUS: 26% horizontal from an origin at 38% dies by 64%, and the net
       column starts at 70%. */
    background:radial-gradient(26% 130% at 38% 50%,
      rgba(255,248,214,.72) 0%, rgba(255,236,160,.34) 34%,
      rgba(240,206,90,.12) 62%, transparent 82%);
    animation:zs-cool 9s ease-out infinite;
  }
  @keyframes zs-cool{
    0%,61.9%{opacity:0}
    62%     {opacity:.95}
    64%     {opacity:.55}
    74%     {opacity:.10}
    82%,100%{opacity:0}
  }

  /* ---- 4 · THE CAPITALS ----------------------------------------------------
     END BLOCKS, NOT FOUR CORNERS, and the aspect ratio decides it exactly as it
     did for Runakmenis: a board row is 12∶1 and the two corners on a 57px edge
     are 57px apart whatever size the ornament is. A column at each end is also
     what the reference actually shows, and it is what a Greek frame IS — the
     entablature runs between two supports.

     Drawn once and mirrored with ONE transform attribute for the right-hand
     end. Egiptas lost a day to a mirror written as two operations, where
     `translate(-CX)` inside `scale(-1,1)` about CX maps to 2CX - x and lands
     the copy back on the original. */
  .zs-cap{
    /* z 4, BEHIND THE BANDS. The piers are painted after the bands in the markup
       and were at the same z-index, so the archivolt was drawn ON TOP of the
       meander and simply stopped there — a gold hook lying across the band
       instead of a moulding running under it. That is what "not connected"
       was. At z 4 the curve disappears under the stone, the way a real moulding
       dies into the course above it. */
    position:absolute; top:0; bottom:0; z-index:4; pointer-events:none;
    width:calc(var(--cap) + 22px);   /* the pier, plus the arch's reach over the corner */
    background:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%2735%27%20height%3D%2757%27%20viewBox%3D%270%200%2035%2057%27%3E%0A%3Cdefs%3E%0A%20%3ClinearGradient%20id%3D%27pier%27%20x1%3D%270%27%20y1%3D%270%27%20x2%3D%271%27%20y2%3D%270%27%3E%0A%20%20%3Cstop%20offset%3D%270%27%20stop-color%3D%27%239B9280%27%2F%3E%3Cstop%20offset%3D%27.22%27%20stop-color%3D%27%23D8D0BC%27%2F%3E%0A%20%20%3Cstop%20offset%3D%27.48%27%20stop-color%3D%27%23EDE7DA%27%2F%3E%3Cstop%20offset%3D%27.74%27%20stop-color%3D%27%23D2C9B5%27%2F%3E%0A%20%20%3Cstop%20offset%3D%271%27%20stop-color%3D%27%23948B7A%27%2F%3E%0A%20%3C%2FlinearGradient%3E%0A%20%3ClinearGradient%20id%3D%27slab%27%20x1%3D%270%27%20y1%3D%270%27%20x2%3D%271%27%20y2%3D%270%27%3E%0A%20%20%3Cstop%20offset%3D%270%27%20stop-color%3D%27%23A69D8A%27%2F%3E%3Cstop%20offset%3D%27.4%27%20stop-color%3D%27%23EFE9DC%27%2F%3E%0A%20%20%3Cstop%20offset%3D%27.78%27%20stop-color%3D%27%23CFC7B3%27%2F%3E%3Cstop%20offset%3D%271%27%20stop-color%3D%27%238E8574%27%2F%3E%0A%20%3C%2FlinearGradient%3E%0A%20%3ClinearGradient%20id%3D%27spanG%27%20x1%3D%270%27%20y1%3D%270%27%20x2%3D%270%27%20y2%3D%271%27%3E%0A%20%20%3Cstop%20offset%3D%270%27%20stop-color%3D%27%23E7E1D3%27%2F%3E%3Cstop%20offset%3D%271%27%20stop-color%3D%27%23CBC2AD%27%2F%3E%0A%20%3C%2FlinearGradient%3E%0A%3C%2Fdefs%3E%0A%3C%21--%20the%20spandrel%3A%20plain%20marble%20filling%20the%20corner%20between%20the%20band%20above%20and%0A%20%20%20%20%20the%20arched%20opening%20below.%20NO%20gold%20on%20it%20%E2%80%94%20the%20gold%20belongs%20to%20the%20band%20and%0A%20%20%20%20%20to%20the%20tablet%27s%20rim%2C%20and%20a%20third%20gold%20line%20here%20is%20what%20made%20the%20corner%0A%20%20%20%20%20read%20as%20two%20mouldings%20with%20a%20gap%20between%20them.%20--%3E%0A%3Cpath%20d%3D%27M0%2C0%20H35%20V9%20C24%2C9%2015%2C14%2013.6%2C23%20H0%20Z%27%20fill%3D%27url%28%23spanG%29%27%2F%3E%0A%3Cpath%20d%3D%27M35%2C9%20C24%2C9%2015%2C14%2013.6%2C23%27%20fill%3D%27none%27%20stroke%3D%27%236B6353%27%20stroke-width%3D%27.9%27%20opacity%3D%27.5%27%2F%3E%0A%3Crect%20x%3D%270%27%20y%3D%270%27%20width%3D%2713%27%20height%3D%273.6%27%20fill%3D%27url%28%23slab%29%27%2F%3E%0A%3Crect%20x%3D%270.6%27%20y%3D%273.6%27%20width%3D%2711.8%27%20height%3D%271.1%27%20fill%3D%27%23D4A93A%27%2F%3E%0A%3Crect%20x%3D%271.6%27%20y%3D%274.7%27%20width%3D%279.8%27%20height%3D%2712.9%27%20fill%3D%27url%28%23pier%29%27%2F%3E%0A%3Crect%20x%3D%270.4%27%20y%3D%2717.6%27%20width%3D%2712.2%27%20height%3D%273%27%20fill%3D%27url%28%23slab%29%27%2F%3E%0A%3Crect%20x%3D%270.4%27%20y%3D%2720.6%27%20width%3D%2712.2%27%20height%3D%271%27%20fill%3D%27%23D4A93A%27%2F%3E%0A%3Crect%20x%3D%271.6%27%20y%3D%2721.6%27%20width%3D%279.8%27%20height%3D%2726.8%27%20fill%3D%27url%28%23pier%29%27%2F%3E%0A%3Cg%20opacity%3D%27.42%27%3E%0A%20%3Cpath%20d%3D%27M5%2C23%20V47%27%20stroke%3D%27%236F6757%27%20stroke-width%3D%27.7%27%2F%3E%0A%20%3Cpath%20d%3D%27M8.6%2C23%20V47%27%20stroke%3D%27%236F6757%27%20stroke-width%3D%27.7%27%2F%3E%0A%20%3Cpath%20d%3D%27M5.8%2C23%20V47%27%20stroke%3D%27%23FFFDF4%27%20stroke-width%3D%27.6%27%2F%3E%0A%20%3Cpath%20d%3D%27M9.4%2C23%20V47%27%20stroke%3D%27%23FFFDF4%27%20stroke-width%3D%27.6%27%2F%3E%0A%3C%2Fg%3E%0A%3Crect%20x%3D%270.6%27%20y%3D%2748.4%27%20width%3D%2711.8%27%20height%3D%271.1%27%20fill%3D%27%23D4A93A%27%2F%3E%0A%3Crect%20x%3D%270%27%20y%3D%2749.5%27%20width%3D%2713%27%20height%3D%277.5%27%20fill%3D%27url%28%23slab%29%27%2F%3E%0A%3Cg%20stroke%3D%27%235F5849%27%20stroke-width%3D%27.5%27%20opacity%3D%27.55%27%20fill%3D%27none%27%3E%0A%20%3Cpath%20d%3D%27M0%2C3.6%20H13%20M0.4%2C17.6%20H12.6%20M0%2C52.6%20H13%27%2F%3E%0A%3C%2Fg%3E%0A%3Cpath%20d%3D%27M0%2C0%20V57%27%20stroke%3D%27%235F5849%27%20stroke-width%3D%27.8%27%20opacity%3D%27.5%27%20fill%3D%27none%27%2F%3E%0A%3C%2Fsvg%3E") no-repeat left center/auto 100%;
    /* NO filter HERE, and this is the rule Runakmenis wrote and this frame
       quietly broke: A STATIC `filter` IS A PERMANENT BUFFER. `drop-shadow`
       renders this element — a 35×57 SVG full of gradients — into an offscreen
       surface and keeps it there, and re-renders it whenever anything in the row
       moves, which on this frame is the clouds, both bolts and the key flash,
       for ever. Two piers per wearer × nine wearers is eighteen permanent
       buffers before a single thing animates, which is exactly the cost that
       got the same property deleted off `.rn`.
       The shadow the pier needs is a dark edge where it meets the tablet, so it
       is PAINTED rather than computed: one gradient layer under the SVG, free. */
  }
  .zs-cap::after{
    /* starts at 40% — the spandrel fills the corner above that and is itself the
       thing casting into the opening, so a dark strip up there would lie across
       the marble instead of beside it. */
    content:''; position:absolute; top:40%; bottom:0; left:var(--cap);
    width:4px; pointer-events:none;
    background:linear-gradient(90deg, rgba(0,0,0,.42), rgba(0,0,0,0));
  }
  .zs-cap.l{left:0}
  .zs-cap.r{right:0; transform:scaleX(-1)}
  /* A FIXED scale, baked in once. Mirroring the right-hand column means the two
     cannot drift apart by construction, and it puts the lit side of each one
     facing the middle of the row — which is where the light in this frame comes
     from when the bolt lands. Egiptas lost a day to a mirror written as two
     operations instead of one. */



  /* ---- 5 · THE GLASS AND THE LEDGER SLOT -----------------------------------
     The panel must CONTAIN the name block. On the app's row the name and its
     sub-line are 34.8px together, and a panel the name overflows is not a
     panel — that is the correction that cost the most on Runakmenis. */
  .zs-panel{
    position:absolute; z-index:3;
    /* THE BRONZE STARTS EXACTLY AT THE PIER, not three pixels in. That gap was
       dark slab showing between the stone and the tablet, and at 3px it read as
       the pier being a separate thing parked beside the frame rather than the
       frame's own edge — a large part of what "not connected" meant. A plate let
       into stone touches the stone it is let into. */
    inset:calc(var(--key) * .72) var(--cap);
    border-radius:15px 15px 4px 4px;   /* the arch IS the opening's corner */
    /* Patinated bronze: a green-black ground, a warm bevel at the top where a
       cast plate catches the light, and a thin gold rim where it is let into the
       stone. */
    background:
      linear-gradient(180deg, rgba(120,150,120,.10) 0%, rgba(0,0,0,0) 40%),
      linear-gradient(180deg, #2A2E26 0%, #191C16 55%, #22261D 100%);
    box-shadow:
      /* GOLD ON THE TOP AND BOTTOM EDGES ONLY, NOT A RING. A full inset ring put
         a vertical gold line down the tablet's sides — between the rank numeral
         and the pier at one end and between the money and the pier at the other
         — and those two lines read as the frame having an extra edge where it
         already had one: the pier IS the side. An inset shadow with a vertical
         offset and no spread follows the border-radius, so the gold runs along
         the arched top and thins away exactly where the curve turns vertical,
         which is where the stone takes over. */
      inset 0 1.2px 0 rgba(212,169,58,.80),
      inset 0 -1.2px 0 rgba(212,169,58,.55),
      inset 0 1px 0 rgba(226,206,150,.30),
      inset 0 -8px 14px rgba(0,0,0,.45),
      0 1px 0 rgba(255,255,255,.35);
  }
  /* one recess under the WHOLE money group — three columns above the breakpoint,
     one below it. Runakmenis shipped this hard-coded at the phone figure and the
     two desktop columns sat on bare stone. */
  .zs-slot{
    position:absolute; z-index:3; pointer-events:none;
    top:50%; height:calc(var(--h) * .42); transform:translateY(-50%);
    right:calc(var(--c-pad) - 8px);
    width:calc(var(--c-money) + 14px);
    border-radius:3px;
    background:linear-gradient(180deg,rgba(0,0,0,.34),rgba(0,0,0,.14));
    box-shadow: inset 0 1px 2px rgba(0,0,0,.6), inset 0 -1px 0 rgba(255,248,224,.10);
    -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 14%,#000 100%);
            mask-image:linear-gradient(90deg,transparent 0,#000 14%,#000 100%);
  }

  @media (max-width:700px){
    .zs{--c-rank:30px; --c-money:92px}
  }

  @media (prefers-reduced-motion:reduce){
    .zs-bolt, .zs-lit, .zs-cloud{display:none !important}
    .zs-key::before{animation:none; opacity:0}
  }


  /* ==== DZEUSAS · SURFACE · AIGIDĖ (the aegis) · RARE ========================
     Zeus's shield. In the Iliad it is fringed and scaled, and on a cast bronze
     tablet that is a scale relief — which is also the honest answer to what a
     SURFACE is for in this project: a ground that is there when the frame is,
     and almost nothing on its own. That is what a rare should be.

     SCALES ARE 11px WIDE, above the measured 9px floor, and each is TWO arcs —
     a dark seat and a lit lip a pixel above it — because at this size relief is
     entirely about where the light sits and never about the outline. A single
     stroke would have read as a net.

     ONE CONTINUOUS ANIMATION AND NO EVENT, which is the ladder's definition of a
     rare: the light crosses the scales once every 24 seconds and that is all it
     ever does. The frame fires; the surface is weather-beaten metal.
  ========================================================================= */
  /* THE CLASS GOES ON THE ROW AND THE LAYER IS A CHILD, and getting this wrong
     is a bug this project has now hit twice. `cosmeticClasses()` writes
     `sf-aigide` onto the row itself, so a rule like `.sf-aigide{position:absolute;
     inset:0}` makes THE ROW absolutely positioned — it leaves the flow, stretches
     to its container and every row after it piles up underneath. Runakmenis did
     exactly this with `.sf-raiziniai` on the comparison board. The row class is a
     GATE; the paint belongs to an injected child. */
  .dz-aegis{display:none}
  .sf-aigide .dz-aegis{
    display:block;
    position:absolute; inset:0; z-index:1; pointer-events:none;
    border-radius:inherit;
    /* AND IT CLIPS ITS OWN LIGHT. The sheen below is a band 38% of this box
       wide that travels from -120% to 300%, so for most of its 24 seconds it
       is somewhere outside this element — and with nothing clipping it, that
       is somewhere on the PAGE: it entered from the left of the card and slid
       across the felt beside it. Every ancestor that could have caught it is
       deliberately overflow:visible, because several frames resolve their own
       layers against the row. So the surface clips its own light. */
    overflow:hidden;
    background:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%2744%27%20height%3D%2724%27%20viewBox%3D%270%200%2044%2024%27%3E%3Cg%20fill%3D%27none%27%20stroke-linecap%3D%27round%27%3E%3Cpath%20d%3D%27M-11%2C8%20C-11%2C2.6%200%2C2.6%200%2C8%20M0%2C8%20C0%2C2.6%2011%2C2.6%2011%2C8%20M11%2C8%20C11%2C2.6%2022%2C2.6%2022%2C8%20M22%2C8%20C22%2C2.6%2033%2C2.6%2033%2C8%20M33%2C8%20C33%2C2.6%2044%2C2.6%2044%2C8%20M-5.5%2C16%20C-5.5%2C10.6%205.5%2C10.6%205.5%2C16%20M5.5%2C16%20C5.5%2C10.6%2016.5%2C10.6%2016.5%2C16%20M16.5%2C16%20C16.5%2C10.6%2027.5%2C10.6%2027.5%2C16%20M27.5%2C16%20C27.5%2C10.6%2038.5%2C10.6%2038.5%2C16%20M38.5%2C16%20C38.5%2C10.6%2049.5%2C10.6%2049.5%2C16%20M-11%2C24%20C-11%2C18.6%200%2C18.6%200%2C24%20M0%2C24%20C0%2C18.6%2011%2C18.6%2011%2C24%20M11%2C24%20C11%2C18.6%2022%2C18.6%2022%2C24%20M22%2C24%20C22%2C18.6%2033%2C18.6%2033%2C24%20M33%2C24%20C33%2C18.6%2044%2C18.6%2044%2C24%27%20stroke%3D%27%230C1410%27%20stroke-width%3D%271.5%27%20opacity%3D%27.60%27%2F%3E%3Cpath%20d%3D%27M-11%2C8%20C-11%2C2.6%200%2C2.6%200%2C8%20M0%2C8%20C0%2C2.6%2011%2C2.6%2011%2C8%20M11%2C8%20C11%2C2.6%2022%2C2.6%2022%2C8%20M22%2C8%20C22%2C2.6%2033%2C2.6%2033%2C8%20M33%2C8%20C33%2C2.6%2044%2C2.6%2044%2C8%20M-5.5%2C16%20C-5.5%2C10.6%205.5%2C10.6%205.5%2C16%20M5.5%2C16%20C5.5%2C10.6%2016.5%2C10.6%2016.5%2C16%20M16.5%2C16%20C16.5%2C10.6%2027.5%2C10.6%2027.5%2C16%20M27.5%2C16%20C27.5%2C10.6%2038.5%2C10.6%2038.5%2C16%20M38.5%2C16%20C38.5%2C10.6%2049.5%2C10.6%2049.5%2C16%20M-11%2C24%20C-11%2C18.6%200%2C18.6%200%2C24%20M0%2C24%20C0%2C18.6%2011%2C18.6%2011%2C24%20M11%2C24%20C11%2C18.6%2022%2C18.6%2022%2C24%20M22%2C24%20C22%2C18.6%2033%2C18.6%2033%2C24%20M33%2C24%20C33%2C18.6%2044%2C18.6%2044%2C24%27%20stroke%3D%27%239DBFA6%27%20stroke-width%3D%27.9%27%20opacity%3D%27.26%27%20transform%3D%27translate%280%2C-1.1%29%27%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") repeat left top;
    background-size:44px 24px;
    /* .38, not .55. At .55 the relief read as a pale net laid over the plate and
       it competed with the name — and a RARE SURFACE THAT COMPETES WITH THE TEXT
       IS THE ONE THING A SURFACE MUST NEVER DO. Cast bronze scales are mostly
       shadow with a thin catch of light along each lip; that is what .38 with a
       dark seat and a .26 lip gives. */
    opacity:.38;
  }
  /* worn inside Perkūnsvaidis it takes the tablet's shape and sits on the plate */
  .zs.sf-aigide .dz-aegis{
    inset:calc(var(--key) * .72) var(--cap);
    border-radius:15px 15px 4px 4px;
    z-index:3;
  }
  /* THE LIGHT ON THE METAL. One pale band crossing the relief — `transform`
     only, so it is composited and never repaints, and the band keeps a constant
     width and lean because a skew or scale that CHANGES re-rasterises the layer
     on every frame. */
  .sf-aigide .dz-aegis::after{
    content:''; position:absolute; top:0; bottom:0; left:0; width:38%;
    border-radius:inherit;
    background:linear-gradient(100deg,
      transparent 0%, rgba(206,222,236,.10) 34%, rgba(226,238,248,.16) 50%,
      rgba(206,222,236,.09) 66%, transparent 100%);
    transform:translateX(-120%);
    animation:ag-sheen 24s linear infinite;
  }
  @keyframes ag-sheen{
    0%      {transform:translateX(-120%)}
    46%     {transform:translateX(300%)}
    46.01%,100%{transform:translateX(-120%)}
  }
  @media (prefers-reduced-motion:reduce){
    .sf-aigide .dz-aegis::after{animation:none; opacity:0}
  }

  /* A SURFACE WORN WITHOUT ITS FRAME NEEDS A CONTAINING BLOCK. `.dz-aegis` is
     `position:absolute; inset:0`, which is fine inside `.zs` (relative) and
     resolves against a distant ancestor on a plain row — painting the scales
     across the whole screen. Found by putting the piece in a price list on its
     own. The row class is still only a gate: `position:relative` does not take
     the row out of the flow, which is what the absolute trap did. */
  .sf-aigide{position:relative}

  /* ==== DZEUSAS · NAMEPLATE · KAPITALĖS (the capitals) · EPIC ================
     Chosen 2026-09-11 after twelve candidates. The eleven before it all answered
     the same question — WHAT ARE THE LETTERS MADE OF — with marble, bronze,
     silver, gold, patina, a scorch, a laurel, a filament, a cut. This one does
     not answer that question at all. It changes HOW THE NAME IS SET.

     A Greek inscription is recognisable across a room before a single letter is
     legible, and not because of its material: it is capitals, tracked, even in
     weight, with no descenders. That is the one thing on this row that makes a
     passer-by say "Greek" without being told, and it is typographic rather than
     decorative — which is why it is the first candidate that did not read as a
     twelfth costume for the same idea.

     THE EVENT IS THE MASON. A hard-edged light crosses the line left to right,
     the way a chisel works along an inscription, and the gold in it is the
     frame's own gold, so the name is made of the same material as the meander
     and the tablet's rim.

     THREE MEASUREMENTS DECIDED THE SETTING, none of them a matter of taste.

     1 · TRACKING DOES NOT FIT AT FULL SIZE. At 390px the name column is 210px
         and `.cell-name` is `overflow:hidden` — a name that stops fitting is not
         wrapped, it is CUT, with no ellipsis and no warning. The longest name on
         the roster, "Marcinkevičius Patrikas", measures 173px lowercase and
         202px in capitals with NO tracking at all: capitals alone cost 29 of a
         37px budget. At .14em, as first drawn, it is 243px — clipped by 33.
         The way out is the classic typographic trade: BUY THE TRACKING WITH
         SIZE. .90em at .10em tracking lands at 208px, inside the column.

     2 · A NAMEPLATE MUST NOT CHANGE ITS ROW'S HEIGHT, and .95em did — 56.8px
         against a plain row's 57.8. Any font-size under 1em has to pay the line
         box back so that font-size × line-height stays 18.85px: .90 × 1.611.
         AND IT MUST BE WRITTEN AT `.cell-name .np-x` SPECIFICITY, because
         `.cell-name .np{line-height:1.45}` outranks a bare class and the
         compensation is silently lost. Same cascade trap as Stela's panel width.

     3 · IT COSTS NOTHING TO READ, which none of the other eleven could claim.
         Measured properly — only pixels above the ground, body at the 35th
         percentile of those — a plain lowercase name is 13.7:1 peak / 6.4:1
         body at 2.45% ink coverage. This is 13.1 / 6.4 at 3.26%. A THIRD MORE
         INK ON THE ROW AT THE SAME CONTRAST.
  ========================================================================= */

  /* INLINE-BLOCK, SO THE PAINT BOX IS THE NAME AND NOT THE COLUMN. The name cell
     is a 210px `1fr` track whatever the name is, so on a bare span the chisel
     crosses a 210px box while "Titas" occupies the first 46 of it — the light
     spends most of its travel on empty felt and the short names barely get lit.
     Third time a box-model default has cost this set an effect (Lauras' wreath
     floated beside short names, Įskilimas' cracks tiled past them).
     `vertical-align:top` is not decoration either: `baseline` re-creates
     Runakmenis' descender gap and `middle` makes the line box a pixel taller.
     In `.zs` the cell is a column flex container, so the item's cross size is
     fit-content there too — both grounds shrink-wrap. */
  .cell-name .np-kapitales, .np-kapitales{
    display:inline-block; vertical-align:top;
    text-transform:uppercase;
    font-weight:600;          /* caps at 11.7px have thin strokes; 500 measured
                                 visibly lighter than the plain row */
    font-size:.90em;
    line-height:1.611;        /* .90 × 1.611 = 1.45. The row does not move. */
    letter-spacing:.10em;
    color:#EFE7D2;
    text-shadow:0 1px 0 rgba(0,0,0,.55);
  }

  /* THE CHISEL. Cream, a hard-edged white-and-gold cut, cream again — hard
     stops, because a mason's light has an edge and a glow does not. */
  @supports ((-webkit-background-clip:text) or (background-clip:text)){
    .cell-name .np-kapitales, .np-kapitales{
      color:transparent; -webkit-text-fill-color:transparent;
      background-image:linear-gradient(100deg,
        #EFE7D2 0 40%,
        #FFF6DC 40% 45%,
        #FFE9A8 45% 49%,
        #FFFDF2 49% 53%,
        #EFE7D2 53% 100%);
      background-size:260% 100%; background-repeat:no-repeat;
      background-position:88% 0;
      -webkit-background-clip:text; background-clip:text;
      animation:kp-cut 9s linear infinite;
    }
  }

  /* TWO RULES ARE BURIED IN THOSE SIX LINES AND BOTH COST A ROUND.

     THE SWEEP MUST STAY INSIDE 0%–100%. With `no-repeat` and a 260%-wide image,
     `background-position:130%` puts the image's right edge at .52 of the box and
     the rest of the line has NO BACKGROUND AT ALL — with
     `-webkit-text-fill-color:transparent` those letters render as HOLES showing
     the plate through them. It looked exactly like a sweep that dims half the
     name, which is the one thing this piece was built not to do. At 100% the
     image covers the box with the band off to the left; at 0% it covers the box
     with the band off to the right.

     AND THE LIGHT IS BRIGHTER THAN THE BASE, NEVER DARKER. Every earlier sweep
     on this set lit part of the name by dimming the rest. A band that only ever
     adds cannot make a nameplate harder to read than a plain row.

     LINEAR, NOT `steps()`. The stepped pieces in this project (Pašvaistė,
     Marmuras, Žalvaris) use 48–120 steps and step because a gradient behind
     `background-clip:text` repaints every glyph on every frame. This shipped at
     steps(16) — a 180ms jump across a 2.9s sweep — and the glint hopped from
     letter to letter instead of crossing them. SAVING WORK IS NOT THE SAME AS
     BEING VISIBLE. The repaints are affordable because they run on one short
     text run, for 2.9s of every 9, and only while the row is on screen. */
  /* THE SWEEP'S USEFUL RANGE IS 88%–2%, NOT 100%–0%, AND THAT IS ARITHMETIC.
     With a 260%-wide image and the band at 40–53% of it, the band's right edge
     only reaches the left of the box at background-position 86%: everything
     between 100% and 86% is the light travelling somewhere off-screen. On the
     2.0s answer that was 330ms of nothing after the strike — the 340ms delay
     silently became 670ms, which is no longer a gap anybody has counted. */
  @keyframes kp-cut{
    0%,   30%{background-position:88% 0}
    62%     {background-position:2% 0}
    62.01%,100%{background-position:88% 0}
  }

  @media (prefers-reduced-motion:reduce){
    .np-kapitales{animation:none; background-position:88% 0}
  }

  /* ==== DZEUSAS · SET BONUS · PERKŪNIJA (the thunderstorm) ===================
     Gated `.fr-perkunsvaidis.sf-aigide:has(.np-kapitales)`. Frame and surface
     sit on the row, the nameplate on the name span inside it — views.js uses two
     helpers landing on two elements, so `:has()` is forced. Gated on `display`
     and on retargeted animations, never on opacity: an incomplete set paints
     nothing extra and pays for nothing.

     ONE BOLT IS LIGHTNING. THREE IN HALF A SECOND IS A STORM. Worn alone the
     frame strikes once per cycle, somewhere different each time. Worn complete
     the single strike becomes a volley: three bolts across the row inside 470ms,
     each at its own random spot.

     WHY THIS AND NOT ATSAKAS, which was drawn first and thrown out. Atsakas was
     the dedicatory-stele reading — the bolt aimed at the head of the name, the
     aegis ringing, and the letters cut 340ms behind it, Griausmas' delay finally
     spent on a light instead of a shake. Its whole event was a change in WHEN
     things happen, and **A PLAYER WHO HAS NEVER SEEN THE PIECES APART CANNOT SEE
     A DELAY.** That is a new rule and it is the sharpest one this set has
     produced: A SET BONUS HAS TO BE VISIBLE COLD. Runakmenis' Raštas is — the
     reading leaves the band and crosses into the name. Three flashes where there
     was one is. A retiming is not.

     AND THE OBJECTION I RAISED AGAINST PERKŪNIJA LAST TIME WAS SIMPLY WRONG.
     It was written for Žaibo vardas, the filament, and I argued it could not
     carry Kapitalės because "a chisel does not stutter three times in half a
     second". A CHISEL IS STRUCK. A mason does not draw a line, he advances it in
     blows, and three blows is exactly what cutting a letter looks like. The
     nameplate's leg is not merely rescued by the volley — it is better under it
     than it is alone.

     THE BEATS, on the frame's own nine seconds:
       0.00 – 5.04s   the storm gathers, unchanged
       5.58s          bolt one   · the cut jumps to a third of the name
       5.78s          bolt two   · to two thirds
       6.05s          bolt three · the name is through
       6.05 – 8.3s    the bronze cools, the gilding settles, the scales fall back
       8.3 – 9.00s    still

     NOTHING IS INJECTED AND NO COMPOSITOR LAYER IS ADDED. The second and third
     bolts are already in the markup and already aimed by perkunas.js; every rule
     below either reveals something that is already there or retargets a layer
     one of the three pieces already paints. That is what "change what a piece
     does" costs when it is done properly, as against Smūgis, which was a fourth
     object with no owner.
  ========================================================================= */

  /* --- 1 · THE VOLLEY -------------------------------------------------------
     Single strokes rather than leader-and-return pairs: a secondary stroke in a
     real volley is dimmer, and the eye is counting three flashes, not six.
     62% is the first strike. +2.2% is 200ms, +5.2% is 470ms — close enough
     together to read as one event, far enough apart to be counted. NEGATIVE
     delays, because a positive one would push the first firing past the end of
     the cycle on the very first pass. */
  .fr-perkunsvaidis.sf-aigide:has(.np-kapitales) .zs-bolt.b2,
  .fr-perkunsvaidis.sf-aigide:has(.np-kapitales) .zs-bolt.b3{
    display:block;
    animation:zs-strike 9s steps(1,end) infinite;
    opacity:0;
  }
  .fr-perkunsvaidis.sf-aigide:has(.np-kapitales) .zs-bolt.b2{animation-delay:-8.802s}
  .fr-perkunsvaidis.sf-aigide:has(.np-kapitales) .zs-bolt.b3{animation-delay:-8.532s}

  /* --- 2 · THE BRONZE IS HIT THREE TIMES ------------------------------------
     The bloom and the gilding answer each bolt instead of once. Same layers, a
     different rhythm — which is precisely what "change what a piece does" means
     as opposed to "add a layer". */
  .fr-perkunsvaidis.sf-aigide:has(.np-kapitales) .zs-lit{
    animation:dz-cool3 9s ease-out infinite;
  }
  @keyframes dz-cool3{
    0%,61.9%{opacity:0}
    62%     {opacity:.95}
    63.6%   {opacity:.42}
    64.2%   {opacity:.90}
    66.0%   {opacity:.38}
    67.2%   {opacity:1}
    70%     {opacity:.45}
    78%     {opacity:.12}
    86%,100%{opacity:0}
  }
  .fr-perkunsvaidis.sf-aigide:has(.np-kapitales) .zs-key::before{
    animation:dz-key3 9s ease-out infinite;
  }
  @keyframes dz-key3{
    0%,61.9%{opacity:0}
    62%     {opacity:1}
    63.4%   {opacity:.25}
    64.2%   {opacity:.9}
    66.2%   {opacity:.2}
    67.2%   {opacity:1}
    70%     {opacity:.3}
    80%,100%{opacity:0}
  }

  /* --- 3 · THE SHIELD IS STRUCK, NOT LIT ------------------------------------
     Worn alone the aegis has one slow light every 24 seconds and no event at
     all, which is the ladder's definition of a rare. Under the volley the relief
     lifts three times, so the metal is visibly being HIT rather than merely lit.
     The whole shield answers at once — not a band sliding along it, which is
     what Smūgis was and why it went: A SHOCK FRONT THAT IS WIDE AND DIM
     DISAPPEARS INTO THE TEXTURE IT CROSSES. */
  .fr-perkunsvaidis.sf-aigide:has(.np-kapitales) .dz-aegis{
    animation:dz-relief3 9s ease-out infinite;
  }
  @keyframes dz-relief3{
    0%,61.9%{opacity:.38}
    62%     {opacity:.62}
    63.8%   {opacity:.44}
    64.2%   {opacity:.60}
    66.4%   {opacity:.42}
    67.2%   {opacity:.66}
    74%     {opacity:.46}
    86%,100%{opacity:.38}
  }

  /* --- 4 · THE NAME IS CUT IN THREE BLOWS ----------------------------------
     THE WHOLE REASON THIS BONUS SURVIVES THE CHANGE OF NAMEPLATE. Worn alone,
     Kapitalės' chisel is a light travelling the line continuously — a mason
     working steadily. Under a storm the line is not worked, it is STRUCK: the
     cut leaps a third of the way along on each bolt and stops dead between
     them, and by the third flash the name is through.

     THE CONSTRUCTION CHANGES, NOT JUST THE TIMING, and that is the difference
     between this and Atsakas. Alone the image is a BAND that crosses and leaves.
     Here it is an EDGE: everything behind the chisel point is cut and stays cut,
     everything ahead of it is untouched stone, and the point itself is the hot
     gold of the frame's own gilding. That is legible with no memory of what the
     piece does alone — you can see a name being carved.

     Two stops behind and two ahead, on a 200%-wide image, so the split sits at
     `1 - p/100` of the box: p=100 nothing cut, p=0 all of it. Three blows land
     at 66.7, 33.3 and 0, each held until the next — the holds are what make them
     BLOWS rather than an eased advance.

     AND THE CUT SIDE IS BARELY BRIGHTER THAN THE UNCUT SIDE (#F7F0DC against
     #EFE7D2). It has to be: the state has to reset at the end of the cycle, and
     a big value difference would snap back visibly. The event is the hot point
     jumping; the residue behind it is almost nothing, which is also what a fresh
     cut in old stone actually looks like. Never darker than the base, on either
     side of the edge — the rule the whole nameplate is built on. */
  .fr-perkunsvaidis.sf-aigide:has(.np-kapitales) .np-kapitales{
    background-image:linear-gradient(100deg,
      #F7F0DC 0 47%,
      #FFFDF2 47% 49%,
      #FFE9A8 49% 50%,
      #EFE7D2 50% 100%);
    background-size:200% 100%;
    animation:dz-blows 9s linear infinite,
              dz-spark 9s ease-out infinite;
  }

  /* AND THE NAME TAKES EACH BLOW, not just the chisel point. Measured: the hot
     point peaks at luminance 253 against the letters' own 231 — twenty-two
     levels, which is right for a mason working quietly and far too polite for a
     bolt landing. So a short gold glow on every flash, on TEXT-SHADOW rather
     than on a layer: WHEN THE THING THAT GLOWS IS TEXT, THE GLOW BELONGS TO THE
     TEXT — a box behind it reads as a pale rectangle somebody forgot to delete,
     and it costs a compositor layer per wearer.
     Kept tighter than the gaps between the letters (3px on .10em tracking at
     11.7px): A GLOW WIDER THAN THOSE GAPS STOPS BEING LETTER-SHAPED. And this
     one is gated, so it is never seen on green felt — the plain-row test that
     forced Žaibo vardas' halo down does not apply to it.
     Different property from dz-blows, so the two compose instead of the later
     one simply winning. */
  @keyframes dz-spark{
    0%,   61.9%{text-shadow:0 1px 0 rgba(0,0,0,.55)}
    62%       {text-shadow:0 1px 0 rgba(0,0,0,.55), 0 0 3px rgba(255,246,214,.95),
                           0 0 6px rgba(255,228,150,.35)}
    63.4%     {text-shadow:0 1px 0 rgba(0,0,0,.55), 0 0 2px rgba(255,246,214,.30)}
    64.2%     {text-shadow:0 1px 0 rgba(0,0,0,.55), 0 0 3px rgba(255,246,214,.95),
                           0 0 6px rgba(255,228,150,.35)}
    66.2%     {text-shadow:0 1px 0 rgba(0,0,0,.55), 0 0 2px rgba(255,246,214,.30)}
    67.2%     {text-shadow:0 1px 0 rgba(0,0,0,.55), 0 0 3.4px rgba(255,250,230,1),
                           0 0 7px rgba(255,228,150,.42)}
    74%       {text-shadow:0 1px 0 rgba(0,0,0,.55), 0 0 2px rgba(255,246,214,.22)}
    86%,100%  {text-shadow:0 1px 0 rgba(0,0,0,.55)}
  }
  @keyframes dz-blows{
    0%,   61.9%{background-position:100% 0}
    62%       {background-position:70% 0}     /* bolt one   · 30% of the name */
    64.1%     {background-position:70% 0}
    64.2%     {background-position:38% 0}     /* bolt two   · 62% */
    67.1%     {background-position:38% 0}
    67.2%     {background-position:6% 0}      /* bolt three · 94% — through */
    92%       {background-position:6% 0}
    92.01%,100%{background-position:100% 0}
  }

  @media (prefers-reduced-motion:reduce){
    .fr-perkunsvaidis.sf-aigide:has(.np-kapitales) .zs-bolt.b2,
    .fr-perkunsvaidis.sf-aigide:has(.np-kapitales) .zs-bolt.b3{display:none !important}
    .fr-perkunsvaidis.sf-aigide:has(.np-kapitales) .dz-aegis,
    .fr-perkunsvaidis.sf-aigide:has(.np-kapitales) .zs-lit,
    .fr-perkunsvaidis.sf-aigide:has(.np-kapitales) .np-kapitales{animation:none;
      text-shadow:0 1px 0 rgba(0,0,0,.55)}
    .fr-perkunsvaidis.sf-aigide:has(.np-kapitales) .np-kapitales{background-position:100% 0}
    .fr-perkunsvaidis.sf-aigide:has(.np-kapitales) .zs-key::before{animation:none; opacity:0}
  }

  /* KAPITALĖS ON A PHONE — step 89.2e, the one fault the measurement found.
     The nameplate was tuned to a 210px name track; this app's phone track is
     173px, and `Marcinkevičius Patrikas` in capitals at .10em tracking cut
     after PATRIK. Capitals alone cost 29px of a 37px margin and the tracking
     adds about 28px over twenty-two glyphs, so the tracking is what gives,
     and only here: the size (.90em) and the line-height (1.611) stay, because
     together they are the 18.85px that keeps the row from moving. Written at
     `.cell-name .np-kapitales` specificity, the same as the base rule, so it
     wins by order. */
  @media (max-width:700px){
    .cell-name .np-kapitales{letter-spacing:.03em;}
  }

  /* ================= EGIPTAS — THE WINGED DISC SET =================
     Ported 2026-09-13 from Claude outputs/egiptas-app.css, verbatim. Frame
     `sparnuotas`, surface `spinduliai`, nameplate `smelis`. src/egiptas.js
     injects the four layers and fills `.art` from wingedDiscSVG(W, H) in
     src/egiptas-art.js, which also seeds the nameplate's `--grains` tile
     once on the root — both arrived in step 89.2e, and migration 046 opened
     the banner 044 had withheld for their absence.
     ==================================================================== */
  /* ==== EGIPTAS, PORTED ONTO THE MEASURED ROW ===============================
     This is the Egyptian set's own CSS from the approved page, moved from that
     page's 65px demo row onto the shipping one: 57.8px tall, `.brow` at
     `34px 1fr 88px 76px 100px`, 10px gap, 11px/14px padding.

     IT HAD THE RUNAKMENIS BUG. Egiptas was drawn, approved and briefed against a
     65px row with a 30/1fr/92 grid and an 8px gap — the same demo numbers that
     forced Runakmenis to be rebuilt from scratch. Nothing here was measured
     against the app. The two places it actually bites:

     1 · THE ART'S HEIGHT IS DERIVED, NOT FIXED. `.art` is inset -11px top and
         bottom, so the SVG box is the row height plus 22 — 87 on a 65px row and
         79.8 on the real one. The generator took H as a CONSTANT 87, so on a
         real row the disc sat 7px too low and the dado rules fell outside the
         box entirely. H is now passed in from the measured element, and the two
         dado rules are placed off H rather than at y=72 and y=77.

     2 · THE NAMEPLATE TARGETED THE WRONG ELEMENT. `.np-smelis .nm` was written
         for a demo whose name span is `.nm`. `nameplateClass()` puts the class
         ON the span, which arrives as `class="np np-smelis"` — so there is no
         descendant to match and the sand simply did not paint.

     And the set-bonus gate: the demo put all three classes on the row, so a
     compound selector saw them. The app puts the nameplate on the span inside,
     so `:has()` is forced — an element cannot `:has()` its own class.
  ========================================================================= */
  :root{ --e-gold:#F0BE45; --e-night:#0A0F18; }

  /* the row keeps .brow's grid; every part of the frame is an absolutely
     positioned decoration around the cells, and the cells sit above them
     because the app gives them no z-index of their own */
  .fr-sparnuotas{ position:relative; isolation:isolate; }
  .fr-sparnuotas > .cell-num, .fr-sparnuotas > .cell-name,
  .fr-sparnuotas > .cell-net, .fr-sparnuotas > .eng{ position:relative; z-index:6 }
  .fr-sparnuotas.framed::before, .fr-sparnuotas.framed::after{ display:none }
  .fr-sparnuotas.framed{ --int:transparent }
  /* and an injected layer that is not positioned would become a GRID ITEM and
     push the cells onto a second line — said once, about all of them */
  .fr-sparnuotas > span.art, .fr-sparnuotas > span.veil,
  .fr-sparnuotas > span.rayflare, .fr-sparnuotas > span.noon{ position:absolute }

  /* THE MONEY KEEPS ITS OWN COLOUR. No override here, deliberately: green for up
     and orange for down is the one thing on this board that carries meaning
     rather than decoration, and a frame does not get to overrule it. */
  /* ===================================================== I · SPARNUOTAS DISKAS
     The frame: the winged sun disc, the shape that has been carved over
     doorways for three thousand years — and a doorway lintel is 5.6:1, which
     is a row. One wing is drawn once and MIRRORED, so the halves cannot drift
     apart by construction; the disc sits on the centre line above the text,
     where a lintel carving actually sits.                                    */
  .art{position:absolute; left:-12px; right:-12px; top:-11px; bottom:-11px;
    z-index:2; pointer-events:none}
  .art svg{width:100%; height:100%; display:block; overflow:visible}
  .fr-sparnuotas{background:var(--e-night)}
  .fr-sparnuotas .veil{position:absolute; inset:7px; z-index:3; pointer-events:none;
    border-radius:3px;
    background:linear-gradient(180deg, rgba(8,10,12,.42) 0 26%, rgba(8,10,12,.16) 62%,
      rgba(8,10,12,.30) 100%)}
  /* the disc is SOLID GOLD and never animates its own opacity — the breathing
     lives in a halo behind it, where being translucent is correct */
  .discglow{animation:pulse 6s ease-in-out infinite}
  @keyframes pulse{0%,100%{transform:scale(1); filter:brightness(.93)}
    50%{transform:scale(1.045); filter:brightness(1.08)}}
  .dischalo{animation:halo 6s ease-in-out infinite}
  @keyframes halo{0%,100%{opacity:.35; transform:scale(.94)}
    50%{opacity:.85; transform:scale(1.16)}}
  .plume{animation:fan 6s ease-in-out infinite}
  @keyframes fan{0%,100%{transform:translateY(0)} 50%{transform:translateY(-1px)}}

  /* ============================================================ II · SPINDULIAI
     The surface: rays fanning from directly behind the disc, thinning to
     nothing before they reach either figure column, so the money and the rank
     both sit on quiet ground.                                                */
  .sf-spinduliai{
    background-color:#0B1018;
    background-image:
      repeating-conic-gradient(from 0deg at 50% 0%,
        rgba(240,190,69,.07) 0deg 2.2deg, transparent 2.2deg 10deg),
      radial-gradient(70% 190% at 50% -10%, rgba(240,190,69,.15), transparent 62%)}

  /* ================================================================ III · SMĖLIS
     The nameplate. The sand is not INSIDE the letters — a 15px stroke is two
     pixels wide and texture was measured dying at nine, so grain in a stroke
     only makes it look dull. Sand is drawn where sand actually collects.     */
  .cell-name .np-smelis, .np-smelis{
    position:relative;
  /* BLOCK, NOT INLINE-BLOCK, and `fit-content` to keep the shrink it was
     inline-block FOR. An inline-block sits on the text baseline, so the
     block container underneath it reserves descender space below the box —
     3px of it here. That is the whole of this row's long-standing 60.78px
     against every other row's 57.78, and it is why measuring `.np` never
     found it: the LINE is 18.84px and correct, the space under it is not
     part of any element. `width:fit-content` on a block gives the same
     shrink-to-the-text with no baseline to sit on, which is the pattern the
     rest of the nameplates already use. Verified: cell 37.78 -> 34.78, row
     60.78 -> 57.78, and the box stays 180px so the sand still spans the
     name rather than the whole cell. */
  display:block; width:fit-content; max-width:100%; overflow:visible;
    color:#EAD1A2; letter-spacing:.022em;
    text-shadow:
      0 0 1.7px rgba(238,214,168,.85),
      0 1px 0 rgba(30,18,4,.92),
      0 2px 6px rgba(226,186,116,.26)}
  .np-smelis::before{
    content:''; position:absolute; left:-7px; right:-12px; bottom:-2px; height:10px;
    background:var(--grains) repeat-x left bottom; background-size:120px 10px;
    -webkit-mask-image:linear-gradient(90deg, transparent 0, #000 12%, #000 76%, transparent 100%);
    mask-image:linear-gradient(90deg, transparent 0, #000 12%, #000 76%, transparent 100%);
    animation:creep 48s linear infinite; pointer-events:none}
  .np-smelis::after{
    content:''; position:absolute; left:0; right:-8px; top:-3px; height:12px;
    background:var(--grains) repeat-x left top; background-size:120px 10px;
    opacity:.22; transform:scaleY(-1);
    animation:creep 71s linear infinite reverse; pointer-events:none}
  @keyframes creep{to{background-position:120px 0}}

  /* The zenith burst has been REMOVED from this frame — 9 September. The
     winged disc keeps only its idle breath; the impact-frame grammar is not
     what this set does. */



  /* ==== EGIPTAS · SET BONUS · VIDUDIENIS ("noon") ============================
     Gated `.fr-sparnuotas.sf-spinduliai:has(.np-smelis)`. The comment below is
     the DEMO's reasoning and it is wrong for the app — kept as the record of how
     the trap works in both directions:
     sit on the row itself, so a plain compound selector sees the whole set and
     `:has()` is not needed. It was tried first and it silently matched nothing:
     an element cannot `:has()` a class that is on the element. THE GATE MUST BE
     WRITTEN AGAINST THE MARKUP THAT SHIPS, not the markup the rule describes.

     THE EVENT IS AN INSTANT, NOT A JOURNEY, and that is deliberate. Runakmenis'
     bonus is a traveller: something leaves the name and crosses the row. If
     Egypt did the same thing in gold, the two sets would be one idea wearing
     two costumes. **Noon is a moment all three pieces agree on at once** — the
     disc at the top of its arc, the rays at their widest, and the sand bleached
     under a light with no angle left in it.

     Šešėlis, the version this replaces, was a whole day passing: a wash
     crossing the row and a shadow leaning away from it. It was the better idea
     on paper and it was invisible on a 65px row, because a shadow that leans
     two pixels is not something anyone notices at arm's length. **The lesson is
     the one the frieze and the dragon already taught: what survives at this size
     is timing and brightness, never a small shape moving a small distance.**

     9 seconds, Egypt's own burst period — the same clock Runakmenis runs on, so
     the two sets tick together on a shared board.

       0.0 – 3.4s   the climb: the halo widens, the rays gather
       3.4 – 4.0s   NOON: the bloom opens, the rays flare, the disc goes white
       4.0 – 6.6s   the fall
       6.6 – 9.0s   still

     Everything here is `opacity` on layers that already exist, plus one
     keyframe set that REPLACES the disc's idle breath rather than adding to it
     — two animations writing `transform` or `filter` do not compose, the later
     one simply wins. Nothing repaints, nothing re-rasterises.
  ========================================================================= */

  .rayflare, .noon{display:none}

  /* ---- 1 · THE RAYS GATHER -------------------------------------------------
     The surface's own fan, redrawn brighter on a layer above it, faded up and
     down. The surface itself is a background and cannot be animated cheaply. */
  .fr-sparnuotas.sf-spinduliai:has(.np-smelis) .rayflare{
    display:block; position:absolute; inset:0; z-index:1; pointer-events:none;
    border-radius:5px; opacity:0;
    background-image:
      repeating-conic-gradient(from 0deg at 50% 0%,
        rgba(255,226,140,.16) 0deg 2.2deg, transparent 2.2deg 10deg),
      radial-gradient(78% 210% at 50% -12%, rgba(255,214,110,.28), transparent 64%);
    animation:eg-rays 9s ease-in-out infinite;
  }
  @keyframes eg-rays{
    0%,   14%{opacity:0}
    32%     {opacity:.45}
    40%     {opacity:1}      /* noon */
    52%     {opacity:.5}
    74%,100%{opacity:0}
  }

  /* ---- 2 · NOON ------------------------------------------------------------
     A bloom opening from behind the disc and across the row. Fixed size, so it
     is an opacity fade and not a scale — a scale that changes re-rasterises the
     layer every frame. */
  .fr-sparnuotas.sf-spinduliai:has(.np-smelis) .noon{
    display:block; position:absolute; inset:-6px -12px; z-index:2;
    pointer-events:none; opacity:0;
    background:
      radial-gradient(46% 140% at 50% 20%,
        rgba(255,248,226,.50) 0%, rgba(255,226,140,.30) 26%,
        rgba(240,190,69,.14) 52%, transparent 78%);
    animation:eg-noon 9s ease-in-out infinite;
  }
  @keyframes eg-noon{
    0%,   26%{opacity:0}
    37%     {opacity:.55}
    40%     {opacity:1}
    44%     {opacity:.62}
    58%     {opacity:.18}
    70%,100%{opacity:0}
  }

  /* ---- 3 · THE DISC CLIMBS AND STANDS STILL --------------------------------
     One keyframe set replacing the 6s idle breath, not a second animation on
     top of it. The halo is where the translucency lives; the disc itself is
     solid gold and changes only its brightness — a solid object that fades
     shows the feathers behind it, which is a bug this set has already had. */
  .fr-sparnuotas.sf-spinduliai:has(.np-smelis) .dischalo{
    animation:eg-halo 9s ease-in-out infinite;
  }
  @keyframes eg-halo{
    0%      {opacity:.35; transform:scale(.94)}
    26%     {opacity:.62; transform:scale(1.10)}
    40%     {opacity:1;   transform:scale(1.38)}
    56%     {opacity:.58; transform:scale(1.08)}
    100%    {opacity:.35; transform:scale(.94)}
  }
  .fr-sparnuotas.sf-spinduliai:has(.np-smelis) .discglow{
    animation:eg-disc 9s ease-in-out infinite;
  }
  @keyframes eg-disc{
    0%      {transform:scale(1);     filter:brightness(.93)}
    26%     {transform:scale(1.03);  filter:brightness(1.22)}
    40%     {transform:scale(1.055); filter:brightness(1.75) saturate(.9)}
    56%     {transform:scale(1.02);  filter:brightness(1.18)}
    100%    {transform:scale(1);     filter:brightness(.93)}
  }
  /* the feather ranks lift a little as the light comes up */
  .fr-sparnuotas.sf-spinduliai:has(.np-smelis) .plume{
    animation:eg-fan 9s ease-in-out infinite;
  }
  @keyframes eg-fan{
    0%,100%{transform:translateY(0)}
    40%    {transform:translateY(-2px)}
  }

  /* ---- 4 · THE SAND IS BLEACHED -------------------------------------------
     The bank at the foot of the name loses its shadow at noon: a second copy of
     the grains, pale, faded up over the original. Opacity only — the letters
     themselves are never touched, because text that changes is text that
     repaints. */
  .fr-sparnuotas.sf-spinduliai:has(.np-smelis) .np-smelis::after{
    opacity:.22;
    animation:creep 71s linear infinite reverse, eg-bleach 9s ease-in-out infinite;
  }
  @keyframes eg-bleach{
    0%,   22%{opacity:.22}
    40%     {opacity:.72}
    62%,100%{opacity:.22}
  }

  @media (prefers-reduced-motion:reduce){
    .rayflare, .noon{display:none !important}
  }

  /* THE POSITIVE SAFETY NET, as for Runakmenis: the stylesheet above lists
     the four layers it knows by name; this says it about anything injected. */
  .fr-sparnuotas > :not(.cell-num):not(.cell-name):not(.cell-net):not(.eng){position:absolute;}

  /* ================= BENDROSIOS DALYS — THE COMMON TIER =================
     Ported 2026-09-13 from Claude outputs/commons.css. Eight surfaces, no
     animation, no variable from any other set, no JS: azuolas, oda, ragas,
     drobe, skalunas, bazaltas, gelezis, svinas — the catalogue's codes, which
     are the class names below. The row class is a gate: each is
     position:relative and paints as the row's own background-image (step
     89.2f; the file's ::before apparatus is gone, see its header). No `.sf-*`
     here positions the row.
     ==================================================================== */
  /* ==== BENDROSIOS DALYS · THE COMMON TIER ==================================

     A common is A MATERIAL WITH NO CLOCK — the ladder's own definition. Nothing
     animates here: no keyframes, no transitions, no filters.

     TWO PASSES FAILED BEFORE THIS ONE, AND BOTH FAULTS ARE THE USEFUL PART.

     PASS ONE drew each as a COMPOSITION — oak got one cathedral arc, slate three
     facets meeting at hard seams, iron two bright hammer catches. On the row the
     iron's catches read as two scratches slashing through the player's name, and
     the slate's largest facet read as a pale rectangle somebody forgot to
     delete. THE RULE: A COMMON IS A GROUND, AND A GROUND HAS NO INCIDENT. Any
     single feature is an EVENT, the eye goes to it and asks what it means, and
     nothing on a common means anything. That is exactly what separates this rung
     from the one above: a rare is a material with something happening to it, so
     the moment a common has a happening it is a bad rare.

     PASS TWO made them uniform and they turned into CLOTH. Slate read as
     corduroy and iron as carbon weave, and the reason is that a regular repeat
     IS a textile — regularity is the thing the eye names as woven. Oak survived
     it, because wood genuinely is a regular repeat and nothing else here is.
     THE RULE: UNIFORM IS NOT THE SAME AS REGULAR. A ground has to be even in
     density and irregular in detail. Without a noise source that means stacking
     three repeats at periods and angles that share no common factor, so the beat
     between them never closes and no lattice ever appears. Two near-mirrored
     sets is the worst case — mirror symmetry is what made the iron a weave.

     THREE CONSTRAINTS DECIDED EVERY VALUE HERE.

     1 · THE GROUND STAYS DARK. A surface replaces the felt, and the felt is what
         the name (#F2ECDC at 13px), the sub-line (#9AA894 at 11px) and both
         money colours were chosen against. Every common is a DARK sample of its
         material — stained oak, weathered slate, forged iron. Not a compromise:
         that is what a card table is actually made of.

     2 · NO GREEN AND NO RED-ORANGE. --win #5FD39B and --loss #E07B52 mean
         something on this board and a cosmetic does not get to borrow them. That
         rules out verdigris copper and rust, which is why the metal is iron.

     3 · THE PERIOD IS THE THING, NOT THE STROKE. The 9px rule applies to a
         repeat as the distance between one mark and the next, not the mark's own
         width. Grain 1px apart is a smear; 1px apart with 6px of clear wood
         between is grain. No period below is under 6px.

     THE ROW CLASS IS A GATE. `cosmeticClasses()` writes `sf-azuolas` onto the
     ROW, so nothing here may position the row — the bug that collapsed whole
     boards three times.

     THE MATERIAL IS THE ROW'S OWN BACKGROUND-IMAGE — step 89.2f. It was first
     painted on the row's ::before at z-index:-1, and inside a free frame that
     collided with the band, which is the frame's ::before: the material became
     a thin textured ring and the interior kept the frame's colour. A background
     paints under the text by itself, so the ::before, the isolation and the
     z-index all go, and the collision cannot recur: the frame draws its band on
     a pseudo-element, and the material is the ground beneath it. The layer
     order is exactly what the `background` shorthand held; the colour is a
     separate background-color so a frame's --int may overwrite it.
  ========================================================================= */

  .sf-azuolas, .sf-skalunas, .sf-gelezis{
    position:relative;              /* relative, NEVER absolute — see above */
    background-color:#12100C;       /* the fallback ground; a frame's --int may
                                       overwrite it, the image stays */
  }

  /* --------------------------------------------------------------- I · ĄŽUOLAS
     OAK. The table itself — the one material here a player has rested their
     elbows on, and the one that is allowed to be a regular repeat, because wood
     is one.

     Grain all the way across at a 7.4px period, 0.7deg off horizontal. Exactly
     horizontal reads as ruled lines; a degree of drift reads as a board that was
     sawn. The figure — oak's wide arcs of darker wood — is a broad tonal drift
     with NO EDGE ANYWHERE, felt as unevenness in the plank rather than seen as a
     shape drawn on it.

     Grain contrast rose from pass one: at .55 over a #33220F plank the lines
     were visible at 3× and gone on the row. A dark line on dark wood is a
     contrast problem, and enlarging never fixes a contrast problem. */
  .sf-azuolas{
    background-image:
      repeating-linear-gradient(0.7deg,
        rgba(11,6,2,.72)  0px,   rgba(11,6,2,.72)  1.1px,
        rgba(0,0,0,0)     1.1px, rgba(0,0,0,0)     3.2px,
        rgba(20,12,4,.46) 3.2px, rgba(20,12,4,.46) 4.0px,
        rgba(0,0,0,0)     4.0px, rgba(0,0,0,0)     7.4px),
      linear-gradient(93deg,
        rgba(104,68,34,.20) 0%,  rgba(60,38,18,.10) 38%,
        rgba(104,68,34,.16) 72%, rgba(60,38,18,.08) 100%),
      linear-gradient(96deg, #3B2818 0%, #342310 46%, #2B1C0E 100%);
  }

  /* -------------------------------------------------------------- II · SKALŪNAS
     SLATE. Cleaved stone. Pass one got the physics right and the scale wrong —
     a plane the width of a row is a panel, while the planes you see on a piece
     of slate this size are narrow, many and roughly parallel. Pass two got the
     scale right and turned it into corduroy.

     Three seam sets at 9.0, 13.7 and 21.3px and 97, 84 and 103 degrees. None of
     those periods divides into another and none of the angles mirrors another,
     so the beat never closes and the surface stays a surface. Each seam is a
     dark groove with a faintly lighter lip on one side, because stone at any
     size is read by where the light sits and never by an outline.

     Near-vertical on purpose: oak runs across the row, so slate running down it
     is a second axis and the two can never look like one texture recoloured. */
  .sf-skalunas{
    background-image:
      repeating-linear-gradient(97deg,
        rgba(0,0,0,.30)       0px,   rgba(0,0,0,.30)       1.0px,
        rgba(176,196,216,.06) 1.0px, rgba(176,196,216,.06) 1.8px,
        rgba(0,0,0,0)         1.8px, rgba(0,0,0,0)         9.0px),
      repeating-linear-gradient(84deg,
        rgba(0,0,0,.17)  0px,   rgba(0,0,0,.17)  1.3px,
        rgba(0,0,0,0)    1.3px, rgba(0,0,0,0)    13.7px),
      repeating-linear-gradient(103deg,
        rgba(158,180,204,.05) 0px,   rgba(158,180,204,.05) 2.2px,
        rgba(0,0,0,0)         2.2px, rgba(0,0,0,0)         21.3px),
      linear-gradient(101deg,
        rgba(140,164,190,.07) 0%, rgba(0,0,0,.06) 55%, rgba(140,164,190,.05) 100%),
      linear-gradient(180deg, #242C36 0%, #1C222A 64%, #181D24 100%);
  }

  /* -------------------------------------------------------------- III · GELEŽIS
     WROUGHT IRON. The metal had to be iron: copper oxidises to the exact green
     this board uses for a win, brass sits where the gold does, and rust is
     --loss. Iron is the one common metal whose whole range is neutral.

     Pass one put two hard bright catches on it and they read as two scratches
     cut through the player's name. THE NAME TRACK IS NOT AVAILABLE — a hard
     light on a common is the same mistake as a hard edge.

     Pass two used two near-mirrored repeats at 64 and -58 degrees and made
     carbon fibre. These lean 41, -73 and 8 at 6.2, 10.9 and 17.5px: three odd
     angles, three coprime periods, no symmetry anywhere. What is left is what
     forging looks like at this size — a surface that is not smooth, everywhere,
     by a small amount, with no stop brighter than 20% over the billet. Iron is
     recognised here by being DULL AND UNEVEN, which is the honest difference
     between it and polished steel. A polish is something that HAPPENS to a
     metal, so polished steel would be a rare. */
  .sf-gelezis{
    background-image:
      repeating-linear-gradient(41deg,
        rgba(226,234,244,.055) 0px,   rgba(226,234,244,.055) 1.4px,
        rgba(0,0,0,.09)        1.4px, rgba(0,0,0,.09)        3.0px,
        rgba(0,0,0,0)          3.0px, rgba(0,0,0,0)          6.2px),
      repeating-linear-gradient(-73deg,
        rgba(0,0,0,.11)        0px,   rgba(0,0,0,.11)        2.3px,
        rgba(210,220,232,.035) 2.3px, rgba(210,220,232,.035) 4.1px,
        rgba(0,0,0,0)          4.1px, rgba(0,0,0,0)          10.9px),
      repeating-linear-gradient(8deg,
        rgba(0,0,0,.08) 0px,   rgba(0,0,0,.08) 3.4px,
        rgba(0,0,0,0)   3.4px, rgba(0,0,0,0)   17.5px),
      linear-gradient(174deg, #2E3236 0%, #24282C 56%, #1B1E21 100%);
  }

  /* ========================================================================
     THE OTHER FIVE. Same three constraints, same ground-not-composition rule,
     and one addition that fell out of the failures above.

     THE FAMILY IS EIGHT MATERIALS ON THREE AXES, and no two share all three:

       piece      family     hue                 texture axis
       Ąžuolas    wood       warm brown          horizontal, regular
       Oda        leather    warm dark neutral   cellular, no direction
       Ragas      horn       olive amber         diagonal, broad bands
       Drobė      cloth      dark oatmeal        orthogonal, regular
       Skalūnas   stone      cool grey-blue      near-vertical seams
       Bazaltas   stone      near-black          pitted, no direction
       Geležis    metal      neutral grey        multi-angle mottle
       Švinas     metal      cool blue-grey      cloudy, no repeat

     DROBĖ IS THE FAILURE TURNED INTO A PIECE. Pass two's iron became carbon
     weave because a regular symmetric repeat reads as cloth. That is not a bug
     in a material that IS cloth, so the eighth common uses the exact
     construction that was wrong everywhere else — two orthogonal repeats at one
     period — and it is the only one here allowed to.

     CELLULAR TEXTURE WITHOUT A NOISE SOURCE: a radial-gradient tiled by
     background-size gives a grid of cells, and a grid of cells is a grid. Two
     tilings at sizes that share no factor (9×7 and 13×11) beat against each
     other over the row's width and the grid never closes. Same trick as the
     coprime periods above, in two dimensions.
  ======================================================================== */

  .sf-oda, .sf-ragas, .sf-drobe, .sf-bazaltas, .sf-svinas{
    position:relative; background-color:#12100C;
  }

  /* ------------------------------------------------------------------ IV · ODA
     LEATHER. The only common with no direction at all — hide grain is cells, and
     a cell has no grain to run along. That is what it is for in this set: seven
     of eight materials lean somewhere, and one does not.

     Each cell is a dark seat with a light dome inside it, the same two-part
     construction Aigidė's scales used, because relief at this size is entirely
     where the light sits. Two tilings at 9×7 and 13×11 so the grid never closes.
     Dark warm neutral rather than oxblood: oxblood lands on --loss. */
  .sf-oda{
    background-image:
      radial-gradient(60% 62% at 42% 38%,
        rgba(196,168,138,.10) 0%, rgba(0,0,0,0) 62%),
      radial-gradient(74% 76% at 56% 64%,
        rgba(0,0,0,.26) 0%, rgba(0,0,0,.10) 48%, rgba(0,0,0,0) 78%),
      radial-gradient(58% 60% at 62% 44%,
        rgba(178,152,124,.06) 0%, rgba(0,0,0,0) 66%),
      radial-gradient(70% 72% at 38% 58%,
        rgba(0,0,0,.18) 0%, rgba(0,0,0,0) 74%),
      linear-gradient(102deg, #2E2621 0%, #26201B 52%, #1E1915 100%);
    background-size: 9px 7px, 9px 7px, 13px 11px, 13px 11px, auto;
  }

  /* ---------------------------------------------------------------- V · RAGAS
     HORN. Translucent material, which at 57px means one thing only: BROAD SOFT
     BANDS OF DIFFERENT DEPTH, no edges anywhere. Light goes some way into horn
     and comes back out, so a darker band is not shadow, it is thickness.

     The first values banded far too hard — on the nine-row board it read as
     olive corduroy next to the slate, which is the pass-two fault returning in a
     piece that had escaped it. Periods widened to 16.2 / 25.9 / 37.3 and every
     alpha roughly halved: a translucent material is READ AS SOFT, so the moment
     its bands have a legible edge it has become a striped opaque one. */
  .sf-ragas{
    background-image:
      repeating-linear-gradient(62deg,
        rgba(0,0,0,.15)      0px,    rgba(0,0,0,.09)      4.6px,
        rgba(0,0,0,0)        9.0px,  rgba(150,124,62,.06) 11.8px,
        rgba(0,0,0,0)        16.2px),
      repeating-linear-gradient(58deg,
        rgba(0,0,0,.08)      0px,    rgba(0,0,0,0)        9.4px,
        rgba(128,106,52,.04) 16.0px, rgba(0,0,0,0)        25.9px),
      repeating-linear-gradient(67deg,
        rgba(0,0,0,.06)      0px,    rgba(0,0,0,0)        14.0px,
        rgba(0,0,0,0)        37.3px),
      linear-gradient(98deg, #38301A 0%, #2E2715 55%, #241E10 100%);
  }

  /* --------------------------------------------------------------- VI · DROBĖ
     CANVAS. The regular orthogonal weave that ruined the iron, used on purpose.
     Two repeats at one period and a right angle, which is the construction of
     woven cloth and of nothing else.

     The period is 4.6px, below the 9px floor the other seven obey, and that is
     deliberate: a weave whose threads you can count is burlap. What must stay
     above the floor is the thing you are meant to READ, and on canvas that is
     the cloth, not the thread. Dark oatmeal — the one warm pale-ish material
     here, held down to #2F2C25 so the name still clears it. */
  .sf-drobe{
    background-image:
      repeating-linear-gradient(90deg,
        rgba(224,214,190,.06) 0px,   rgba(224,214,190,.06) 1.5px,
        rgba(0,0,0,.13)       1.5px, rgba(0,0,0,.13)       2.3px,
        rgba(0,0,0,0)         2.3px, rgba(0,0,0,0)         4.6px),
      repeating-linear-gradient(0deg,
        rgba(224,214,190,.05) 0px,   rgba(224,214,190,.05) 1.5px,
        rgba(0,0,0,.12)       1.5px, rgba(0,0,0,.12)       2.3px,
        rgba(0,0,0,0)         2.3px, rgba(0,0,0,0)         4.6px),
      linear-gradient(94deg, #2F2C25 0%, #29261F 58%, #221F19 100%);
  }

  /* ------------------------------------------------------------ VII · BAZALTAS
     BASALT. The second stone, and it had to differ from slate by CONSTRUCTION
     and not by colour, or the two would be one piece in two greys. Slate cleaves
     — straight seams, one direction. Basalt is frozen froth: vesicles, round,
     scattered, no direction at all.

     Each pit is a dark hole with a lit lower lip, which is a pit lit from above;
     invert the two and the same drawing is a bump. Tiled at 11×9 and 17×13. The
     darkest of the eight and the only one approaching the felt's own value, so
     it keeps a faint warm drift to stop it reading as an unstyled row. */
  .sf-bazaltas{
    background-image:
      radial-gradient(38% 42% at 50% 44%,
        rgba(0,0,0,.42) 0%, rgba(0,0,0,.16) 58%, rgba(0,0,0,0) 76%),
      radial-gradient(34% 30% at 50% 62%,
        rgba(170,168,164,.09) 0%, rgba(0,0,0,0) 70%),
      radial-gradient(30% 34% at 44% 52%,
        rgba(0,0,0,.30) 0%, rgba(0,0,0,0) 74%),
      radial-gradient(28% 26% at 44% 66%,
        rgba(160,158,154,.06) 0%, rgba(0,0,0,0) 72%),
      linear-gradient(107deg,
        rgba(74,66,58,.10) 0%, rgba(0,0,0,0) 46%, rgba(74,66,58,.07) 100%),
      linear-gradient(180deg, #1E1E1E 0%, #181818 60%, #131313 100%);
    background-size: 11px 9px, 11px 9px, 17px 13px, 17px 13px, auto, auto;
  }

  /* -------------------------------------------------------------- VIII · ŠVINAS
     LEAD. The counterpart to iron in the way basalt is to slate: iron is forged,
     so it is faceted and busy; lead is cast and soft, so it has NO SMALL REPEAT
     AT ALL — only broad cloudy drifts at 53, 79 and 113px, periods far longer
     than anything else in the eight and longer than the row is tall.

     IT WAS DRAWN TWICE. The first version tiled four radial gradients at 97×61
     and 143×89, and on the nine-row board the tile SEAMS were plainly visible as
     vertical steps in the cloud — a background-size tiling of a radial is a grid
     of identical blobs however large you make it, and a grid is exactly what
     this piece must not have. It was also far too light: a pale row among eight
     dark ones, with the sub-line nearly lost. Long-period gradients have no
     seams by construction, and the billet came down to iron's own value.

     Cool blue-grey against iron's neutral. Both stay well clear of --win. */
  .sf-svinas{
    background-image:
      repeating-linear-gradient(21deg,
        rgba(186,202,220,.055) 0px,    rgba(186,202,220,.02) 13.0px,
        rgba(0,0,0,0)          26.0px, rgba(0,0,0,.11)       40.0px,
        rgba(0,0,0,0)          53.0px),
      repeating-linear-gradient(-64deg,
        rgba(0,0,0,.13)        0px,    rgba(0,0,0,0)         38.0px,
        rgba(172,188,208,.035) 58.0px, rgba(0,0,0,0)         79.0px),
      repeating-linear-gradient(96deg,
        rgba(0,0,0,.08)        0px,    rgba(0,0,0,0)         47.0px,
        rgba(0,0,0,0)          113.0px),
      linear-gradient(176deg, #262B31 0%, #1F242A 58%, #181C21 100%);
  }

/* =========================================================================
   KOMETA · the third Kosmosas set (step 147, 2026-09-29)

   "A comet. The frame has a bright head circling the row with a long ion
   tail behind it, the nameplate trails a tail, and the surface is a meteor
   shower." Then: "make it on par with the other two … go all out."

      fr-kometa      Kometa       MYTHIC  a comet on an orbit round the row
      np-uodega      Uodega       EPIC    the name itself becomes a comet
      sf-meteorai    Meteorai     RARE    a meteor shower from one radiant

      PERIHELIS (set effect, all three): three blows once a lap — the tail
      whips round the row and cracks, its debris rains down as meteors, and
      the comet dives into the row. Hard cuts and shakes, in starlight.

   The frame is DRAWN, not painted: src/kometa.js writes one SVG per row
   (nucleus, coma with hood and jets, a tapered ion envelope, filaments and
   plasma knots, the dust tail, and the light it throws into the row), all
   riding one path so the tail bends round the corners with the head. This
   sheet seats it, draws the orbit it rides on, and carries the other two
   pieces and the set effect.

   ONE CLOCK: 11 seconds a lap. The frame's SMIL and every CSS animation below are
   put on the document's own timeline by the dresser, so the storm lands on
   the flare and two wearers on one board lap together.

   Letters for the surface's layers are UPPER CASE (M-P): Tekelas uses every
   free lower-case letter and the layered surfaces use a-e and p-r; the
   dresser unions letters per row, so upper case is the one range nobody
   else speaks for.
   ========================================================================= */

/* ------------------------------------------------------ the frame: seating */
.fr-kometa{--int:#060A17; isolation:isolate}
.fr-kometa:not([class*="sf-"]){background-image:
    radial-gradient(1px 1px at 9px 5px,   rgba(214,228,255,.5), transparent),
    radial-gradient(1px 1px at 47px 51px, rgba(214,228,255,.35), transparent),
    radial-gradient(1.2px 1.2px at 88px 8px, rgba(214,228,255,.45), transparent),
    radial-gradient(1px 1px at 131px 47px, rgba(214,228,255,.3), transparent),
    radial-gradient(130% 120% at 50% 50%, rgba(40,56,120,.16), transparent 70%),
    linear-gradient(180deg, #080D1F, #050814);
  background-size:161px 58px, 161px 58px, 161px 58px, 161px 58px, 100% 100%, 100% 100%}
/* The orbit: a dark track the comet rides, and a hairline fillet inside it. */
.fr-kometa::before{background:linear-gradient(135deg, #0B1230, #070B1D 45%, #0A1128 70%, #060A1A)}
.fr-kometa::after{background:rgba(140,176,255,.22)}
/* the dust plane behind the row (step 152): breathing slowly, the dust
   twinkling in three groups on their own periods */
.km-sky .km-disk{animation:km-disk 11s ease-in-out infinite}
@keyframes km-disk{0%,100%{transform:scale(1); opacity:1} 50%{transform:scale(1.04,1.08); opacity:.82}}
.km-sky .km-glit{animation:km-glit 3.4s ease-in-out infinite}
.km-sky .km-glit.g1{animation-duration:4.3s; animation-delay:-1.2s}
.km-sky .km-glit.g2{animation-duration:2.7s; animation-delay:-.6s}
@keyframes km-glit{0%,100%{opacity:1} 50%{opacity:.4}}
/* worn complete, the dust plane answers Perihelis (step 152): the crack of
   the whip sends a ripple through it; it sinks with the row into deep space
   as the comet comes in, and the impact throws it wide open before it
   settles back. On the group inside the mask, so the row's hole stays put. */
.fr-kometa.sf-meteorai:has(.np-uodega) .km-plane{animation:px-plane 11s linear infinite}
.fr-kometa.sf-meteorai:has(.np-uodega) .km-react{animation:px-react 11s linear infinite}
@keyframes px-plane{0%,20%{opacity:1; animation-timing-function:ease-in} 25.4%{opacity:.3; animation-timing-function:steps(1,end)} 25.5%,100%{opacity:1}}
@keyframes px-react{0%,6.59%{transform:scale(1); animation-timing-function:steps(1,end)}
  6.6%{transform:scale(1.08,1.45); animation-timing-function:cubic-bezier(.15,.7,.3,1)} 15%{transform:scale(1)}
  21%{transform:scale(1); animation-timing-function:ease-in} 25.4%{transform:scale(.97,.85); animation-timing-function:steps(1,end)}
  25.5%{transform:scale(1.16,1.9); animation-timing-function:cubic-bezier(.12,.7,.3,1)} 44%,100%{transform:scale(1)}}
.fr-kometa > .km-sky{position:absolute; left:-14px; top:-12px; overflow:visible;
  pointer-events:none; z-index:2}
.fr-kometa > .cell-num, .fr-kometa > .cell-name, .fr-kometa > .cell-net,
.fr-kometa > .eng{position:relative; z-index:4}

/* ----------------------------------------------------------- the nameplate
   THE NAME IS THE COMET. Nothing is laid over or under the letters: the
   letters themselves are lit like one — white-hot at the front (the last
   letter, the way the name reads it is travelling right), cooling through
   blue into the tail, and at the start the letters come apart into bits,
   which stream off behind as dust. "Instead of obstructing the names, the
   nameplate turns the name itself into a comet" — Rapolas, 2026-09-29.

   How:
   - the fill is a gradient clipped to the glyphs, white at the right end;
   - a mask breaks the first letters into grains: a solid ramp from the
     right, plus a tile of scattered grains that is all that is left of the
     letters at the left. The grains drift backwards, so the bits stream off;
   - a bright body runs from the head down the tail every 5.5s (half a lap);
   - the dust leaving the tail is the cell's own ::before, left of the name,
     so it never crosses a letter.
   Clocks: the grains 2.4s, the surge 5.5s. */
.cell-name:has(.np-uodega){position:relative; overflow:visible}
.np-uodega{font-weight:600; color:#EAF4FF;
  background:
    radial-gradient(closest-side, rgba(255,255,255,.95), rgba(255,255,255,0)) no-repeat,
    linear-gradient(90deg, rgba(92,110,226,.7) 0%, #7B98EE 22%, #A9C9FF 52%, #E2F1FF 78%, #FFFFFF 92%);
  background-size:36% 160%, 100% 100%;
  background-position:115% 50%, 0 0;
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent;
  text-shadow:0 0 7px rgba(150,205,255,.28);
  -webkit-mask-image:
    linear-gradient(90deg, rgba(0,0,0,.3) 0, rgba(0,0,0,.65) 9%, #000 24%),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='18'%3E%3Cg fill='%23000'%3E%3Ccircle cx='7.8' cy='2.7' r='0.74' fill-opacity='1.00'/%3E%3Ccircle cx='12.9' cy='6.6' r='0.38' fill-opacity='1.00'/%3E%3Ccircle cx='0.9' cy='7.8' r='0.39' fill-opacity='1.00'/%3E%3Ccircle cx='10.2' cy='14.9' r='0.42' fill-opacity='1.00'/%3E%3Ccircle cx='15.1' cy='17.1' r='0.70' fill-opacity='1.00'/%3E%3Ccircle cx='23.4' cy='0.8' r='0.87' fill-opacity='1.00'/%3E%3Ccircle cx='3.5' cy='2.1' r='0.54' fill-opacity='1.00'/%3E%3Ccircle cx='4.3' cy='10.5' r='0.73' fill-opacity='1.00'/%3E%3Ccircle cx='13.1' cy='1.1' r='0.39' fill-opacity='1.00'/%3E%3Ccircle cx='16.3' cy='7.7' r='0.54' fill-opacity='1.00'/%3E%3Ccircle cx='10.9' cy='5.4' r='0.83' fill-opacity='1.00'/%3E%3Ccircle cx='5.9' cy='10.3' r='0.67' fill-opacity='1.00'/%3E%3Ccircle cx='17.5' cy='5.2' r='0.94' fill-opacity='1.00'/%3E%3Ccircle cx='10.0' cy='13.6' r='0.44' fill-opacity='1.00'/%3E%3Ccircle cx='0.9' cy='12.0' r='0.81' fill-opacity='1.00'/%3E%3Ccircle cx='21.0' cy='5.6' r='0.77' fill-opacity='1.00'/%3E%3Ccircle cx='13.9' cy='8.2' r='0.85' fill-opacity='1.00'/%3E%3Ccircle cx='11.4' cy='12.0' r='0.39' fill-opacity='1.00'/%3E%3Ccircle cx='15.5' cy='17.9' r='0.84' fill-opacity='1.00'/%3E%3Ccircle cx='9.3' cy='12.0' r='0.36' fill-opacity='1.00'/%3E%3Ccircle cx='4.0' cy='2.1' r='0.39' fill-opacity='1.00'/%3E%3Ccircle cx='3.1' cy='4.5' r='0.58' fill-opacity='1.00'/%3E%3Ccircle cx='1.9' cy='8.1' r='0.68' fill-opacity='1.00'/%3E%3Ccircle cx='19.7' cy='15.6' r='0.52' fill-opacity='1.00'/%3E%3Ccircle cx='8.6' cy='15.9' r='0.92' fill-opacity='1.00'/%3E%3Ccircle cx='4.2' cy='4.2' r='0.49' fill-opacity='1.00'/%3E%3Ccircle cx='14.1' cy='4.7' r='0.35' fill-opacity='1.00'/%3E%3Ccircle cx='8.9' cy='10.2' r='0.92' fill-opacity='1.00'/%3E%3Ccircle cx='12.4' cy='11.1' r='0.76' fill-opacity='1.00'/%3E%3Ccircle cx='21.6' cy='14.0' r='0.87' fill-opacity='1.00'/%3E%3Ccircle cx='9.4' cy='7.2' r='0.41' fill-opacity='1.00'/%3E%3Ccircle cx='1.5' cy='1.2' r='0.48' fill-opacity='1.00'/%3E%3Ccircle cx='8.2' cy='0.9' r='0.35' fill-opacity='1.00'/%3E%3Ccircle cx='2.4' cy='6.5' r='0.37' fill-opacity='1.00'/%3E%3Ccircle cx='14.7' cy='2.7' r='0.50' fill-opacity='1.00'/%3E%3Ccircle cx='8.7' cy='2.2' r='0.86' fill-opacity='1.00'/%3E%3Ccircle cx='11.2' cy='8.7' r='0.40' fill-opacity='1.00'/%3E%3Ccircle cx='8.2' cy='4.8' r='0.85' fill-opacity='1.00'/%3E%3Ccircle cx='0.6' cy='17.1' r='0.67' fill-opacity='1.00'/%3E%3Ccircle cx='13.0' cy='0.5' r='0.67' fill-opacity='1.00'/%3E%3Ccircle cx='20.7' cy='12.5' r='0.51' fill-opacity='1.00'/%3E%3Ccircle cx='4.0' cy='13.9' r='0.67' fill-opacity='1.00'/%3E%3Ccircle cx='7.9' cy='4.0' r='0.84' fill-opacity='1.00'/%3E%3Ccircle cx='20.5' cy='14.5' r='0.84' fill-opacity='1.00'/%3E%3Ccircle cx='5.4' cy='9.3' r='0.56' fill-opacity='1.00'/%3E%3Ccircle cx='0.7' cy='5.0' r='0.51' fill-opacity='1.00'/%3E%3Ccircle cx='23.0' cy='8.1' r='0.91' fill-opacity='1.00'/%3E%3Ccircle cx='22.9' cy='6.6' r='0.48' fill-opacity='1.00'/%3E%3Ccircle cx='4.7' cy='3.7' r='0.72' fill-opacity='1.00'/%3E%3Ccircle cx='20.2' cy='8.6' r='0.74' fill-opacity='1.00'/%3E%3Ccircle cx='2.0' cy='11.9' r='0.90' fill-opacity='1.00'/%3E%3Ccircle cx='18.0' cy='8.6' r='0.46' fill-opacity='1.00'/%3E%3Ccircle cx='8.0' cy='14.4' r='0.93' fill-opacity='1.00'/%3E%3Ccircle cx='9.6' cy='17.0' r='0.78' fill-opacity='1.00'/%3E%3Ccircle cx='3.0' cy='2.7' r='0.89' fill-opacity='1.00'/%3E%3Ccircle cx='3.5' cy='14.9' r='0.94' fill-opacity='1.00'/%3E%3Ccircle cx='8.4' cy='9.9' r='0.43' fill-opacity='1.00'/%3E%3Ccircle cx='23.3' cy='11.7' r='0.67' fill-opacity='1.00'/%3E%3Ccircle cx='10.4' cy='15.7' r='0.85' fill-opacity='1.00'/%3E%3Ccircle cx='6.0' cy='5.3' r='0.49' fill-opacity='1.00'/%3E%3Ccircle cx='6.2' cy='7.5' r='0.43' fill-opacity='1.00'/%3E%3Ccircle cx='8.5' cy='8.2' r='0.70' fill-opacity='1.00'/%3E%3Ccircle cx='10.1' cy='16.5' r='0.65' fill-opacity='1.00'/%3E%3Ccircle cx='12.6' cy='0.3' r='0.61' fill-opacity='1.00'/%3E%3Ccircle cx='0.1' cy='14.4' r='0.45' fill-opacity='1.00'/%3E%3Ccircle cx='17.4' cy='10.0' r='0.55' fill-opacity='1.00'/%3E%3Ccircle cx='13.3' cy='14.1' r='0.41' fill-opacity='1.00'/%3E%3Ccircle cx='6.0' cy='5.0' r='0.81' fill-opacity='1.00'/%3E%3Ccircle cx='13.5' cy='13.7' r='0.90' fill-opacity='1.00'/%3E%3Ccircle cx='14.7' cy='9.1' r='0.66' fill-opacity='1.00'/%3E%3C/g%3E%3C/svg%3E");
          mask-image:
    linear-gradient(90deg, rgba(0,0,0,.3) 0, rgba(0,0,0,.65) 9%, #000 24%),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='18'%3E%3Cg fill='%23000'%3E%3Ccircle cx='7.8' cy='2.7' r='0.74' fill-opacity='1.00'/%3E%3Ccircle cx='12.9' cy='6.6' r='0.38' fill-opacity='1.00'/%3E%3Ccircle cx='0.9' cy='7.8' r='0.39' fill-opacity='1.00'/%3E%3Ccircle cx='10.2' cy='14.9' r='0.42' fill-opacity='1.00'/%3E%3Ccircle cx='15.1' cy='17.1' r='0.70' fill-opacity='1.00'/%3E%3Ccircle cx='23.4' cy='0.8' r='0.87' fill-opacity='1.00'/%3E%3Ccircle cx='3.5' cy='2.1' r='0.54' fill-opacity='1.00'/%3E%3Ccircle cx='4.3' cy='10.5' r='0.73' fill-opacity='1.00'/%3E%3Ccircle cx='13.1' cy='1.1' r='0.39' fill-opacity='1.00'/%3E%3Ccircle cx='16.3' cy='7.7' r='0.54' fill-opacity='1.00'/%3E%3Ccircle cx='10.9' cy='5.4' r='0.83' fill-opacity='1.00'/%3E%3Ccircle cx='5.9' cy='10.3' r='0.67' fill-opacity='1.00'/%3E%3Ccircle cx='17.5' cy='5.2' r='0.94' fill-opacity='1.00'/%3E%3Ccircle cx='10.0' cy='13.6' r='0.44' fill-opacity='1.00'/%3E%3Ccircle cx='0.9' cy='12.0' r='0.81' fill-opacity='1.00'/%3E%3Ccircle cx='21.0' cy='5.6' r='0.77' fill-opacity='1.00'/%3E%3Ccircle cx='13.9' cy='8.2' r='0.85' fill-opacity='1.00'/%3E%3Ccircle cx='11.4' cy='12.0' r='0.39' fill-opacity='1.00'/%3E%3Ccircle cx='15.5' cy='17.9' r='0.84' fill-opacity='1.00'/%3E%3Ccircle cx='9.3' cy='12.0' r='0.36' fill-opacity='1.00'/%3E%3Ccircle cx='4.0' cy='2.1' r='0.39' fill-opacity='1.00'/%3E%3Ccircle cx='3.1' cy='4.5' r='0.58' fill-opacity='1.00'/%3E%3Ccircle cx='1.9' cy='8.1' r='0.68' fill-opacity='1.00'/%3E%3Ccircle cx='19.7' cy='15.6' r='0.52' fill-opacity='1.00'/%3E%3Ccircle cx='8.6' cy='15.9' r='0.92' fill-opacity='1.00'/%3E%3Ccircle cx='4.2' cy='4.2' r='0.49' fill-opacity='1.00'/%3E%3Ccircle cx='14.1' cy='4.7' r='0.35' fill-opacity='1.00'/%3E%3Ccircle cx='8.9' cy='10.2' r='0.92' fill-opacity='1.00'/%3E%3Ccircle cx='12.4' cy='11.1' r='0.76' fill-opacity='1.00'/%3E%3Ccircle cx='21.6' cy='14.0' r='0.87' fill-opacity='1.00'/%3E%3Ccircle cx='9.4' cy='7.2' r='0.41' fill-opacity='1.00'/%3E%3Ccircle cx='1.5' cy='1.2' r='0.48' fill-opacity='1.00'/%3E%3Ccircle cx='8.2' cy='0.9' r='0.35' fill-opacity='1.00'/%3E%3Ccircle cx='2.4' cy='6.5' r='0.37' fill-opacity='1.00'/%3E%3Ccircle cx='14.7' cy='2.7' r='0.50' fill-opacity='1.00'/%3E%3Ccircle cx='8.7' cy='2.2' r='0.86' fill-opacity='1.00'/%3E%3Ccircle cx='11.2' cy='8.7' r='0.40' fill-opacity='1.00'/%3E%3Ccircle cx='8.2' cy='4.8' r='0.85' fill-opacity='1.00'/%3E%3Ccircle cx='0.6' cy='17.1' r='0.67' fill-opacity='1.00'/%3E%3Ccircle cx='13.0' cy='0.5' r='0.67' fill-opacity='1.00'/%3E%3Ccircle cx='20.7' cy='12.5' r='0.51' fill-opacity='1.00'/%3E%3Ccircle cx='4.0' cy='13.9' r='0.67' fill-opacity='1.00'/%3E%3Ccircle cx='7.9' cy='4.0' r='0.84' fill-opacity='1.00'/%3E%3Ccircle cx='20.5' cy='14.5' r='0.84' fill-opacity='1.00'/%3E%3Ccircle cx='5.4' cy='9.3' r='0.56' fill-opacity='1.00'/%3E%3Ccircle cx='0.7' cy='5.0' r='0.51' fill-opacity='1.00'/%3E%3Ccircle cx='23.0' cy='8.1' r='0.91' fill-opacity='1.00'/%3E%3Ccircle cx='22.9' cy='6.6' r='0.48' fill-opacity='1.00'/%3E%3Ccircle cx='4.7' cy='3.7' r='0.72' fill-opacity='1.00'/%3E%3Ccircle cx='20.2' cy='8.6' r='0.74' fill-opacity='1.00'/%3E%3Ccircle cx='2.0' cy='11.9' r='0.90' fill-opacity='1.00'/%3E%3Ccircle cx='18.0' cy='8.6' r='0.46' fill-opacity='1.00'/%3E%3Ccircle cx='8.0' cy='14.4' r='0.93' fill-opacity='1.00'/%3E%3Ccircle cx='9.6' cy='17.0' r='0.78' fill-opacity='1.00'/%3E%3Ccircle cx='3.0' cy='2.7' r='0.89' fill-opacity='1.00'/%3E%3Ccircle cx='3.5' cy='14.9' r='0.94' fill-opacity='1.00'/%3E%3Ccircle cx='8.4' cy='9.9' r='0.43' fill-opacity='1.00'/%3E%3Ccircle cx='23.3' cy='11.7' r='0.67' fill-opacity='1.00'/%3E%3Ccircle cx='10.4' cy='15.7' r='0.85' fill-opacity='1.00'/%3E%3Ccircle cx='6.0' cy='5.3' r='0.49' fill-opacity='1.00'/%3E%3Ccircle cx='6.2' cy='7.5' r='0.43' fill-opacity='1.00'/%3E%3Ccircle cx='8.5' cy='8.2' r='0.70' fill-opacity='1.00'/%3E%3Ccircle cx='10.1' cy='16.5' r='0.65' fill-opacity='1.00'/%3E%3Ccircle cx='12.6' cy='0.3' r='0.61' fill-opacity='1.00'/%3E%3Ccircle cx='0.1' cy='14.4' r='0.45' fill-opacity='1.00'/%3E%3Ccircle cx='17.4' cy='10.0' r='0.55' fill-opacity='1.00'/%3E%3Ccircle cx='13.3' cy='14.1' r='0.41' fill-opacity='1.00'/%3E%3Ccircle cx='6.0' cy='5.0' r='0.81' fill-opacity='1.00'/%3E%3Ccircle cx='13.5' cy='13.7' r='0.90' fill-opacity='1.00'/%3E%3Ccircle cx='14.7' cy='9.1' r='0.66' fill-opacity='1.00'/%3E%3C/g%3E%3C/svg%3E");
  -webkit-mask-size:100% 100%, 24px 18px;
          mask-size:100% 100%, 24px 18px;
  -webkit-mask-repeat:no-repeat, repeat;
          mask-repeat:no-repeat, repeat;
  -webkit-mask-composite:source-over; mask-composite:add;
  animation:np-uo-grain 2.4s linear infinite, np-uo-surge 5.5s ease-in infinite}
/* the grains stream backwards, so the break-up at the start moves */
@keyframes np-uo-grain{
  from{-webkit-mask-position:0 0, 0 0; mask-position:0 0, 0 0}
  to  {-webkit-mask-position:0 0, -24px 0; mask-position:0 0, -24px 0}}
/* a bright body leaves the head and runs down the tail */
@keyframes np-uo-surge{
  0%  {background-position:115% 50%, 0 0}
  55% {background-position:-40% 50%, 0 0}
  100%{background-position:-40% 50%, 0 0}}
/* the dust coming off the tail: grains left of the first letter, drifting
   back and thinning out */
.cell-name:has(.np-uodega)::before{content:''; position:absolute; pointer-events:none;
  right:100%; top:.15em; width:30px; height:1.05em; margin-right:-2px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='16'%3E%3Cg fill='%23B8CCFF'%3E%3Ccircle cx='13.6' cy='8.5' r='0.57' fill-opacity='0.87'/%3E%3Ccircle cx='21.0' cy='14.0' r='0.77' fill-opacity='0.49'/%3E%3Ccircle cx='16.8' cy='15.1' r='0.73' fill-opacity='0.43'/%3E%3Ccircle cx='3.6' cy='7.1' r='0.38' fill-opacity='0.48'/%3E%3Ccircle cx='2.2' cy='10.7' r='0.70' fill-opacity='0.84'/%3E%3Ccircle cx='4.6' cy='11.5' r='0.65' fill-opacity='0.43'/%3E%3Ccircle cx='26.5' cy='15.5' r='0.45' fill-opacity='0.87'/%3E%3Ccircle cx='11.9' cy='7.8' r='0.80' fill-opacity='0.81'/%3E%3Ccircle cx='4.8' cy='6.9' r='0.58' fill-opacity='0.54'/%3E%3Ccircle cx='5.9' cy='5.1' r='0.67' fill-opacity='0.36'/%3E%3Ccircle cx='16.6' cy='7.0' r='0.36' fill-opacity='0.53'/%3E%3Ccircle cx='18.7' cy='8.2' r='0.38' fill-opacity='0.89'/%3E%3Ccircle cx='23.7' cy='15.5' r='0.40' fill-opacity='0.50'/%3E%3Ccircle cx='1.2' cy='12.5' r='0.47' fill-opacity='0.42'/%3E%3C/g%3E%3C/svg%3E");
  background-size:30px 16px;
  -webkit-mask-image:linear-gradient(90deg, transparent, #000 85%);
          mask-image:linear-gradient(90deg, transparent, #000 85%);
  animation:np-uo-dust 2.4s linear infinite}
@keyframes np-uo-dust{from{background-position:0 0} to{background-position:-30px 0}}

/* ------------------------------------------------------------- the surface
   A meteor shower: every meteor leaves from the same RADIANT, a point above
   the top-right of the row, so every streak points away from it — that is
   what makes it a shower and not rain. Eight meteors on one 7.3s clock, each
   alive for about half a second. They are placed in the bands above and
   below the text and in the gap before the money, and the ground is a
   still starfield of three coprime tiles (the Migla construction) under a
   faint glow from the radiant's side. */
.sf-meteorai{--int:#070B19; position:relative; isolation:isolate;
  background-color:var(--int);
  background-image:
    radial-gradient(1px 1px at 11px 7px,  rgba(222,234,255,.55), transparent),
    radial-gradient(1px 1px at 40px 31px, rgba(222,234,255,.28), transparent),
    radial-gradient(1.3px 1.3px at 23px 50px, rgba(222,234,255,.5), transparent),
    radial-gradient(1px 1px at 71px 12px, rgba(222,234,255,.4), transparent),
    radial-gradient(1px 1px at 58px 44px, rgba(222,234,255,.3), transparent),
    radial-gradient(1px 1px at 96px 4px,  rgba(222,234,255,.45), transparent),
    radial-gradient(90% 160% at 92% -40%, rgba(80,100,190,.2), transparent 60%),
    linear-gradient(180deg, #0A1026, #060917);
  background-size:67px 58px, 67px 58px, 89px 58px, 89px 58px, 113px 58px, 113px 58px, 100% 100%, 100% 100%}
.sf-meteorai > .cell-num, .sf-meteorai > .cell-name, .sf-meteorai > .cell-net,
.sf-meteorai > .eng{position:relative; z-index:4}
.sf-meteorai > :is(.M,.N,.O,.P){position:absolute; inset:0; overflow:hidden; border-radius:5px;
  pointer-events:none; z-index:1}
.framed.sf-meteorai > :is(.M,.N,.O,.P){inset:7px; border-radius:2px}
.sf-meteorai > :is(.M,.N,.O,.P)::before, .sf-meteorai > :is(.M,.N,.O,.P)::after{content:'';
  position:absolute; width:var(--len); height:1.3px; border-radius:1px;
  transform-origin:0 50%;
  background:linear-gradient(90deg, rgba(170,205,255,0), rgba(200,225,255,.5) 70%, #FFFFFF);
  box-shadow:0 0 3px rgba(190,220,255,.25);
  opacity:0; animation:sf-me-fall 7.3s linear infinite}
.sf-meteorai > .M::before{left:71%; top:3px;     --a:126deg; --len:34px; --run:46px; animation-delay:0s}
.sf-meteorai > .M::after {left:38%; top:5px;     --a:155deg; --len:26px; --run:40px; animation-delay:.9s}
.sf-meteorai > .N::before{left:56%; top:14px;    --a:141deg; --len:30px; --run:44px; animation-delay:2.1s}
.sf-meteorai > .N::after {left:22%; top:2px;     --a:161deg; --len:22px; --run:34px; animation-delay:3s}
.sf-meteorai > .O::before{left:63%; bottom:6px;  --a:124deg; --len:28px; --run:40px; animation-delay:3.8s}
.sf-meteorai > .O::after {left:84%; top:9px;     --a:99deg;  --len:24px; --run:36px; animation-delay:4.7s}
.sf-meteorai > .P::before{left:47%; bottom:4px;  --a:138deg; --len:24px; --run:38px; animation-delay:5.6s}
.sf-meteorai > .P::after {left:30%; bottom:9px;  --a:148deg; --len:20px; --run:32px; animation-delay:6.5s}
@keyframes sf-me-fall{
  0%   {opacity:0; transform:rotate(var(--a)) translateX(0)}
  1%   {opacity:1}
  5.5% {opacity:.9}
  7%   {opacity:0; transform:rotate(var(--a)) translateX(var(--run))}
  100% {opacity:0; transform:rotate(var(--a)) translateX(var(--run))}}

/* ------------------------------------------------ SET EFFECT · PERIHELIS
   Three blows in one sequence, once a lap (11s), starting as the comet
   reaches the top-left corner. Chosen by Rapolas from five candidates:
   Botagas, Bombardavimas and Smūgis, "one big sequence"; then "polish the
   animation and don't forget the space feel". Drawn in kometa.js (`.km-fx`);
   timed here.

     0 - 7 %      THE WHIP. The tail lashes round the whole row and CRACKS at
                  the corner: WHITE, an anamorphic flare along the top edge,
                  rays and a glint out of the crack, a shake. The comet is
                  flung off; the lash is left as an ionised trail that cools
                  from white through blue to violet.
     11 - 21 %    THE RAIN. Four meteors of its debris, one after another: a
                  streak, a star-shaped glint, a plasma glow, a ring, stardust.
     22 - 27 %    THE IMPACT. The comet comes back from the top right: the row
                  drops to deep space and the stars stretch into warp lines
                  converging on where it will land; WHITE on the hit; then
                  space in NEGATIVE — a pale field, the crater a black hole,
                  the stars as dark points; a hard shake, a two-colour
                  shockwave, stardust drifting outward, and a cloud of
                  glowing gas billowing out of the crater and thinning away.
     55 %         the comet is back on its orbit.

   THE SPACE FEEL, in rules: nothing is orange. Light is white, blue and
   violet; sparks are four-point stars (the shape a lens gives a point of
   light), not dots; debris drifts and slows rather than falling, because
   there is no gravity to fall in; what is left behind is a nebula, not smoke.

   AN IMPACT FRAME IS A HARD CUT: `steps(1,end)` on everything that belongs
   to one. The flashes are in the SVG at z 2, under the cells at z 4, which
   invert for exactly those frames. Two white frames a lap, 2.1s apart. */
.fr-kometa .km-fx{display:none}
.fr-kometa.sf-meteorai:has(.np-uodega) .km-fx{display:inline}
.km-fx > *{opacity:0}
.km-fx > .fx-hit, .km-fx .fx-ejecta{opacity:1}
.km-fx .fx-hit > *:not(.fx-ejecta){opacity:0}
.km-fx > g:not([class]), .km-fx .fx-hit > g:not([class]){opacity:1}
.km-fx .dust, .km-fx .fx-glint, .km-fx .fx-flash{opacity:0}
.km-fx .fx-streak{stroke-dasharray:1 1}

/* The shared pieces. Each is written for an event at 2.68 % of the lap and
   moved to its moment by --hd, a custom property: the `animation` shorthand
   resets animation-delay, so a delay in a separate rule would lose to any
   more specific shorthand. */
.km-fx .dust{animation:px-dust 11s linear infinite}
@keyframes px-dust{
  0%,2.67%{opacity:0; transform:translate(0,0) scale(.4); animation-timing-function:steps(1,end)}
  2.68%{opacity:1; transform:translate(0,0) scale(1.3); animation-timing-function:cubic-bezier(.1,.75,.3,1)}
  7%{opacity:.55} 9%{opacity:1} 12%{opacity:.45} 14%{opacity:.9}
  22%,100%{opacity:0; transform:translate(var(--dx),var(--dy)) scale(.5)}}
@keyframes px-glint{
  0%,2.67%{opacity:0; transform:scale(0) rotate(0deg); animation-timing-function:steps(1,end)}
  2.68%{opacity:1; transform:scale(1.5) rotate(0deg); animation-timing-function:cubic-bezier(.2,.7,.3,1)}
  8%,100%{opacity:0; transform:scale(.2) rotate(45deg)}}
@keyframes px-plasma{0%,2.67%{opacity:0; transform:scale(.5); animation-timing-function:steps(1,end)}
  2.68%{opacity:1; transform:scale(1.25); animation-timing-function:cubic-bezier(.2,.7,.3,1)} 10%{opacity:.8; transform:scale(1)} 34%,100%{opacity:0; transform:scale(.85)}}

/* ---- 1. the whip */
.km-fx .fx-lash  {animation:px-lash 11s steps(1,end) infinite}
.km-fx .fx-white1{animation:px-white1 11s steps(1,end) infinite}
.km-fx .fx-burn  {animation:px-burn 11s linear infinite}
.km-fx .fx-burn-halo{animation-name:px-burn-halo}
.km-fx .fx-flare {animation:px-flare 11s linear infinite}
.km-fx .fx-lines {animation:px-lines 11s linear infinite}
.km-fx .fx-crater.fx-crack{animation:px-plasma 11s linear infinite; animation-delay:0.515s}
.km-fx .fx-glint.fx-crack{animation:px-glint 11s linear infinite; animation-delay:0.515s}
.km-fx .fx-ejecta.fx-crack{--hd:0.515s}
@keyframes px-lash  {0%{opacity:0; animation-timing-function:ease-out} 1%{opacity:1; animation-timing-function:steps(1,end)} 6.6%{opacity:0} 100%{opacity:0}}
@keyframes px-white1{0%{opacity:0} 6.6%{opacity:1} 7.36%{opacity:0} 100%{opacity:0}}
@keyframes px-burn{0%,7.35%{opacity:0; stroke:#FFFFFF; animation-timing-function:steps(1,end)}
  7.36%{opacity:.75; stroke:#FFFFFF; animation-timing-function:ease-out} 13%{opacity:.5; stroke:#A9D4FF}
  22%{opacity:.25; stroke:#8C7CFF; animation-timing-function:ease-in} 34%,100%{opacity:0; stroke:#6A4CE0}}
@keyframes px-burn-halo{0%,7.35%{opacity:0; stroke:#9FC8FF; animation-timing-function:steps(1,end)}
  7.36%{opacity:.22; stroke:#CFE6FF; animation-timing-function:ease-out} 14%{opacity:.1; stroke:#7F8CFF} 24%,100%{opacity:0; stroke:#6A4CE0}}
@keyframes px-flare{0%,7.35%{opacity:0; transform:scaleX(.2); animation-timing-function:steps(1,end)}
  7.36%{opacity:1; transform:scaleX(.6); animation-timing-function:cubic-bezier(.15,.8,.3,1)} 13%,100%{opacity:0; transform:scaleX(1.15)}}
@keyframes px-lines{0%,7.35%{opacity:0; transform:scale(.7); animation-timing-function:steps(1,end)}
  7.36%{opacity:1; transform:scale(.85); animation-timing-function:cubic-bezier(.1,.85,.3,1)} 8.8%{opacity:.45; transform:scale(1.15)} 9.8%,100%{opacity:0; transform:scale(1.25)}}

/* ---- 2. the rain: meteors at 11, 14, 17 and 20 % of the lap */
.km-fx .fx-hit1{--hd:0.915s}
.km-fx .fx-hit2{--hd:1.245s}
.km-fx .fx-hit3{--hd:1.575s}
.km-fx .fx-hit4{--hd:1.905s}
.km-fx .fx-streak{animation:px-streak 11s linear infinite; animation-delay:var(--hd,0s)}
.km-fx .fx-flash {animation:px-glint 11s linear infinite; animation-delay:var(--hd,0s)}
.km-fx .fx-hit .fx-crater{animation:px-plasma 11s linear infinite; animation-delay:var(--hd,0s)}
.km-fx .fx-hit .fx-wave  {animation:px-wave 11s linear infinite; animation-delay:var(--hd,0s)}
@keyframes px-streak{0%,.1%{opacity:1; stroke-dashoffset:1; animation-timing-function:cubic-bezier(.55,0,1,1)} 2.68%{opacity:1; stroke-dashoffset:0} 3.6%,100%{opacity:0; stroke-dashoffset:0}}
@keyframes px-wave{0%,2.67%{opacity:0; transform:scale(.08); animation-timing-function:steps(1,end)}
  2.68%{opacity:1; transform:scale(.1); animation-timing-function:cubic-bezier(.12,.85,.25,1)} 12%,100%{opacity:0; transform:scale(1)}}

/* ---- 3. the impact */
.km-fx .fx-dim   {animation:px-dim 11s linear infinite}
.km-fx .fx-warp  {animation:px-warp 11s linear infinite}
.km-fx .fx-dive  {animation:px-dive 11s steps(1,end) infinite}
.km-fx .fx-white2{animation:px-white2 11s steps(1,end) infinite}
.km-fx .fx-neg   {animation:px-neg 11s steps(1,end) infinite}
.km-fx .fx-bigcrater{animation:px-bigcrater 11s linear infinite}
.km-fx .fx-cloud{animation:px-cloud 11s linear infinite}
.km-fx .fx-cloud .blob{animation:px-blob 11s linear infinite}
.km-fx .fx-cloud .wisps{animation:px-wisps 11s linear infinite}
.km-fx .fx-bigwave{animation:px-bigwave 11s linear infinite}
.km-fx .fx-bigwave2{animation-delay:.1s}
.km-fx .fx-bigglint{animation:px-glint 11s linear infinite; animation-delay:2.636s}
.km-fx .fx-bigejecta{--hd:2.636s}
@keyframes px-dim   {0%,22%{opacity:0; animation-timing-function:ease-in} 25.49%{opacity:1; animation-timing-function:steps(1,end)} 25.5%,100%{opacity:0}}
@keyframes px-warp  {0%,22%{opacity:0; transform:scale(1.6); animation-timing-function:cubic-bezier(.5,0,.9,.6)}
  25.49%{opacity:.85; transform:scale(1); animation-timing-function:steps(1,end)} 25.5%,100%{opacity:0; transform:scale(1)}}
@keyframes px-dive  {0%{opacity:0} 22%{opacity:1} 25.5%{opacity:0} 100%{opacity:0}}
@keyframes px-white2{0%{opacity:0} 25.5%{opacity:1} 26.26%{opacity:0} 100%{opacity:0}}
@keyframes px-neg   {0%{opacity:0} 26.26%{opacity:1} 26.64%{opacity:0} 100%{opacity:0}}
@keyframes px-bigcrater{0%,26.63%{opacity:0; transform:scale(.5); animation-timing-function:steps(1,end)}
  26.64%{opacity:1; transform:scale(1.2); animation-timing-function:cubic-bezier(.2,.7,.3,1)} 34%{opacity:.85; transform:scale(1)} 66%,100%{opacity:0; transform:scale(.85)}}
/* the cloud billows out of the crater, drifts apart and thins away */
@keyframes px-cloud{0%,26.63%{opacity:0; transform:scale(.2); animation-timing-function:steps(1,end)}
  26.64%{opacity:.4; transform:scale(.2); animation-timing-function:cubic-bezier(.12,.75,.3,1)}
  32%{opacity:1; transform:scale(.85)} 52%{opacity:.8; transform:scale(1.12); animation-timing-function:ease-in}
  86%,100%{opacity:0; transform:scale(1.4)}}
@keyframes px-blob{0%,26.64%{transform:translate(0,0); animation-timing-function:cubic-bezier(.2,.6,.4,1)} 86%,100%{transform:translate(var(--bx),var(--by))}}
@keyframes px-wisps{0%,26.64%{opacity:0; transform:rotate(0deg)} 34%{opacity:1} 60%{opacity:.7} 86%,100%{opacity:0; transform:rotate(7deg)}}
@keyframes px-bigwave{0%,26.63%{opacity:0; transform:scale(.05); animation-timing-function:steps(1,end)}
  26.64%{opacity:1; transform:scale(.08); animation-timing-function:cubic-bezier(.12,.85,.25,1)} 40%,100%{opacity:0; transform:scale(1)}}

/* ---- the row answers every blow */
.fr-kometa.sf-meteorai:has(.np-uodega) > :is(.cell-num,.cell-name,.cell-net,.eng){animation:px-cells 11s linear infinite}
.fr-kometa.sf-meteorai:has(.np-uodega) > .km-sky{animation:px-sky 11s linear infinite}
.fr-kometa.sf-meteorai:has(.np-uodega) :is(.km-head,.km-ion,.km-dust,.km-light){animation:px-body 11s linear infinite}
.fr-kometa.sf-meteorai:has(.np-uodega){animation:px-bloom 11s linear infinite}
@keyframes px-cells{
  0%,6.59%{filter:none; transform:none; animation-timing-function:steps(1,end)}
  6.6%{filter:invert(1) hue-rotate(180deg) contrast(1.35)}
  7.36%{filter:none; transform:translate(-4px,-2px)} 7.74%{transform:translate(3px,2px)} 8.12%{transform:translate(-2px,1px)}
  8.5%{transform:translate(1px,-.5px)} 8.88%{transform:none}
  11%{transform:translate(1px,-1px)} 11.38%{transform:none}
  14%{transform:translate(-1px,1px)} 14.38%{transform:none}
  17%{transform:translate(1px,1px)} 17.38%{transform:none}
  20%{transform:translate(-1px,-1px)} 20.38%{transform:none}
  22%{filter:none; transform:none; animation-timing-function:ease-in}
  25.49%{filter:brightness(.5) saturate(.6); transform:none; animation-timing-function:steps(1,end)}
  25.5%{filter:invert(1) hue-rotate(180deg) contrast(1.35)}
  26.26%{filter:none; transform:translate(5px,-3px)}
  26.64%{filter:none; transform:translate(-5px,3px)} 27.02%{transform:translate(4px,2px)} 27.4%{transform:translate(-2.5px,-1px)}
  27.78%{transform:translate(1.5px,1px)} 28.16%{transform:translate(-.5px,0)} 28.54%,100%{filter:none; transform:none}}
@keyframes px-sky{
  0%,7.35%{transform:none; animation-timing-function:steps(1,end)}
  7.36%{transform:translate(-4px,-2px)} 7.74%{transform:translate(3px,2px)} 8.12%{transform:translate(-2px,1px)}
  8.5%{transform:translate(1px,-.5px)} 8.88%{transform:none}
  11%{transform:translate(1px,-1px)} 11.38%{transform:none}
  14%{transform:translate(-1px,1px)} 14.38%{transform:none}
  17%{transform:translate(1px,1px)} 17.38%{transform:none}
  20%{transform:translate(-1px,-1px)} 20.38%{transform:none}
  26.26%{transform:translate(5px,-3px)} 26.64%{transform:translate(-5px,3px)} 27.02%{transform:translate(4px,2px)}
  27.4%{transform:translate(-2.5px,-1px)} 27.78%{transform:translate(1.5px,1px)} 28.16%{transform:translate(-.5px,0)} 28.54%,100%{transform:none}}
/* The orbiting comet hands over to the whip's own head at the corner (lap
   time 0) — otherwise it sat there, lit, while its lash went round without
   it — and comes back once the impact has cleared. */
/* the comet does not vanish on the lap's first frame: it fades over the first
   moments of the lash, which grows out of its tail (buildFX's whip) */
@keyframes px-body{0%{opacity:1; animation-timing-function:ease-in} 1.6%{opacity:0} 52%{opacity:0; animation-timing-function:ease-in-out} 65%,100%{opacity:1}}
@keyframes px-bloom{
  0%,7.35%{box-shadow:inset 0 2px 7px rgba(0,0,0,.55), inset 0 0 0 1px rgba(0,0,0,.45), 0 2px 5px rgba(0,0,0,.4), 0 0 0 0 rgba(150,190,255,0); animation-timing-function:steps(1,end)}
  7.36%{box-shadow:inset 0 2px 7px rgba(0,0,0,.55), inset 0 0 0 1px rgba(0,0,0,.45), 0 2px 5px rgba(0,0,0,.4), 0 0 34px 5px rgba(200,228,255,.55); animation-timing-function:ease-out}
  16%{box-shadow:inset 0 2px 7px rgba(0,0,0,.55), inset 0 0 0 1px rgba(0,0,0,.45), 0 2px 5px rgba(0,0,0,.4), 0 0 0 0 rgba(150,190,255,0); animation-timing-function:steps(1,end)}
  26.64%{box-shadow:inset 0 2px 7px rgba(0,0,0,.55), inset 0 0 0 1px rgba(0,0,0,.45), 0 2px 5px rgba(0,0,0,.4), 0 0 48px 9px rgba(170,150,255,.6); animation-timing-function:ease-out}
  40%{box-shadow:inset 0 2px 7px rgba(0,0,0,.55), inset 0 0 0 1px rgba(0,0,0,.45), 0 2px 5px rgba(0,0,0,.4), 0 0 22px 3px rgba(110,140,255,.28); animation-timing-function:ease-in}
  60%,100%{box-shadow:inset 0 2px 7px rgba(0,0,0,.55), inset 0 0 0 1px rgba(0,0,0,.45), 0 2px 5px rgba(0,0,0,.4), 0 0 0 0 rgba(110,140,255,0)}}

/* Reduced motion. `*` in index.html's global rule does not reach pseudo-
   elements, so every one is named here. The frame's SMIL is stripped by the
   dresser, which draws the comet standing still on the top edge. */
@media (prefers-reduced-motion: reduce){
  .np-uodega, .cell-name:has(.np-uodega)::before{animation:none}
  .sf-meteorai > :is(.M,.N,.O,.P)::before, .sf-meteorai > :is(.M,.N,.O,.P)::after{animation:none; opacity:0}
  .sf-meteorai > .M::before, .sf-meteorai > .N::after{opacity:.7; transform:rotate(var(--a)) translateX(10px)}
  .fr-kometa .km-fx{display:none !important}
  .fr-kometa .km-sky :is(.km-plane,.km-react,.km-disk,.km-glit){animation:none}
  .fr-kometa.sf-meteorai:has(.np-uodega),
  .fr-kometa.sf-meteorai:has(.np-uodega) :is(.km-ion,.km-head,.km-dust,.km-light,.km-sky),
  .fr-kometa.sf-meteorai:has(.np-uodega) > :is(.cell-num,.cell-name,.cell-net,.eng){animation:none}
}
