/* ==========================================================================
   Aurora voting template - styles.css
   Anything Tailwind's CDN build can't reasonably express lives here:
   brand CSS custom properties, the fixed background layer, the basket
   panel/sheet animation choreography, list reorder animations, skeletons
   and reduced-motion overrides.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Brand tokens (defaults - overwritten at runtime from data/config.json
   by js/modules/theme.js so a brand swap never touches this file)
   -------------------------------------------------------------------------- */
:root {
  --color-primary: #ff3d6e;
  --color-primary-contrast: #ffffff;
  --color-secondary: #151033;
  --color-surface: #ffffff;
  --color-surface-alt: #f4f3fa;
  --color-text: #161226;
  --color-text-muted: #5c5872;
  --color-accent: #ffd23f;

  --font-display: Georgia, 'Times New Roman', serif;
  --font-body: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;

  --overlay-opacity: 0.45;

  --anim-fast: 180ms;
  --anim-base: 220ms;
  --anim-slow: 300ms;
  --ease-in: cubic-bezier(0.32, 0.72, 0, 1);
  --ease-out: ease-out;
}

* {
  box-sizing: border-box;
}

html,
body {
  overflow-x: hidden;
}

html {
  scroll-behavior: smooth;
}

body {
  font-family: var(--font-body);
}

/* --------------------------------------------------------------------------
   2. Fixed background layer
   -------------------------------------------------------------------------- */
.page-background {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
}

.page-background picture,
.page-background img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.page-background__overlay {
  position: absolute;
  inset: 0;
  background: var(--color-secondary);
  opacity: var(--overlay-opacity);
}

/* --------------------------------------------------------------------------
   2a. Full-screen hero (brand.hero.enabled in config.json)
   Sits before the header in the DOM, at 100% of the viewport height, so on
   load it's the only thing visible on both mobile and desktop. The sticky
   header right after it is simply out of view until the visitor scrolls (or
   taps the CTA) - no extra JS needed for that hand-off.
   -------------------------------------------------------------------------- */
.hero-screen {
  position: relative;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: var(--color-secondary);
}

.hero-screen__bg {
  position: absolute;
  inset: 0;
}

.hero-screen__bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.hero-screen__content {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  max-width: 34rem;
  padding: 2rem 1.5rem calc(2.5rem + env(safe-area-inset-bottom, 0px));
}

.hero-screen__logo {
  width: min(72vw, 320px);
  height: auto;
  filter: drop-shadow(0 12px 40px rgba(0, 0, 0, 0.45));
}

.hero-screen__tagline {
  margin-top: 1.5rem;
  color: #fff;
  font-size: 1.05rem;
  font-weight: 500;
  line-height: 1.5;
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.55);
}

.hero-screen__cta {
  margin-top: 2.5rem;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  color: #fff;
  font-weight: 700;
  font-size: 0.9rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  text-decoration: none;
}

.hero-screen__cta svg {
  animation: hero-chevron 1.8s ease-in-out infinite;
}

.hero-screen__cta:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 6px;
  border-radius: 4px;
}

@keyframes hero-chevron {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(6px);
  }
}

@media (min-width: 640px) {
  .hero-screen__tagline {
    font-size: 1.2rem;
  }
}

/* --------------------------------------------------------------------------
   3. Skip links
   -------------------------------------------------------------------------- */
.skip-links {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 100;
}

.skip-link {
  position: absolute;
  left: 0;
  top: -100px;
  background: var(--color-accent);
  color: var(--color-secondary);
  font-weight: 700;
  padding: 0.75rem 1.25rem;
  border-radius: 0 0 0.5rem 0;
  white-space: nowrap;
  transition: top var(--anim-fast) var(--ease-out);
}

.skip-link:focus {
  top: 0;
  outline: 3px solid var(--color-secondary);
  outline-offset: -3px;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------------------------------------
   4. Header
   -------------------------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: linear-gradient(to bottom, rgba(21, 16, 51, 0.85), rgba(21, 16, 51, 0.4));
  backdrop-filter: blur(6px);
}

@media (max-width: 639px) {
  .site-header .max-w-6xl {
    flex-direction: column;
    align-items: center;
    text-align: center;
  }
}

/* --------------------------------------------------------------------------
   5. Content panels
   -------------------------------------------------------------------------- */
.content-panel {
  background: rgba(255, 255, 255, 0.85);
  border-radius: 1.25rem;
  color: var(--color-text);
  box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.35);
}

/* Instruction steps */
#instructions li {
  position: relative;
  counter-increment: step;
  background: rgba(255, 255, 255, 0.92);
  border-radius: 1rem;
  padding: 1.25rem 1.25rem 1.25rem 3.25rem;
  color: var(--color-text);
  font-size: 0.95rem;
  box-shadow: 0 6px 18px -8px rgba(0, 0, 0, 0.3);
}

#instructions {
  counter-reset: step;
  list-style: none;
}

#instructions li::before {
  content: counter(step);
  position: absolute;
  left: 1rem;
  top: 1.1rem;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 999px;
  background: var(--color-accent);
  color: var(--color-surface);
  font-weight: 800;
  font-size: 0.9rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* --------------------------------------------------------------------------
   6. Search
   -------------------------------------------------------------------------- */
.search-icon {
  position: absolute;
  left: 1rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--color-text-muted);
  pointer-events: none;
}

.search-input {
  border: 1px solid transparent;
}

.search-clear {
  position: absolute;
  right: 0.6rem;
  top: 50%;
  transform: translateY(-50%);
  width: 2rem;
  height: 2rem;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text-muted);
  background: var(--color-surface-alt);
}

.search-clear:hover {
  color: var(--color-text);
}

mark {
  background: color-mix(in srgb, var(--color-accent) 55%, transparent);
  color: inherit;
  border-radius: 0.15em;
  padding: 0 0.05em;
}

/* --------------------------------------------------------------------------
   7. Song list + row
   One row per song - image left, title/artist centered, action on the
   right - modelled on Heart's results-chart list rows.
   -------------------------------------------------------------------------- */
.song-grid {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  list-style: none;
  padding: 0;
}

.song-card {
  display: grid;
  grid-template-columns: 120px 1fr 5.5em;
  align-items: stretch;
  /* Without this, a flex item (this card, inside .song-grid's column flex)
     is allowed to grow past its stretched width whenever its own content
     (an unbroken title/artist string) has a larger min-content size — which
     row that happens to hit depends on the text, so rows end up different
     widths and the last column (the Vote button) gets pushed off-screen on
     narrow viewports. min-width: 0 makes it respect the flex-given width
     and let its own grid columns shrink instead. */
  min-width: 0;
  background: var(--color-surface);
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.12);
}

@media (min-width: 640px) {
  .song-card {
    grid-template-columns: 180px 1fr 8em;
  }
}

.song-card__artwork-wrap {
  background: var(--color-surface-alt);
  overflow: hidden;
}

.song-card__artwork {
  width: 100%;
  height: 100%;
  min-height: 110px;
  object-fit: cover;
  display: block;
}

@media (min-width: 640px) {
  .song-card__artwork {
    min-height: 160px;
  }
}

.song-card__meta {
  /* Same reasoning as .song-card's min-width: 0 above, one level down — this
     is the actual 1fr grid track that needs to be allowed to shrink below
     its text's natural width so long titles/artists wrap instead of
     stretching the row. */
  min-width: 0;
  padding: 1rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.song-card__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.1rem;
  line-height: 1.25;
  color: var(--color-text);
  overflow-wrap: break-word;
}

@media (min-width: 640px) {
  .song-card__title {
    font-size: 1.4rem;
  }
}

.song-card__artist {
  color: var(--color-text-muted);
  font-size: 0.8rem;
  margin-top: 0.25rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  overflow-wrap: break-word;
}

@media (min-width: 640px) {
  .song-card__artist {
    font-size: 0.9rem;
  }
}

.song-card__action-wrap {
  background: var(--color-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.5rem;
}

.song-card__action {
  min-width: 44px;
  min-height: 44px;
  padding: 0 0.75rem;
  border-radius: 999px;
  font-weight: 700;
  font-size: 0.8rem;
  background: #fff;
  color: var(--color-primary);
  transition: transform var(--anim-fast) var(--ease-out), filter var(--anim-fast);
}

@media (min-width: 640px) {
  .song-card__action {
    font-size: 0.9rem;
  }
}

.song-card__action:hover:not(:disabled) {
  filter: brightness(0.95);
}

.song-card__action:active:not(:disabled) {
  transform: scale(0.94);
}

.song-card__action:focus-visible {
  outline: 2px solid var(--color-secondary);
  outline-offset: 2px;
}

.song-card__action[data-state='added'] {
  background: var(--color-secondary);
  color: #fff;
}

.song-card__action:disabled {
  background: rgba(255, 255, 255, 0.5);
  color: var(--color-primary);
  cursor: not-allowed;
  opacity: 0.7;
}

/* Skeleton loading state */
.song-card--skeleton {
  box-shadow: none;
}

.skeleton-block,
.skeleton-line {
  background: linear-gradient(
    90deg,
    var(--color-surface-alt) 25%,
    #e9e8f0 37%,
    var(--color-surface-alt) 63%
  );
  background-size: 400% 100%;
  animation: skeleton-shimmer 1.4s ease infinite;
  border-radius: 0.4rem;
}

.skeleton-line {
  height: 0.9rem;
  margin: 0.85rem 1rem 0;
}

.skeleton-line--artist {
  width: 60%;
  margin-top: 0.5rem;
  margin-bottom: 1rem;
}

@keyframes skeleton-shimmer {
  0% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0 50%;
  }
}

/* --------------------------------------------------------------------------
   8. Pagination
   -------------------------------------------------------------------------- */
.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  margin-top: 1.5rem;
  flex-wrap: wrap;
}

.page-btn,
.page-number {
  min-width: 44px;
  min-height: 44px;
  border-radius: 999px;
  background: var(--color-surface-alt);
  color: var(--color-text);
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.page-btn:hover:not(:disabled),
.page-number:hover:not([aria-current='page']) {
  background: var(--color-surface-alt);
  filter: brightness(0.94);
}

.page-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

.page-number[aria-current='page'] {
  background: var(--color-primary);
  color: var(--color-primary-contrast);
}

.page-numbers {
  display: none;
  gap: 0.4rem;
}

.page-indicator {
  color: var(--color-text);
  font-weight: 600;
  min-width: 5rem;
  text-align: center;
}

@media (min-width: 768px) {
  .page-numbers {
    display: flex;
  }
  .page-indicator {
    display: none;
  }
}

.page-ellipsis {
  color: var(--color-text-muted);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.5rem;
}

/* --------------------------------------------------------------------------
   9. Footer
   -------------------------------------------------------------------------- */
.site-footer {
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}

.footer-link {
  color: rgba(255, 255, 255, 0.8);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.footer-link:hover {
  color: #fff;
}

/* --------------------------------------------------------------------------
   10. Floating basket trigger (FAB)
   -------------------------------------------------------------------------- */
.basket-fab {
  position: fixed;
  /* env(safe-area-inset-*) keeps this clear of iOS Safari's bottom
     home-indicator strip and any side notch in landscape - without it the
     button can end up rendered underneath that reserved system UI on real
     devices / accurate device emulation (though not in DevTools' generic
     "Responsive" mode, which has no chrome to reserve space for). */
  right: calc(1.25rem + env(safe-area-inset-right, 0px));
  bottom: calc(1.25rem + env(safe-area-inset-bottom, 0px));
  z-index: 50;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  min-height: 52px;
  padding: 0 1.25rem;
  border-radius: 999px;
  background: var(--color-primary);
  color: var(--color-primary-contrast);
  font-weight: 700;
  box-shadow: 0 10px 30px -8px rgba(0, 0, 0, 0.5);
  transform: scale(0.6);
  opacity: 0;
  pointer-events: none;
  transition: transform var(--anim-base) var(--ease-in), opacity var(--anim-base) var(--ease-in);
}

.basket-fab.is-visible {
  transform: scale(1);
  opacity: 1;
  pointer-events: auto;
}

.basket-fab:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}

.basket-fab__count {
  background: rgba(255, 255, 255, 0.25);
  border-radius: 999px;
  min-width: 1.5rem;
  height: 1.5rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.8rem;
  padding: 0 0.35rem;
}

.basket-fab__count.is-popping {
  animation: fab-pop 180ms ease-out;
}

@keyframes fab-pop {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.15);
  }
  100% {
    transform: scale(1);
  }
}

/* --------------------------------------------------------------------------
   11. Basket backdrop + panel/sheet
   -------------------------------------------------------------------------- */
body.basket-open {
  overflow: hidden;
}

.basket-backdrop {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(0, 0, 0, 0.5);
  opacity: 0;
  transition: opacity var(--anim-base) var(--ease-out);
}

.basket-backdrop.is-visible {
  opacity: 1;
}

.basket-panel {
  position: fixed;
  z-index: 61;
  background: var(--color-surface);
  color: var(--color-text);
  display: flex;
  flex-direction: column;
}

.basket-panel[hidden] {
  display: none;
}

.basket-panel__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  padding: 1.25rem 1.25rem 0.75rem;
  border-bottom: 1px solid var(--color-surface-alt);
}

.basket-close {
  width: 40px;
  height: 40px;
  min-width: 44px;
  min-height: 44px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text-muted);
  margin: -8px -8px 0 0;
}

.basket-close:hover {
  background: var(--color-surface-alt);
}

.basket-panel__body {
  flex: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.basket-panel__footer {
  /* The panel/sheet touches the true bottom edge of the screen, so the
     submit button gets extra bottom padding on devices that reserve a
     home-indicator strip there (falls back to 0 everywhere else). */
  padding: 1rem 1.25rem calc(1.25rem + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--color-surface-alt);
}

.basket-panel__grabber {
  display: none;
}

/* Step 2: entrant email */
.basket-email-step {
  padding: 0.5rem 1.25rem 1.5rem;
}

.basket-email-step__intro {
  color: var(--color-text-muted);
  font-size: 0.9rem;
  margin-bottom: 1.25rem;
}

.basket-email-step__label {
  display: block;
  font-weight: 700;
  font-size: 0.875rem;
  color: var(--color-text);
  margin-bottom: 0.4rem;
}

.basket-email-step__input {
  width: 100%;
  min-height: 48px;
  padding: 0 1rem;
  border-radius: 0.75rem;
  border: 1.5px solid var(--color-surface-alt);
  background: var(--color-surface);
  color: var(--color-text);
  font-size: 1rem;
}

.basket-email-step__input:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 1px;
}

.basket-email-step__input[aria-invalid='true'] {
  border-color: var(--color-primary);
}

.basket-email-step__error {
  color: var(--color-primary);
  font-size: 0.85rem;
  font-weight: 600;
  margin-top: 0.5rem;
}

.basket-email-step__consents {
  margin-top: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}

.basket-checkbox {
  display: flex;
  align-items: flex-start;
  gap: 0.65rem;
  cursor: pointer;
  font-size: 0.85rem;
  color: var(--color-text);
  line-height: 1.4;
}

.basket-checkbox input[type='checkbox'] {
  width: 20px;
  height: 20px;
  min-width: 20px;
  margin-top: 0.1rem;
  accent-color: var(--color-primary);
  cursor: pointer;
}

.basket-checkbox input[type='checkbox']:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

.basket-checkbox__link {
  color: var(--color-primary);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.basket-footer-email {
  display: flex;
  gap: 0.75rem;
}

/* An attribute selector on top of the class selector outranks it, so this
   wins over `.basket-footer-email { display: flex }` above regardless of
   stylesheet order - without it, `[hidden]`'s UA-stylesheet `display: none`
   would lose to our own `display: flex` and the step would stay visible. */
.basket-footer-email[hidden] {
  display: none;
}

/* Mobile: full-height bottom sheet */
@media (max-width: 767px) {
  .basket-panel {
    left: 0;
    right: 0;
    bottom: 0;
    top: 0;
    border-radius: 1.25rem 1.25rem 0 0;
    transform: translateY(100%);
    transition: transform var(--anim-slow) var(--ease-in);
    padding-top: 0.5rem;
  }

  .basket-panel.is-open {
    transform: translateY(0);
  }

  .basket-panel__grabber {
    display: block;
    width: 40px;
    height: 4px;
    border-radius: 999px;
    background: var(--color-surface-alt);
    margin: 0.5rem auto 0.25rem;
  }
}

/* Desktop: right-edge side panel */
@media (min-width: 768px) {
  .basket-panel {
    top: 0;
    right: 0;
    bottom: 0;
    width: 400px;
    max-width: 92vw;
    max-height: 100vh;
    box-shadow: -20px 0 60px -15px rgba(0, 0, 0, 0.45);
    transform: translateX(24px);
    opacity: 0;
    transition: transform var(--anim-base) var(--ease-out), opacity var(--anim-base) var(--ease-out);
  }

  .basket-panel.is-open {
    transform: translateX(0);
    opacity: 1;
  }
}

/* --------------------------------------------------------------------------
   12. Basket list + reordering
   -------------------------------------------------------------------------- */
.basket-list {
  list-style: none;
  margin: 0;
  padding: 0.5rem 1rem 1rem;
}

.basket-item {
  display: grid;
  grid-template-columns: 1.5rem 2.75rem 1fr auto auto;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 0.25rem;
  border-bottom: 1px solid var(--color-surface-alt);
  background: var(--color-surface);
  position: relative;
}

.basket-item.is-removing {
  pointer-events: none;
}

.basket-item__position {
  font-weight: 800;
  color: var(--color-text-muted);
  text-align: center;
}

.basket-item__artwork {
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 0.5rem;
  object-fit: cover;
  background: var(--color-surface-alt);
}

.basket-item__meta {
  min-width: 0;
}

.basket-item__title {
  font-weight: 700;
  font-size: 0.9rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.basket-item__artist {
  font-size: 0.8rem;
  color: var(--color-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.basket-item__reorder {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.basket-item__arrow {
  width: 40px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.75rem;
  color: var(--color-text-muted);
  background: var(--color-surface-alt);
  border-radius: 0.6rem;
  transition: transform 120ms ease-out, background 120ms ease-out, color 120ms ease-out;
}

.basket-item__arrow:hover:not(:disabled) {
  color: var(--color-primary);
  background: color-mix(in srgb, var(--color-primary) 12%, var(--color-surface-alt));
}

.basket-item__arrow:active:not(:disabled) {
  transform: scale(0.94);
}

.basket-item__arrow:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

.basket-item__remove {
  width: 36px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text-muted);
}

.basket-item__remove:hover {
  color: var(--color-primary);
}

.basket-item__arrow:focus-visible,
.basket-item__remove:focus-visible,
.basket-close:focus-visible,
.basket-fab:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* Reordering happens by tapping, so the arrows get generous touch targets
   here - 44px is the minimum recommended hit area for a finger tap. */
@media (max-width: 767px) {
  .basket-item {
    grid-template-columns: 1.5rem 2.75rem 1fr auto auto;
    gap: 0.6rem;
    padding: 0.85rem 0.25rem;
  }

  .basket-item__reorder {
    gap: 0.4rem;
  }

  .basket-item__arrow {
    width: 46px;
    height: 44px;
    font-size: 0.9rem;
  }

  .basket-item__remove {
    width: 40px;
    height: 44px;
  }
}

/* Entering / leaving basket items */
.basket-item.is-entering {
  animation: item-enter var(--anim-base) var(--ease-in);
}

@keyframes item-enter {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.basket-item.is-leaving {
  animation: item-leave var(--anim-fast) var(--ease-out) forwards;
}

@keyframes item-leave {
  from {
    opacity: 1;
    max-height: 80px;
  }
  to {
    opacity: 0;
    max-height: 0;
    padding-top: 0;
    padding-bottom: 0;
    margin: 0;
  }
}

/* --------------------------------------------------------------------------
   13. Toasts / inline errors
   -------------------------------------------------------------------------- */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(6.5rem + env(safe-area-inset-bottom, 0px));
  transform: translate(-50%, 8px);
  z-index: 70;
  background: var(--color-secondary);
  color: #fff;
  padding: 0.75rem 1.25rem;
  border-radius: 999px;
  font-size: 0.9rem;
  font-weight: 600;
  box-shadow: 0 10px 24px -8px rgba(0, 0, 0, 0.5);
  opacity: 0;
  transition: opacity var(--anim-fast) var(--ease-out), transform var(--anim-fast) var(--ease-out);
}

.toast.is-visible {
  opacity: 1;
  transform: translate(-50%, 0);
}

.submit-error {
  position: fixed;
  left: 50%;
  bottom: calc(6.5rem + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  z-index: 70;
  background: #fff;
  color: var(--color-text);
  padding: 0.9rem 1.1rem;
  border-radius: 0.9rem;
  box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  gap: 0.75rem;
  max-width: 90vw;
}

.submit-retry {
  background: var(--color-primary);
  color: var(--color-primary-contrast);
  font-weight: 700;
  border-radius: 999px;
  padding: 0.4rem 0.9rem;
  font-size: 0.85rem;
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   13a. Cookie consent banner
   -------------------------------------------------------------------------- */
.cookie-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 90;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.85rem;
  background: var(--color-surface);
  color: var(--color-text);
  padding: 1.1rem 1.5rem calc(1.1rem + env(safe-area-inset-bottom, 0px));
  box-shadow: 0 -10px 30px -10px rgba(0, 0, 0, 0.35);
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--anim-base) var(--ease-in), transform var(--anim-base) var(--ease-in);
}

.cookie-banner.is-visible {
  opacity: 1;
  transform: translateY(0);
}

.cookie-banner__message {
  max-width: 44rem;
  font-size: 0.85rem;
  line-height: 1.45;
  color: var(--color-text-muted);
  text-align: center;
  margin: 0;
}

.cookie-banner__actions {
  display: flex;
  justify-content: center;
  gap: 0.75rem;
  flex-shrink: 0;
}

.cookie-banner__btn {
  min-height: 42px;
  padding: 0 1.25rem;
  border-radius: 999px;
  font-weight: 700;
  font-size: 0.875rem;
  white-space: nowrap;
}

.cookie-banner__btn--primary {
  background: var(--color-primary);
  color: var(--color-primary-contrast);
}

.cookie-banner__btn--primary:hover {
  filter: brightness(1.1);
}

.cookie-banner__btn--ghost {
  background: var(--color-surface-alt);
  color: var(--color-text);
}

.cookie-banner__btn--ghost:hover {
  filter: brightness(0.96);
}

.cookie-banner__btn:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

@media (max-width: 639px) {
  .cookie-banner {
    gap: 0.65rem;
    padding: 0.9rem 1.1rem calc(0.9rem + env(safe-area-inset-bottom, 0px));
  }

  .cookie-banner__message {
    font-size: 0.78rem;
  }

  .cookie-banner__btn {
    min-height: 40px;
    padding: 0 1rem;
    font-size: 0.82rem;
  }
}

/* --------------------------------------------------------------------------
   14. Success screen
   -------------------------------------------------------------------------- */
.success-screen {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: rgba(10, 6, 26, 0.72);
  backdrop-filter: blur(4px);
}

.success-screen__card {
  max-width: 32rem;
  width: 100%;
  text-align: center;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 1.5rem;
  padding: 2.5rem 1.75rem;
  animation: success-in var(--anim-slow) var(--ease-in);
}

@keyframes success-in {
  from {
    opacity: 0;
    transform: translateY(12px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

.success-vote-list {
  list-style: none;
  margin: 1.5rem 0 0;
  padding: 0;
  text-align: left;
  display: grid;
  gap: 0.5rem;
}

.success-vote-list__item {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  background: rgba(255, 255, 255, 0.06);
  border-radius: 0.6rem;
  padding: 0.5rem 0.75rem;
  color: #fff;
}

.success-vote-list__position {
  font-weight: 800;
  color: var(--color-accent);
  min-width: 1.25rem;
}

.success-vote-list__artist {
  color: rgba(255, 255, 255, 0.7);
  font-size: 0.85rem;
}

.success-screen__actions {
  margin-top: 1.5rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem;
}

/* --------------------------------------------------------------------------
   15. Focus visibility
   -------------------------------------------------------------------------- */
a:focus-visible,
button:focus-visible,
input:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   16. Reduced motion
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}
