/* #819 (epic #815) -- the vote seats row. Loaded by index.html; every rule is scoped to .vs-row (or to #screen-vote.vs-on, which
   public/vote-seats.js sets only while a row is mounted), so with FLAGS.voteSeats off nothing here matches anything.

   THE SPEC: docs/design/vote-seats/models.md (the rig, the states, the 60 fps rules) and commingled.md section 6 (the beat table,
   implemented line for line below). 60 fps rules kept here:
     - only transform and opacity animate; there is no filter, mask or blur anywhere in this file;
     - every rig part uses transform-box: fill-box;
     - CSS runs the motion; JavaScript only swaps one class per seat per 1.5 s tick;
     - the whole row pauses (animation-play-state) when it is off screen or the page is hidden (.vs-paused).
   Keyframes are prefixed vs- because @keyframes names are global and the page already owns one called "breathe".
   The reference rig is docs/design/vote-seats/canvas/Seats.dc.html; its .dc.html runtime is not used. */

/* ---------------------------------------------------------------- palette (DESIGN.md section 2) */
.vs-row {
  /* Night: Drexel */
  --vs-gold: #FFC600; --vs-gold-2: #ffd84d;
  --vs-cream: #FBF4DD; --vs-cream-2: #efe3bd;
  --vs-navy: #07294D; --vs-navy-2: #0e3c6b;
  --vs-blue: #2E78C0; --vs-blue-2: #4b93d6;
  --vs-red: #BD3039; --vs-red-2: #d4505a;
  --vs-ink: #0a1c33; --vs-zig-blue: #2E78C0;
}
html[data-mode="day"] .vs-row {
  /* Day: Masterman. Each role maps to the Masterman palette; Zig's blue accents sit on cream, so they take the board blue. */
  --vs-gold: #FFD200; --vs-gold-2: #ffdf4d;
  --vs-cream: #FFF7E2; --vs-cream-2: #f3e8c6;
  --vs-navy: #0c2a66; --vs-navy-2: #1746a0;
  --vs-blue: #7FD0F5; --vs-blue-2: #a4dcf7;
  --vs-red: #FF5A66; --vs-red-2: #ff7f88;
  --vs-ink: #081d44; --vs-zig-blue: #1C56B8;
}
.vs-row .c-chalky { --vs-body: var(--vs-navy); --vs-belly: var(--vs-navy-2); --vs-acc: var(--vs-gold); --vs-feet: var(--vs-gold); --vs-frame: var(--vs-gold); --vs-rim: var(--vs-cream); --vs-mouth: var(--vs-red); }
.vs-row .c-bloop { --vs-body: var(--vs-blue); --vs-belly: var(--vs-blue-2); --vs-acc: var(--vs-cream); --vs-feet: var(--vs-gold); --vs-frame: var(--vs-gold); --vs-rim: var(--vs-cream); --vs-mouth: var(--vs-red); }
.vs-row .c-pip { --vs-body: var(--vs-red); --vs-belly: var(--vs-red-2); --vs-acc: var(--vs-gold); --vs-feet: var(--vs-gold); --vs-frame: var(--vs-cream); --vs-rim: var(--vs-cream); --vs-mouth: var(--vs-ink); }
.vs-row .c-mo { --vs-body: var(--vs-gold); --vs-belly: var(--vs-gold-2); --vs-acc: var(--vs-navy); --vs-feet: var(--vs-navy); --vs-frame: var(--vs-navy); --vs-rim: var(--vs-cream); --vs-mouth: var(--vs-red); }
.vs-row .c-zig { --vs-body: var(--vs-cream); --vs-belly: var(--vs-cream-2); --vs-acc: var(--vs-zig-blue); --vs-feet: var(--vs-zig-blue); --vs-frame: var(--vs-zig-blue); --vs-rim: var(--vs-ink); --vs-mouth: var(--vs-red); }
.vs-row .f-body { fill: var(--vs-body); }
.vs-row .f-belly { fill: var(--vs-belly); }
.vs-row .f-acc { fill: var(--vs-acc); }
.vs-row .f-feet { fill: var(--vs-feet); }
.vs-row .f-stalk { stroke: var(--vs-acc); }
.vs-row .f-bead { fill: var(--vs-gold); }
.vs-row .f-frame { stroke: var(--vs-frame); }
.vs-row .f-rim { stroke: var(--vs-rim); }
.vs-row .f-mouth { fill: var(--vs-mouth); }
.vs-row .f-ink { fill: var(--vs-ink); }
.vs-row .f-tip { fill: var(--vs-red); }

/* ---------------------------------------------------------------- layout */
/* The Exit link above has a -8px bottom margin, so the row starts 8px up inside it; the 2px of padding keeps the first seat clear of it. */
/* Nothing in the row takes a tap except the "+N" button, so the row's own box lets the taps through to the Exit link it overlaps. */
.vs-row { margin: 0 0 4px; padding: 2px 0 0; pointer-events: none; }
.vs-more { pointer-events: auto; }
.vs-list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: 2px 0.25rem; }
.vs-seat { width: 3.25rem; flex: none; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 1px; }
.vs-fig { position: relative; width: 2.75rem; height: 2.75rem; display: flex; align-items: flex-end; contain: layout style; }
.vs-name { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.6875rem; font-weight: 800; line-height: 1.2; color: var(--chalk); }
/* "You" is a gold pill with navy text: gold TEXT on the day board fails 4.5:1 where the page's highlight lightens it (about 4.2:1);
   navy on gold is above 9:1 in both modes. */
.vs-seat.you .vs-name { background: var(--p); color: #07294D; padding: 0 0.4rem; border-radius: 0.5rem; }
.vs-badge { position: absolute; top: 0; right: -2px; width: 0.9375rem; height: 0.9375rem; border-radius: 50%; background: var(--p); color: #07294D;
  display: flex; align-items: center; justify-content: center; opacity: 0; transform: scale(0.4);
  transition: transform .32s cubic-bezier(.34,1.56,.64,1), opacity .2s ease; }
.vs-badge svg { width: 0.5625rem; height: 0.5625rem; }
.vs-badge.on { opacity: 1; transform: scale(1); }
/* the check waits until its seat has landed (the arrival is 620 ms, seat n starts at n * 90 ms) */
.vs-row .b-arrive + .vs-badge.on { opacity: 0; transform: scale(0.4); animation: vs-badgein .32s cubic-bezier(.34,1.56,.64,1) calc(var(--a, 0s) + .5s) both; }

/* the "+N" chip: a real button, a 44 pt target */
.vs-more { width: 2.75rem; height: 2.75rem; padding: 0; border-radius: 50%; border: 2px dashed var(--dim); background: transparent; color: var(--chalk);
  font-family: "Nunito", system-ui, sans-serif; font-size: 0.9375rem; font-weight: 800; line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center; }
.vs-more:active { background: var(--faint); }
.vs-more:focus-visible { outline: 3px solid var(--chalk); outline-offset: 3px; }

/* ---------------------------------------------------------------- the rig (reference: canvas/Seats.dc.html) */
.vs-row .m { display: block; width: 100%; height: auto; overflow: visible; }
.vs-row .m .shadow, .vs-row .m .lift, .vs-row .m .rig, .vs-row .m .arm-l, .vs-row .m .arm-r, .vs-row .m .eyes, .vs-row .m .blink, .vs-row .m .pupils { transform-box: fill-box; }
.vs-row .m .shadow { transform-origin: 50% 50%; transition: transform .36s cubic-bezier(.34,1.56,.64,1), opacity .36s ease; }
.vs-row .m .lift { transform-origin: 50% 100%; transition: transform .36s cubic-bezier(.34,1.56,.64,1); }
.vs-row .m .rig { transform-origin: 50% 100%; }
.vs-row .m .arm-l { transform-origin: 85% 12%; }
.vs-row .m .arm-r { transform-origin: 50% 4%; transform: rotate(-20deg); transition: transform .42s cubic-bezier(.34,1.56,.64,1); }
.vs-row .m .eyes, .vs-row .m .blink, .vs-row .m .pupils { transform-origin: 50% 50%; }
.vs-row .m .eyes { transition: transform .3s ease; }
/* the two poses: slumped while waiting, sitting tall with the chalk raised once voted. Reduce Motion shows exactly these. */
.vs-row .p-wait .lift { transform: translateY(8px) scale(1, .94); }
.vs-row .p-wait .eyes { transform: scaleY(.5); }
.vs-row .p-wait.b-perk .eyes { transform: scaleY(1); }
.vs-row .p-voted .lift { transform: translateY(-6px); }
.vs-row .p-voted .arm-r { transform: rotate(-150deg); }
.vs-row .p-voted .shadow { transform: scale(.86); opacity: .8; }

/* custom properties the beat table uses, in this order so the equal-specificity rules override .m (commingled.md section 6).
   --lean and --look also serve the greet (ack) beats, whose keyframes read them; --d and --a are set per seat by the row, --g per tick. */
.vs-row .m { --ad: 150ms; --tap: -8deg; }
.vs-row .c-zig { --ad: 100ms; }
.vs-row .p-wait { --rest: -20deg; }
.vs-row .p-voted { --rest: -150deg; }
.vs-row .b-ackl, .vs-row .b-ansl { --lean: -6deg; --look: -7px; }
.vs-row .b-ackr, .vs-row .b-ansr { --lean: 6deg; --look: 7px; }
.vs-row .b-lookl { --look: -7px; }
.vs-row .c-chalky.b-perk, .vs-row .b-cheer { --tap: -20deg; }

/* ---------------------------------------------------------------- the keyframes (commingled.md section 6: 19, plus the check's) */
@keyframes vs-breathe { 0%, 100% { transform: scale(1, 1); } 50% { transform: scale(1.015, 1.03); } }
@keyframes vs-blink { 0%, 93%, 100% { transform: scaleY(1); } 96% { transform: scaleY(.08); } }
@keyframes vs-blink2 { 0%, 90%, 93%, 94.8%, 97%, 100% { transform: scaleY(1); } 91.5% { transform: scaleY(.08); } 95.9% { transform: scaleY(.3); } }
@keyframes vs-peek { 0%, 83%, 100% { transform: translateX(0); } 86%, 97% { transform: translateX(-4px); } }
@keyframes vs-wtap { 0%, 14%, 100% { transform: rotate(var(--rest)); } 7% { transform: rotate(calc(var(--rest) - 6deg)); } }
@keyframes vs-arrive { 0% { transform: translateY(-70px) scale(.85); opacity: 0; } 55% { transform: translateY(0) scale(1.12, .84); opacity: 1; } 75% { transform: translateY(-8px) scale(.96, 1.05); } 100% { transform: none; opacity: 1; } }
@keyframes vs-situp { 0% { transform: scale(1, .92); } 40% { transform: translateY(-18px) scale(.95, 1.08); } 70% { transform: translateY(-3px) scale(1.04, .97); } 100% { transform: none; } }
@keyframes vs-nod { 0%, 100% { transform: rotate(0deg); } 30% { transform: rotate(var(--lean)); } 60% { transform: rotate(calc(var(--lean) * -0.4)); } }
@keyframes vs-look { 0%, 100% { transform: translateX(0); } 20%, 80% { transform: translateX(var(--look)); } }
@keyframes vs-wave { 0%, 100% { transform: rotate(0deg); } 20% { transform: rotate(110deg); } 35% { transform: rotate(80deg); } 50% { transform: rotate(110deg); } 65% { transform: rotate(80deg); } 80% { transform: rotate(110deg); } }
@keyframes vs-wave1 { 0%, 100% { transform: rotate(0deg); } 45% { transform: rotate(110deg); } }
@keyframes vs-tap { 0%, 100% { transform: rotate(var(--rest)); } 50% { transform: rotate(calc(var(--rest) + var(--tap))); } }
@keyframes vs-tap2 { 0%, 50%, 100% { transform: rotate(var(--rest)); } 25%, 75% { transform: rotate(calc(var(--rest) - 6deg)); } }
@keyframes vs-hopnod { 0%, 100% { transform: none; } 40% { transform: translateY(-6px) rotate(var(--lean)); } }
@keyframes vs-perk { 0%, 100% { transform: none; } 30% { transform: translateY(-14px) scale(.96, 1.06); } 60% { transform: scale(1.06, .94); } }
@keyframes vs-widen { 0%, 100% { transform: scale(1); } 40% { transform: scale(1.14); } }
@keyframes vs-dart { 0%, 100% { transform: translateX(0); } 30% { transform: translateX(-7px); } 65% { transform: translateX(7px); } }
@keyframes vs-stretch { 0%, 100% { transform: none; } 40%, 65% { transform: scale(.95, 1.1); } 85% { transform: scale(1.03, .97); } }
@keyframes vs-squint { 0%, 100% { transform: scaleY(1); } 30%, 70% { transform: scaleY(.35); } }
@keyframes vs-badgein { from { opacity: 0; transform: scale(.4); } to { opacity: 1; transform: scale(1); } }

/* ---------------------------------------------------------------- the beats (commingled.md section 6, one row per line) */
/* arrive: the screen opens; seats land 90 ms apart (--a = seat x 90 ms) */
.vs-row .b-arrive .rig { animation: vs-arrive .62s cubic-bezier(.34,1.3,.64,1) var(--a, 0s) both; }
/* sit up: their vote lands */
.vs-row .b-situp .rig { animation: vs-situp .56s cubic-bezier(.34,1.56,.64,1) both; }
/* idle: breathe, blink, and the waiting chalk tap (not Mo), each seat at its own negative delay --d */
.vs-row .b-idle .rig { animation: vs-breathe 3.2s ease-in-out var(--d, 0s) infinite; }
.vs-row .b-idle .blink { animation: vs-blink 4.6s linear var(--d, 0s) infinite; }
.vs-row .c-chalky.b-idle .blink { animation-name: vs-blink2; }
.vs-row .c-bloop.b-idle .pupils { animation: vs-peek 4.6s ease-in-out var(--d, 0s) infinite; }
.vs-row .c-chalky.p-wait.b-idle .arm-r, .vs-row .c-pip.p-wait.b-idle .arm-r { animation: vs-wtap 3.2s ease-in-out var(--d, 0s) infinite; }
.vs-row .c-bloop.p-wait.b-idle .arm-r, .vs-row .c-zig.p-wait.b-idle .arm-r { animation: vs-wtap 1.6s ease-in-out var(--d, 0s) infinite; }
/* greet (ack): a neighbor sat up, or the greeter of a random pair. Mo is late: 750 ms from 150 ms (capped at 1 s from the tick) */
.vs-row .b-ackl .pupils, .vs-row .b-ackr .pupils { animation: vs-look .9s ease-in-out both; }
.vs-row .b-ackl .rig, .vs-row .b-ackr .rig { animation: vs-nod .9s ease-in-out both; }
.vs-row .b-ackl .arm-l, .vs-row .b-ackr .arm-l { animation: vs-wave .9s ease-in-out both; }
.vs-row .c-mo.b-ackl .rig, .vs-row .c-mo.b-ackr .rig { animation: vs-nod .75s ease-in-out .15s both; }
.vs-row .c-mo.b-ackl .arm-l, .vs-row .c-mo.b-ackr .arm-l { animation: vs-wave .75s ease-in-out .15s both; }
/* answer (ans): the other seat of a pair replies in its own way, --ad after the greeter starts (Zig 100 ms, Mo 300 ms) */
.vs-row .b-ansl .pupils, .vs-row .b-ansr .pupils { animation: vs-look .75s ease-in-out var(--ad) both; }
.vs-row .c-chalky.b-ansl .arm-r, .vs-row .c-chalky.b-ansr .arm-r { animation: vs-tap .36s ease-in-out var(--ad) both; }
.vs-row .c-bloop.b-ansl .rig, .vs-row .c-bloop.b-ansr .rig, .vs-row .c-pip.b-ansl .rig, .vs-row .c-pip.b-ansr .rig { animation: vs-nod .75s ease-in-out var(--ad) both; }
.vs-row .c-bloop.b-ansl .arm-l, .vs-row .c-bloop.b-ansr .arm-l, .vs-row .c-zig.b-ansl .arm-l, .vs-row .c-zig.b-ansr .arm-l { animation: vs-wave1 .5s ease-in-out var(--ad) both; }
.vs-row .c-pip.b-ansl .arm-r, .vs-row .c-pip.b-ansr .arm-r { animation: vs-tap2 .48s ease-in-out var(--ad) both; }
.vs-row .c-mo.b-ansl .rig, .vs-row .c-mo.b-ansr .rig { animation: vs-nod .7s ease-in-out .3s both; }
.vs-row .c-mo.b-ansl .arm-l, .vs-row .c-mo.b-ansr .arm-l { animation: vs-wave .7s ease-in-out .3s both; }
.vs-row .c-zig.b-ansl .rig, .vs-row .c-zig.b-ansr .rig { animation: vs-hopnod .5s ease-in-out var(--ad) both; }
/* re-engage: a random seat, or the whole row coming back */
.vs-row .b-perk .rig { animation: vs-perk .6s cubic-bezier(.34,1.56,.64,1) both; }
.vs-row .b-perk .blink { animation: vs-widen .6s ease-out both; }
.vs-row .c-chalky.b-perk .arm-r { animation: vs-tap .6s cubic-bezier(.34,1.56,.64,1) both; }
.vs-row .c-zig.b-perk .pupils { animation: vs-dart .6s ease-in-out both; }
/* group moments (once per visit): everyone voted, you just voted, a quiet row */
.vs-row .b-cheer .rig { animation: vs-perk .6s cubic-bezier(.34,1.56,.64,1) var(--g, 0ms) both; }
.vs-row .b-cheer .arm-r { animation: vs-tap .6s cubic-bezier(.34,1.56,.64,1) var(--g, 0ms) both; }
.vs-row .b-stretch .rig { animation: vs-stretch .6s ease-in-out var(--g, 0ms) both; }
.vs-row .b-stretch .blink { animation: vs-squint .6s ease-in-out var(--g, 0ms) both; }
.vs-row .b-lookl .pupils { animation: vs-look .8s ease-in-out var(--g, 0ms) both; }

/* ---------------------------------------------------------------- pause and Reduce Motion */
/* off screen, or the page hidden: the row (and its tick) stop; coming back is a re-engage beat, not a replay of the arrival */
.vs-row.vs-paused * { animation-play-state: paused !important; }
/* The OS setting, not an app option: still poses (waiting seats slump; voters sit tall, chalk raised, with the check), and the row
   starts no timer. */
@media (prefers-reduced-motion: reduce) {
  .vs-row *, .vs-row *::before, .vs-row *::after { animation: none !important; transition: none !important; }
  .vs-row .vs-badge.on { opacity: 1; transform: scale(1); }
}

/* ---------------------------------------------------------------- the height the row costs, paid back only while a row is mounted
   The vote screen has no spare height at 375x667 (see the .vfoot comments in index.html). The row costs about 63 px. While a row is
   mounted, at EVERY screen height (so there is no cliff where a trim switches on):
     - the title underline goes (9 px of decoration), and the title keeps 3px below it;
     - the page's bottom padding drops from 40px to 14px (plus the home-indicator inset).
   On a short screen (max-height 700px: the iPhone SE class, 375x667) the rest is paid back, so the page still does not scroll at all,
   even with the native status-bar inset above it (about 20px on an SE):
     - the bottom padding drops again, to 4px (plus the home-indicator inset);
     - the "Voting ends in ..." line is 11.5px instead of 12.5px, which keeps it on one line (it wraps to two once the countdown has real
       digits, and that second line is 19px);
     - the "made with love by MooseQuest" footer is hidden. It is the brand footer, so it is hidden ONLY here: the vote screen, with a row
       mounted, on a screen 700px tall or less (the reading screen does the same at 520px, body[data-screen="walk-fan"]). Every other
       screen and every taller phone keeps it. */
#screen-vote.vs-on #ballotWrap .underline { display: none; }
#screen-vote.vs-on .hed { margin-bottom: 3px; }
body:has(#screen-vote.vs-on:not([hidden])) { padding-bottom: calc(14px + env(safe-area-inset-bottom)); }
@media (max-height: 700px) {
  body:has(#screen-vote.vs-on:not([hidden])) { padding-bottom: calc(4px + env(safe-area-inset-bottom)); }
  body:has(#screen-vote.vs-on:not([hidden])) .sitefoot { display: none; }
  #screen-vote.vs-on .sub { font-size: 0.71875rem; }
}
