diff --git a/mobile.html b/mobile.html index 49f070b..a016a5e 100644 --- a/mobile.html +++ b/mobile.html @@ -59,21 +59,27 @@ #app{ position:fixed; inset:0; overflow:hidden; display:flex; flex-direction:column; padding:max(8px,env(safe-area-inset-top)) max(12px,env(safe-area-inset-right)) - max(12px,env(safe-area-inset-bottom)) max(12px,env(safe-area-inset-left)); } + max(10px,env(safe-area-inset-bottom)) max(12px,env(safe-area-inset-left)); } - /* ---- top bar ---- */ - #bar{ flex:0 0 auto; display:flex; align-items:center; gap:10px; min-height:44px; } - #bar .id{ flex:1 1 auto; min-width:0; line-height:1.15; } - #bar .nm{ font-size:clamp(15px,2.7vmin,22px); font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; } - #bar .sub{ font-size:clamp(11px,1.9vmin,14px); color:var(--muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; } - .icon{ flex:0 0 auto; width:44px; height:44px; border-radius:50%; display:flex; align-items:center; justify-content:center; - font-size:19px; line-height:1; cursor:pointer; color:var(--txt); + /* ---- top: set-list + track dropdowns, volume, theme/fullscreen ---- */ + #top{ flex:0 0 auto; display:flex; flex-direction:column; gap:8px; } + .sels{ display:flex; gap:8px; } + .sel{ flex:1 1 0; min-width:0; display:flex; flex-direction:column; gap:3px; } + .sel > span{ font-size:10px; letter-spacing:.14em; text-transform:uppercase; color:var(--muted); padding-left:3px; } + .sel select{ width:100%; background:var(--field-bg); color:var(--txt); border:1px solid var(--field-bd); + border-radius:10px; padding:10px 8px; font-size:15px; } + .trow{ display:flex; align-items:center; gap:10px; } + .vol{ flex:1 1 auto; display:flex; align-items:center; gap:9px; color:var(--muted); font-size:15px; min-width:0; } + .vol input{ flex:1 1 auto; min-width:0; accent-color:var(--cyan); } + .icon{ flex:0 0 auto; width:42px; height:42px; border-radius:50%; display:flex; align-items:center; justify-content:center; + font-size:18px; line-height:1; cursor:pointer; color:var(--txt); background:rgba(127,139,154,.14); border:1px solid var(--panel-bd); } .icon:active{ background:rgba(127,139,154,.30); } - /* ---- stage: beats + pulse ---- */ + /* ---- middle: beats + pulse, then transport (row in landscape) ---- */ + #mid{ flex:1 1 auto; min-height:0; display:flex; flex-direction:column; } #stage{ flex:1 1 auto; min-height:0; display:flex; flex-direction:column; align-items:center; justify-content:center; - gap:clamp(14px,3.4vmin,40px); } + gap:clamp(12px,3vmin,36px); } #beats{ display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap:clamp(8px,1.7vmin,16px); max-width:92%; } .dot{ width:clamp(13px,3vmin,30px); height:clamp(13px,3vmin,30px); border-radius:50%; background:var(--led-off); border:1px solid rgba(0,0,0,.35); transition:background .05s, box-shadow .05s, transform .05s; } @@ -81,135 +87,147 @@ .dot.on{ background:var(--cyan); box-shadow:0 0 12px var(--glow); transform:scale(1.12); } .dot.on.group{ background:var(--amber); box-shadow:0 0 14px var(--aglow); } - #pulse{ position:relative; width:clamp(190px,48vmin,460px); height:clamp(190px,48vmin,460px); border-radius:50%; + #pulse{ position:relative; width:clamp(180px,46vmin,440px); height:clamp(180px,46vmin,440px); border-radius:50%; display:flex; flex-direction:column; align-items:center; justify-content:center; text-align:center; border:2px solid var(--ring); background:radial-gradient(circle at 50% 40%, rgba(127,139,154,.07), transparent 70%); transition:transform .12s ease-out, box-shadow .12s ease-out, border-color .12s ease-out; touch-action:none; cursor:ns-resize; } #pulse.hit{ transform:scale(1.045); border-color:var(--cyan); box-shadow:0 0 60px var(--glow); } #pulse.hit.acc{ border-color:var(--amber); box-shadow:0 0 72px var(--aglow); } - #bpm{ font-size:clamp(58px,19vmin,180px); font-weight:800; line-height:.85; font-variant-numeric:tabular-nums; letter-spacing:-.01em; } + #bpm{ font-size:clamp(54px,18vmin,170px); font-weight:800; line-height:.85; font-variant-numeric:tabular-nums; letter-spacing:-.01em; } #bpmlab{ font-size:clamp(11px,2.3vmin,18px); letter-spacing:.34em; color:var(--muted); margin-top:.7em; } - #bpmIn{ display:none; width:62%; text-align:center; font:inherit; font-size:clamp(50px,16vmin,150px); font-weight:800; + #bpmIn{ display:none; width:62%; text-align:center; font:inherit; font-size:clamp(48px,15vmin,140px); font-weight:800; background:transparent; color:var(--txt); border:none; border-bottom:2px solid var(--cyan); outline:none; font-variant-numeric:tabular-nums; -moz-appearance:textfield; } #bpmIn::-webkit-outer-spin-button, #bpmIn::-webkit-inner-spin-button{ -webkit-appearance:none; margin:0; } #meterline{ font-size:clamp(12px,2.1vmin,17px); color:var(--muted); min-height:1.2em; letter-spacing:.02em; } - /* ---- transport ---- */ - #transport{ flex:0 0 auto; display:flex; flex-direction:column; align-items:center; gap:clamp(8px,1.6vmin,14px); - padding-top:clamp(8px,1.6vmin,16px); width:100%; } - /* buttons SHARE the row width (flex:1) so 5 of them never overflow a narrow phone — they - just get narrower; capped by max-width so they don't sprawl on a tablet. */ - .row{ display:flex; align-items:center; justify-content:center; gap:clamp(6px,2vmin,16px); - width:100%; max-width:560px; } - .tbtn{ flex:1 1 0; min-width:0; background:linear-gradient(180deg,var(--btn1),var(--btn2)); color:var(--txt); border:1px solid var(--btn-bd); - border-radius:14px; height:clamp(56px,15vmin,84px); font-size:clamp(20px,5vmin,30px); - cursor:pointer; box-shadow:0 3px 0 rgba(0,0,0,.28), inset 0 1px 0 rgba(255,255,255,.06); - display:flex; align-items:center; justify-content:center; } + /* ---- transport: tempo grid (−10/− +/+10) + prev/next + play/practice + tap ---- */ + #transport{ flex:0 0 auto; display:flex; flex-direction:column; align-items:center; gap:clamp(7px,1.4vmin,12px); + padding-top:clamp(6px,1.2vmin,12px); width:100%; } + .tgrid{ display:grid; width:100%; max-width:560px; gap:clamp(6px,1.7vmin,13px); + grid-template-columns:1fr 1.5fr 1.5fr 1fr; + grid-template-areas:"dn10 prev next up10" "dn play prac up"; } + .tbtn{ background:linear-gradient(180deg,var(--btn1),var(--btn2)); color:var(--txt); border:1px solid var(--btn-bd); + border-radius:14px; height:clamp(50px,12.5vmin,76px); font-size:clamp(18px,4.6vmin,28px); cursor:pointer; + box-shadow:0 3px 0 rgba(0,0,0,.28), inset 0 1px 0 rgba(255,255,255,.06); + display:flex; flex-direction:column; align-items:center; justify-content:center; gap:2px; } + .tbtn small{ font-size:clamp(8px,1.5vmin,11px); letter-spacing:.1em; color:inherit; opacity:.8; } .tbtn:active{ transform:translateY(2px); box-shadow:0 1px 0 rgba(0,0,0,.28), inset 0 1px 0 rgba(255,255,255,.06); } - .tbtn.play{ flex:1.6 1 0; background:linear-gradient(180deg,#1f7a4d,#155f3b); border-color:#2e7d32; color:#eafff3; } + .tbtn:disabled{ opacity:.42; pointer-events:none; } + #bDn10{grid-area:dn10} #bPrev{grid-area:prev} #bNext{grid-area:next} #bUp10{grid-area:up10} + #bDown{grid-area:dn} #bPlay{grid-area:play} #bPrac{grid-area:prac} #bUp{grid-area:up} + .tbtn.play{ background:linear-gradient(180deg,#1f7a4d,#155f3b); border-color:#2e7d32; color:#eafff3; } .tbtn.play.on{ background:linear-gradient(180deg,#b23b3b,#8f2d2d); border-color:#c0392b; color:#fff; } - .tap{ background:transparent; color:var(--muted); border:1px solid var(--panel-bd); border-radius:12px; - padding:9px 22px; font-size:clamp(12px,2.2vmin,15px); letter-spacing:.16em; cursor:pointer; } - .tap:active{ color:var(--txt); background:rgba(127,139,154,.14); } + .tbtn.prac{ background:linear-gradient(180deg,#1c87b8,#136488); border-color:#1f9bd0; color:#eaf8ff; } + .tbtn.prac.on{ background:linear-gradient(180deg,#b23b3b,#8f2d2d); border-color:#c0392b; color:#fff; } + .tap{ width:100%; max-width:560px; height:clamp(44px,9vmin,58px); border-radius:13px; + background:linear-gradient(180deg,var(--btn1),var(--btn2)); color:var(--txt); border:1px solid var(--btn-bd); + font-size:clamp(13px,2.4vmin,16px); letter-spacing:.16em; cursor:pointer; + box-shadow:0 3px 0 rgba(0,0,0,.28), inset 0 1px 0 rgba(255,255,255,.06); } + .tap:active{ transform:translateY(2px); box-shadow:0 1px 0 rgba(0,0,0,.28), inset 0 1px 0 rgba(255,255,255,.06); } - /* shorter viewports (landscape phones): tighten so it all fits */ - @media (max-height:540px){ - #stage{ gap:clamp(8px,2vmin,18px); } - #bpmlab{ margin-top:.4em; } - .tbtn{ height:clamp(48px,18vmin,70px); } + /* landscape phones: pulse on the left, transport on the right (use width, not height) */ + @media (orientation:landscape) and (max-height:600px){ + #mid{ flex-direction:row; align-items:center; gap:3vw; } + #stage{ flex:1 1 52%; gap:clamp(8px,2vmin,18px); } + #transport{ flex:1 1 48%; max-width:560px; } + #pulse{ width:clamp(150px,40vmin,300px); height:clamp(150px,40vmin,300px); } + #bpmlab{ display:none; } + .tgrid > .tbtn, .tap{ height:clamp(42px,13vmin,62px); } } - /* ---- menu sheet ---- */ + /* ---- collapsible practice log (thin bar → bottom-sheet overlay) ---- */ + #logbar{ flex:0 0 auto; display:flex; align-items:center; gap:8px; width:100%; + margin-top:6px; padding:9px 12px; border-radius:11px; cursor:pointer; + background:rgba(127,139,154,.10); border:1px solid var(--panel-bd); color:var(--muted); font-size:13px; } + #logbar .grow{ flex:1 1 auto; } + #logbar b{ color:var(--txt); } #scrim{ position:fixed; inset:0; background:rgba(0,0,0,.55); opacity:0; pointer-events:none; transition:opacity .2s; z-index:40; } #scrim.open{ opacity:1; pointer-events:auto; } - #sheet{ position:fixed; left:0; right:0; bottom:0; z-index:50; max-height:86vh; overflow-y:auto; + #logsheet{ position:fixed; left:0; right:0; bottom:0; z-index:50; max-height:74vh; overflow-y:auto; background:var(--panel-bg); border-top:1px solid var(--panel-bd); border-radius:18px 18px 0 0; transform:translateY(110%); transition:transform .26s cubic-bezier(.2,.8,.2,1); - padding:14px max(16px,env(safe-area-inset-right)) max(20px,env(safe-area-inset-bottom)) max(16px,env(safe-area-inset-left)); } - #sheet.open{ transform:none; } - #sheet .grab{ width:42px; height:5px; border-radius:3px; background:var(--panel-bd); margin:0 auto 12px; } - #sheet h2{ margin:2px 0 4px; font-size:15px; } - #sheet label{ display:block; font-size:12px; color:var(--muted); margin:14px 0 5px; } - #sheet select, #sheet textarea, #sheet input[type=range]{ width:100%; } - #sheet select{ background:var(--field-bg); color:var(--txt); border:1px solid var(--field-bd); border-radius:10px; padding:11px; font-size:15px; } - #sheet textarea{ background:var(--field-bg); color:var(--txt); border:1px solid var(--field-bd); border-radius:10px; padding:11px; - font-family:"Courier New",monospace; font-size:13px; resize:vertical; min-height:56px; } - .srow{ display:flex; gap:10px; align-items:center; margin-top:10px; } - .ld{ flex:0 0 auto; cursor:pointer; color:#eafff3; background:linear-gradient(180deg,#1f7a4d,#155f3b); border:1px solid #2e7d32; - border-radius:10px; padding:11px 18px; font-size:15px; } - #status{ margin-top:10px; font-size:12px; min-height:1.2em; font-family:"Courier New",monospace; color:var(--muted); } - #status.ok{ color:#5fd08a; } #status.err{ color:#ff7a7a; } - .vol{ display:flex; align-items:center; gap:12px; } - .sheet-foot{ display:flex; align-items:center; justify-content:space-between; margin-top:18px; padding-top:12px; + padding:14px max(16px,env(safe-area-inset-right)) max(18px,env(safe-area-inset-bottom)) max(16px,env(safe-area-inset-left)); } + #logsheet.open{ transform:none; } + #logsheet .grab{ width:42px; height:5px; border-radius:3px; background:var(--panel-bd); margin:0 auto 12px; } + #logsheet .lhead{ display:flex; align-items:baseline; justify-content:space-between; gap:10px; margin-bottom:4px; } + #logsheet h2{ margin:0; font-size:15px; } + #logsheet .sub{ font-size:12px; color:var(--muted); } + .hist-row{ display:flex; align-items:center; gap:10px; padding:9px 2px; border-bottom:1px solid var(--panel-bd); font-size:13px; } + .hist-row .t{ flex:1 1 auto; font-variant-numeric:tabular-nums; } + .hist-del{ flex:0 0 auto; background:transparent; border:1px solid var(--panel-bd); color:var(--muted); + border-radius:8px; width:30px; height:30px; cursor:pointer; } + .lempty{ font-size:13px; color:var(--muted); padding:10px 2px; } + .lfoot{ display:flex; align-items:center; justify-content:space-between; margin-top:14px; padding-top:12px; border-top:1px solid var(--panel-bd); font-size:12px; color:var(--muted); } - .sheet-foot a{ color:var(--link); text-decoration:none; } - #installBtn{ display:none; cursor:pointer; color:var(--txt); background:transparent; border:1px solid var(--panel-bd); - border-radius:9px; padding:7px 14px; font-size:13px; } - .dev-logo{ height:18px; opacity:.85; } + .lbtn{ cursor:pointer; color:var(--txt); background:transparent; border:1px solid var(--panel-bd); border-radius:9px; padding:7px 13px; font-size:13px; } + .dev-logo{ height:16px; opacity:.85; vertical-align:middle; } [data-theme="light"] .logo-dark{ display:none; } [data-theme="dark"] .logo-light{ display:none; }