/* Polish layer — loaded last. Visual system + motion for the Web studio.
   It restyles; it does not change layout contracts pinned by tests/layout.test.cjs (those live in style.css).
   Motion rules: transform/opacity only, strong custom curves, UI motion ≤ 300ms,
   hover gated to fine pointers, every movement has a reduced-motion fallback. */

:root {
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);

  --ring: 0 0 0 1px rgb(20 32 51 / .09);
  --ring-strong: 0 0 0 1px rgb(20 32 51 / .18);
  --lift: 0 1px 2px rgb(20 32 51 / .05);
  --card: 0 0 0 1px rgb(20 32 51 / .055), 0 1px 2px rgb(20 32 51 / .04), 0 12px 32px -18px rgb(20 32 51 / .18);
  --float: 0 0 0 1px rgb(20 32 51 / .06), 0 18px 48px -16px rgb(20 32 51 / .28);
  --wash: #eef2f7;
}

/* ---------- Platform baseline (mobile-native) ---------- */
html {
  -webkit-tap-highlight-color: transparent;
  -webkit-text-size-adjust: 100%;
  overscroll-behavior: none;
}
body { -webkit-font-smoothing: antialiased; }
button, [role="button"], summary, label[for], .choice {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
@media (pointer: coarse) {
  input, textarea, select { font-size: 16px; }
}
#library, .note-panel #notes, dialog { overscroll-behavior: contain; }
#clock, #seek-time, time, .live-stem span, #live-percent, .pagination { font-variant-numeric: tabular-nums; }

/* ---------- Controls: rings and soft fills instead of hard borders ---------- */
button, select {
  border-color: transparent;
  box-shadow: var(--ring), var(--lift);
  transition: transform 140ms var(--ease-out), box-shadow 160ms ease, background-color 160ms ease, color 160ms ease;
}
button:active:not(:disabled) { transform: scale(0.97); }
.primary {
  box-shadow: 0 1px 0 rgb(255 255 255 / .16) inset, 0 1px 2px rgb(35 73 166 / .3), 0 6px 16px -8px rgb(49 92 202 / .6);
}
button.active, button[aria-pressed="true"] {
  border-color: transparent;
  box-shadow: 0 0 0 1px rgb(49 92 202 / .28);
}
/* Controls that were deliberately chrome-less stay that way (the attribute variants outrank [aria-pressed]). */
.track-name[aria-pressed], nav button.active, #projects button.active { box-shadow: none; }
nav button, #projects button, .track-label button, dialog #close, #jump-notes, .note,
.track-name, .back-home, #process-home, #record-list button, #home-all-records,
#home-record-list > button, .workspace-heading nav button {
  box-shadow: none;
}
button:hover, select:hover { border-color: transparent; }
@media (hover: hover) and (pointer: fine) {
  button:not(:disabled):not(.primary):not(.active):not([aria-pressed="true"]):hover,
  select:hover { box-shadow: var(--ring-strong), var(--lift); }
  nav button:hover, #projects button:hover, .track-name:hover, .note:hover,
  #home-record-list > button:hover, #record-list button:hover { box-shadow: none; }
  .primary:not(:disabled):hover { background: var(--blue-deep); }
  #projects button:not(.active):hover { background: rgb(20 32 51 / .045); }
}
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]), textarea {
  border-color: transparent;
  box-shadow: var(--ring);
  transition: box-shadow 160ms ease;
}
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):focus, textarea:focus {
  outline: none;
  box-shadow: 0 0 0 1px var(--blue), 0 0 0 4px rgb(49 92 202 / .16);
}

/* ---------- Chrome ---------- */
header {
  background: rgb(247 249 252 / .82);
  -webkit-backdrop-filter: saturate(180%) blur(16px);
  backdrop-filter: saturate(180%) blur(16px);
  border-bottom: 0;
  box-shadow: 0 1px 0 rgb(20 32 51 / .06);
}
.brand-mark { box-shadow: 0 1px 0 rgb(255 255 255 / .2) inset, 0 4px 10px -4px rgb(49 92 202 / .7); }
.engine-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  background: rgb(0 140 138 / .09);
}
.engine-pill::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

/* Library: the grid item must be allowed to shrink, otherwise nowrap titles push it to 425px. */
#library { background: transparent; border-right: 0; box-shadow: 1px 0 0 rgb(20 32 51 / .06); }
#projects { grid-template-columns: minmax(0, 1fr); }
#projects button { min-width: 0; width: 100%; border-radius: 10px; border-left: 0 !important; }
#projects button.active { background: var(--paper); box-shadow: var(--ring), var(--lift); }
#library > button { box-shadow: none; background: rgb(20 32 51 / .045); }

/* ---------- Surfaces ---------- */
.timeline, .listening-bar, #processing-status, #target-options, .link-import,
.analysis-wave, .choice:not(.choice-primary), .score-tools, .note-panel {
  border-color: transparent !important;
  box-shadow: var(--card);
}
.paper { box-shadow: var(--card); }
.file-drop { border-style: dashed; border-color: rgb(20 32 51 / .16); box-shadow: none; }
#practice, #exports { box-shadow: 0 0 0 1px rgb(49 92 202 / .08); }

/* Home cards */
.choice { transition: transform 160ms var(--ease-out), box-shadow 200ms ease, background-color 200ms ease; }
.choice:active:not(:disabled) { transform: scale(0.985); }
.choice-primary {
  background: linear-gradient(160deg, #3a68dc 0%, var(--blue) 46%, var(--blue-deep) 100%);
  box-shadow: 0 1px 0 rgb(255 255 255 / .18) inset, 0 20px 40px -22px rgb(35 73 166 / .9);
}
.choice i { transition: transform 200ms var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
  .choice:not(.choice-primary):hover { background: var(--paper); box-shadow: var(--float); }
  .choice-primary:hover { background: linear-gradient(160deg, #3a68dc 0%, var(--blue) 46%, var(--blue-deep) 100%); }
  .choice:hover i { transform: translateX(3px); }
  #home-record-list > button:hover i { transform: translateX(3px); }
}
#home-record-list > button {
  background: var(--paper);
  color: var(--ink);
  box-shadow: var(--card);
  transition: transform 160ms var(--ease-out);
}
#home-record-list > button:active { transform: scale(0.99); }
#home-record-list small { color: var(--muted); }
#home-record-list time { color: var(--muted); }
#home-record-list i { color: var(--blue); transition: transform 200ms var(--ease-out); }

/* Workspace tabs: a single pill slides between modes (motion.js positions it). */
.workspace-heading nav { isolation: isolate; }
@media (min-width: 821px) { .workspace-heading nav { position: relative; } } /* phones keep position: sticky, which also anchors the pill */
.workspace-heading nav .tab-pill {
  position: absolute;
  z-index: -1;
  top: 4px;
  left: 0;
  height: calc(100% - 8px);
  border-radius: 10px;
  background: var(--paper);
  box-shadow: 0 1px 2px rgb(20 32 51 / .08), 0 4px 12px -4px rgb(20 32 51 / .12);
  pointer-events: none;
  transition: transform 220ms var(--ease-in-out), width 220ms var(--ease-in-out);
}
.workspace-heading nav.has-pill button.active { background: transparent; box-shadow: none; }
.workspace-heading nav button { transition: color 160ms ease; }

/* Tracks */
#tracks .track {
  border: 0 !important;
  box-shadow: none;
  transition: background-color 200ms ease, box-shadow 200ms ease;
}
#tracks .track.selected { background: rgb(49 92 202 / .05); box-shadow: inset 0 0 0 1px rgb(49 92 202 / .2); }
#tracks .wave { position: relative; isolation: isolate; }
#tracks .wave canvas { transition: opacity 220ms ease, filter 220ms ease; }
/* State indication: a stem that is out of the mix visibly falls silent. */
#tracks .track:has(.include-button:not(.active)) .wave canvas { opacity: .38; filter: saturate(0); }
/* Unplayed part washes out once playback has a position; transform-only, driven by motion.js. */
#tracks .wave .wave-rest {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: rgb(237 243 245 / .62);
  transform: translateX(var(--played, 0%));
  opacity: 0;
  transition: opacity 240ms ease;
}
#tracks.has-progress .wave .wave-rest { opacity: 1; }
#tracks .wave i { z-index: 2; box-shadow: 0 0 0 3px rgb(242 122 69 / .18); }

/* Waveforms of a newly opened project write themselves in, left to right. */
@keyframes wave-write { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
#tracks.revealing .wave canvas { animation: wave-write 640ms var(--ease-out) both; }
#tracks.revealing .track:nth-child(2) .wave canvas { animation-delay: 50ms; }
#tracks.revealing .track:nth-child(3) .wave canvas { animation-delay: 100ms; }
#tracks.revealing .track:nth-child(4) .wave canvas { animation-delay: 150ms; }
#tracks.revealing .track:nth-child(5) .wave canvas { animation-delay: 200ms; }
#tracks.revealing .track:nth-child(6) .wave canvas { animation-delay: 250ms; }

/* Live separation: a stem that has just come out of the model slides into its lane. */
@keyframes stem-arrive {
  from { opacity: 0; transform: translateY(-10px); }
  to { opacity: 1; transform: none; }
}
.live-stem.arrived { animation: stem-arrive 420ms var(--ease-out) both; }
.live-stem.arrived canvas { animation: wave-write 520ms var(--ease-out) 80ms both; }

/* Score: the HTML heading stands in for OSMD's title on screen; OSMD's still prints. */
.paper:has(#score svg) #paper-title { display: none; }

/* Transport: floating glass bar */
.transport {
  background: rgb(255 255 255 / .86);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  backdrop-filter: saturate(180%) blur(18px);
  border-top: 0;
  box-shadow: 0 -1px 0 rgb(20 32 51 / .06), 0 -12px 32px -24px rgb(20 32 51 / .3);
}
.transport #play {
  border-radius: 50%;
  box-shadow: 0 6px 16px -6px rgb(49 92 202 / .7);
  transition: transform 140ms var(--ease-out), box-shadow 160ms ease;
}
.transport #play:active { transform: scale(0.92); }
#seek { accent-color: var(--playhead); }
@media (max-width: 820px) {
  /* mobile-language.css made the bar dark with white text; the glass bar needs ink text. */
  .transport { color: var(--ink); background: rgb(255 255 255 / .88); }
  .transport #play { color: #fff; background: var(--blue); }
  .transport-practice { border-top-color: rgb(20 32 51 / .06); }
}

/* ---------- Page and mode transitions ----------
   Entry only, fill "backwards" so the animation never holds a transform that would override :active. */
@keyframes rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.flow-page:not([hidden]), #workspace:not([hidden]) { animation: rise 260ms var(--ease-out) backwards; }
#welcome:not([hidden]) .home-choices > *, #home-record-list > button { animation: rise 380ms var(--ease-out) backwards; }
#welcome .home-choices > :nth-child(1), #home-record-list > button:nth-child(1) { animation-delay: 60ms; }
#welcome .home-choices > :nth-child(2), #home-record-list > button:nth-child(2) { animation-delay: 100ms; }
#welcome .home-choices > :nth-child(3), #home-record-list > button:nth-child(3) { animation-delay: 140ms; }
#home-record-list > button:nth-child(4) { animation-delay: 180ms; }
#home-record-list > button:nth-child(n+5) { animation-delay: 220ms; }
/* Switching mode inside the workspace: a quick settle, not a page change. */
@keyframes settle { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
#workspace.mode-swap > :not(.workspace-heading) { animation: settle 180ms var(--ease-out) backwards; }

/* ---------- Toast ---------- */
#toast {
  bottom: calc(108px + env(safe-area-inset-bottom, 0px));
  transform: translate(-50%, 12px) scale(.98);
  border-radius: 999px;
  box-shadow: var(--float);
  transition: opacity 200ms var(--ease-out), transform 240ms var(--ease-out);
}
#toast.visible { transform: translate(-50%, 0); }

/* ---------- Dialog: centred modal on desktop, sheet from the bottom on phones ---------- */
dialog {
  border: 0;
  box-shadow: var(--float);
  transition: opacity 200ms var(--ease-out), transform 220ms var(--ease-out), overlay 220ms allow-discrete, display 220ms allow-discrete;
  opacity: 0;
  transform: scale(.96);
}
dialog[open] {
  opacity: 1;
  transform: none;
  @starting-style { opacity: 0; transform: scale(.96); }
}
dialog::backdrop {
  background: rgb(20 32 51 / 0);
  -webkit-backdrop-filter: blur(0);
  backdrop-filter: blur(0);
  transition: background-color 220ms ease, backdrop-filter 220ms ease, overlay 220ms allow-discrete, display 220ms allow-discrete;
}
dialog[open]::backdrop {
  background: rgb(20 32 51 / .32);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  @starting-style { background: rgb(20 32 51 / 0); backdrop-filter: blur(0); }
}
@media (max-width: 560px) {
  dialog {
    width: 100%;
    max-width: 100%;
    margin: auto 0 0;
    border-radius: 22px 22px 0 0;
    padding-bottom: calc(18px + env(safe-area-inset-bottom, 0px));
    transform: translateY(100%);
    transition: opacity 200ms ease, transform 420ms var(--ease-drawer), overlay 420ms allow-discrete, display 420ms allow-discrete;
  }
  dialog[open] {
    transform: none;
    @starting-style { opacity: 1; transform: translateY(100%); }
  }
  dialog::before {
    content: '';
    display: block;
    width: 36px;
    height: 5px;
    margin: -6px auto 12px;
    border-radius: 99px;
    background: rgb(20 32 51 / .16);
  }
}

/* ---------- Home hero: one mix, pulled apart into its parts, then into notation ---------- */
#welcome { display: grid; grid-template-columns: minmax(0, 1fr) minmax(280px, 380px); column-gap: 48px; }
#welcome > * { grid-column: 1 / -1; }
#welcome > .home-greeting, #welcome > h2, #welcome > .home-lede { grid-column: 1; }
#welcome > .hero-art { grid-column: 2; grid-row: 1 / span 3; align-self: center; }

.hero-art {
  position: relative;
  height: 236px;
  padding: 18px 18px 18px 54px;
  border-radius: 24px;
  background: var(--paper);
  box-shadow: var(--card);
  overflow: hidden;
  contain: layout paint;
}
.hero-art .lanes { position: relative; height: 150px; }
.hero-art .bar {
  position: absolute;
  width: 1.6%;
  border-radius: 2px;
  background: var(--c);
  animation: hero-split 600ms var(--ease-in-out) both;
}
@keyframes hero-split {
  from { transform: translateY(var(--dy)); background: #2a3a55; }
  to { transform: none; background: var(--c); }
}
.hero-art .label {
  position: absolute;
  left: -40px;
  width: 34px;
  font-size: 11px;
  font-weight: 650;
  color: var(--muted);
  text-align: right;
  transform: translateY(-50%);
  animation: hero-fade 300ms ease-out 450ms both;
}
.hero-art .sweep {
  position: absolute;
  inset: -6px 0;
  pointer-events: none;
  animation: hero-sweep 1500ms linear 250ms both;
}
.hero-art .sweep::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  border-radius: 2px;
  background: var(--playhead);
  box-shadow: 0 0 12px rgb(242 122 69 / .6);
}
@keyframes hero-sweep {
  0% { transform: translateX(0); opacity: 1; }
  92% { opacity: 1; }
  100% { transform: translateX(100%); opacity: 0; }
}
.hero-art .staff { position: relative; height: 30px; margin-top: 18px; }
.hero-art .staff-lines {
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(180deg, rgb(20 32 51 / .22) 0 1px, transparent 1px 6px);
  height: 25px;
  animation: wave-write 600ms var(--ease-out) 1650ms both;
}
.hero-art .staff .label { top: 12px; animation-delay: 1650ms; }
.hero-art .note-head {
  position: absolute;
  width: 7px;
  height: 5.5px;
  margin-left: -3.5px;
  margin-top: -2.75px;
  border-radius: 50%;
  background: var(--ink);
  transform: rotate(-20deg);
  animation: hero-note 260ms var(--ease-out) both;
}
@keyframes hero-note {
  from { opacity: 0; transform: rotate(-20deg) translateY(4px) scale(.9); }
  to { opacity: 1; transform: rotate(-20deg); }
}
@keyframes hero-fade { from { opacity: 0; } to { opacity: 1; } }
.hero-art.settled * { animation: none !important; }
.hero-art.settled .sweep { display: none; }

@media (max-width: 820px) {
  #welcome { grid-template-columns: minmax(0, 1fr); }
  #welcome > .hero-art { grid-column: 1; grid-row: auto; margin: 0 0 18px; height: auto; padding: 12px 14px 10px 48px; border-radius: 18px; }
  .hero-art .lanes { height: 94px; }
  .hero-art .staff { margin-top: 6px; }
  #welcome .home-lede { margin: 12px 0 20px; }
}

/* ---------- Reduced motion: keep fades that explain state, drop movement ---------- */
@media (prefers-reduced-motion: reduce) {
  .hero-art * { animation: none !important; }
  .hero-art .sweep { display: none; }
  #tracks.revealing .wave canvas, .live-stem.arrived canvas { animation: none; }
  .live-stem.arrived { animation: hero-fade 200ms ease both; }
  .flow-page:not([hidden]), #workspace:not([hidden]), #welcome:not([hidden]) .home-choices > *,
  #home-record-list > button, #workspace.mode-swap > :not(.workspace-heading) { animation-name: hero-fade; }
  dialog, dialog[open] { transform: none !important; }
  .workspace-heading nav .tab-pill { transition: none; }
  #toast, #toast.visible { transform: translateX(-50%); }
  button:active:not(:disabled), .choice:active:not(:disabled), .transport #play:active { transform: none; }
}

@media print {
  .hero-art, .tab-pill, .wave-rest { display: none !important; }
}
/* Two-column hero: the headline has ~600px, keep it to two lines. */
@media (min-width: 821px) { #welcome h2 { font-size: clamp(36px, 3.9vw, 54px); } }

/* ---------- Hosted beta (server.js) ---------- */
body.no-links .link-import { display: none; }
body.hosted .library-footer a[href*="performance"] { display: none; }
#account { min-width: 0; padding-inline: 14px; background: transparent; box-shadow: none; color: var(--muted); }
@media (hover: hover) and (pointer: fine) { #account:hover { color: var(--ink); box-shadow: none; } }
#delete-project {
  margin-top: 10px;
  padding: 6px 12px;
  min-height: 34px;
  color: #b0412a;
  font-size: 12px;
  background: transparent;
  box-shadow: none;
}
@media (hover: hover) and (pointer: fine) { #delete-project:hover { background: rgb(176 65 42 / .07); box-shadow: none; } }
#server-range {
  margin: 0 0 16px;
  padding: 16px 18px;
  border: 0;
  border-radius: 14px;
  background: var(--blue-soft);
}
#server-range legend { padding: 0; font-weight: 650; }
#server-range p { margin: 6px 0 10px; font-size: 13px; }
#server-range input { width: 76px; margin: 0 6px; padding: 8px 10px; font-size: 16px; text-align: center; border-radius: 10px; }

body.logged-out > :not(#login) { visibility: hidden; }
#login {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: 24px 18px calc(24px + env(safe-area-inset-bottom, 0px));
  background:
    radial-gradient(1200px 600px at 50% -10%, rgb(49 92 202 / .10), transparent 60%),
    var(--page);
}
.login-card {
  width: min(380px, 100%);
  padding: 34px 30px 26px;
  border-radius: 24px;
  background: var(--paper);
  box-shadow: var(--card);
  animation: rise 360ms var(--ease-out) backwards;
}
.login-card .brand-mark { width: 44px; height: 44px; font-size: 20px !important; border-radius: 12px; }
.login-card h1 { margin: 18px 0 6px; font-size: 24px; font-weight: 720; letter-spacing: -.02em; flex: none; white-space: normal; }
.login-card > p:not(.login-error) { margin-bottom: 22px; font-size: 14px; line-height: 1.6; }
.login-card label { display: block; margin-bottom: 8px; font-size: 13px; font-weight: 650; color: var(--ink); }
.login-card input { display: block; width: 100%; min-height: 48px; padding: 0 14px; font-size: 16px; border-radius: 12px; letter-spacing: .04em; }
.login-card button { width: 100%; min-height: 48px; margin-top: 14px; font-weight: 700; }
.login-error { min-height: 20px; margin-top: 12px !important; color: #b0412a !important; font-size: 13px; }
@keyframes shake {
  0%, 100% { transform: none; }
  25% { transform: translateX(-5px); }
  75% { transform: translateX(5px); }
}
.login-card.shake { animation: shake 260ms var(--ease-in-out); }
@media (prefers-reduced-motion: reduce) {
  .login-card, .login-card.shake { animation: hero-fade 200ms ease both; }
}

/* style.css stacks the workspace heading at ≤1050px and aligns it left, but mobile-language.css later
   sets align-items:end for every width, which pushed the stacked title to the right (821–1050px). */
@media (max-width: 1050px) { .workspace-heading { align-items: flex-start; } }

/* Hosted export page: compressed stems first (server.js) */
#stems-bundle { display: none; order: 1; }
body[data-mode="export"] #stems-bundle { display: block; }
#stems-bundle { margin: 6px 0 18px; padding: 18px 20px; border-radius: 16px; background: var(--paper); box-shadow: var(--card); }
#stems-bundle h4 { margin: 0 0 4px; font-size: 16px; }
#stems-bundle .bundle-lede { margin: 0 0 12px; font-size: 13px; }
#stems-bundle .bundle-buttons { display: flex; flex-wrap: wrap; gap: var(--web-control-gap, 8px); }
#stems-bundle .bundle-status { margin: 10px 0 0; font-size: 13px; color: var(--muted); min-height: 1em; }
@media (max-width: 560px) { #stems-bundle .bundle-buttons > * { width: 100%; } }
@media print { #stems-bundle { display: none !important; } }

/* Hosted feedback (server.js) */
#feedback-open { min-width: 0; padding-inline: 14px; background: transparent; box-shadow: none; color: var(--muted); }
@media (hover: hover) and (pointer: fine) { #feedback-open:hover { color: var(--ink); box-shadow: none; } }
#feedback-dialog { width: min(460px, calc(100vw - 32px)); padding: 24px 24px 20px; border-radius: 20px; }
.feedback-form { display: grid; gap: 14px; }
.feedback-form h2 { margin: 0; font-size: 20px; }
.feedback-form label { display: grid; gap: 6px; font-size: 13px; font-weight: 600; color: var(--ink); }
.feedback-form textarea, .feedback-form select { font: inherit; font-size: 16px; padding: 10px 12px; border-radius: 12px; resize: vertical; }
.feedback-form .feedback-context { display: flex; align-items: center; gap: 8px; font-weight: 400; color: var(--muted); }
.feedback-error { min-height: 1em; margin: 0; color: #b0412a; font-size: 13px; }
.feedback-actions { display: flex; justify-content: flex-end; gap: 8px; }
@media (max-width: 560px) {
  #feedback-dialog { width: 100%; }
  #feedback-open { padding-inline: 8px; }
}

/* ---------- Waiting: the stem loader ----------
   Four short stems rising and falling in turn — the product's waveform, mid-separation. Used wherever
   the app is waiting (waiting.js attaches it to status text that says 正在…). Pure CSS on transform, so
   it keeps moving while the main thread is busy laying out a score. Constant motion: a symmetric
   ease-in-out loop; 1 s cycle, 120 ms stagger. */
.st-loader {
  display: inline-flex;
  align-items: center;
  gap: 0.16em;
  height: 1.15em;
  margin-right: 0.55em;
  vertical-align: -0.2em;
  color: var(--blue);
  flex: none;
}
.st-loader > i {
  display: block;
  width: 0.18em;
  min-width: 2px;
  height: 100%;
  border-radius: 999px;
  background: currentColor;
  transform: scaleY(0.35);
  animation: st-stem 1000ms var(--ease-in-out) infinite;
  will-change: transform;
}
.st-loader > i:nth-child(2) { opacity: 0.8; }
.st-loader > i:nth-child(3) { opacity: 0.65; }
.st-loader > i:nth-child(4) { opacity: 0.5; }
@keyframes st-stem {
  0%, 100% { transform: scaleY(0.35); }
  50% { transform: scaleY(1); }
}
@media (prefers-reduced-motion: reduce) {
  /* Fewer, gentler: no growing bars, a soft opacity pulse that still says "working". */
  .st-loader > i { transform: scaleY(0.6); animation: st-stem-fade 1400ms ease infinite; }
  @keyframes st-stem-fade { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }
}
/* The score's status line reads as a calm "working" note while waiting, not as the amber caution. */
#score-message.is-waiting {
  display: flex;
  align-items: center;
  color: var(--blue-deep);
  background: var(--blue-soft);
  border-left-color: var(--blue);
  font-size: 14px;
}
/* In headings the bars stay a quiet companion to the words, not a second headline. */
h1 > .st-loader, h2 > .st-loader { font-size: 0.6em; vertical-align: 0.12em; }
@media print { .st-loader { display: none !important; } }

/* ---------- Hosted sign-in by e-mail code ---------- */
.login-card form { margin: 0; }
.login-card form[hidden] { display: none; }
.login-card .login-lede { margin-bottom: 22px; font-size: 14px; line-height: 1.6; }
.login-card label small { font-weight: 500; color: var(--muted); }
.login-card .login-turnstile:not(:empty) { margin-top: 12px; min-height: 65px; }
.login-card .login-link {
  width: auto; min-height: 0; margin: 14px auto 0; padding: 6px 8px; display: block;
  background: none; box-shadow: none; color: var(--blue); font-weight: 600; font-size: 13px;
}
#login-code { letter-spacing: .4em; font-variant-numeric: tabular-nums; }

/* ---------- Plan badge, billing dialog, what a run will use ---------- */
#plan-pill {
  min-width: 0; padding: 6px 12px; border-radius: 999px; font-size: 13px; font-weight: 600;
  background: var(--wash); box-shadow: none; color: var(--ink); white-space: nowrap;
  transition: transform 160ms var(--ease-out), background-color 160ms ease;
}
#plan-pill[data-tier="member"] { background: var(--blue-soft); color: var(--blue-deep); }
#plan-pill:active { transform: scale(0.97); }
#billing-dialog { width: min(720px, calc(100vw - 32px)); padding: 24px; border-radius: 20px; }
#billing-dialog h2 { margin: 0 0 6px; font-size: 20px; }
.billing-now { margin: 0 0 16px; font-size: 14px; color: var(--ink); }
.billing-tiers { width: 100%; border-collapse: collapse; font-size: 13px; }
.billing-tiers th, .billing-tiers td { padding: 9px 10px; text-align: left; vertical-align: top; border-bottom: 1px solid var(--line); }
.billing-tiers thead th { font-size: 13px; color: var(--ink); }
.billing-tiers tbody th { font-weight: 600; color: var(--muted); white-space: nowrap; }
.billing-note { margin: 12px 0 18px; font-size: 12px; line-height: 1.6; color: var(--muted); }
.billing-redeem label { display: block; margin-bottom: 6px; font-size: 13px; font-weight: 650; }
.billing-redeem > div { display: flex; gap: 8px; }
.billing-redeem input { flex: 1; min-width: 0; letter-spacing: .06em; text-transform: uppercase; }
.billing-message { min-height: 1.2em; margin: 8px 0 0; font-size: 13px; color: var(--muted); }
.billing-actions { display: flex; justify-content: flex-end; margin-top: 12px; }
#billing-quote { margin: 10px 0 0; font-size: 13px; line-height: 1.6; color: var(--muted); }
#billing-quote[data-kind="preview"] { color: var(--amber, #996a20); }
#billing-quote[data-kind="blocked"] { color: #b42318; }
#preview-note {
  order: 1; margin: 0 0 14px; padding: 12px 14px; border-radius: 12px; font-size: 13px; line-height: 1.6;
  background: #fff8ed; color: #7a5212; box-shadow: inset 3px 0 0 #d6a354;
}
.quote-upgrade {
  min-width: 0; min-height: 0; padding: 2px 8px; border-radius: 8px; font-size: 13px; font-weight: 600;
  background: none; box-shadow: none; color: var(--blue); text-decoration: underline; text-underline-offset: 3px;
}
@media (max-width: 560px) {
  #plan-pill { padding: 5px 10px; font-size: 12px; }
  .billing-tiers { font-size: 12px; }
  .billing-tiers th, .billing-tiers td { padding: 7px 6px; }
}
@media print { #plan-pill, #billing-quote, #preview-note { display: none !important; } }

/* Sign in with Google / Facebook / WeChat: one quiet row per provider, above the e-mail form. */
.login-providers { display: grid; gap: 10px; margin-bottom: 4px; }
.login-provider {
  display: flex; align-items: center; justify-content: center; gap: 10px; min-height: 48px; border-radius: 12px;
  background: var(--paper); box-shadow: var(--ring-strong); color: var(--ink); font-weight: 650; text-decoration: none;
  transition: transform 160ms var(--ease-out), box-shadow 160ms ease;
}
.login-provider:active { transform: scale(0.98); }
@media (hover: hover) and (pointer: fine) { .login-provider:hover { box-shadow: 0 0 0 1px rgb(20 32 51 / .3); } }
.login-provider span { display: grid; place-items: center; width: 22px; height: 22px; border-radius: 6px; font-size: 13px; font-weight: 800; color: #fff; }
.login-provider[data-provider="google"] span { background: #4285f4; }
.login-provider[data-provider="facebook"] span { background: #1877f2; }
.login-provider[data-provider="wechat"] span { background: #07c160; font-size: 11px; }
.login-or { margin: 16px 0 10px !important; text-align: center; font-size: 12px !important; color: var(--muted); }

.login-legal { margin: 18px 0 0; font-size: 12px; color: var(--muted); text-align: center; }
.login-legal a, .home-foot a { color: var(--muted); text-decoration: underline; text-underline-offset: 3px; }

/* Closing the account: quiet entry, explicit dialog. */
.billing-actions { gap: 8px; }
.billing-close-account { margin-right: auto; background: none; box-shadow: none; color: var(--muted); font-size: 13px; padding-inline: 4px; }
@media (hover: hover) and (pointer: fine) { .billing-close-account:hover { color: #b42318; } }
#close-account-dialog { width: min(460px, calc(100vw - 32px)); padding: 24px; border-radius: 20px; }
#close-account-dialog h2 { margin: 0 0 8px; font-size: 20px; }
.close-account ul { margin: 6px 0 10px; padding-left: 1.2em; font-size: 14px; line-height: 1.7; }
.close-account-note { font-size: 12px; color: var(--muted); line-height: 1.6; }
.close-account label { display: block; margin: 14px 0 6px; font-size: 13px; font-weight: 650; }
.close-account input { width: 100%; }
.close-account-error { min-height: 1.2em; margin: 8px 0 0; font-size: 13px; color: #b42318; }
.close-account .danger { background: #b42318; color: #fff; box-shadow: none; }
.close-account .danger:disabled { opacity: .6; }

/* Buying: one card per product, consent first. */
.billing-buy { margin: 4px 0 16px; padding-top: 14px; border-top: 1px solid var(--line); }
.billing-buy h3 { margin: 0 0 10px; font-size: 15px; }
.billing-products { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 8px; }
.billing-product {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px; min-height: 64px; padding: 10px 12px;
  border-radius: 12px; background: var(--paper); box-shadow: var(--ring-strong); text-align: left;
  transition: transform 160ms var(--ease-out), box-shadow 160ms ease;
}
.billing-product[data-kind="member"] { box-shadow: 0 0 0 1.5px var(--blue); }
.billing-product strong { font-size: 14px; }
.billing-product span { font-size: 13px; color: var(--muted); }
.billing-product:active:not(:disabled) { transform: scale(0.97); }
.billing-product:disabled { opacity: .5; }
.billing-consent { display: flex; gap: 8px; align-items: flex-start; margin: 12px 0 0; font-size: 12px; line-height: 1.6; color: var(--muted); }
.billing-consent input { margin-top: 3px; flex: none; }
.billing-pay-note { margin: 8px 0 0; font-size: 12px; color: var(--muted); }
.billing-portal { margin-left: 6px; }
