fffiloni commited on
Commit
e317d49
·
verified ·
1 Parent(s): 4598cad

Upload 8 files

Browse files
frontend/app.css CHANGED
@@ -20,20 +20,23 @@
20
  :host {
21
  display: block;
22
  min-height: 100vh;
 
23
  color-scheme: dark;
 
 
24
  background:
25
  linear-gradient(115deg, rgba(69,209,181,.045) 0 1px, transparent 1px 100%),
26
  linear-gradient(180deg, #101315 0%, #0b0d0e 34%, #090b0c 100%);
27
  background-size: 56px 56px, auto;
28
  }
29
 
30
- html, body { min-height: 100%; background: var(--ui-bg) !important; }
31
  body { margin: 0; color: var(--ui-text); font-family: var(--ui-font); -webkit-font-smoothing: antialiased; }
32
- .gradio-container, .gradio-container.dark { min-height: 100vh !important; max-width: none !important; margin: 0 !important; padding: 0 !important; color: var(--ui-text) !important; background: transparent !important; font-family: var(--ui-font) !important; }
33
  .gradio-container .prose, .gradio-container .prose * { color: inherit; }
34
  .gradio-container footer { display: none !important; }
35
 
36
- #app-shell { width: min(1360px, calc(100% - 44px)); margin: 0 auto; padding: 22px 0 48px; gap: 14px; }
37
  #masthead, #intro { padding: 0 !important; border: 0 !important; background: transparent !important; }
38
 
39
  .workbench-nav { display: flex; align-items: center; justify-content: space-between; min-height: 48px; gap: 20px; padding: 0 2px 11px; border-bottom: 1px solid var(--ui-line); }
@@ -72,9 +75,7 @@ body { margin: 0; color: var(--ui-text); font-family: var(--ui-font); -webkit-fo
72
 
73
  #input-workbench, #transcription-panel { position: relative; min-width: 0; padding: clamp(16px,1.9vw,23px) !important; border: 1px solid var(--ui-line) !important; background: rgba(18,21,23,.94) !important; box-shadow: 0 20px 58px rgba(0,0,0,.19) !important; }
74
  #input-workbench { border-radius: 14px !important; }
75
- #input-workbench::before { position: absolute; top: -1px; left: 28px; width: 92px; height: 2px; content: ""; background: var(--ui-accent); }
76
- #transcription-panel { border-radius: 8px 17px 17px 17px !important; }
77
- #transcription-panel::before { position: absolute; top: -1px; left: -1px; width: 84px; height: 5px; content: ""; background: linear-gradient(90deg,var(--ui-warm),#d8784f); }
78
 
79
  .panel-heading { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; padding: 0 1px 13px; border-bottom: 1px solid var(--ui-line); }
80
  .panel-heading span { display: block; margin-bottom: 5px; color: var(--ui-accent); font: 620 .57rem var(--ui-mono); letter-spacing: .1em; text-transform: uppercase; }
@@ -186,9 +187,9 @@ body { margin: 0; color: var(--ui-text); font-family: var(--ui-font); -webkit-fo
186
  }
187
 
188
  @media (max-width: 720px) {
189
- #app-shell { width: min(100% - 18px,1360px); padding-top: 14px; }
190
  .workbench-nav, .panel-heading, .footnote { align-items: flex-start; flex-direction: column; }
191
- .runtime-status { width: 100%; }
192
  .workbench-intro { padding: 28px 2px 24px; }
193
  .intro-statement h1 { font-size: clamp(2.35rem,12vw,3.6rem); }
194
  .project-references { width: 100%; grid-template-columns: 1fr; }
@@ -199,6 +200,7 @@ body { margin: 0; color: var(--ui-text); font-family: var(--ui-font); -webkit-fo
199
  #decode-panel, #notation-panel { width: 100% !important; flex-basis: 100% !important; }
200
  #run-row { align-items: stretch; flex-direction: column !important; }
201
  #transcribe-button { width: 100% !important; flex-basis: auto !important; }
 
202
  }
203
 
204
  @media (prefers-reduced-motion: reduce) {
 
20
  :host {
21
  display: block;
22
  min-height: 100vh;
23
+ overflow-x: hidden;
24
  color-scheme: dark;
25
+ -webkit-text-size-adjust: 100%;
26
+ text-size-adjust: 100%;
27
  background:
28
  linear-gradient(115deg, rgba(69,209,181,.045) 0 1px, transparent 1px 100%),
29
  linear-gradient(180deg, #101315 0%, #0b0d0e 34%, #090b0c 100%);
30
  background-size: 56px 56px, auto;
31
  }
32
 
33
+ html, body { min-height: 100%; overflow-x: hidden; background: var(--ui-bg) !important; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
34
  body { margin: 0; color: var(--ui-text); font-family: var(--ui-font); -webkit-font-smoothing: antialiased; }
35
+ .gradio-container, .gradio-container.dark { min-height: 100vh !important; max-width: none !important; overflow-x: hidden !important; margin: 0 !important; padding: 0 !important; color: var(--ui-text) !important; background: transparent !important; font-family: var(--ui-font) !important; }
36
  .gradio-container .prose, .gradio-container .prose * { color: inherit; }
37
  .gradio-container footer { display: none !important; }
38
 
39
+ #app-shell { width: min(1360px, calc(100% - 44px)); min-width: 0; margin: 0 auto; padding: 22px 0 48px; gap: 14px; }
40
  #masthead, #intro { padding: 0 !important; border: 0 !important; background: transparent !important; }
41
 
42
  .workbench-nav { display: flex; align-items: center; justify-content: space-between; min-height: 48px; gap: 20px; padding: 0 2px 11px; border-bottom: 1px solid var(--ui-line); }
 
75
 
76
  #input-workbench, #transcription-panel { position: relative; min-width: 0; padding: clamp(16px,1.9vw,23px) !important; border: 1px solid var(--ui-line) !important; background: rgba(18,21,23,.94) !important; box-shadow: 0 20px 58px rgba(0,0,0,.19) !important; }
77
  #input-workbench { border-radius: 14px !important; }
78
+ #transcription-panel { border-radius: 14px !important; }
 
 
79
 
80
  .panel-heading { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; padding: 0 1px 13px; border-bottom: 1px solid var(--ui-line); }
81
  .panel-heading span { display: block; margin-bottom: 5px; color: var(--ui-accent); font: 620 .57rem var(--ui-mono); letter-spacing: .1em; text-transform: uppercase; }
 
187
  }
188
 
189
  @media (max-width: 720px) {
190
+ #app-shell { width: calc(100% - 18px); max-width: 1360px; padding-top: 14px; }
191
  .workbench-nav, .panel-heading, .footnote { align-items: flex-start; flex-direction: column; }
192
+ .runtime-status { width: 100%; flex-wrap: wrap; }
193
  .workbench-intro { padding: 28px 2px 24px; }
194
  .intro-statement h1 { font-size: clamp(2.35rem,12vw,3.6rem); }
195
  .project-references { width: 100%; grid-template-columns: 1fr; }
 
200
  #decode-panel, #notation-panel { width: 100% !important; flex-basis: 100% !important; }
201
  #run-row { align-items: stretch; flex-direction: column !important; }
202
  #transcribe-button { width: 100% !important; flex-basis: auto !important; }
203
+ #input-workbench input[type="text"], #input-workbench input[type="number"], #input-workbench input[type="search"], #input-workbench input[type="email"], #input-workbench input[type="url"], #input-workbench textarea, #input-workbench select { font-size: 16px !important; }
204
  }
205
 
206
  @media (prefers-reduced-motion: reduce) {
frontend/studio.css CHANGED
@@ -1,5 +1,7 @@
1
  :root {
2
  color-scheme: dark;
 
 
3
  --ms-bg: #0b0e0f;
4
  --ms-panel: #121617;
5
  --ms-panel-2: #171c1e;
@@ -19,18 +21,21 @@
19
  }
20
 
21
  * { box-sizing: border-box; }
22
- .ms-root { display: grid; min-width: 0; gap: 12px; color: var(--ms-text); font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; container-type: inline-size; }
23
  .ms-root [hidden] { display: none !important; }
24
- .ms-root button, .ms-root input, .ms-root select { font: inherit; }
25
 
26
- .ms-topbar { display: flex; align-items: flex-start; justify-content: space-between; min-width: 0; gap: 20px; padding: 4px 4px 11px 12px; border-left: 3px solid var(--ms-faint); transition: border-color 160ms ease; }
27
- .ms-root[data-state="queued"] .ms-topbar, .ms-root[data-state="loading"] .ms-topbar, .ms-root[data-state="transcribing"] .ms-topbar, .ms-root[data-state="generating_score"] .ms-topbar { border-left-color: var(--ms-warning); }
28
  .ms-root[data-state="complete"] .ms-topbar, .ms-root[data-state="ready"] .ms-topbar { border-left-color: var(--ms-success); }
29
- .ms-root[data-state="error"] .ms-topbar, .ms-root[data-state="notation_error"] .ms-topbar { border-left-color: var(--ms-danger); }
30
  .ms-heading { min-width: 0; }
31
  .ms-heading h2 { overflow: hidden; max-width: 760px; margin: 0; color: var(--ms-text); font-size: clamp(1.02rem,2vw,1.3rem); font-weight: 620; letter-spacing: -.03em; text-overflow: ellipsis; white-space: nowrap; }
32
- .ms-eyebrow { display: flex; align-items: center; gap: 8px; margin: 0 0 7px; color: var(--ms-muted); font: 610 .57rem/1 var(--ms-mono); letter-spacing: .1em; text-transform: uppercase; }
33
  .ms-state-dot { width: 7px; height: 7px; flex: none; border-radius: 2px; background: var(--ms-faint); transform: rotate(45deg); }
 
 
 
34
  .ms-root[data-state="queued"] .ms-state-dot, .ms-root[data-state="loading"] .ms-state-dot, .ms-root[data-state="transcribing"] .ms-state-dot, .ms-root[data-state="generating_score"] .ms-state-dot { background: var(--ms-warning); box-shadow: 0 0 12px rgba(238,173,104,.55); animation: ms-blink 1.3s ease-in-out infinite; }
35
  .ms-root[data-state="complete"] .ms-state-dot, .ms-root[data-state="ready"] .ms-state-dot { background: var(--ms-success); box-shadow: 0 0 10px rgba(102,214,167,.42); }
36
  .ms-root[data-state="error"] .ms-state-dot, .ms-root[data-state="notation_error"] .ms-state-dot { background: var(--ms-danger); }
@@ -38,19 +43,25 @@
38
  .ms-subtitle b { color: var(--ms-faint); font: 550 .55rem var(--ms-mono); white-space: nowrap; }
39
  .ms-subtitle b::before { margin-right: 8px; content: "/"; }
40
 
41
- .ms-quick-downloads { display: flex; flex: none; gap: 5px; }
42
  .ms-quick-downloads a, .ms-tracks-heading button, .ms-track-controls button, .ms-track-controls a { display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--ms-line); border-radius: 4px; color: var(--ms-soft); background: rgba(255,255,255,.018); cursor: pointer; text-decoration: none; transition: border-color 130ms ease, color 130ms ease, background 130ms ease; }
43
  .ms-quick-downloads a { min-height: 31px; gap: 6px; padding: 0 9px; font: 610 .56rem var(--ms-mono); text-transform: uppercase; }
44
  .ms-quick-downloads svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.6; }
45
  .ms-quick-downloads a:hover:not([aria-disabled="true"]), .ms-tracks-heading button:hover, .ms-track-controls button:hover, .ms-track-controls a:hover:not([aria-disabled="true"]) { border-color: rgba(69,209,181,.42); color: #d9fff7; background: rgba(69,209,181,.075); }
46
  .ms-quick-downloads a[aria-disabled="true"], .ms-track-controls a[aria-disabled="true"] { pointer-events: none; opacity: .28; }
47
 
48
- .ms-progress { display: grid; grid-template-columns: minmax(0,1fr) minmax(180px,.35fr); align-items: center; gap: 15px; padding: 9px 11px; border-top: 1px solid var(--ms-line); border-bottom: 1px solid var(--ms-line); background: rgba(238,173,104,.025); }
49
- .ms-progress > div { display: flex; justify-content: space-between; gap: 12px; color: var(--ms-soft); font-size: .65rem; }
50
- .ms-progress b { color: var(--ms-warning); font: 590 .58rem var(--ms-mono); }
51
- .ms-progress i { display: block; overflow: hidden; height: 4px; background: repeating-linear-gradient(90deg,rgba(255,255,255,.055) 0 calc(10% - 2px),transparent calc(10% - 2px) 10%); }
 
 
52
  .ms-progress i span { display: block; width: 0; height: 100%; background: repeating-linear-gradient(90deg,var(--ms-warm) 0 calc(10% - 2px),rgba(216,120,79,.35) calc(10% - 2px),rgba(216,120,79,.35) 10%); box-shadow: 0 0 13px rgba(238,173,104,.2); transition: width 300ms ease; }
53
  .ms-progress[data-indeterminate="true"] i span { width: 34% !important; animation: ms-progress-scan 1.25s ease-in-out infinite; }
 
 
 
 
54
 
55
  .ms-empty { min-height: 440px; display: grid; align-content: center; justify-items: center; padding: 35px 20px; border: 1px dashed var(--ms-line-strong); background: repeating-linear-gradient(90deg,transparent 0 79px,rgba(255,255,255,.018) 80px), #0b0f10; text-align: center; }
56
  .ms-empty-icon { display: grid; width: 46px; height: 46px; border: 1px solid rgba(69,209,181,.27); color: var(--ms-accent); background: rgba(69,209,181,.035); place-items: center; }
@@ -118,7 +129,7 @@
118
  .ms-roll-surface { display: grid; grid-template-columns: 56px minmax(0,1fr); min-width: 0; min-height: 0; flex: 1; overflow: hidden; border: 1px solid var(--ms-line); background: #090c0d; }
119
  .ms-roll-surface canvas { display: block; }
120
  .ms-piano-keys { width: 56px; height: 100%; border-right: 1px solid rgba(255,255,255,.09); background: #10141b; }
121
- .ms-roll-scroll { position: relative; min-width: 0; min-height: 0; overflow-x: auto; overflow-y: hidden; scrollbar-width: thin; scrollbar-color: rgba(255,255,255,.16) #090c0d; overscroll-behavior-x: contain; }
122
  .ms-roll-scroll::-webkit-scrollbar { height: 8px; }
123
  .ms-roll-scroll::-webkit-scrollbar-track { background: #090c0d; }
124
  .ms-roll-scroll::-webkit-scrollbar-thumb { border: 2px solid #090c0d; border-radius: 999px; background: rgba(255,255,255,.18); }
@@ -146,13 +157,13 @@
146
  .ms-root[data-state="generating_score"] .ms-score-empty span { animation: ms-score-pulse 1.15s ease-in-out infinite; }
147
  .ms-score-document { width: 100%; height: 100%; }
148
  .ms-score-document[hidden] { display: none; }
149
- .ms-score-document[data-mode="pages"] { display: grid; overflow: auto; min-width: 720px; gap: 14px; padding: 13px; overscroll-behavior: contain; }
150
  .ms-score-document[data-mode="message"] { display: grid; overflow: auto; padding: 24px; place-items: center; }
151
  .ms-score-message { display: grid; max-width: 420px; justify-items: center; padding: 24px; border: 1px solid var(--ms-line); border-radius: 4px; color: var(--ms-muted); background: #131819; text-align: center; }
152
  .ms-score-message strong { color: var(--ms-soft); font-size: .76rem; }
153
  .ms-score-message p { margin: 7px 0 14px; font-size: .62rem; line-height: 1.5; }
154
  .ms-score-message a { display: inline-flex; min-height: 31px; align-items: center; padding: 0 10px; border: 1px solid rgba(238,173,104,.38); border-radius: 3px; color: #ffe4c4; background: rgba(238,173,104,.07); font: 600 .56rem var(--ms-mono); text-decoration: none; }
155
- .ms-score-page { position: relative; margin: 0; padding: 17px; background: #fffdf7; box-shadow: 0 10px 30px rgba(0,0,0,.3); }
156
  .ms-score-page img, .ms-score-page svg { display: block; width: 100%; height: auto; color: #111; }
157
  .ms-score-page-number { position: absolute; right: 8px; bottom: 5px; color: rgba(18,18,18,.45); font: 8px var(--ms-mono); letter-spacing: .02em; }
158
 
@@ -162,7 +173,7 @@
162
  .ms-kicker { color: var(--ms-soft); font-size: .67rem; font-weight: 620; }
163
  .ms-tracks-heading strong { margin-top: 3px; color: var(--ms-faint); font: .53rem var(--ms-mono); }
164
  .ms-tracks-heading button { min-height: 27px; padding: 0 7px; font-size: .54rem; }
165
- .ms-track-list { display: grid; align-content: start; min-height: 0; overflow-y: auto; scrollbar-color: rgba(255,255,255,.14) transparent; }
166
  .ms-track-placeholder { padding: 18px 12px; color: var(--ms-faint); font-size: .63rem; line-height: 1.5; text-align: center; }
167
  .ms-track-row { display: grid; grid-template-columns: 5px minmax(0,1fr) auto; align-items: center; min-width: 0; min-height: 76px; gap: 9px; padding: 10px; border-bottom: 1px solid var(--ms-line); background: rgba(255,255,255,.008); transition: opacity 130ms ease, background 130ms ease; }
168
  .ms-track-row:hover { background: rgba(255,255,255,.025); }
@@ -189,6 +200,7 @@
189
  .ms-announcer { position: absolute; overflow: hidden; width: 1px; height: 1px; clip: rect(0 0 0 0); }
190
 
191
  @keyframes ms-blink { 0%,100% { opacity:.35; } 50% { opacity:1; } }
 
192
  @keyframes ms-progress-scan { 0% { transform: translateX(-120%); } 60%,100% { transform: translateX(310%); } }
193
  @keyframes ms-score-pulse { 0%,100% { opacity:.45; transform: translateY(0); } 50% { opacity:1; transform: translateY(-4px); } }
194
 
@@ -224,6 +236,10 @@
224
  .ms-synth-state { width: 100%; max-width: none; }
225
  .ms-view-shell { height: 350px; }
226
  .ms-tabs > span { display: none; }
 
 
 
 
227
  .ms-score-toolbar { grid-template-columns: minmax(0,1fr) auto; gap: 6px; }
228
  .ms-score-toolbar > span { display: none; }
229
  .ms-score-toolbar label > span { display: none; }
@@ -231,6 +247,57 @@
231
  .ms-track-row:nth-child(odd) { border-right: 0; }
232
  .ms-notation-info { align-items: flex-start; }
233
  .ms-notation-info dl { display: grid; grid-template-columns: repeat(2,1fr); gap: 5px 12px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  }
235
 
236
  @media (prefers-reduced-motion: reduce) {
 
1
  :root {
2
  color-scheme: dark;
3
+ -webkit-text-size-adjust: 100%;
4
+ text-size-adjust: 100%;
5
  --ms-bg: #0b0e0f;
6
  --ms-panel: #121617;
7
  --ms-panel-2: #171c1e;
 
21
  }
22
 
23
  * { box-sizing: border-box; }
24
+ .ms-root { display: grid; width: 100%; max-width: 100%; min-width: 0; overflow: hidden; gap: 12px; color: var(--ms-text); font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; container-type: inline-size; }
25
  .ms-root [hidden] { display: none !important; }
26
+ .ms-root button, .ms-root input, .ms-root select { min-width: 0; font: inherit; }
27
 
28
+ .ms-topbar { display: flex; align-items: flex-start; justify-content: space-between; width: 100%; max-width: 100%; min-width: 0; gap: 20px; padding: 7px 7px 11px 12px; border-left: 3px solid var(--ms-faint); transition: border-color 160ms ease, background 160ms ease; }
29
+ .ms-root[data-state="queued"] .ms-topbar, .ms-root[data-state="loading"] .ms-topbar, .ms-root[data-state="transcribing"] .ms-topbar, .ms-root[data-state="generating_score"] .ms-topbar { border-left-color: var(--ms-warning); background: linear-gradient(90deg,rgba(238,173,104,.055),transparent 58%); }
30
  .ms-root[data-state="complete"] .ms-topbar, .ms-root[data-state="ready"] .ms-topbar { border-left-color: var(--ms-success); }
31
+ .ms-root[data-state="error"] .ms-topbar, .ms-root[data-state="notation_error"] .ms-topbar { border-left-color: var(--ms-danger); background: linear-gradient(90deg,rgba(251,113,133,.06),transparent 58%); }
32
  .ms-heading { min-width: 0; }
33
  .ms-heading h2 { overflow: hidden; max-width: 760px; margin: 0; color: var(--ms-text); font-size: clamp(1.02rem,2vw,1.3rem); font-weight: 620; letter-spacing: -.03em; text-overflow: ellipsis; white-space: nowrap; }
34
+ .ms-eyebrow { display: flex; width: max-content; min-height: 23px; align-items: center; gap: 8px; margin: 0 0 8px; padding: 0 8px; border: 1px solid var(--ms-line); border-radius: 999px; color: var(--ms-muted); background: rgba(255,255,255,.018); font: 630 .57rem/1 var(--ms-mono); letter-spacing: .1em; text-transform: uppercase; }
35
  .ms-state-dot { width: 7px; height: 7px; flex: none; border-radius: 2px; background: var(--ms-faint); transform: rotate(45deg); }
36
+ .ms-root[data-state="queued"] .ms-eyebrow, .ms-root[data-state="loading"] .ms-eyebrow, .ms-root[data-state="transcribing"] .ms-eyebrow, .ms-root[data-state="generating_score"] .ms-eyebrow { border-color: rgba(238,173,104,.38); color: #ffd8aa; background: rgba(238,173,104,.09); }
37
+ .ms-root[data-state="complete"] .ms-eyebrow, .ms-root[data-state="ready"] .ms-eyebrow { border-color: rgba(102,214,167,.34); color: #c8f8e2; background: rgba(102,214,167,.075); }
38
+ .ms-root[data-state="error"] .ms-eyebrow, .ms-root[data-state="notation_error"] .ms-eyebrow { border-color: rgba(251,113,133,.42); color: #ffc1cb; background: rgba(251,113,133,.085); }
39
  .ms-root[data-state="queued"] .ms-state-dot, .ms-root[data-state="loading"] .ms-state-dot, .ms-root[data-state="transcribing"] .ms-state-dot, .ms-root[data-state="generating_score"] .ms-state-dot { background: var(--ms-warning); box-shadow: 0 0 12px rgba(238,173,104,.55); animation: ms-blink 1.3s ease-in-out infinite; }
40
  .ms-root[data-state="complete"] .ms-state-dot, .ms-root[data-state="ready"] .ms-state-dot { background: var(--ms-success); box-shadow: 0 0 10px rgba(102,214,167,.42); }
41
  .ms-root[data-state="error"] .ms-state-dot, .ms-root[data-state="notation_error"] .ms-state-dot { background: var(--ms-danger); }
 
43
  .ms-subtitle b { color: var(--ms-faint); font: 550 .55rem var(--ms-mono); white-space: nowrap; }
44
  .ms-subtitle b::before { margin-right: 8px; content: "/"; }
45
 
46
+ .ms-quick-downloads { display: flex; min-width: 0; flex: none; flex-wrap: wrap; gap: 5px; }
47
  .ms-quick-downloads a, .ms-tracks-heading button, .ms-track-controls button, .ms-track-controls a { display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--ms-line); border-radius: 4px; color: var(--ms-soft); background: rgba(255,255,255,.018); cursor: pointer; text-decoration: none; transition: border-color 130ms ease, color 130ms ease, background 130ms ease; }
48
  .ms-quick-downloads a { min-height: 31px; gap: 6px; padding: 0 9px; font: 610 .56rem var(--ms-mono); text-transform: uppercase; }
49
  .ms-quick-downloads svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.6; }
50
  .ms-quick-downloads a:hover:not([aria-disabled="true"]), .ms-tracks-heading button:hover, .ms-track-controls button:hover, .ms-track-controls a:hover:not([aria-disabled="true"]) { border-color: rgba(69,209,181,.42); color: #d9fff7; background: rgba(69,209,181,.075); }
51
  .ms-quick-downloads a[aria-disabled="true"], .ms-track-controls a[aria-disabled="true"] { pointer-events: none; opacity: .28; }
52
 
53
+ .ms-progress { display: grid; grid-template-columns: minmax(0,1fr) minmax(220px,.42fr); align-items: center; gap: 16px; padding: 12px 13px; border: 1px solid rgba(238,173,104,.3); border-left: 4px solid var(--ms-warning); border-radius: 6px; background: linear-gradient(105deg,rgba(238,173,104,.09),rgba(238,173,104,.025) 62%); box-shadow: inset 0 1px rgba(255,255,255,.025), 0 8px 24px rgba(0,0,0,.12); }
54
+ .ms-progress > div { display: flex; align-items: center; justify-content: space-between; min-width: 0; gap: 10px; color: var(--ms-soft); font-size: .71rem; }
55
+ .ms-progress > div::before { width: 9px; height: 9px; flex: none; border-radius: 50%; content: ""; background: var(--ms-warning); box-shadow: 0 0 0 4px rgba(238,173,104,.1),0 0 15px rgba(238,173,104,.45); animation: ms-status-pulse 1.25s ease-in-out infinite; }
56
+ .ms-progress > div > span { overflow: hidden; flex: 1; font-weight: 620; text-overflow: ellipsis; white-space: nowrap; }
57
+ .ms-progress b { flex: none; color: #ffd5a3; font: 650 .67rem var(--ms-mono); }
58
+ .ms-progress i { display: block; overflow: hidden; height: 7px; border-radius: 999px; background: repeating-linear-gradient(90deg,rgba(255,255,255,.065) 0 calc(10% - 2px),transparent calc(10% - 2px) 10%); }
59
  .ms-progress i span { display: block; width: 0; height: 100%; background: repeating-linear-gradient(90deg,var(--ms-warm) 0 calc(10% - 2px),rgba(216,120,79,.35) calc(10% - 2px),rgba(216,120,79,.35) 10%); box-shadow: 0 0 13px rgba(238,173,104,.2); transition: width 300ms ease; }
60
  .ms-progress[data-indeterminate="true"] i span { width: 34% !important; animation: ms-progress-scan 1.25s ease-in-out infinite; }
61
+ .ms-root[data-state="error"] .ms-progress, .ms-root[data-state="notation_error"] .ms-progress { border-color: rgba(251,113,133,.35); border-left-color: var(--ms-danger); background: linear-gradient(105deg,rgba(251,113,133,.1),rgba(251,113,133,.025) 62%); }
62
+ .ms-root[data-state="error"] .ms-progress > div::before, .ms-root[data-state="notation_error"] .ms-progress > div::before { background: var(--ms-danger); box-shadow: 0 0 0 4px rgba(251,113,133,.1),0 0 15px rgba(251,113,133,.38); animation: none; }
63
+ .ms-root[data-state="error"] .ms-progress b, .ms-root[data-state="notation_error"] .ms-progress b { color: #ffc1cb; }
64
+ .ms-root[data-state="error"] .ms-progress i span, .ms-root[data-state="notation_error"] .ms-progress i span { background: var(--ms-danger); }
65
 
66
  .ms-empty { min-height: 440px; display: grid; align-content: center; justify-items: center; padding: 35px 20px; border: 1px dashed var(--ms-line-strong); background: repeating-linear-gradient(90deg,transparent 0 79px,rgba(255,255,255,.018) 80px), #0b0f10; text-align: center; }
67
  .ms-empty-icon { display: grid; width: 46px; height: 46px; border: 1px solid rgba(69,209,181,.27); color: var(--ms-accent); background: rgba(69,209,181,.035); place-items: center; }
 
129
  .ms-roll-surface { display: grid; grid-template-columns: 56px minmax(0,1fr); min-width: 0; min-height: 0; flex: 1; overflow: hidden; border: 1px solid var(--ms-line); background: #090c0d; }
130
  .ms-roll-surface canvas { display: block; }
131
  .ms-piano-keys { width: 56px; height: 100%; border-right: 1px solid rgba(255,255,255,.09); background: #10141b; }
132
+ .ms-roll-scroll { position: relative; min-width: 0; min-height: 0; overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; scrollbar-width: thin; scrollbar-color: rgba(255,255,255,.16) #090c0d; overscroll-behavior-x: contain; }
133
  .ms-roll-scroll::-webkit-scrollbar { height: 8px; }
134
  .ms-roll-scroll::-webkit-scrollbar-track { background: #090c0d; }
135
  .ms-roll-scroll::-webkit-scrollbar-thumb { border: 2px solid #090c0d; border-radius: 999px; background: rgba(255,255,255,.18); }
 
157
  .ms-root[data-state="generating_score"] .ms-score-empty span { animation: ms-score-pulse 1.15s ease-in-out infinite; }
158
  .ms-score-document { width: 100%; height: 100%; }
159
  .ms-score-document[hidden] { display: none; }
160
+ .ms-score-document[data-mode="pages"] { display: grid; overflow: auto; min-width: 0; gap: 14px; padding: 13px; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; }
161
  .ms-score-document[data-mode="message"] { display: grid; overflow: auto; padding: 24px; place-items: center; }
162
  .ms-score-message { display: grid; max-width: 420px; justify-items: center; padding: 24px; border: 1px solid var(--ms-line); border-radius: 4px; color: var(--ms-muted); background: #131819; text-align: center; }
163
  .ms-score-message strong { color: var(--ms-soft); font-size: .76rem; }
164
  .ms-score-message p { margin: 7px 0 14px; font-size: .62rem; line-height: 1.5; }
165
  .ms-score-message a { display: inline-flex; min-height: 31px; align-items: center; padding: 0 10px; border: 1px solid rgba(238,173,104,.38); border-radius: 3px; color: #ffe4c4; background: rgba(238,173,104,.07); font: 600 .56rem var(--ms-mono); text-decoration: none; }
166
+ .ms-score-page { position: relative; min-width: 680px; margin: 0; padding: 17px; background: #fffdf7; box-shadow: 0 10px 30px rgba(0,0,0,.3); }
167
  .ms-score-page img, .ms-score-page svg { display: block; width: 100%; height: auto; color: #111; }
168
  .ms-score-page-number { position: absolute; right: 8px; bottom: 5px; color: rgba(18,18,18,.45); font: 8px var(--ms-mono); letter-spacing: .02em; }
169
 
 
173
  .ms-kicker { color: var(--ms-soft); font-size: .67rem; font-weight: 620; }
174
  .ms-tracks-heading strong { margin-top: 3px; color: var(--ms-faint); font: .53rem var(--ms-mono); }
175
  .ms-tracks-heading button { min-height: 27px; padding: 0 7px; font-size: .54rem; }
176
+ .ms-track-list { display: grid; align-content: start; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; scrollbar-color: rgba(255,255,255,.14) transparent; }
177
  .ms-track-placeholder { padding: 18px 12px; color: var(--ms-faint); font-size: .63rem; line-height: 1.5; text-align: center; }
178
  .ms-track-row { display: grid; grid-template-columns: 5px minmax(0,1fr) auto; align-items: center; min-width: 0; min-height: 76px; gap: 9px; padding: 10px; border-bottom: 1px solid var(--ms-line); background: rgba(255,255,255,.008); transition: opacity 130ms ease, background 130ms ease; }
179
  .ms-track-row:hover { background: rgba(255,255,255,.025); }
 
200
  .ms-announcer { position: absolute; overflow: hidden; width: 1px; height: 1px; clip: rect(0 0 0 0); }
201
 
202
  @keyframes ms-blink { 0%,100% { opacity:.35; } 50% { opacity:1; } }
203
+ @keyframes ms-status-pulse { 0%,100% { opacity:.55; transform: scale(.82); } 50% { opacity:1; transform: scale(1); } }
204
  @keyframes ms-progress-scan { 0% { transform: translateX(-120%); } 60%,100% { transform: translateX(310%); } }
205
  @keyframes ms-score-pulse { 0%,100% { opacity:.45; transform: translateY(0); } 50% { opacity:1; transform: translateY(-4px); } }
206
 
 
236
  .ms-synth-state { width: 100%; max-width: none; }
237
  .ms-view-shell { height: 350px; }
238
  .ms-tabs > span { display: none; }
239
+ .ms-tabs { min-height: 0; flex-wrap: wrap; gap: 0 14px; padding: 0 8px 7px; }
240
+ .ms-tabs button { min-height: 40px; }
241
+ .ms-roll-zoom { width: 100%; padding-top: 7px; border-top: 1px solid var(--ms-line); }
242
+ .ms-roll-zoom input { width: auto; flex: 1; }
243
  .ms-score-toolbar { grid-template-columns: minmax(0,1fr) auto; gap: 6px; }
244
  .ms-score-toolbar > span { display: none; }
245
  .ms-score-toolbar label > span { display: none; }
 
247
  .ms-track-row:nth-child(odd) { border-right: 0; }
248
  .ms-notation-info { align-items: flex-start; }
249
  .ms-notation-info dl { display: grid; grid-template-columns: repeat(2,1fr); gap: 5px 12px; }
250
+ .ms-program-select, .ms-score-toolbar select { font-size: 16px; }
251
+ .ms-empty { min-height: 320px; }
252
+ }
253
+
254
+ /* Viewport fallbacks for Safari versions without reliable container queries. */
255
+ @media (max-width: 1030px) {
256
+ .ms-transport { grid-template-columns: 1fr; }
257
+ .ms-transport-options { padding-top: 7px; padding-left: 68px; border-top: 1px solid var(--ms-line); border-left: 0; }
258
+ .ms-studio-grid { grid-template-columns: 1fr; height: auto; }
259
+ .ms-view-shell { width: 100%; height: 440px; }
260
+ .ms-mixer { width: 100%; max-height: 430px; }
261
+ .ms-track-list { grid-template-columns: repeat(2,minmax(0,1fr)); }
262
+ .ms-track-row:nth-child(odd) { border-right: 1px solid var(--ms-line); }
263
+ }
264
+
265
+ @media (max-width: 650px) {
266
+ .ms-topbar { display: grid; gap: 12px; }
267
+ .ms-quick-downloads { width: 100%; }
268
+ .ms-quick-downloads a { min-width: 0; flex: 1; }
269
+ .ms-subtitle { align-items: flex-start; flex-direction: column; }
270
+ .ms-subtitle b::before { display: none; }
271
+ .ms-progress { grid-template-columns: 1fr; gap: 10px; }
272
+ .ms-progress > div > span { white-space: normal; }
273
+ .ms-stats { grid-template-columns: repeat(2,minmax(0,1fr)); }
274
+ .ms-stats > div:nth-child(3) { border-top: 1px solid var(--ms-line); border-left: 0; }
275
+ .ms-stats > div:nth-child(4) { border-top: 1px solid var(--ms-line); }
276
+ .ms-transport-main { flex-wrap: wrap; }
277
+ .ms-seek { min-width: calc(100% - 132px); }
278
+ .ms-transport-options { padding-left: 0; flex-wrap: wrap; }
279
+ .ms-loop-strip { align-items: flex-start; flex-direction: column; gap: 6px; }
280
+ .ms-loop-actions { width: 100%; flex-wrap: wrap; }
281
+ .ms-loop-actions button { flex: 1; }
282
+ .ms-loop-readout { width: 100%; justify-content: space-between; }
283
+ .ms-source-mix { width: 100%; }
284
+ .ms-source-mix input { flex: 1; }
285
+ .ms-synth-state { width: 100%; max-width: none; }
286
+ .ms-view-shell { height: 350px; }
287
+ .ms-tabs > span { display: none; }
288
+ .ms-tabs { min-height: 0; flex-wrap: wrap; gap: 0 14px; padding: 0 8px 7px; }
289
+ .ms-tabs button { min-height: 40px; }
290
+ .ms-roll-zoom { width: 100%; padding-top: 7px; border-top: 1px solid var(--ms-line); }
291
+ .ms-roll-zoom input { width: auto; flex: 1; }
292
+ .ms-score-toolbar { grid-template-columns: minmax(0,1fr) auto; gap: 6px; }
293
+ .ms-score-toolbar > span, .ms-score-toolbar label > span { display: none; }
294
+ .ms-score-page { min-width: 620px; }
295
+ .ms-track-list { grid-template-columns: 1fr; }
296
+ .ms-track-row:nth-child(odd) { border-right: 0; }
297
+ .ms-notation-info { align-items: flex-start; }
298
+ .ms-notation-info dl { display: grid; grid-template-columns: repeat(2,1fr); gap: 5px 12px; }
299
+ .ms-program-select, .ms-score-toolbar select { font-size: 16px; }
300
+ .ms-empty { min-height: 320px; }
301
  }
302
 
303
  @media (prefers-reduced-motion: reduce) {
frontend/studio.html CHANGED
@@ -12,9 +12,9 @@
12
  </div>
13
  </header>
14
 
15
- <div class="ms-progress" hidden>
16
  <div><span data-field="progress-label">Preparing inference…</span><b data-field="progress-value">0%</b></div>
17
- <i role="progressbar" aria-valuemin="0" aria-valuemax="100"><span data-field="progress-bar"></span></i>
18
  </div>
19
 
20
  <section class="ms-empty">
 
12
  </div>
13
  </header>
14
 
15
+ <div class="ms-progress" role="status" aria-live="polite" hidden>
16
  <div><span data-field="progress-label">Preparing inference…</span><b data-field="progress-value">0%</b></div>
17
+ <i role="progressbar" aria-label="Transcription progress" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><span data-field="progress-bar"></span></i>
18
  </div>
19
 
20
  <section class="ms-empty">
frontend/studio.js CHANGED
@@ -10,7 +10,7 @@ const ui = {
10
  status: $('[data-field="status"]'), audioName: $('[data-field="audio-name"]'),
11
  summary: $('[data-field="summary"]'), progress: $('.ms-progress'),
12
  progressLabel: $('[data-field="progress-label"]'), progressValue: $('[data-field="progress-value"]'),
13
- progressBar: $('[data-field="progress-bar"]'), play: $('[data-action="play"]'),
14
  stop: $('[data-action="stop"]'), seek: $('[data-action="seek"]'), clock: $('[data-field="clock"]'),
15
  duration: $('[data-field="duration"]'), volume: $('[data-action="volume"]'),
16
  loop: $('[data-action="loop"]'), selectRegion: $('[data-action="select-region"]'),
@@ -1123,14 +1123,25 @@ function render(data, { silent = false } = {}) {
1123
  state.songTime = clamp(state.songTime, 0, Math.max(data.duration, playableEnd()));
1124
  }
1125
  root.dataset.state = data.state; const active = ['queued', 'loading', 'transcribing', 'generating_score'].includes(data.state);
 
1126
  const hasResults = data.tracks.length > 0 || active;
1127
  ui.empty.hidden = hasResults; ui.workspace.hidden = !hasResults;
1128
  ui.state.textContent = ({ idle: 'Ready for audio', queued: 'ZeroGPU queued', loading: 'Loading model', transcribing: 'Transcribing', generating_score: 'Generating score', complete: 'MIDI ready', ready: 'Score ready', error: 'Error', notation_error: 'MIDI ready' })[data.state] || data.state;
1129
  ui.status.textContent = data.status; ui.audioName.textContent = data.audio_name || 'Your transcription';
1130
  ui.summary.textContent = data.audio_name ? `${data.note_count.toLocaleString('en-US')} notes · ${data.tracks.length} tracks` : '—';
1131
  const indeterminate = data.state === 'generating_score';
1132
- ui.progress.hidden = !active; ui.progress.dataset.indeterminate = String(indeterminate);
1133
- ui.progressLabel.textContent = data.status; ui.progressValue.textContent = indeterminate ? 'Rendering…' : `${Math.round(data.progress * 100)}%`; ui.progressBar.style.width = `${data.progress * 100}%`;
 
 
 
 
 
 
 
 
 
 
1134
  ui.duration.textContent = formatTime(data.duration); ui.seek.max = String(Math.max(.01, data.duration));
1135
  setText('[data-field="track-count"]', data.tracks.length ? `${data.tracks.length} track${data.tracks.length > 1 ? 's' : ''}` : 'No tracks yet');
1136
  setText('[data-field="info-duration"]', formatTime(data.duration)); setText('[data-field="note-count"]', data.note_count ? data.note_count.toLocaleString('en-US') : '—');
 
10
  status: $('[data-field="status"]'), audioName: $('[data-field="audio-name"]'),
11
  summary: $('[data-field="summary"]'), progress: $('.ms-progress'),
12
  progressLabel: $('[data-field="progress-label"]'), progressValue: $('[data-field="progress-value"]'),
13
+ progressBar: $('[data-field="progress-bar"]'), progressTrack: $('.ms-progress [role="progressbar"]'), play: $('[data-action="play"]'),
14
  stop: $('[data-action="stop"]'), seek: $('[data-action="seek"]'), clock: $('[data-field="clock"]'),
15
  duration: $('[data-field="duration"]'), volume: $('[data-action="volume"]'),
16
  loop: $('[data-action="loop"]'), selectRegion: $('[data-action="select-region"]'),
 
1123
  state.songTime = clamp(state.songTime, 0, Math.max(data.duration, playableEnd()));
1124
  }
1125
  root.dataset.state = data.state; const active = ['queued', 'loading', 'transcribing', 'generating_score'].includes(data.state);
1126
+ const failed = ['error', 'notation_error'].includes(data.state);
1127
  const hasResults = data.tracks.length > 0 || active;
1128
  ui.empty.hidden = hasResults; ui.workspace.hidden = !hasResults;
1129
  ui.state.textContent = ({ idle: 'Ready for audio', queued: 'ZeroGPU queued', loading: 'Loading model', transcribing: 'Transcribing', generating_score: 'Generating score', complete: 'MIDI ready', ready: 'Score ready', error: 'Error', notation_error: 'MIDI ready' })[data.state] || data.state;
1130
  ui.status.textContent = data.status; ui.audioName.textContent = data.audio_name || 'Your transcription';
1131
  ui.summary.textContent = data.audio_name ? `${data.note_count.toLocaleString('en-US')} notes · ${data.tracks.length} tracks` : '—';
1132
  const indeterminate = data.state === 'generating_score';
1133
+ const progressPercent = failed ? 100 : Math.round(data.progress * 100);
1134
+ ui.progress.hidden = !(active || failed); ui.progress.dataset.indeterminate = String(indeterminate);
1135
+ ui.progressLabel.textContent = data.status;
1136
+ ui.progressValue.textContent = failed ? (data.state === 'notation_error' ? 'Score issue' : 'Failed') : indeterminate ? 'Rendering…' : `${progressPercent}%`;
1137
+ ui.progressBar.style.width = `${progressPercent}%`;
1138
+ if (indeterminate) {
1139
+ ui.progressTrack.removeAttribute('aria-valuenow');
1140
+ ui.progressTrack.setAttribute('aria-valuetext', 'Rendering in progress');
1141
+ } else {
1142
+ ui.progressTrack.setAttribute('aria-valuenow', String(progressPercent));
1143
+ ui.progressTrack.setAttribute('aria-valuetext', failed ? 'Operation failed' : `${progressPercent}% complete`);
1144
+ }
1145
  ui.duration.textContent = formatTime(data.duration); ui.seek.max = String(Math.max(.01, data.duration));
1146
  setText('[data-field="track-count"]', data.tracks.length ? `${data.tracks.length} track${data.tracks.length > 1 ? 's' : ''}` : 'No tracks yet');
1147
  setText('[data-field="info-duration"]', formatTime(data.duration)); setText('[data-field="note-count"]', data.note_count ? data.note_count.toLocaleString('en-US') : '—');