:root {
  color-scheme: dark;
  --background: #0e0d12;
  --surface: #17151d;
  --surface-soft: rgba(255, 255, 255, 0.05);
  --line: rgba(255, 255, 255, 0.13);
  --line-strong: rgba(255, 255, 255, 0.24);
  --text: #faf7f4;
  --muted: #a8a2ad;
  --accent: #ff6b35;
  --accent-2: #f2328a;
  --danger: #ff7b82;
  --success: #72e7ad;
  --radius: 18px;
  /* One motion language: quick to start, soft landing; "spring" overshoots a touch. */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --spring: cubic-bezier(0.34, 1.4, 0.64, 1);
  --fast: 0.18s;
  --normal: 0.32s;
  --slow: 0.5s;
  font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-synthesis: none;
}

* {
  box-sizing: border-box;
}

[hidden] {
  display: none !important;
}

html {
  scroll-behavior: smooth;
  /* The header stays pinned over the page: whatever is scrolled to lands below it. How tall it
     is depends on the width and on who is signed in, so header.ts measures it; the number after
     the variable is the guess for the moment before. */
  scroll-padding-top: calc(var(--header-height, 76px) + 12px);
  min-width: 320px;
  background: var(--background);
}

/* Nothing that moves (the gusli dancing, notes flying, glows) may widen the page: on a phone a
   wider page lets the visitor zoom out past the screen. Clipped, not hidden, so nothing scrolls. */
html {
  overflow-x: hidden;
}

@supports (overflow: clip) {
  html,
  body {
    overflow-x: clip;
  }
}

body {
  min-height: 100vh;
  margin: 0;
  display: flex;
  flex-direction: column;
  color: var(--text);
  background:
    radial-gradient(circle at 50% 0, rgba(255, 107, 53, 0.13), transparent 34rem),
    var(--background);
  line-height: 1.5;
}

/* The site is an app, not a document: a long press selects nothing and opens no callout.
   Only what the visitor types or copies (fields, the invite link) stays selectable. */
body {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

input,
textarea,
[contenteditable] {
  -webkit-user-select: text;
  user-select: text;
  -webkit-touch-callout: default;
}

img,
svg {
  -webkit-user-drag: none;
}

button,
input,
textarea {
  font: inherit;
  color: inherit;
}

button {
  cursor: pointer;
}

a {
  color: inherit;
  transition: color var(--fast) ease, opacity var(--fast) ease;
}

a:hover {
  color: var(--text);
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* The header is pinned: it stays on the screen however far the page scrolls. It runs the
   whole width so the page slides under a band, not a strip; its content keeps the page's column. */
.topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px 16px;
  width: 100%;
  padding: 14px max(16px, calc((100% - 760px) / 2));
  padding-top: calc(14px + env(safe-area-inset-top));
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  background: rgba(14, 13, 18, 0.8);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  backdrop-filter: blur(14px) saturate(1.4);
}

/* The site's sections (views.ts). */
.sections {
  display: flex;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface-soft);
}

.section-link {
  padding: 6px 13px;
  border-radius: 999px;
  color: var(--muted);
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--fast) ease, background var(--fast) ease;
}

.section-link:hover {
  color: var(--text);
  background: var(--surface-soft);
}

.section-link[aria-current="page"] {
  color: #fff;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
}

/* On a narrow screen the menu takes a row of its own under the brand and the account. The
   account never drops to a row of its own: it takes what the brand leaves, and the address in
   it shortens. */
@media (max-width: 700px) {
  .topbar {
    flex-wrap: wrap;
  }

  .account {
    display: flex;
    flex: 1 1 0;
    justify-content: flex-end;
    min-width: 0;
  }

  .account-chip {
    max-width: 100%;
  }

  .sections {
    order: 3;
    width: 100%;
  }

  .section-link {
    flex: 1;
    padding: 7px 4px;
    text-align: center;
    font-size: 0.86rem;
  }

  html {
    scroll-padding-top: calc(var(--header-height, 116px) + 12px);
  }
}

/* The narrowest phones: with the own voice the menu has five tabs, and none may be cut off. */
@media (max-width: 359px) {
  .section-link {
    padding: 7px 2px;
    font-size: 0.78rem;
  }
}

/* ---------- sections ---------- */

/* A browser that may be new: for the moment it takes to learn whether the main page opens on
   the onboarding, nothing but the brand shows (main.ts). */
.is-deciding main,
.is-deciding .footer,
.is-deciding .sections {
  visibility: hidden;
}

/* The form is the «Создать» section; the gusli have theirs (below); «Мои песни» is the list
   alone; the cabinet is a section by itself. The banner over the form goes when the operator
   takes it away in the admin panel (hero.ts). */
[data-view="songs"] .hero,
[data-view="songs"] #song-form,
[data-view="cabinet"] .hero,
[data-view="cabinet"] #song-form,
[data-view="cabinet"] #progress,
[data-view="cabinet"] #songs-section,
.is-hero-off .hero {
  display: none;
}

[data-view="songs"] main,
[data-view="cabinet"] main,
.is-hero-off[data-view="create"] main {
  padding-top: 20px;
}

.songs-empty {
  display: none;
  padding: 48px 0;
  text-align: center;
}

.songs-empty p {
  margin: 0 0 6px;
}

[data-view="songs"] #songs-section[hidden] ~ .songs-empty {
  display: block;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
  font-size: 1.15rem;
  letter-spacing: 0.01em;
  text-decoration: none;
}

.brand-mark {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  height: 22px;
}

.brand-mark i {
  width: 4px;
  border-radius: 2px;
  background: linear-gradient(180deg, var(--accent), var(--accent-2));
}

.brand-mark i:nth-child(1) { height: 40%; }
.brand-mark i:nth-child(2) { height: 100%; }
.brand-mark i:nth-child(3) { height: 65%; }
.brand-mark i:nth-child(4) { height: 85%; }

main {
  flex: 1;
  width: min(100% - 32px, 760px);
  margin: 0 auto;
  padding-bottom: 56px;
}

.hero {
  padding: 28px 0 24px;
  text-align: center;
}

h1 {
  margin: 0 0 12px;
  font-size: clamp(1.9rem, 5.2vw, 2.9rem);
  line-height: 1.12;
  letter-spacing: -0.02em;
}

h2 {
  margin: 0;
  font-size: 1.2rem;
}

h3 {
  margin: 24px 0 8px;
  font-size: 1rem;
  color: var(--muted);
  font-weight: 600;
}

.lead {
  max-width: 34rem;
  margin: 0 auto;
  color: var(--muted);
  font-size: 1.05rem;
}

.card {
  margin-bottom: 20px;
  padding: 22px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}

.tabs {
  position: relative;
  display: inline-flex;
  gap: 4px;
  margin-bottom: 18px;
  padding: 4px;
  border-radius: 999px;
  background: var(--surface-soft);
}

.tabs-thumb {
  position: absolute;
  top: 4px;
  left: 0;
  width: var(--thumb-width, 0);
  height: calc(100% - 8px);
  border-radius: 999px;
  background: var(--text);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
  transform: translateX(var(--thumb-x, 4px));
  transition: transform var(--normal) var(--spring), width var(--normal) var(--ease);
}

/* The first placement must not slide in from the corner. */
.tabs:not(.is-ready) .tabs-thumb {
  transition: none;
}

.tab {
  position: relative;
  z-index: 1;
  padding: 8px 16px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-weight: 600;
  font-size: 0.92rem;
  white-space: nowrap;
  transition: color var(--normal) var(--ease);
}

.tab:hover:not(.is-active) {
  color: var(--text);
}

.tab.is-active {
  color: #141217;
}

/* Fields that belong to one mode open and close instead of popping. */
.reveal {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transform: translateY(-6px);
  transition:
    grid-template-rows var(--normal) var(--ease),
    opacity var(--normal) ease,
    transform var(--normal) var(--ease);
}

.reveal.is-open {
  grid-template-rows: 1fr;
  opacity: 1;
  transform: none;
}

/* The clipping box reaches past the fields on either side: the 4px focus ring round a field
   stays whole (room given to the field itself sat inside the clip, and the ring's sides were
   cut off). */
.reveal-inner {
  min-height: 0;
  overflow: hidden;
  margin: 0 -4px;
  padding: 0 4px;
}

.field {
  display: block;
  position: relative;
  margin-bottom: 16px;
}

.field > span {
  display: block;
  margin-bottom: 6px;
  color: var(--muted);
  font-size: 0.9rem;
}

input[type="text"],
input[type="email"],
textarea {
  width: 100%;
  padding: 13px 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: rgba(0, 0, 0, 0.28);
  transition:
    border-color var(--fast) ease,
    box-shadow var(--normal) var(--ease),
    background-color var(--fast) ease;
}

input[type="text"]:hover,
input[type="email"]:hover,
textarea:hover {
  border-color: var(--line-strong);
}

textarea {
  min-height: 132px;
  resize: vertical;
}

input[type="text"]:focus,
input[type="email"]:focus,
textarea:focus {
  border-color: rgba(255, 107, 53, 0.65);
  box-shadow: 0 0 0 4px rgba(255, 107, 53, 0.14);
  background: rgba(0, 0, 0, 0.36);
  outline: none;
}

::placeholder {
  color: #6f6976;
}

.counter {
  display: block;
  margin-top: 4px;
  color: var(--muted);
  font-size: 0.8rem;
  text-align: right;
}

.field.is-flush {
  margin-bottom: 0;
}

/* The words can be written for you: the offer sits under the description,
   opposite its counter, and never competes with the button that makes the song. */
.field-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
  min-height: 34px;
}

.field-foot .counter {
  margin-top: 0;
  margin-left: auto;
}

.ghost.draft {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px 7px 11px;
  font-size: 0.88rem;
}

.ghost.draft .icon {
  width: 18px;
  height: 18px;
  color: var(--accent);
  transition: transform var(--normal) var(--spring);
}

.ghost.draft:hover .icon {
  transform: rotate(-12deg) scale(1.08);
}

/* Waiting for the words: the button holds its place and visibly works —
   a light runs along it and the spark keeps flickering until they arrive. */
.ghost.draft.is-drafting {
  position: relative;
  overflow: hidden;
  border-color: rgba(255, 107, 53, 0.5);
  background: rgba(255, 107, 53, 0.09);
  cursor: progress;
}

.ghost.draft.is-drafting::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 107, 53, 0.26), transparent);
  transform: translateX(-100%);
  animation: shimmer 1.5s ease-in-out infinite;
}

.ghost.draft.is-drafting .icon {
  animation: twinkle 1.5s var(--ease) infinite;
}

/* The words will land in the field below, so it waits along with the button. */
textarea.is-drafting {
  border-color: rgba(255, 107, 53, 0.45);
  animation: breathe 2.2s ease-in-out infinite;
}

/* Quieter than the offer beside it: wiping the form is never the thing to do first. */
.ghost.clear {
  padding: 7px 14px;
  border-color: transparent;
  color: var(--muted);
  font-size: 0.88rem;
}

.ghost.clear:hover {
  border-color: var(--line);
  color: var(--text);
}

/* Asking again: the second press is the one that empties the fields. */
.ghost.clear.is-armed {
  border-color: var(--danger);
  color: var(--danger);
}

.ghost.clear.is-armed:hover {
  border-color: var(--danger);
  background: rgba(255, 123, 130, 0.08);
  color: var(--danger);
}

/* Emptying, once it is confirmed: the words fade out where they stand and the
   field flashes as it comes back empty, so the wipe is watched, not just found. */
.is-wiping {
  color: transparent;
  transition: color 0.19s ease;
}

.is-wiped {
  animation: wiped var(--slow) var(--ease);
}

/* The pixels come apart over the field they are leaving, and the words
   themselves wait out of sight until it is empty. */
.shatter {
  position: absolute;
  z-index: 20;
  pointer-events: none;
}

.is-shattering {
  color: transparent;
}

/* The die: an idea for the song at a toss. It sits in the head of the field it
   fills, the way «Вставить» sits over the code, and fades out of the custom
   tab, where the field holds the words themselves. */
.ghost.dice {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 13px 5px 9px;
  font-size: 0.85rem;
  white-space: nowrap;
  transition:
    border-color var(--fast) ease,
    background-color var(--fast) ease,
    transform var(--fast) var(--ease),
    opacity var(--normal) ease,
    visibility var(--normal);
}

/* The pill stays compact, but a finger gets a full-size target around it. */
.dice::after {
  content: "";
  position: absolute;
  inset: -7px -4px;
}

.dice .icon {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.8;
  transition: transform var(--normal) var(--spring);
}

.dice .icon circle {
  fill: var(--accent);
  stroke: none;
  opacity: 0;
  transition: opacity 0.08s ease;
}

.dice .icon circle.is-on {
  opacity: 1;
}

.dice:hover .icon {
  transform: rotate(-14deg) scale(1.08);
}

/* Tossed: the die flies up turning its faces, lands with a squash and a small
   bounce, and the pill stays warm while it is in the air. 0.82s is the length
   of a roll in app.js (ROLL_MS). */
.dice.is-rolling {
  animation: dice-warm 0.82s var(--ease);
}

.dice.is-rolling .icon {
  animation: tumble 0.82s linear;
}

.dice.is-away {
  opacity: 0;
  visibility: hidden;
  transform: scale(0.9);
}

/* While the reels spin the field is theirs; when they stop it glows once,
   the way a pasted code does. */
textarea.is-rolling {
  border-color: rgba(255, 107, 53, 0.55);
  box-shadow: 0 0 0 4px rgba(255, 107, 53, 0.12);
}

textarea.is-rolled {
  animation: pasted var(--slow) var(--ease);
}

.check {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-bottom: 16px;
  color: var(--muted);
  font-size: 0.93rem;
}

.check {
  cursor: pointer;
  transition: color var(--fast) ease;
}

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

.check input {
  width: 18px;
  height: 18px;
  margin: 2px 0 0;
  accent-color: var(--accent);
  flex: none;
  cursor: pointer;
  transition: transform var(--fast) var(--spring);
}

.check input:active {
  transform: scale(0.86);
}

.composer-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

.hint {
  margin: 0;
  color: var(--muted);
  font-size: 0.9rem;
}

/* Basis 0: on a narrow card the notes wrap inside their column instead of pushing the button down. */
.composer-notes {
  display: grid;
  gap: 4px;
  flex: 1 1 0;
  min-width: 0;
}

/* Says what Yandex's floating notice would say; that notice is switched off (hideShield). */
.captcha-note {
  margin: 0;
  color: var(--muted);
  font-size: 0.78rem;
}

/* A narrow line breaks before the link, not inside it. */
.captcha-note a {
  white-space: nowrap;
  text-underline-offset: 2px;
}

.primary {
  padding: 13px 26px;
  border: 0;
  border-radius: 999px;
  background: linear-gradient(95deg, var(--accent), var(--accent-2));
  color: #fff;
  font-weight: 700;
  box-shadow: 0 6px 20px rgba(242, 50, 138, 0.22);
  transition:
    filter var(--fast) ease,
    transform var(--fast) var(--ease),
    box-shadow var(--normal) var(--ease),
    opacity var(--normal) ease;
}

.primary:hover:not(:disabled) {
  filter: brightness(1.08);
  transform: translateY(-1px);
  box-shadow: 0 10px 28px rgba(242, 50, 138, 0.34);
}

.primary:active:not(:disabled) {
  transform: translateY(0) scale(0.98);
  box-shadow: 0 4px 12px rgba(242, 50, 138, 0.22);
}

.primary:disabled {
  opacity: 0.6;
  cursor: progress;
  box-shadow: none;
}

.primary.is-loading::after {
  content: "";
  display: inline-block;
  width: 14px;
  height: 14px;
  margin-left: 10px;
  vertical-align: -2px;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}

.wide {
  width: 100%;
}

.ghost {
  padding: 9px 16px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  font-size: 0.92rem;
  transition:
    border-color var(--fast) ease,
    background-color var(--fast) ease,
    transform var(--fast) var(--ease);
}

.ghost:hover {
  border-color: var(--line-strong);
  background: var(--surface-soft);
}

.ghost:active {
  transform: scale(0.97);
}

.link {
  padding: 0;
  border: 0;
  background: none;
  color: var(--muted);
  font-size: 0.9rem;
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: color var(--fast) ease, opacity var(--fast) ease;
}

.link:hover:not(:disabled) {
  color: var(--text);
}

.link:disabled {
  text-decoration: none;
  cursor: default;
  opacity: 0.7;
}

/* The account in the header: the energy, then the picture as the chip's round end. */
.account-chip {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 3px 3px 3px 13px;
}

.account-chip .avatar {
  width: 30px;
  height: 30px;
}

/* «⚡ 10» is one word: split over two lines it made the header a row taller. */
.balance {
  flex: none;
  font-weight: 700;
  font-size: 0.88rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ---------- the account's picture (avatars.ts) ---------- */

/* A young animal in a round frame: its gradient, lit from the top left. */
.avatar {
  display: block;
  flex: none;
  width: 32px;
  height: 32px;
  overflow: hidden;
  border-radius: 50%;
  background:
    radial-gradient(circle at 30% 22%, rgba(255, 255, 255, 0.28), transparent 58%),
    linear-gradient(135deg, var(--sky-from, #3a3745), var(--sky-to, #24212c));
}

.avatar svg,
.avatar img {
  display: block;
  width: 100%;
  height: 100%;
}

/* The person's own photo fills the frame, whatever its gradient. */
.avatar img {
  object-fit: cover;
}

/* A new pick lands with a little bounce, in the header and in the cabinet alike. */
.avatar.is-new {
  animation: avatar-land var(--slow) var(--spring);
}

@keyframes avatar-land {
  from {
    opacity: 0.3;
    transform: scale(0.6) rotate(-8deg);
  }
}

/* The cabinet's head: the picture, which opens the picker, beside the title. */
.profile {
  display: flex;
  align-items: center;
  gap: 16px;
  min-width: 0;
}

.avatar-edit {
  position: relative;
  flex: none;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  transition: transform var(--fast) var(--ease);
}

.avatar-edit .avatar {
  width: 64px;
  height: 64px;
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.35);
}

.avatar-edit:hover {
  transform: translateY(-1px) scale(1.03);
}

.avatar-edit:active {
  transform: scale(0.96);
}

.avatar-pen {
  position: absolute;
  right: -3px;
  bottom: -3px;
  display: grid;
  place-items: center;
  width: 25px;
  height: 25px;
  border: 2.5px solid var(--surface);
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
  transition: transform var(--normal) var(--spring);
}

.avatar-pen svg {
  width: 13px;
  height: 13px;
  fill: currentColor;
}

.avatar-edit[aria-expanded="true"] .avatar-pen {
  transform: rotate(-20deg) scale(1.1);
}

/* The animals to pick from: unfolded under the head, the account's own one ringed. */
.avatar-picker {
  margin: 0 0 16px;
}

.avatar-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 60px));
  gap: 12px;
  padding: 2px 0 4px;
}

.avatar-choice {
  position: relative;
  display: block;
  aspect-ratio: 1;
  padding: 4.5px;
  border: 0;
  border-radius: 50%;
  background: none;
  animation: avatar-come var(--normal) var(--spring) both;
  animation-delay: calc(var(--i, 0) * 22ms);
}

.avatar-choice::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  opacity: 0;
  transform: scale(0.86);
  transition:
    opacity var(--fast) ease,
    transform var(--normal) var(--spring);
}

.avatar-choice[aria-pressed="true"]::before {
  opacity: 1;
  transform: none;
}

/* The height follows the width: WebKit (Safari, messengers on iPhone) took height: 100% in a
   button from its outer edge, padding and all, and drew the animals as ovals. */
.avatar-choice .avatar {
  position: relative;
  width: 100%;
  height: auto;
  aspect-ratio: 1;
  box-shadow: 0 0 0 2px var(--surface);
  transition: transform var(--fast) var(--ease);
}

.avatar-choice:hover .avatar {
  transform: scale(1.07);
}

.avatar-choice:active .avatar {
  transform: scale(0.94);
}

@keyframes avatar-come {
  from {
    opacity: 0;
    transform: translateY(8px) scale(0.7);
  }
}

/* The first tile sends a photo of one's own: an empty frame with a camera in it. The file
   field itself is out of sight; the whole tile opens it. */
.avatar-upload {
  position: relative;
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  padding: 4.5px;
  border-radius: 50%;
  cursor: pointer;
  animation: avatar-come var(--normal) var(--spring) both;
}

.avatar-upload-ring {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  border: 1.5px dashed var(--line-strong);
  border-radius: 50%;
  color: var(--muted);
  transition:
    border-color var(--fast) ease,
    color var(--fast) ease,
    transform var(--fast) var(--ease);
}

.avatar-upload:hover .avatar-upload-ring {
  border-color: var(--accent);
  color: var(--text);
  transform: scale(1.07);
}

.avatar-upload:focus-within {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.avatar-upload-ring svg {
  width: 44%;
  height: 44%;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linejoin: round;
}

/* While the photo is on its way the camera gives way to a spinner. */
.avatar-upload.is-busy {
  cursor: progress;
}

.avatar-upload.is-busy .avatar-upload-ring svg {
  visibility: hidden;
}

.avatar-upload.is-busy::after {
  content: "";
  position: absolute;
  width: 34%;
  height: 34%;
  border: 2px solid var(--line-strong);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}

/* The photo's own tile, and the cross that throws the photo away. */
.avatar-photo {
  position: relative;
}

.avatar-remove {
  position: absolute;
  top: -3px;
  right: -3px;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 2px solid var(--surface);
  border-radius: 50%;
  background: #3a3745;
  color: var(--text);
  transition: background-color var(--fast) ease, transform var(--fast) var(--ease);
}

.avatar-remove:hover {
  background: var(--danger);
  transform: scale(1.08);
}

.avatar-remove svg {
  width: 12px;
  height: 12px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.6;
  stroke-linecap: round;
}

.avatar-picker .error {
  margin: 10px 0 0;
}

@media (max-width: 520px) {
  .profile {
    gap: 12px;
  }

  .avatar-edit .avatar {
    width: 54px;
    height: 54px;
  }

  .avatar-grid {
    grid-template-columns: repeat(4, minmax(0, 64px));
    justify-content: space-between;
    gap: 12px 10px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .avatar.is-new,
  .avatar-choice,
  .avatar-upload {
    animation: none;
  }
}

.notice {
  margin: 0 0 20px;
  padding: 14px 18px;
  border: 1px solid rgba(255, 159, 46, 0.4);
  border-radius: 14px;
  background: rgba(255, 159, 46, 0.09);
}

.notice.is-error {
  border-color: rgba(255, 123, 130, 0.45);
  background: rgba(255, 123, 130, 0.09);
}

.error {
  margin: 0 0 14px;
  color: var(--danger);
  font-size: 0.92rem;
}

.progress-head,
.section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}

.badge {
  padding: 4px 11px;
  border-radius: 999px;
  background: var(--surface-soft);
  color: var(--muted);
  font-size: 0.82rem;
  white-space: nowrap;
}

.bar {
  height: 6px;
  margin-bottom: 12px;
  overflow: hidden;
  border-radius: 999px;
  background: var(--surface-soft);
}

.bar span {
  position: relative;
  display: block;
  width: 8%;
  height: 100%;
  overflow: hidden;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  transition: width 1.4s var(--ease);
}

.bar span::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.55), transparent);
  transform: translateX(-100%);
  animation: shimmer 1.8s ease-in-out infinite;
}

.badge {
  transition: background-color var(--normal) ease, color var(--normal) ease;
}

.song {
  margin-bottom: 16px;
  padding: 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  transition: border-color var(--normal) ease;
}

.song:hover {
  border-color: var(--line-strong);
}

.song.is-entering,
.song.is-unveiling .track {
  animation: rise-in var(--slow) var(--ease) both;
}

.song.is-unveiling .track:nth-child(n + 4) {
  animation-delay: 0.12s;
}

.song-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 4px;
}

.song-title {
  margin: 0;
  font-size: 1.05rem;
  overflow-wrap: anywhere;
}

.song-meta {
  margin: 0 0 12px;
  color: var(--muted);
  font-size: 0.85rem;
}

/* ---------- search in «Мои песни» (search.ts) ---------- */

/* The field is «Мои песни»'s own, and so is what it hides: other sections show the whole list. */
.song-search,
.song-search-empty {
  display: none;
}

[data-view="songs"] .song-search,
[data-view="songs"] .song-search-empty {
  display: block;
}

[data-view="songs"] .song.is-filtered-out {
  display: none;
}

/* A card the search gives back rises into place. */
.song.is-found {
  animation: rise-in var(--normal) var(--ease) both;
}

.song-search {
  margin-bottom: 18px;
}

/* One pill: the magnifier, the words, and at the end how many were found and the cross. */
.song-search-field {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 7px 0 17px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.28);
  cursor: text;
  transition:
    border-color var(--fast) ease,
    box-shadow var(--normal) var(--ease),
    background-color var(--fast) ease;
}

.song-search-field:hover {
  border-color: var(--line-strong);
}

.song-search-field:focus-within {
  border-color: rgba(255, 107, 53, 0.65);
  box-shadow: 0 0 0 4px rgba(255, 107, 53, 0.14);
  background: rgba(0, 0, 0, 0.36);
}

.song-search .song-search-icon {
  flex: none;
  width: 20px;
  height: 20px;
  color: var(--muted);
  transition: color var(--fast) ease, transform var(--normal) var(--spring);
}

.song-search-field:focus-within .song-search-icon,
.song-search.is-searching .song-search-icon {
  color: var(--accent);
}

.song-search .song-search-field:focus-within .song-search-icon {
  transform: scale(1.1) rotate(-8deg);
}

/* 16px and up: a phone zooms into a smaller field when it is tapped. */
.song-search input {
  flex: 1;
  min-width: 0;
  height: 50px;
  padding: 0;
  border: 0;
  background: none;
  font-size: 1rem;
  -webkit-appearance: none;
  appearance: none;
}

/* The pill shows the focus; the browser's own cross is replaced by the page's. */
.song-search input:focus,
.song-search input:focus-visible {
  outline: none;
}

.song-search input::-webkit-search-decoration,
.song-search input::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}

/* «/» is the way in from a keyboard, shown while the field waits; a phone has no such key. */
.song-search-key {
  flex: none;
  display: inline-grid;
  place-items: center;
  min-width: 24px;
  height: 24px;
  margin-right: 8px;
  padding: 0 7px;
  border: 1px solid var(--line-strong);
  border-bottom-width: 2px;
  border-radius: 7px;
  color: var(--muted);
  font: 600 0.78rem/1 ui-monospace, SFMono-Regular, Menlo, monospace;
}

.song-search-field:focus-within .song-search-key,
.song-search.is-searching .song-search-key {
  display: none;
}

@media (hover: none), (pointer: coarse) {
  .song-search-key {
    display: none;
  }
}

.song-search-count {
  flex: none;
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(255, 107, 53, 0.14);
  color: var(--accent);
  font-size: 0.8rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  animation: fade-in var(--fast) ease;
}

.song-search-count:empty {
  display: none;
}

.song-search.is-nothing .song-search-count {
  background: var(--surface-soft);
  color: var(--muted);
}

.song-search-clear {
  flex: none;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--surface-soft);
  color: var(--muted);
  animation: pop-in var(--normal) var(--spring);
  transition:
    background-color var(--fast) ease,
    color var(--fast) ease,
    transform var(--fast) var(--ease);
}

.song-search-clear:hover {
  background: rgba(255, 255, 255, 0.1);
  color: var(--text);
}

.song-search-clear:active {
  transform: scale(0.9);
}

.song-search-clear .icon.icon-line {
  width: 16px;
  height: 16px;
  stroke-width: 2.2;
}

/* What was found, lit up in the titles; the margin keeps the words where they stood. */
.song mark {
  margin: 0 -2px;
  padding: 0 2px;
  border-radius: 5px;
  background: linear-gradient(95deg, rgba(255, 107, 53, 0.3), rgba(242, 50, 138, 0.3));
  color: var(--text);
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

.song-search-empty {
  padding: 34px 20px 30px;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  text-align: center;
  animation: rise-in var(--normal) var(--ease);
}

.song-search-empty .song-search-empty-icon {
  width: 40px;
  height: 40px;
  margin-bottom: 6px;
  color: var(--muted);
  stroke-width: 1.4;
}

.song-search-empty-title {
  margin: 0 0 4px;
  font-size: 1.05rem;
  font-weight: 700;
}

.song-search-empty .hint {
  margin-bottom: 18px;
  overflow-wrap: anywhere;
}

@keyframes pop-in {
  from {
    opacity: 0;
    transform: scale(0.6);
  }
}

/* Read aloud to a screen reader, never seen. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  border: 0;
  clip-path: inset(50%);
  white-space: nowrap;
}

.track {
  position: relative;
  margin-top: 10px;
  padding: 14px;
  border-radius: 14px;
  background: var(--surface-soft);
}

.track-name {
  margin: 0 0 8px;
  font-size: 0.92rem;
  color: var(--muted);
  overflow-wrap: anywhere;
}

/* The main take is marked only when there are others to tell it from. */
.track-badge {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 8px;
  border-radius: 999px;
  background: rgba(255, 107, 53, 0.14);
  color: var(--accent);
  font-size: 0.75rem;
  vertical-align: 1px;
}

/* The other takes wait folded under the main one. */
.takes-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
  padding: 4px 0;
  border: 0;
  background: none;
  color: var(--muted);
  font-size: 0.88rem;
  transition: color var(--fast) ease;
}

.takes-toggle:hover {
  color: var(--text);
}

/* The search found the words in a take folded away here. */
.takes-toggle.is-found {
  color: var(--accent);
}

.takes-chevron {
  transition: transform var(--normal) var(--ease);
}

.takes-toggle[aria-expanded='true'] .takes-chevron {
  transform: rotate(180deg);
}

.takes-more {
  overflow: hidden;
}

.take-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 16px;
  margin-top: 12px;
}

.take-actions .ghost {
  padding: 7px 14px;
  font-size: 0.88rem;
}

/* ---------- player ---------- */

.player {
  display: flex;
  align-items: center;
  gap: 14px;
}

.player-toggle {
  position: relative;
  flex: none;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
  box-shadow: 0 6px 18px rgba(242, 50, 138, 0.3);
  transition:
    transform var(--fast) var(--ease),
    box-shadow var(--normal) var(--ease),
    filter var(--fast) ease;
}

button.player-toggle:hover {
  transform: scale(1.06);
  filter: brightness(1.08);
  box-shadow: 0 8px 26px rgba(242, 50, 138, 0.45);
}

button.player-toggle:active {
  transform: scale(0.95);
}

/* A slow ring breathes out of the button while the song plays. */
.player-toggle::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  border: 2px solid var(--accent-2);
  opacity: 0;
}

.player.is-playing .player-toggle::before {
  animation: ring 1.8s var(--ease) infinite;
}

.icon {
  width: 22px;
  height: 22px;
  fill: currentColor;
}

.player-toggle .icon {
  position: absolute;
  inset: 0;
  margin: auto;
  transition: opacity var(--fast) ease, transform var(--normal) var(--spring);
}

.icon-play {
  translate: 1px 0;
}

.icon-pause,
.player.is-playing .icon-play {
  opacity: 0;
  transform: scale(0.4) rotate(-90deg);
}

.player.is-playing .icon-pause {
  opacity: 1;
  transform: none;
}

.player-spinner {
  position: absolute;
  inset: -4px;
  border: 2px solid transparent;
  border-top-color: var(--text);
  border-radius: 50%;
  opacity: 0;
  transition: opacity var(--fast) ease;
}

.player.is-loading .player-spinner {
  opacity: 1;
  animation: spin 0.8s linear infinite;
}

.player-main {
  flex: 1;
  min-width: 0;
}

.wave {
  display: flex;
  align-items: center;
  gap: 2px;
  height: 40px;
  border-radius: 8px;
  cursor: pointer;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
}

.wave:focus-visible {
  outline-offset: 4px;
}

.wave-bar {
  position: relative;
  flex: 1;
  min-width: 2px;
  overflow: hidden;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.16);
  transition: background-color var(--fast) ease, transform var(--normal) var(--spring);
}

/* The gradient sits on top and fades in: a background-image itself cannot transition. */
.wave-bar::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, var(--accent), var(--accent-2));
  opacity: 0;
  transition: opacity var(--normal) ease;
}

.wave-bar.is-played::after {
  opacity: 1;
}

.wave-bar.is-preview:not(.is-played) {
  background: rgba(255, 255, 255, 0.36);
}

.wave:hover .wave-bar {
  transform: scaleY(1.08);
}

.player-meta {
  display: flex;
  justify-content: space-between;
  margin-top: 4px;
  color: var(--muted);
  font-size: 0.76rem;
  font-variant-numeric: tabular-nums;
}

.player-download {
  display: grid;
  flex: none;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--line);
  border-radius: 50%;
  color: var(--muted);
  transition:
    color var(--fast) ease,
    border-color var(--fast) ease,
    background-color var(--fast) ease,
    transform var(--fast) var(--ease);
}

.player-download .icon {
  width: 19px;
  height: 19px;
}

.player-download:hover {
  color: var(--text);
  border-color: var(--line-strong);
  background: var(--surface-soft);
  transform: translateY(-1px);
}

.player-download:active {
  transform: scale(0.94);
}

/* The clip for stories: drawn on the first tap, handed to the share sheet on the next. */
.player-story {
  position: relative;
  padding: 0;
  background: none;
}

.player-story.is-busy {
  pointer-events: none;
}

.player-story.is-busy .icon {
  opacity: 0.35;
}

.player-story.is-busy::after {
  content: "";
  position: absolute;
  inset: -1px;
  border: 2px solid transparent;
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

.story-hint,
.story-hint.error {
  margin: 10px 0 0;
}

.player-story.is-ready,
.player-story.is-ready:hover {
  color: #fff;
  border-color: transparent;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  box-shadow: 0 6px 20px rgba(242, 50, 138, 0.4);
}

.player.is-broken .player-toggle {
  background: rgba(255, 255, 255, 0.12);
  box-shadow: none;
  pointer-events: none;
}

.player.is-broken .player-meta {
  color: var(--danger);
}

.track {
  transition: background-color var(--normal) ease;
}

.track:not(.is-locked):hover {
  background: rgba(255, 255, 255, 0.075);
}

.track-lock {
  transition: transform var(--normal) var(--ease);
}

.track.is-locked:hover .track-lock {
  transform: scale(1.02);
}

.track.is-locked .track-body {
  filter: blur(5px);
  opacity: 0.5;
  pointer-events: none;
  user-select: none;
}

.track-lock {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 8px;
  text-align: center;
  font-size: 0.92rem;
}

.track-lock .primary {
  padding: 9px 18px;
  font-size: 0.9rem;
}

/* ---------- the dock: the player pinned to the bottom of the window ---------- */

/* The song that is on stays in reach however far the list scrolls: the dock floats over the
   bottom of the window, as wide as the page, and rises into view with the first song there
   is to play. The page keeps room for it under the footer. */
.dock {
  position: fixed;
  z-index: 40;
  right: 0;
  bottom: calc(12px + env(safe-area-inset-bottom));
  left: 0;
  width: min(100% - 20px, 760px);
  margin: 0 auto;
  border: 1px solid var(--line-strong);
  border-radius: 20px;
  background: rgba(26, 24, 32, 0.86);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  backdrop-filter: blur(18px) saturate(1.4);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.55);
  opacity: 0;
  visibility: hidden;
  transform: translateY(calc(100% + 28px));
  transition:
    transform var(--slow) var(--ease),
    opacity var(--normal) ease,
    box-shadow var(--slow) ease,
    visibility 0s linear var(--slow);
}

.dock.is-shown:not(.is-tucked) {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition-delay: 0s;
}

/* While it plays, the dock glows in the page's warm colours. */
.dock.is-playing {
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.55), 0 8px 34px rgba(242, 50, 138, 0.16);
}

/* Nothing the page scrolls to lands under the dock either. */
.has-dock {
  --dock-room: calc(92px + env(safe-area-inset-bottom));
  scroll-padding-bottom: var(--dock-room);
}

.has-dock body {
  padding-bottom: var(--dock-room);
}

.dock-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px 10px 10px;
}

/* The song's face and name: a press finds it in the list. */
.dock-now {
  display: flex;
  flex: 1;
  align-items: center;
  gap: 12px;
  min-width: 0;
  padding: 0;
  border: 0;
  border-radius: 12px;
  background: none;
  text-align: left;
}

.dock-art {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  gap: 3px;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  box-shadow: 0 6px 18px rgba(242, 50, 138, 0.28);
  transition: transform var(--normal) var(--spring);
}

.dock-now:hover .dock-art {
  transform: scale(1.05);
}

.dock-now:active .dock-art {
  transform: scale(0.95);
}

/* The logo's four bars: they dance while the song plays and hold still where it stopped. */
.dock-art i {
  width: 4px;
  height: 20px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.94);
  animation: equalize 0.9s ease-in-out infinite paused;
}

.dock-art i:nth-child(2) { animation-delay: -0.25s; }
.dock-art i:nth-child(3) { animation-delay: -0.5s; }
.dock-art i:nth-child(4) { animation-delay: -0.7s; }

.dock.is-playing .dock-art i {
  animation-play-state: running;
}

.dock-text {
  display: grid;
  gap: 1px;
  min-width: 0;
}

.dock-title {
  overflow: hidden;
  font-size: 0.95rem;
  line-height: 1.3;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: color var(--fast) ease;
}

.dock-now:hover .dock-title {
  color: #fff;
}

.dock-sub {
  display: flex;
  gap: 6px;
  min-width: 0;
  color: var(--muted);
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.dock-take {
  overflow: hidden;
  text-overflow: ellipsis;
}

.dock-take::before {
  content: "·";
  margin-right: 6px;
}

.dock.is-broken .dock-sub {
  color: var(--danger);
}

.dock-controls {
  display: flex;
  flex: none;
  align-items: center;
  gap: 6px;
}

.dock-button {
  display: grid;
  flex: none;
  place-items: center;
  width: 38px;
  height: 38px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--muted);
  transition:
    color var(--fast) ease,
    background-color var(--fast) ease,
    opacity var(--fast) ease,
    transform var(--fast) var(--ease);
}

.dock-button:hover:not(:disabled) {
  color: var(--text);
  background: var(--surface-soft);
}

.dock-button:active:not(:disabled) {
  transform: scale(0.9);
}

.dock-button:disabled {
  opacity: 0.35;
  cursor: default;
}

.dock-button .icon {
  width: 20px;
  height: 20px;
}

.icon-next {
  transform: scaleX(-1);
}

/* One song to play: there is nothing to go back or on to. */
.dock.is-single .dock-skip {
  display: none;
}

.dock-toggle {
  width: 44px;
  height: 44px;
}

.dock.is-playing .dock-toggle .icon-play {
  opacity: 0;
  transform: scale(0.4) rotate(-90deg);
}

.dock.is-playing .dock-toggle .icon-pause {
  opacity: 1;
  transform: none;
}

.dock.is-loading .player-spinner {
  opacity: 1;
  animation: spin 0.8s linear infinite;
}

/* The line along the dock's top edge is how far the song has gone. It takes a press or a
   drag anywhere along it, and a finger gets a full-size strip around the thin line. */
.dock-seek {
  position: absolute;
  top: -10px;
  right: 20px;
  left: 20px;
  height: 20px;
  cursor: pointer;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  --played: 0;
  --at: 0%;
}

.dock-seek:focus-visible {
  outline: none;
}

.dock-line {
  position: absolute;
  top: 50%;
  right: 0;
  left: 0;
  height: 3px;
  overflow: hidden;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.14);
  transform: translateY(-50%);
  transition: height var(--fast) var(--ease), box-shadow var(--fast) ease;
}

.dock-seek:hover .dock-line,
.dock-seek.is-dragging .dock-line,
.dock-seek:focus-visible .dock-line {
  height: 5px;
}

.dock-seek:focus-visible .dock-line {
  box-shadow: 0 0 0 2px var(--accent);
}

/* The colours run the whole length and show as far as the song has gone. */
.dock-fill {
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  clip-path: inset(0 calc(100% - var(--played) * 100%) 0 0);
}

.dock-knob {
  position: absolute;
  top: 50%;
  left: calc(var(--played) * 100%);
  width: 13px;
  height: 13px;
  margin: -6.5px 0 0 -6.5px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.45);
  transform: scale(0);
  transition: transform var(--fast) var(--spring);
  pointer-events: none;
}

.dock-seek:hover .dock-knob,
.dock-seek.is-dragging .dock-knob,
.dock-seek:focus-visible .dock-knob {
  transform: scale(1);
}

/* Where a press would land. */
.dock-tip {
  position: absolute;
  bottom: calc(100% + 2px);
  left: var(--at);
  padding: 3px 8px;
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  background: #211e29;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.45);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  opacity: 0;
  transform: translate(-50%, 4px);
  pointer-events: none;
  transition: opacity var(--fast) ease, transform var(--fast) var(--ease);
}

.dock-seek.is-aiming .dock-tip:not(:empty) {
  opacity: 1;
  transform: translate(-50%, 0);
}

.dock-volume {
  display: none;
  flex: none;
  align-items: center;
  gap: 2px;
}

/* A volume slider only where there is a mouse to drag it: a phone has its own buttons. */
@media (hover: hover) and (pointer: fine) and (min-width: 700px) {
  .dock-volume {
    display: flex;
  }
}

.icon-line {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.dock .icon-muted,
.dock .is-muted .icon-sound {
  display: none;
}

.dock .is-muted .icon-muted {
  display: block;
}

.dock-level {
  width: 84px;
  height: 20px;
  margin: 0 4px 0 0;
  background: transparent;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  --level: 100%;
}

.dock-level::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 999px;
  background:
    linear-gradient(90deg, var(--accent), var(--accent-2)) 0 0 / var(--level) 100% no-repeat,
    rgba(255, 255, 255, 0.16);
}

.dock-level::-moz-range-track {
  height: 4px;
  border-radius: 999px;
  background:
    linear-gradient(90deg, var(--accent), var(--accent-2)) 0 0 / var(--level) 100% no-repeat,
    rgba(255, 255, 255, 0.16);
}

.dock-level::-webkit-slider-thumb {
  width: 12px;
  height: 12px;
  margin-top: -4px;
  border: 0;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
  -webkit-appearance: none;
  appearance: none;
  transition: transform var(--fast) var(--spring);
}

.dock-level::-moz-range-thumb {
  width: 12px;
  height: 12px;
  border: 0;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
}

.dock-level:hover::-webkit-slider-thumb {
  transform: scale(1.2);
}

/* Found from the dock: the song glows once where it sits in the list. */
.song.is-spotlit {
  animation: spotlit 1.8s var(--ease);
}

@keyframes spotlit {
  0%,
  30% {
    border-color: rgba(255, 107, 53, 0.8);
    box-shadow: 0 0 0 4px rgba(255, 107, 53, 0.16);
  }
}

/* On a phone the dock is a capsule: the screen's rounded corners cut off a square-cornered one,
   while round ends follow them. It keeps the page's own 16px from the sides; the cover and the
   last button sit at the centres of the round ends. */
@media (max-width: 520px) {
  :root {
    --dock-lift: max(16px, env(safe-area-inset-bottom));
  }

  /* A messenger runs the page down to the very bottom of the phone, under its home bar, and
     says nothing of it through env(): Telegram sets its own variable, and without one the dock
     still stands clear of the corners and the bar. */
  .in-messenger {
    --dock-lift: max(24px, calc(var(--tg-safe-area-inset-bottom, 0px) - 10px));
  }

  .dock {
    bottom: var(--dock-lift);
    width: calc(100% - 32px);
    border-radius: 999px;
  }

  .has-dock {
    --dock-room: calc(var(--dock-lift) + 78px);
  }

  .dock-row {
    gap: 8px;
    padding: 8px 12px 8px 9px;
  }

  .dock-now {
    gap: 10px;
    border-radius: 999px;
  }

  .dock-art {
    width: 42px;
    height: 42px;
    border-radius: 50%;
  }

  .dock-controls {
    gap: 2px;
  }

  .dock-button {
    width: 36px;
    height: 36px;
  }

  /* Along the straight part of the top edge, between the round ends. */
  .dock-seek {
    right: 30px;
    left: 30px;
  }
}

/* The narrowest phones (or a page zoomed in) keep the song's name and take readable and leave
   out the skip buttons: the list switches songs as well. */
@media (max-width: 340px) {
  .dock-skip {
    display: none;
  }
}

.facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  margin: 0 0 14px;
}

.facts div {
  padding: 14px;
  border-radius: 14px;
  background: var(--surface-soft);
}

.facts dt {
  color: var(--muted);
  font-size: 0.85rem;
}

.facts dd {
  margin: 4px 0 0;
  font-weight: 700;
  overflow-wrap: anywhere;
}

.history {
  margin: 0;
  padding: 0;
  list-style: none;
}

.history li {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 0;
  border-bottom: 1px solid var(--line);
  font-size: 0.92rem;
}

.history .plus {
  color: var(--success);
}

/* The cabinet's «Заработать»: the partner link and what the network brought. */
.earn {
  margin: 8px 0 18px;
}

.earn-link {
  display: flex;
  gap: 8px;
  align-items: center;
  margin: 0 0 14px;
}

.earn-link input {
  flex: 1;
  min-width: 0;
  font-variant-numeric: tabular-nums;
}

.earn-link .ghost {
  flex: none;
}

.earn-link .primary.is-done {
  background: var(--success);
  color: #0e0d12;
}

.earn-table {
  margin: 0 0 10px;
  font-size: 0.92rem;
}

.earn-row {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) repeat(3, minmax(0, 1fr));
  gap: 8px;
  padding: 9px 0;
  border-bottom: 1px solid var(--line);
}

.earn-row span:not(:first-child) {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.earn-row.is-head {
  color: var(--muted);
  font-size: 0.8rem;
}

.earn-row b {
  color: var(--success);
}

@media (max-width: 520px) {
  .earn-link {
    flex-wrap: wrap;
  }

  .earn-link input {
    flex-basis: 100%;
  }

  .earn-link .primary.small {
    flex: 1;
  }

  .earn-facts {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px;
  }

  .earn-facts div {
    padding: 10px;
  }

  .earn-facts dt {
    font-size: 0.75rem;
  }

  .earn-row {
    grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr));
    font-size: 0.86rem;
  }
}

.cabinet-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 20px;
}

.footer {
  display: flex;
  justify-content: center;
  gap: 20px;
  flex-wrap: wrap;
  padding: 24px 16px 32px;
  color: var(--muted);
  font-size: 0.85rem;
}

.modal {
  width: min(100% - 24px, 420px);
  padding: 26px;
  border: 1px solid var(--line-strong);
  border-radius: 22px;
  background: #1a1820;
  color: var(--text);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.55);
  opacity: 0;
  transform: translateY(16px) scale(0.96);
  transition:
    opacity var(--normal) var(--ease),
    transform var(--normal) var(--ease),
    overlay var(--normal) allow-discrete,
    display var(--normal) allow-discrete;
}

.modal[open] {
  opacity: 1;
  transform: none;
}

/* A window opens with itself in focus (openWindow in dom.ts): it is plain enough where it stands,
   and no ring goes round it. */
.modal:focus {
  outline: none;
}

.modal::backdrop {
  background: rgba(6, 5, 9, 0);
  backdrop-filter: blur(0);
  transition:
    background-color var(--normal) ease,
    backdrop-filter var(--normal) ease,
    overlay var(--normal) allow-discrete,
    display var(--normal) allow-discrete;
}

.modal[open]::backdrop {
  background: rgba(6, 5, 9, 0.72);
  backdrop-filter: blur(6px);
}

/* Where the opening animation starts from (the closed state above is where it ends). */
@starting-style {
  .modal[open] {
    opacity: 0;
    transform: translateY(16px) scale(0.96);
  }

  .modal[open]::backdrop {
    background: rgba(6, 5, 9, 0);
    backdrop-filter: blur(0);
  }
}

.modal form:not([hidden]):not([method="dialog"]),
.modal .step:not([hidden]) {
  animation: step-in var(--normal) var(--ease) both;
}

.error:not([hidden]) {
  animation: shake 0.36s var(--ease) both;
}

.modal h2 {
  margin-bottom: 8px;
  font-size: 1.35rem;
}

.modal .hint {
  margin-bottom: 18px;
}

.modal .captcha-note {
  margin-top: 14px;
  text-align: center;
}

.modal-close {
  position: absolute;
  top: 12px;
  right: 14px;
  width: 34px;
  height: 34px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--muted);
  font-size: 1.5rem;
  line-height: 1;
  transition:
    color var(--fast) ease,
    background-color var(--fast) ease,
    transform var(--normal) var(--spring);
}

.modal-close:hover {
  color: var(--text);
  background: var(--surface-soft);
  transform: rotate(90deg);
}

/* Two links that do not fit side by side stand one under the other rather than break in two. */
.modal-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 12px;
  margin-top: 16px;
}

/* The narrowest phones give the window's words the room its sides took: «Войти через Telegram»
   and the two links under the code keep to one line each. */
@media (max-width: 360px) {
  .modal {
    padding-right: 18px;
    padding-left: 18px;
  }
}

/* A yes-or-no window: two equal answers side by side, the safe one first. */
.modal-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.modal-actions > button {
  padding: 12px 16px;
  font-size: 0.95rem;
}

/* What cannot be undone keeps the primary's shape but trades its warm colours for red. */
.primary.danger {
  background: linear-gradient(95deg, #ff5c62, #e0344c);
  box-shadow: 0 6px 20px rgba(224, 52, 76, 0.24);
}

/* No energy for a song (invite.ts): one offer, a friend; the daily gift is the quiet line under it. */
.invite h2 {
  padding-right: 28px;
}

.invite .primary.is-done {
  background: var(--success);
  box-shadow: none;
  color: #0e0d12;
}

.invite-link {
  margin-top: 10px;
}

.modal .invite-wait {
  margin: 14px 0 0;
  font-size: 0.85rem;
  text-align: center;
}

.primary.danger:hover:not(:disabled) {
  box-shadow: 0 10px 28px rgba(224, 52, 76, 0.36);
}

.primary.danger:active:not(:disabled) {
  box-shadow: 0 4px 12px rgba(224, 52, 76, 0.24);
}

.primary.danger:disabled {
  box-shadow: none;
}

.code-input {
  font-size: 1.6rem !important;
  font-weight: 700;
  letter-spacing: 0.5em;
  text-align: center;
}

/* A pasted code lands with a short glow, just before the form sends it. */
.code-input.is-pasted {
  animation: pasted var(--slow) var(--ease);
}

/* The label shares its line with the button that brings the code from the clipboard. */
.field-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}

.field-head label {
  color: var(--muted);
  font-size: 0.9rem;
}

.paste {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 13px 5px 10px;
  font-size: 0.85rem;
  font-weight: 600;
}

/* The pill stays compact, but a finger gets a full-size target around it. */
.paste::after {
  content: "";
  position: absolute;
  inset: -7px -4px;
}

.paste .icon {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.page {
  max-width: 42rem;
  margin: 0 auto;
  padding: 24px 0;
}

.page h1 {
  font-size: 1.8rem;
  text-align: left;
}

.page h2 {
  margin: 28px 0 8px;
}

.button-link {
  display: inline-block;
  text-decoration: none;
}

.page p,
.page li {
  color: var(--muted);
}

@media (max-width: 520px) {
  .card {
    padding: 18px;
  }

  .tab {
    padding: 8px 13px;
    font-size: 0.88rem;
  }

  .player {
    gap: 10px;
  }

  .player-toggle {
    width: 44px;
    height: 44px;
  }

  .player-download {
    width: 36px;
    height: 36px;
  }

  .composer-footer {
    flex-direction: column-reverse;
    align-items: stretch;
  }

  .composer-notes {
    flex: none;
    text-align: center;
  }
}

/* Inside a messenger the app already has its own title bar and close button. */
.in-messenger .topbar {
  padding-top: 10px;
  padding-bottom: 10px;
}

.in-messenger .hero {
  padding-top: 12px;
}

.in-messenger .footer {
  padding-bottom: calc(32px + env(safe-area-inset-bottom));
}

/* ---------- motion ---------- */

@keyframes rise-in {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
}

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

@keyframes step-in {
  from {
    opacity: 0;
    transform: translateX(14px);
  }
}

@keyframes shake {
  0% { opacity: 0; transform: translateX(-6px); }
  40% { transform: translateX(4px); }
  70% { transform: translateX(-2px); }
  100% { opacity: 1; transform: none; }
}

@keyframes wiped {
  from {
    border-color: rgba(255, 123, 130, 0.85);
    box-shadow: 0 0 0 5px rgba(255, 123, 130, 0.2);
  }
}

@keyframes pasted {
  from {
    border-color: rgba(255, 107, 53, 0.9);
    box-shadow: 0 0 0 6px rgba(255, 107, 53, 0.24);
  }
}

@keyframes tumble {
  0% { transform: translateY(0) scale(1) rotate(0deg); }
  24% { transform: translateY(-8px) scale(1.16) rotate(170deg); }
  50% { transform: translateY(-9px) scale(1.12) rotate(420deg); }
  72% { transform: translateY(1px) scale(1.1, 0.84) rotate(660deg); }
  86% { transform: translateY(-2px) scale(0.96, 1.05) rotate(708deg); }
  100% { transform: translateY(0) scale(1) rotate(720deg); }
}

@keyframes dice-warm {
  0%, 72% {
    border-color: rgba(255, 107, 53, 0.55);
    background-color: rgba(255, 107, 53, 0.1);
  }
}

@keyframes shimmer {
  to {
    transform: translateX(100%);
  }
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

@keyframes twinkle {
  0%, 100% {
    opacity: 0.5;
    transform: scale(0.86) rotate(-10deg);
  }

  50% {
    opacity: 1;
    transform: scale(1.12) rotate(10deg);
  }
}

@keyframes breathe {
  0%, 100% {
    box-shadow: 0 0 0 0 rgba(255, 107, 53, 0);
  }

  50% {
    box-shadow: 0 0 0 5px rgba(255, 107, 53, 0.14);
  }
}

@keyframes ring {
  from {
    opacity: 0.7;
    transform: scale(1);
  }

  to {
    opacity: 0;
    transform: scale(1.55);
  }
}

@keyframes equalize {
  0%, 100% { transform: scaleY(0.45); }
  50% { transform: scaleY(1); }
}

/* First paint: the page settles in from top to bottom. */
.topbar { animation: fade-in var(--slow) ease both; }
.hero { animation: rise-in var(--slow) var(--ease) 0.05s both; }
.composer { animation: rise-in var(--slow) var(--ease) 0.14s both; }
.footer { animation: fade-in var(--slow) ease 0.3s both; }
.page { animation: rise-in var(--slow) var(--ease) both; }

.account > :not([hidden]) {
  animation: fade-in var(--normal) ease both;
}

/* While a song — or its words — is being made the logo plays along. */
.brand-mark i {
  transform-origin: center;
}

body.is-working .brand-mark i,
body.is-drafting .brand-mark i {
  animation: equalize 0.9s ease-in-out infinite;
}

body.is-working .brand-mark i:nth-child(2),
body.is-drafting .brand-mark i:nth-child(2) { animation-delay: -0.25s; }
body.is-working .brand-mark i:nth-child(3),
body.is-drafting .brand-mark i:nth-child(3) { animation-delay: -0.5s; }
body.is-working .brand-mark i:nth-child(4),
body.is-drafting .brand-mark i:nth-child(4) { animation-delay: -0.7s; }

/* ---------- the daily song: a record that counts a day down ---------- */

.gift {
  display: flex;
  align-items: center;
  gap: 18px;
  margin: 0 0 14px;
  padding: 14px;
  border-radius: 14px;
  background: var(--surface-soft);
  transition: opacity var(--slow) var(--ease), transform var(--slow) var(--ease);
}

/* The song has arrived: the record spins off before the block closes. */
.gift.is-done {
  opacity: 0;
  transform: scale(0.96);
}

.gift.is-done .vinyl {
  transform: scale(1.12) rotate(200deg);
}

.gift-text {
  display: grid;
  gap: 4px;
  min-width: 0;
}

.vinyl-wrap {
  position: relative;
  flex: none;
}

.vinyl {
  position: relative;
  display: grid;
  place-items: center;
  width: 132px;
  height: 132px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  transition: transform var(--slow) var(--spring);
}

.vinyl:hover {
  transform: scale(1.03);
}

.vinyl:active {
  transform: scale(0.98);
}

.vinyl-disc {
  position: absolute;
  inset: 8px;
  border-radius: 50%;
  background:
    radial-gradient(circle, transparent 0 40%, #0a090d 40.5% 41.5%, transparent 42%),
    conic-gradient(from 20deg, transparent 0 7%, rgba(255, 255, 255, 0.17) 13%, transparent 20% 50%, rgba(255, 255, 255, 0.11) 62%, transparent 70%),
    repeating-radial-gradient(circle, #0a090d 0 1.2px, #1d1b25 1.2px 2.6px);
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.5), inset 0 0 0 1px rgba(255, 255, 255, 0.07);
  animation: vinyl-spin 5.4s linear infinite;
}

/* The paper label: its colours are what makes the turning visible. */
.vinyl-disc::after {
  content: "";
  position: absolute;
  inset: 11%;
  border-radius: 50%;
  background: conic-gradient(from 0deg, var(--accent), var(--accent-2), #ffb36b, var(--accent));
}

.vinyl-ring {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
}

.vinyl-ring circle {
  fill: none;
  stroke-width: 3;
}

.vinyl-ring-track {
  stroke: var(--line);
}

.vinyl-ring-left {
  stroke-linecap: round;
  stroke-dasharray: 100 100;
  transition: stroke-dasharray 1s linear;
}

/* The plate in the middle stands still, so the time can be read. */
.vinyl-label {
  position: relative;
  display: grid;
  place-content: center;
  justify-items: center;
  width: 74px;
  height: 74px;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: 0 0 0 1px var(--line-strong), 0 0 18px rgba(255, 107, 53, 0.28);
}

.vinyl-time {
  font-weight: 700;
  font-size: 0.86rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

.vinyl-label small {
  color: var(--muted);
  font-size: 0.62rem;
  line-height: 1.2;
}

.vinyl-tip {
  position: absolute;
  z-index: 5;
  left: 0;
  top: calc(100% + 10px);
  width: min(320px, calc(100vw - 76px));
  margin: 0;
  padding: 12px 14px;
  border: 1px solid var(--line-strong);
  border-radius: 14px;
  background: #211e29;
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.55);
  font-size: 0.86rem;
  line-height: 1.45;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  pointer-events: none;
  transition: opacity var(--fast) ease, transform var(--normal) var(--ease), visibility 0s linear var(--normal);
}

.vinyl-tip::before {
  content: "";
  position: absolute;
  left: 58px;
  top: -6px;
  width: 10px;
  height: 10px;
  border-left: 1px solid var(--line-strong);
  border-top: 1px solid var(--line-strong);
  background: inherit;
  transform: rotate(45deg);
}

.vinyl-wrap.is-open .vinyl-tip,
.vinyl:focus-visible + .vinyl-tip {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition-delay: 0s;
}

/* A finger has no hover: there a tap opens the note, and a tap elsewhere closes it. */
@media (hover: hover) {
  .vinyl-wrap:hover .vinyl-tip {
    opacity: 1;
    visibility: visible;
    transform: none;
    transition-delay: 0s;
  }
}

.chip-vinyl {
  flex: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background:
    radial-gradient(circle, var(--surface) 0 14%, var(--accent) 15% 38%, transparent 39%),
    conic-gradient(from 20deg, #0a090d 0 8%, #4a4656 14%, #0a090d 22% 50%, #3a3745 62%, #0a090d 70%);
  box-shadow: 0 0 0 1px var(--line-strong);
  animation: vinyl-spin 3.6s linear infinite;
}

@keyframes vinyl-spin {
  to { transform: rotate(360deg); }
}

@media (max-width: 520px) {
  .gift {
    flex-direction: column;
    text-align: center;
  }

  .vinyl-tip {
    left: 50%;
    width: min(300px, calc(100vw - 76px));
    text-align: left;
    transform: translate(-50%, -4px);
  }

  .vinyl-tip::before {
    left: calc(50% - 5px);
  }

  .vinyl-wrap.is-open .vinyl-tip,
  .vinyl:focus-visible + .vinyl-tip {
    transform: translate(-50%, 0);
  }
}

@media (max-width: 520px) and (hover: hover) {
  .vinyl-wrap:hover .vinyl-tip {
    transform: translate(-50%, 0);
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---------- ways into the account ---------- */

.or {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 20px 0 16px;
  color: var(--muted);
  font-size: 0.85rem;
}

.or::before,
.or::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}

.messengers {
  display: grid;
  gap: 10px;
}

.messenger {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  padding: 13px 20px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--surface-soft);
  color: var(--text);
  font-weight: 600;
  transition:
    border-color var(--fast) ease,
    background-color var(--fast) ease,
    transform var(--fast) var(--ease);
}

.messenger:hover {
  border-color: var(--accent);
  background: rgba(255, 107, 53, 0.1);
}

.messenger:active {
  transform: scale(0.98);
}

.messenger .icon {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linejoin: round;
  stroke-linecap: round;
}

.consent {
  margin-top: 14px;
  text-align: center;
  font-size: 0.8rem;
}

a.primary {
  display: block;
  text-align: center;
  text-decoration: none;
}

#wait-step .modal-links {
  justify-content: center;
}

.waiting {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-top: 16px;
  color: var(--muted);
  font-size: 0.9rem;
}

.spinner {
  width: 16px;
  height: 16px;
  border: 2px solid var(--line-strong);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

#wait-step .hint {
  text-align: center;
}

.ways {
  display: grid;
  gap: 10px;
  margin: 0 0 18px;
  padding: 0;
  list-style: none;
}

.way {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--surface-soft);
}

.way .icon {
  width: 22px;
  height: 22px;
  flex: none;
  fill: none;
  stroke: var(--muted);
  stroke-width: 1.6;
  stroke-linejoin: round;
  stroke-linecap: round;
}

.way.is-linked .icon {
  stroke: var(--success);
}

.way-text {
  display: grid;
  gap: 2px;
  min-width: 0;
  flex: 1;
}

.way-text span {
  color: var(--muted);
  font-size: 0.85rem;
  /* An address is worth two lines; cutting it off hides the very thing it names. */
  overflow-wrap: anywhere;
}

.way-state {
  flex: none;
  padding: 7px 14px;
  border-radius: 999px;
  background: rgba(114, 231, 173, 0.12);
  color: var(--success);
  font-size: 0.85rem;
  white-space: nowrap;
}

.way-state.is-off {
  background: var(--surface-soft);
  color: var(--muted);
}

.primary.small {
  flex: none;
  padding: 9px 18px;
  font-size: 0.88rem;
  box-shadow: none;
}

/* ---------- гусли-самогуды (/gusli) ---------- */

/* The gusli in place of the form; after the onboarding «Написать словами» unfolds it under them. */
.is-gusli .hero,
.is-gusli:not(.is-composer-open) #song-form,
.is-gusli.is-gusli-bare #song-form {
  display: none;
}

/* It fades in where it stands: the page scrolls to it at that moment (gusli.ts), and a form
   still rising into place would come to rest under the header. */
.is-gusli.is-composer-open #song-form {
  animation: fade-in var(--slow) ease both;
}

.gusli {
  --gold: #f4c15d;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 24px 0 20px;
  text-align: center;
  animation: rise-in var(--slow) var(--ease) 0.05s both;
}

.gusli-title {
  margin-bottom: 6px;
  background: linear-gradient(100deg, #fff6e0 20%, #f4c15d 50%, #fff6e0 80%);
  background-size: 220% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: gusli-gilt 6s ease-in-out infinite;
}

.gusli-lead {
  min-height: 1.6em;
  max-width: 30rem;
  margin: 0 auto 10px;
  color: var(--muted);
  font-size: 1.05rem;
}

/* The gusli are the button: a stage with depth, the body turning inside it (gusli-art.ts). */
.gusli-button {
  position: relative;
  width: min(86vw, 400px);
  aspect-ratio: 3 / 2;
  margin: 10px 0 24px;
  padding: 0;
  border: 0;
  border-radius: 40px;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  /* Held, not tapped: no scrolling, zooming or callout may take the finger away. */
  touch-action: none;
  -webkit-touch-callout: none;
}

.gusli-button > * {
  pointer-events: none;
}

.gusli-button:focus-visible {
  outline-offset: 8px;
}

.gusli-button:active .gusli-stage {
  transform: scale(0.97);
}

.gusli-stage {
  --light: 50%;
  position: absolute;
  inset: 0;
  z-index: 1;
  perspective: 820px;
  perspective-origin: 50% 20%;
  transition: transform var(--fast) var(--ease);
}

.gusli-body3d {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transform: rotateX(24deg) rotateY(-10deg);
  will-change: transform;
}

.gusli-depth,
.gusli-face,
.gusli-layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.gusli-depth {
  overflow: visible;
}

.gusli-depth {
  transform-style: preserve-3d;
}

/* The wood's thickness: copies of the outline pushed back, darker the deeper they sit. */
.gusli-layer {
  transform: translateZ(calc(var(--z) * 1px));
}

.gusli-layer path {
  stroke: rgba(20, 6, 1, 0.35);
  stroke-width: 0.6;
}

.gusli-face {
  transform: translateZ(0.5px);
  filter: drop-shadow(0 1px 0 rgba(255, 214, 160, 0.25));
}

.gusli-rim {
  fill: url(#gw-rim);
}

.gusli-edge {
  fill: none;
  stroke: rgba(255, 222, 176, 0.55);
  stroke-width: 1;
}

.gusli-bevel {
  fill: none;
  stroke: rgba(46, 16, 4, 0.75);
  stroke-width: 2.4;
}

.gusli-grain path {
  fill: none;
  stroke: rgba(110, 48, 12, 0.22);
  stroke-width: 0.9;
}

.gusli-trim {
  fill: none;
  stroke: var(--gold);
  stroke-width: 1.3;
  stroke-dasharray: 0.1 4.2;
  stroke-linecap: round;
  opacity: 0.9;
}

.gusli-rose-ring {
  stroke: var(--gold);
  stroke-width: 0.9;
}

.gusli-petals ellipse,
.gusli-petals circle {
  fill: #f0c064;
  stroke: #6b3a0c;
  stroke-width: 0.4;
}

.gusli-rose-dots {
  fill: none;
  stroke: #ffe3a1;
  stroke-width: 1.1;
  stroke-dasharray: 0.1 3.3;
  stroke-linecap: round;
}

.gusli-peg-bar,
.gusli-bridge {
  stroke: #2a0f04;
  fill: #2a0f04;
  stroke-width: 8;
  stroke-linecap: round;
}

.gusli-bridge {
  stroke-width: 1;
}

.gusli-peg-bar-light,
.gusli-bridge-light {
  stroke: rgba(255, 196, 120, 0.35);
  stroke-width: 1.2;
  stroke-linecap: round;
}

.gusli-peg-shine {
  fill: #fff;
  opacity: 0.85;
}

.gusli-string {
  fill: none;
  stroke: url(#gw-string);
  stroke-width: 1.25;
  stroke-linecap: round;
}

.gusli-string-glow {
  fill: none;
  stroke: #ffe2a0;
  stroke-width: 2.4;
  stroke-linecap: round;
  opacity: 0;
  mix-blend-mode: screen;
}

.gusli-string-shadow {
  fill: none;
  stroke: rgba(40, 12, 2, 0.45);
  stroke-width: 1.6;
}

.gusli-gloss {
  opacity: 0.45;
}

/* Light running over the lacquer now and then. */
.gusli-sheen {
  animation: gusli-sheen 5.5s ease-in-out infinite;
}

/* A soft glow behind: breathing while the gusli wait, pulsing while they listen. */
.gusli-ring {
  position: absolute;
  inset: -6% -4%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 140, 60, 0.3), transparent);
  animation: gusli-breathe 3.2s ease-in-out infinite;
}

.gusli[data-state="listening"] .gusli-ring {
  background: radial-gradient(closest-side, rgba(242, 50, 138, 0.5), transparent);
  transform: scale(calc(1 + var(--level, 0.3) * 0.25));
  animation: none;
  transition: transform 0.08s linear;
}

.gusli[data-state="thinking"] .gusli-ring {
  background: radial-gradient(closest-side, rgba(255, 196, 90, 0.45), transparent);
  animation-duration: 1.2s;
}

.is-dancing .gusli-ring {
  background: conic-gradient(from 0deg, rgba(255, 107, 53, 0.4), rgba(242, 50, 138, 0.4), rgba(244, 193, 93, 0.45), rgba(255, 107, 53, 0.4));
  filter: blur(26px);
  animation: gusli-spin 3s linear infinite;
}

/* The shadow the floating gusli cast. */
.gusli-floor {
  position: absolute;
  left: 14%;
  right: 14%;
  bottom: -10%;
  height: 16%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(0, 0, 0, 0.6), transparent);
  filter: blur(4px);
}

/* Notes flying off while the song plays. */
.gusli-flight {
  position: absolute;
  inset: 0;
  z-index: 2;
  overflow: visible;
}


.gusli-flying {
  position: absolute;
  color: var(--gold);
  font-size: var(--size, 1.2rem);
  text-shadow: 0 0 10px rgba(255, 190, 90, 0.8);
  animation: gusli-fly 1.8s var(--ease) forwards;
}

.gusli-heard {
  min-height: 1.5em;
  max-width: 32rem;
  margin: 12px auto 4px;
  font-size: 1.1rem;
  font-style: italic;
}

.gusli-heard:not(:empty)::before { content: "«"; }
.gusli-heard:not(:empty)::after { content: "»"; }

.gusli-type {
  display: grid;
  gap: 12px;
  width: 100%;
  max-width: 32rem;
  margin-top: 8px;
  text-align: left;
}

.gusli-type .primary {
  justify-self: center;
}

.gusli-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px 22px;
  margin-top: 8px;
}

.gusli-lyrics {
  width: 100%;
  max-width: 32rem;
  margin-top: 18px;
  padding: 18px 20px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  text-align: center;
}

.gusli-lyrics h2 {
  margin-bottom: 10px;
}

.gusli-lyrics p {
  max-height: 16rem;
  margin: 0;
  overflow-y: auto;
  color: var(--muted);
  white-space: pre-line;
}

.gusli-lyrics .song-part {
  color: var(--text);
  font-size: 0.85em;
  font-weight: 600;
  letter-spacing: 0.04em;
}

.gusli-notes {
  margin-top: 14px;
}

.gusli-notes p {
  margin: 4px 0;
}

@keyframes gusli-gilt {
  0%, 100% { background-position: 100% 0; }
  50% { background-position: 0 0; }
}

@keyframes gusli-sheen {
  0%, 55% { transform: translateX(0) skewX(-18deg); }
  85%, 100% { transform: translateX(360px) skewX(-18deg); }
}

@keyframes gusli-breathe {
  0%, 100% { opacity: 0.55; transform: scale(0.96); }
  50% { opacity: 1; transform: scale(1.05); }
}

@keyframes gusli-spin {
  to { transform: rotate(360deg); }
}

@keyframes gusli-fly {
  0% { opacity: 0; transform: translate(0, 0) scale(0.4) rotate(0); }
  15% { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--dx), -150px) scale(1.15) rotate(var(--turn)); }
}

/* Before the first song or a sign-in: the header and the gusli in the middle, nothing else. */
.is-gusli.is-gusli-bare .gusli-actions,
.is-gusli.is-gusli-bare .gusli-notes,
.is-gusli.is-gusli-bare .sections,
.is-gusli.is-gusli-bare .footer {
  display: none;
}

@supports (min-height: 100dvh) {
  .is-gusli.is-gusli-bare {
    min-height: 100dvh;
  }
}

.is-gusli.is-gusli-bare main {
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* As much room below as the header takes above, so the gusli sit in the middle of the screen. */
  padding-bottom: 72px;
}

/* ---------- гусли: первое знакомство (gusli-intro.ts) ---------- */

/* Nothing but the mascot until it has spoken: the page waits underneath. */
.is-gusli-intro {
  overflow: hidden;
}

.is-gusli-intro .phoenix-layer {
  visibility: hidden;
}

.gusli-intro {
  --ease-soft: cubic-bezier(0.22, 1, 0.36, 1);
  position: fixed;
  inset: 0;
  z-index: 45;
  display: grid;
  place-items: center;
  padding: 16px;
  background:
    radial-gradient(circle at 50% 58%, rgba(255, 107, 53, 0.12), transparent 22rem),
    var(--background);
  transition: opacity 0.7s var(--ease-soft) 0.25s;
}

.gusli-intro.is-leaving {
  opacity: 0;
  pointer-events: none;
}

/* The window is in focus while it asks (gusli-intro.ts), without a ring round the whole screen. */
.gusli-intro:focus {
  outline: none;
}

.gi-stage {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  max-width: 360px;
  padding-top: 140px;
}

.gi-hero {
  position: relative;
  width: 160px;
  height: 160px;
  transition: transform 0.9s var(--ease-soft);
}

.is-leaving .gi-hero {
  transform: translate(var(--away-x, 0), var(--away-y, 0)) scale(var(--away-scale, 0.4));
}

.gi-art {
  display: block;
  width: 100%;
  height: 100%;
  transform-origin: 50% 90%;
  animation: gi-bob 3.2s ease-in-out infinite;
}

.gi-art svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.gusli-intro:is([data-bird="firebird"], [data-bird="firehorse"]) .gi-art svg {
  filter: drop-shadow(0 0 12px rgba(255, 210, 63, 0.6));
}

.is-talking .gi-art {
  animation: gi-talk 0.46s ease-in-out infinite;
}

.is-waking .gi-art {
  animation: gi-hop 0.55s var(--spring);
}

.gi-halo {
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: -8px;
  height: 38px;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 170, 80, 0.5), rgba(242, 50, 138, 0.12) 65%, transparent);
  animation: gi-halo 2.6s ease-in-out infinite;
  transition: opacity 0.5s;
}

.is-awake .gi-halo {
  opacity: 0.4;
  animation: none;
}

/* It wants to say something: three dots in a small bubble over its head. */
.gi-dots {
  position: absolute;
  left: 82px;
  top: -34px;
  display: flex;
  gap: 6px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 18px 18px 18px 6px;
  background: var(--surface);
  transform-origin: 20% 100%;
  animation: gi-pop 0.5s var(--spring) 0.9s both;
}

.gi-dots i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #ffd98a;
  animation: gi-dot 1.3s ease-in-out infinite;
}

.gi-dots i:nth-child(2) {
  animation-delay: 0.18s;
}

.gi-dots i:nth-child(3) {
  animation-delay: 0.36s;
}

.is-awake .gi-dots {
  animation: gi-poof 0.3s var(--ease-soft) both;
}

.gi-tap {
  position: absolute;
  inset: -44px -24px 0;
  padding: 0;
  border: 0;
  border-radius: 40%;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.gi-tap:focus-visible {
  outline: 2px solid #ffd9a0;
  outline-offset: -8px;
}

.gi-touch {
  margin: 34px 0 0;
  color: var(--muted);
  font-size: 1rem;
  animation: gi-rise 0.7s var(--ease-soft) 1.6s both;
  transition: opacity 0.3s;
}

.is-awake .gi-touch {
  animation: gi-fade 0.3s var(--ease-soft) both;
}

/* What it says: a bubble over its head, the words lighting up letter by letter. */
.gi-bubble {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(100% - 122px);
  display: flex;
  flex-direction: column;
  gap: 22px;
  padding: 26px 22px 22px;
  border: 1px solid var(--line);
  border-radius: 24px;
  background: var(--surface);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
  transform-origin: 50% 100%;
  transition: opacity 0.35s var(--ease-soft);
}

.gi-bubble::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -9px;
  width: 18px;
  height: 18px;
  margin-left: -9px;
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: var(--surface);
  transform: rotate(45deg);
}

.gi-bubble.is-open {
  animation: gi-pop 0.55s var(--spring) both;
}

.gi-bubble.is-writing {
  animation: gi-pop 0.55s var(--spring) both, gi-aura 2.2s ease-in-out 0.3s infinite;
}

.is-leaving .gi-bubble {
  opacity: 0;
}

.gi-line {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-content: center;
  column-gap: 0.28em;
  row-gap: 0.1em;
  min-height: 58px;
  margin: 0;
  font-size: 1.375rem;
  font-weight: 500;
  line-height: 1.32;
  letter-spacing: -0.01em;
}

.gi-word {
  display: inline-flex;
  white-space: nowrap;
}

.gi-letter {
  position: relative;
  display: inline-block;
  opacity: 0;
  color: #ffe3a1;
  filter: blur(7px);
  transform: translateY(0.35em) scale(0.7) rotate(-6deg);
  animation: gi-ink 0.9s var(--ease-soft) forwards;
}

.gi-spark {
  position: absolute;
  left: 50%;
  top: -0.2em;
  width: 0.62em;
  height: 0.62em;
  margin-left: -0.31em;
  opacity: 0;
  background: #ffd98a;
  clip-path: polygon(50% 0, 60% 40%, 100% 50%, 60% 60%, 50% 100%, 40% 60%, 0 50%, 40% 40%);
  pointer-events: none;
  animation: gi-spark 1.1s var(--ease-soft) forwards;
}

.gi-choices {
  display: flex;
  gap: 12px;
  animation: gi-rise 0.45s var(--ease-soft) both;
}

.gi-answer {
  flex: 1;
  height: 52px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 1.06rem;
  font-weight: 500;
  cursor: pointer;
  transition: transform var(--fast) var(--ease-soft), background var(--fast) var(--ease-soft);
}

.gi-answer:hover {
  background: rgba(255, 255, 255, 0.08);
}

.gi-answer.is-main {
  border-color: transparent;
  background: var(--accent);
  color: #1a0b04;
  font-weight: 600;
}

.gi-answer.is-main:hover {
  background: #ff7d4d;
}

.gi-answer.is-single {
  flex: 0 0 160px;
  margin: 0 auto;
}

.gi-answer:active {
  transform: scale(0.96);
}

.gi-answer:focus-visible {
  outline: 2px solid #ffd9a0;
  outline-offset: 3px;
}

/* The gusli come out of the air where the mascot was. */
.gusli.is-arriving .gusli-button {
  animation: gi-arrive 0.9s var(--spring) 0.3s both;
}

.gusli.is-arriving .gusli-title,
.gusli.is-arriving .gusli-lead,
.gusli.is-arriving .gusli-actions,
.gusli.is-arriving .gusli-notes {
  animation: gi-rise 0.6s var(--ease-soft) 0.8s both;
}

@keyframes gi-bob {
  0%, 100% { transform: translateY(0) rotate(0); }
  50% { transform: translateY(-6px) rotate(-2deg); }
}

@keyframes gi-talk {
  0%, 100% { transform: translateY(0) rotate(0); }
  50% { transform: translateY(-4px) rotate(-3deg); }
}

@keyframes gi-hop {
  0% { transform: none; }
  40% { transform: translateY(-20px) rotate(-7deg) scale(1.06); }
  100% { transform: none; }
}

@keyframes gi-halo {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.55; transform: scale(1.18); }
}

@keyframes gi-dot {
  0%, 70%, 100% { opacity: 0.35; transform: translateY(0); }
  35% { opacity: 1; transform: translateY(-4px); }
}

@keyframes gi-pop {
  from { opacity: 0; transform: translateY(14px) scale(0.86); }
  to { opacity: 1; transform: none; }
}

@keyframes gi-fade {
  to { opacity: 0; }
}

@keyframes gi-poof {
  to { opacity: 0; transform: scale(1.3); }
}

@keyframes gi-rise {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

@keyframes gi-aura {
  0%, 100% { box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45), 0 0 0 1px rgba(255, 193, 93, 0), 0 0 28px rgba(255, 160, 70, 0); }
  50% { box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45), 0 0 0 1px rgba(255, 193, 93, 0.35), 0 0 34px rgba(255, 160, 70, 0.22); }
}

@keyframes gi-ink {
  0% { opacity: 0; color: #ffe3a1; filter: blur(7px); transform: translateY(0.35em) scale(0.7) rotate(-6deg); text-shadow: 0 0 0 rgba(255, 190, 90, 0); }
  35% { opacity: 1; color: #fff1c4; filter: blur(0); transform: translateY(-0.06em) scale(1.08); text-shadow: 0 0 14px rgba(255, 190, 90, 0.95), 0 0 3px rgba(255, 236, 190, 0.9); }
  100% { opacity: 1; color: var(--text); filter: blur(0); transform: none; text-shadow: 0 0 0 rgba(255, 190, 90, 0); }
}

@keyframes gi-spark {
  0% { opacity: 0; transform: translateY(0.2em) scale(0.2) rotate(0); }
  30% { opacity: 1; transform: translateY(-0.3em) scale(1) rotate(60deg); }
  100% { opacity: 0; transform: translateY(-1.3em) scale(0.3) rotate(160deg); }
}

@keyframes gi-arrive {
  from { opacity: 0; transform: translateY(48px) scale(0.72); filter: blur(10px); }
  to { opacity: 1; transform: none; filter: none; }
}

/* ---------- свой голос (/golos) ---------- */

/* The own voice is a section by itself, like the cabinet; the songs it makes show under it. */
[data-view="golos"] .hero,
[data-view="golos"] #song-form {
  display: none;
}

[data-view="golos"] main {
  padding-top: 20px;
}

.golos h2 .badge {
  margin-left: 6px;
  padding: 2px 9px;
  font-size: 0.72rem;
  font-weight: 600;
  vertical-align: 2px;
}

.golos-lead {
  margin-bottom: 16px;
}

/* Three steps: the one the person stands at is lit, the ones behind them are done. */
.golos-steps {
  display: flex;
  gap: 8px;
  margin: 0 0 18px;
  padding: 0;
  list-style: none;
  counter-reset: golos-step;
}

.golos-steps li {
  flex: 1;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--muted);
  font-size: 0.86rem;
  text-align: center;
  counter-increment: golos-step;
  transition: color var(--normal) ease, border-color var(--normal) ease, background-color var(--normal) ease;
}

.golos-steps li::before {
  content: counter(golos-step) ". ";
}

.golos-steps li[aria-current="step"] {
  border-color: transparent;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #fff;
  font-weight: 600;
}

.golos[data-step="read"] .golos-steps li[data-step="sing"],
.golos[data-step="song"] .golos-steps li[data-step="sing"],
.golos[data-step="song"] .golos-steps li[data-step="read"] {
  border-color: rgba(114, 231, 173, 0.4);
  color: var(--success);
}

.golos-panel:not([hidden]) {
  animation: step-in var(--normal) var(--ease) both;
}

.golos-panel h3 {
  margin-top: 4px;
  color: var(--text);
}

.golos-panel > .hint {
  margin-bottom: 16px;
}

.golos-phrase {
  margin: 0 0 14px;
  padding: 18px 20px;
  border-left: 3px solid var(--accent);
  border-radius: 12px;
  background: var(--surface-soft);
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1.4;
}

.golos-note {
  margin: 0 0 14px;
  font-size: 0.92rem;
}

.golos-note.is-error {
  color: var(--danger);
}

.golos-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.golos-wait {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 18px 0 8px;
}

.golos-wait p {
  margin-top: 4px;
}

.golos-spinner {
  flex: none;
  width: 34px;
  height: 34px;
  border: 3px solid var(--surface-soft);
  border-top-color: var(--accent);
  border-right-color: var(--accent-2);
  border-radius: 50%;
  animation: spin 0.9s linear infinite;
}

.golos-cancel {
  margin-top: 14px;
}

#golos-voice {
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: rgba(0, 0, 0, 0.28);
  color: var(--text);
  font: inherit;
}

.golos #golos-error {
  margin: 14px 0 0;
}

/* The song button has written the words: what to do next, said calmly. */
.golos #golos-error.is-hint {
  color: inherit;
  animation: none;
}

.golos-voices {
  margin-top: 22px;
  padding-top: 4px;
  border-top: 1px solid var(--line);
}

.golos-voices ul {
  display: grid;
  gap: 8px;
  margin: 0 0 12px;
  padding: 0;
  list-style: none;
}

.golos-voice {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
}

.golos-voice > span {
  min-width: 0;
  overflow-wrap: anywhere;
}

.golos-voice .ghost {
  flex: none;
  padding: 6px 12px;
  font-size: 0.84rem;
}

.golos-voice .ghost.is-armed {
  border-color: var(--danger);
  color: var(--danger);
}

/* One recording: the button, the clock and the loudness while it runs; the take after. */
.recorder-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
}

.recorder-record {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

.recorder-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: #fff;
  transition: border-radius var(--fast) ease;
}

.recorder[data-state="recording"] .recorder-dot {
  border-radius: 3px;
  animation: breathe 1.4s ease-in-out infinite;
}

.recorder-time {
  display: none;
  min-width: 5.5em;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.recorder[data-state="recording"] .recorder-time {
  display: inline;
}

.recorder-meter {
  display: none;
  flex: 1 1 120px;
  height: 8px;
  overflow: hidden;
  border-radius: 999px;
  background: var(--surface-soft);
}

.recorder[data-state="recording"] .recorder-meter {
  display: block;
}

.recorder-meter i {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--success), var(--accent), var(--accent-2));
  transform: scaleX(var(--level, 0));
  transform-origin: left center;
  transition: transform 80ms linear;
}

.recorder-take {
  display: grid;
  gap: 12px;
}

.recorder-take audio {
  width: 100%;
}

.recorder-note {
  min-height: 1.3em;
  margin: 10px 0 0;
  color: var(--muted);
  font-size: 0.9rem;
}

.recorder-note.is-error {
  color: var(--danger);
}

@media (max-width: 520px) {
  .golos-steps li {
    padding: 7px 4px;
    font-size: 0.8rem;
  }
}
