/* The voters' side: curtain, envelopes, nominees and the sealing moment. */

/* ------------------------------------------------------------- curtain */

/* Velvet folds: three repeating bands with unrelated periods, so the folds
   never line up into an even stripe, lit from the stage lights above. */
.stage {
  background-color: var(--velvet-950);
  background-image:
    var(--grain),
    linear-gradient(180deg, var(--velvet-800) 0, var(--velvet-950) 36rem),
    repeating-linear-gradient(90deg, transparent 0 18px, var(--fold-dark) 31px, transparent 44px),
    repeating-linear-gradient(90deg, var(--fold-light) 0 9px, transparent 23px 61px),
    repeating-linear-gradient(90deg, transparent 0 40px, var(--fold-dark) 68px, transparent 97px);
  background-blend-mode: normal, normal, multiply, screen, multiply;
  background-attachment: scroll;
}

/* Side curtains, pulled back and gathered low, framing the stage. Only where
   the screen is wide enough to leave the content untouched. */
.drape {
  display: none;
}

@media (min-width: 64rem) {
  .drape {
    position: fixed;
    top: 0;
    bottom: 0;
    z-index: 0;
    display: block;
    width: clamp(4rem, 9vw, 9rem);
    pointer-events: none;
    background:
      var(--grain),
      linear-gradient(90deg, var(--fold-dark), transparent 28%, var(--fold-light) 46%, transparent 62%, var(--fold-dark)) 0 0 / 2.4rem 100% repeat-x,
      linear-gradient(180deg, var(--velvet-600), var(--velvet-800) 40%, var(--velvet-900));
  }

  .drape-left {
    left: 0;
    clip-path: polygon(0 0, 100% 0, 100% 52%, 62% 78%, 30% 100%, 0 100%);
    filter: drop-shadow(8px 0 10px var(--shadow-deep));
  }

  .drape-right {
    right: 0;
    clip-path: polygon(0 0, 100% 0, 100% 100%, 70% 100%, 38% 78%, 0 52%);
  }

  .stage-main,
  .topbar,
  .ceremony-stage,
  .ceremony-controls {
    position: relative;
    z-index: 1;
  }
}

/* Scalloped valance across the top of every page, with a gold piping. */
.valance {
  height: 2.25rem;
  background:
    linear-gradient(var(--gold-500), var(--gold-500)) top / 100% 3px no-repeat,
    radial-gradient(26px 30px at 50% 0, var(--velvet-600) 95%, transparent 100%) 0 0 / 52px 100% repeat-x,
    radial-gradient(27px 32px at 50% 0, var(--gold-700) 95%, transparent 100%) 0 0 / 52px 100% repeat-x;
}

.topbar {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2xs) var(--space-m);
  max-width: var(--measure);
  margin: 0 auto;
  padding: var(--space-xs) var(--space-m) 0;
  font-size: var(--text-s);
}

.topbar-home {
  font-family: var(--font-marquee);
  font-size: var(--text-m);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gold-300);
  text-decoration: none;
}

.topbar-greeting {
  color: var(--ivory-300);
}

/* Items never break inside; on a narrow phone the actions move to a second
   line instead. */
.topbar-home,
.topbar-greeting,
.topbar-actions {
  white-space: nowrap;
}

.topbar-actions {
  display: flex;
  align-items: baseline;
  gap: var(--space-m);
  margin-left: auto;
}

.topbar form {
  margin: 0;
}

.stage-main {
  max-width: var(--measure);
  margin: 0 auto;
  padding: var(--space-xl) var(--space-m) var(--space-2xl);
}

/* ------------------------------------------------------------- marquee */

/* The logotype hangs on a picture-palace marquee: an Art Deco plate with cut
   corners, a gold edge, and a frame of bulbs that switch on once when the
   page opens. It is the one moving thing on a page that otherwise holds still. */
.marquee-sign {
  --cut: 16px;
  position: relative;
  width: 100%;
  container-type: inline-size;
  display: grid;
  justify-items: center;
  gap: var(--space-s);
  padding: 2.6rem 1.5rem 2.2rem;
  text-align: center;
  isolation: isolate;
  background: var(--gold-500);
  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));
}

.marquee-plate {
  position: absolute;
  inset: 2px;
  z-index: -1;
  background:
    var(--grain),
    radial-gradient(120% 90% at 50% 0%, var(--velvet-600), var(--velvet-900) 70%);
  clip-path: polygon(calc(var(--cut) - 1px) 0, calc(100% - var(--cut) + 1px) 0, 100% calc(var(--cut) - 1px), 100% calc(100% - var(--cut) + 1px), calc(100% - var(--cut) + 1px) 100%, calc(var(--cut) - 1px) 100%, 0 calc(100% - var(--cut) + 1px), 0 calc(var(--cut) - 1px));
}

.marquee-bulbs {
  position: absolute;
  inset: 0;
  z-index: -1;
  filter: drop-shadow(0 0 3px var(--bulb-glow));
  animation: power-on 1.5s linear 0.25s both;
}

.marquee-bulbs::before,
.marquee-bulbs::after {
  content: "";
  position: absolute;
  --bulb: radial-gradient(circle, var(--bulb-core) 0 1.5px, var(--bulb-glass) 2.5px, var(--bulb-glow) 3.5px, transparent 5px);
}

/* Top and bottom rows. */
.marquee-bulbs::before {
  inset: 9px calc(var(--cut) + 4px);
  background:
    var(--bulb) top / 18px 10px space no-repeat,
    var(--bulb) bottom / 18px 10px space no-repeat;
}

/* Left and right columns, kept clear of the corners. */
.marquee-bulbs::after {
  inset: calc(var(--cut) + 8px) 9px;
  background:
    var(--bulb) left / 10px 18px no-repeat space,
    var(--bulb) right / 10px 18px no-repeat space;
}

@keyframes power-on {
  0% { opacity: 0.1; }
  8% { opacity: 1; }
  13% { opacity: 0.3; }
  21% { opacity: 1; }
  27% { opacity: 0.55; }
  40%, 100% { opacity: 1; }
}

.wordmark {
  display: grid;
  justify-items: center;
  gap: 0.35rem;
  margin: 0;
  font-family: var(--font-marquee);
  font-weight: 400;
  line-height: 0.9;
}

/* Gold leaf: bright at the top, a soft fold in the middle, never dark enough
   to lose the letters against the velvet. */
/* Sized from the sign's own width so the word never breaks: 20cqi fits a
   seven-letter first word in Limelight. Retune if the product name changes. */
.wordmark-main {
  font-size: min(var(--text-display), 20cqi);
  white-space: nowrap;
  letter-spacing: 0.015em;
  text-transform: uppercase;
  color: var(--gold-300);
  background: linear-gradient(180deg, var(--gold-100) 8%, var(--gold-300) 40%, var(--gold-500) 58%, var(--gold-300) 78%, var(--gold-100) 96%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 3px 0 var(--velvet-950));
}

.wordmark-sub {
  display: flex;
  align-items: center;
  gap: 0.7em;
  padding-left: 0.34em;
  font-size: min(2rem, 7cqi);
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--ivory-100);
}

.wordmark-sub::before,
.wordmark-sub::after {
  content: "";
  width: 1.8em;
  height: 1px;
  background: var(--gold-500);
}

.wordmark-edition {
  font-weight: 500;
  letter-spacing: 0.03em;
  color: var(--gold-300);
}

@media (prefers-reduced-motion: reduce) {
  .marquee-bulbs {
    animation: none;
  }
}

.marquee {
  display: grid;
  justify-items: center;
  gap: var(--space-s);
  margin-bottom: var(--space-xl);
  text-align: center;
}

.marquee-kicker {
  font-family: var(--font-display);
  font-variation-settings: var(--display-opsz);
  font-weight: var(--display-weight);
  font-size: var(--text-l);
  color: var(--gold-500);
}

.marquee-sub {
  max-width: 32rem;
  margin-inline: auto;
  color: var(--ivory-300);
}

.marquee-compact {
  gap: var(--space-m);
  margin-top: var(--space-l);
}

.countdown {
  max-width: 32rem;
  margin-inline: auto;
  color: var(--ivory-300);
}

.countdown-left {
  color: var(--gold-300);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

.countdown.is-closed {
  color: var(--gold-300);
}

/* --------------------------------------------------------------- login */

.login-card {
  display: grid;
  gap: var(--space-l);
  max-width: 26rem;
  margin-inline: auto;
  padding: var(--space-xl) var(--space-l);
}

.login-card .button {
  width: 100%;
}

.paper-note {
  font-size: var(--text-s);
  color: var(--ink-600);
}

/* ------------------------------------------------------------ envelopes */

.ballot-head {
  display: grid;
  justify-items: center;
  gap: var(--space-2xs);
  text-align: center;
  margin-bottom: var(--space-xl);
  padding-top: var(--space-l);
  border-top: 1px solid var(--velvet-600);
}

.ballot-progress {
  color: var(--gold-300);
}

.empty {
  color: var(--ivory-300);
}

.envelope-stack {
  display: grid;
  gap: var(--space-2xl);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* A pile on a table, not a grid: each envelope tilts a little, alternating. */
.envelope-stack > li:nth-child(odd) .envelope {
  rotate: -0.7deg;
}

.envelope-stack > li:nth-child(even) .envelope {
  rotate: 0.5deg;
}

/* Wider screens: the classic long envelope. */
@media (min-width: 30rem) {
  .envelope {
    --flap-depth: 44%;
    aspect-ratio: 8 / 5;
  }
}

.envelope {
  --flap-depth: 40%;
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  min-height: 13rem;
  background: var(--ivory-100);
  color: var(--ink-900);
  border-radius: var(--radius-paper);
  box-shadow: 0 1px 0 var(--ivory-50) inset, 0 22px 30px -20px var(--shadow-deep), 0 2px 5px var(--shadow-soft);
  text-decoration: none;
  transition: translate var(--duration-quick) var(--ease-out), rotate var(--duration-quick) var(--ease-out);
}

/* Bottom and side flaps of the envelope back, as one lighter triangle. */
.envelope::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(0deg, var(--ivory-50), var(--ivory-100));
  clip-path: polygon(0 100%, 50% 40%, 100% 100%);
  border-radius: var(--radius-paper);
}

/* Under the flap, a gold foil edge (the envelopes of the night are gilded). */
.envelope::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: calc(var(--flap-depth) + 3px);
  background: linear-gradient(90deg, var(--gold-500), var(--gold-300) 50%, var(--gold-500));
  clip-path: polygon(0 0, 100% 0, 50% 100%);
  z-index: 1;
}

.envelope-flap {
  position: absolute;
  inset: 0 0 auto;
  height: var(--flap-depth);
  background: linear-gradient(180deg, var(--ivory-300), var(--ivory-100));
  clip-path: polygon(0 0, 100% 0, 50% 100%);
  transform-origin: top;
  z-index: 2;
}

/* Not voted yet: the flap stands open behind the envelope, foreshortened. */
.envelope.is-open .envelope-flap {
  background: linear-gradient(0deg, var(--ivory-500), var(--ivory-300));
  transform: scaleY(-0.55);
  z-index: 0;
}

.envelope.is-open::before {
  height: 22%;
  clip-path: none;
  background: linear-gradient(180deg, var(--ivory-500), transparent);
  border-radius: var(--radius-paper) var(--radius-paper) 0 0;
}

.envelope-seal {
  position: absolute;
  top: var(--flap-depth);
  left: 50%;
  width: clamp(3.25rem, 13vw, 4.25rem);
  translate: -50% -55%;
  rotate: -8deg;
  z-index: 3;
  filter: drop-shadow(0 3px 2px var(--shadow-soft));
}

.envelope-body {
  position: absolute;
  inset: auto var(--space-l) var(--space-l);
  display: grid;
  justify-items: center;
  gap: var(--space-2xs);
  text-align: center;
  z-index: 3;
}

.envelope-title {
  font-family: var(--font-display);
  font-variation-settings: var(--display-opsz);
  font-size: var(--text-l);
  font-weight: var(--display-weight);
  line-height: 1.12;
  letter-spacing: -0.01em;
  text-wrap: balance;
  overflow-wrap: anywhere;
}

.envelope-meta {
  font-size: var(--text-s);
  color: var(--ink-600);
}

.envelope.is-sealed .envelope-meta {
  color: var(--wax-700);
  font-weight: 500;
}

@media (hover: hover) and (pointer: fine) {
  .envelope:hover {
    translate: 0 -3px;
    rotate: 0deg;
  }
}

.envelope:focus-visible {
  outline-offset: 6px;
}

/* -------------------------------------------------------------- category */

.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-xs) var(--space-m);
  margin-bottom: var(--space-xl);
  font-size: var(--text-s);
}

.crumb-back {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  min-height: 2.75rem;
  text-decoration: none;
}

.crumb-position {
  color: var(--ivory-300);
}

.category-head {
  display: grid;
  justify-items: center;
  gap: var(--space-s);
  margin-bottom: var(--space-xl);
  text-align: center;
}

.category-title {
  font-size: clamp(2.2rem, 9vw, 3.5rem);
}

.category-description {
  max-width: 32rem;
  color: var(--ivory-300);
}

.ballot-form > .form-error,
.category-head + .form-error {
  margin-bottom: var(--space-l);
}

.nominees {
  --columns: 2;
  --gap-x: var(--space-m);
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-xl) var(--gap-x);
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

@media (min-width: 40rem) {
  .nominees {
    --columns: 3;
  }
}

/* Flex rather than grid so an incomplete last row sits centred. */
.nominees > .nominee {
  width: calc((100% - (var(--columns) - 1) * var(--gap-x)) / var(--columns));
}

.nominee {
  position: relative;
  display: grid;
  align-content: start;
  gap: var(--space-2xs);
  min-width: 0;
  text-align: center;
}

.nominee-card {
  display: grid;
  gap: var(--space-xs);
  cursor: pointer;
}

/* A printed press photo: the portrait sits in an ivory border. */
.nominee-frame {
  position: relative;
  display: block;
  padding: 5px;
  background: var(--ivory-100);
  border-radius: var(--radius-paper);
  box-shadow: 0 16px 24px -18px var(--shadow-deep);
  transition: background-color var(--duration-quick) ease;
}

.portrait {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  background: var(--velvet-800);
}

.portrait-monogram {
  display: grid;
  place-items: center;
  background:
    linear-gradient(180deg, var(--velvet-600), var(--velvet-900));
  color: var(--gold-300);
  font-family: var(--font-display);
  font-variation-settings: var(--display-opsz);
  font-size: clamp(2rem, 9vw, 3rem);
  font-weight: var(--display-weight);
  letter-spacing: -0.02em;
}

.nominee-name {
  font-family: var(--font-display);
  font-variation-settings: var(--display-opsz);
  font-size: var(--text-l);
  font-weight: var(--display-weight);
  line-height: 1.1;
  overflow-wrap: anywhere;
}

.nominee-badge {
  position: absolute;
  top: var(--space-xs);
  left: 50%;
  translate: -50% 0;
  white-space: nowrap;
  padding: 0.2rem 0.55rem;
  background: var(--gold-500);
  color: var(--ink-900);
  font-size: var(--text-s);
  font-weight: 500;
  border-radius: var(--radius-paper);
  opacity: 0;
  transition: opacity var(--duration-quick) ease;
}

.nominee-handle {
  justify-self: center;
  font-size: var(--text-s);
  color: var(--gold-500);
  text-decoration: none;
  overflow-wrap: anywhere;
}

.nominee-handle:hover {
  text-decoration: underline;
}

.nominee-input:checked + .nominee-card .nominee-frame {
  background: linear-gradient(160deg, var(--gold-300), var(--gold-500) 50%, var(--gold-700));
}

.nominee-input:checked + .nominee-card .nominee-name {
  color: var(--gold-300);
}

.nominee-input:checked + .nominee-card .nominee-badge {
  opacity: 1;
}

.nominee-input:focus-visible + .nominee-card .nominee-frame {
  outline: 2px solid var(--gold-300);
  outline-offset: 3px;
}

.nominees:disabled .nominee-card {
  cursor: default;
}

.ballot-actions {
  position: sticky;
  bottom: 0;
  display: grid;
  justify-items: center;
  gap: var(--space-xs);
  text-align: center;
  margin-top: var(--space-xl);
  padding: var(--space-l) 0 var(--space-m);
  background: linear-gradient(180deg, transparent, var(--velvet-950) 35%);
  z-index: 5;
}

.ballot-actions .button {
  width: 100%;
}

@media (min-width: 40rem) {
  .ballot-actions .button {
    width: auto;
    min-width: 16rem;
  }
}

.ballot-hint {
  font-size: var(--text-s);
  color: var(--ivory-300);
}

.pager {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-m);
  margin-top: var(--space-xl);
  padding-top: var(--space-l);
  border-top: 1px solid var(--velvet-600);
  font-size: var(--text-s);
}

.pager-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  max-width: 48%;
  min-height: 2.75rem;
  text-decoration: none;
}

.pager-next {
  margin-left: auto;
  text-align: right;
}

/* -------------------------------------------------------------- the seal */

.seal {
  aspect-ratio: 1;
  height: auto;
}

.wax-stop-light { stop-color: var(--wax-300); }
.wax-stop-mid { stop-color: var(--wax-600); }
.wax-stop-deep { stop-color: var(--wax-800); }
.wax-stop-press-light { stop-color: var(--wax-500); }
.wax-stop-press-deep { stop-color: var(--wax-700); }
.wax-rim-inner { stroke: var(--wax-800); stroke-opacity: 0.55; }
.wax-rim-outer { stroke: var(--wax-200); stroke-opacity: 0.35; }
.wax-sheen { stroke: var(--wax-100); stroke-opacity: 0.45; }

/* The pressed letter catches the light on its edges. */
.seal-letter {
  font-family: var(--font-display);
  font-variation-settings: var(--display-opsz);
  font-size: 46px;
  font-weight: var(--display-weight);
  fill: var(--wax-200);
  fill-opacity: 0.8;
  stroke: var(--wax-800);
  stroke-width: 2.5px;
  stroke-opacity: 0.6;
  paint-order: stroke;
}

/* --------------------------------------------------------------- sealing */

/* Played once per vote, so it is allowed to take its time (about 1.5 s). */
.sealing {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: var(--space-xl);
  padding: var(--space-m);
  background: var(--veil);
  animation: sealing-veil 160ms ease-out both;
}

.sealing[hidden] {
  display: none;
}

.sealing-envelope {
  position: relative;
  width: min(80vw, 22rem);
  aspect-ratio: 8 / 5;
  perspective: 900px;
}

.sealing-back {
  position: absolute;
  inset: 0;
  background: var(--ivory-500);
  border-radius: var(--radius-paper);
}

.sealing-card {
  position: absolute;
  inset: 8% 7% 10%;
  display: grid;
  justify-items: center;
  align-items: start;
  padding: 9% var(--space-s) var(--space-s);
  background: var(--ivory-50);
  color: var(--ink-900);
  font-family: var(--font-display);
  font-variation-settings: var(--display-opsz);
  font-size: var(--text-l);
  font-weight: var(--display-weight);
  text-align: center;
  border-radius: var(--radius-paper);
  box-shadow: 0 2px 6px var(--shadow-soft);
  z-index: 1;
  animation: card-in 480ms var(--ease-out) 160ms both;
}

.sealing-front {
  position: absolute;
  inset: 0;
  background: linear-gradient(0deg, var(--ivory-50), var(--ivory-100));
  clip-path: polygon(0 0, 50% 52%, 100% 0, 100% 100%, 0 100%);
  border-radius: var(--radius-paper);
  z-index: 2;
}

.sealing-flap {
  position: absolute;
  inset: 0 0 auto;
  height: 54%;
  background: linear-gradient(180deg, var(--ivory-300), var(--ivory-100));
  clip-path: polygon(0 0, 100% 0, 50% 100%);
  transform-origin: top;
  backface-visibility: visible;
  animation: flap-close 360ms var(--ease-in-out) 600ms both;
}

.sealing-seal {
  position: absolute;
  top: 54%;
  left: 50%;
  width: 4.5rem;
  translate: -50% -55%;
  z-index: 4;
  filter: drop-shadow(0 4px 3px var(--shadow-deep));
  animation: seal-stamp 240ms var(--ease-out) 980ms both;
}

.sealing-caption {
  font-family: var(--font-display);
  font-variation-settings: var(--display-opsz);
  font-weight: var(--display-weight);
  font-size: var(--text-xl);
  color: var(--gold-300);
  animation: caption-in 320ms ease-out 1120ms both;
}

@keyframes sealing-veil {
  from { opacity: 0; }
}

@keyframes card-in {
  from { transform: translateY(-78%); }
  to { transform: translateY(0); }
}

/* The flap starts open behind the envelope and folds over the card; it changes
   layer at the halfway point, when it is edge-on and the switch is invisible. */
@keyframes flap-close {
  0% { transform: rotateX(180deg); z-index: 0; }
  49% { z-index: 0; }
  50% { z-index: 3; }
  100% { transform: rotateX(0deg); z-index: 3; }
}

@keyframes seal-stamp {
  from { opacity: 0; transform: scale(1.35) rotate(-14deg); }
  to { opacity: 1; transform: scale(1) rotate(-8deg); }
}

@keyframes caption-in {
  from { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .sealing-card,
  .sealing-flap {
    animation: none;
  }
  .sealing-flap {
    z-index: 3;
  }
  .sealing-seal {
    animation-name: caption-in;
    animation-delay: 100ms;
  }
  .sealing-caption {
    animation-delay: 200ms;
  }
  .envelope-stack > li .envelope {
    rotate: 0deg;
  }
}
