All checks were successful
release / build-release (push) Successful in 4m31s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kf4MAbZ3c3B4Xy5XfuGsCP
646 lines
38 KiB
HTML
646 lines
38 KiB
HTML
<title>FitnessDroid — designförslag</title>
|
||
<meta name="description" content="Passpilot-konceptet: mockups för passläge, hemskärm, övningsväljare, Android-ytor, kroppskarta och API-förslag.">
|
||
<style>
|
||
:root{
|
||
--ground:#0c0f0b; --panel:#131812; --panel-hi:#1a201a; --line:#263026;
|
||
--ink:#e4e7de; --dim:#96a093; --accent:#8fd694; --accent-deep:#2e4a33;
|
||
--m3-bg:#101410; --m3-surf:#1a211a; --m3-surf2:#232b23; --m3-surf3:#2b342b;
|
||
--m3-pri:#8fd694; --m3-onpri:#08300f; --m3-on:#e2e5dc; --m3-dim:#a9b2a5;
|
||
--m3-outline:#3e483d; --m3-seccont:#33503a; --m3-onsec:#cfeacf;
|
||
--heat0:#233026; --heat1:#3d5c42; --heat2:#5f8f60; --heat3:#8fd694; --heat4:#d3f0c9;
|
||
}
|
||
*{box-sizing:border-box;margin:0}
|
||
body{background:var(--ground);color:var(--ink);
|
||
font:16px/1.55 Roboto,system-ui,-apple-system,"Segoe UI",sans-serif;
|
||
-webkit-font-smoothing:antialiased;padding:0 20px 96px}
|
||
.wrap{max-width:1180px;margin:0 auto}
|
||
a{color:var(--accent)}
|
||
|
||
header.top{padding:64px 0 24px;border-bottom:1px solid var(--line);margin-bottom:8px}
|
||
.eyebrow{font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--accent);font-weight:600}
|
||
h1{font-size:clamp(28px,4.5vw,44px);font-weight:800;letter-spacing:-.02em;text-wrap:balance;margin:10px 0 12px}
|
||
.lede{color:var(--dim);max-width:66ch}
|
||
section{padding:52px 0 8px}
|
||
.secnum{font:600 12px/1 ui-monospace,monospace;color:var(--dim);letter-spacing:.1em}
|
||
h2{font-size:26px;font-weight:750;letter-spacing:-.01em;margin:8px 0 6px;text-wrap:balance}
|
||
.secintro{color:var(--dim);max-width:64ch;margin-bottom:28px}
|
||
h3{font-size:17px;font-weight:700;margin:0 0 4px}
|
||
|
||
/* koncept-kort */
|
||
.modes{display:flex;gap:14px;flex-wrap:wrap;margin-top:22px}
|
||
.mode{flex:1 1 240px;background:var(--panel);border:1px solid var(--line);border-radius:16px;padding:18px}
|
||
.mode b{display:block;font-size:15px;margin-bottom:5px}
|
||
.mode span{color:var(--dim);font-size:14px}
|
||
.mode .k{font:700 11px/1 ui-monospace,monospace;color:var(--accent);letter-spacing:.12em;display:block;margin-bottom:10px}
|
||
|
||
/* telefonram */
|
||
.phone{width:320px;background:#000;border:1px solid #2c342c;border-radius:30px;
|
||
padding:9px;flex:0 0 auto;box-shadow:0 24px 60px -30px rgba(0,0,0,.8)}
|
||
.screen{background:var(--m3-bg);border-radius:22px;overflow:hidden;display:flex;
|
||
flex-direction:column;height:640px;font-size:13.5px;color:var(--m3-on)}
|
||
.statusbar{display:flex;justify-content:space-between;align-items:center;
|
||
padding:10px 18px 4px;font-size:11px;color:var(--m3-dim)}
|
||
.sb-ic{display:flex;gap:5px;align-items:center}
|
||
.content{flex:1;overflow:hidden;padding:6px 14px 0;display:flex;flex-direction:column;gap:11px}
|
||
.gesture{height:18px;display:flex;align-items:center;justify-content:center}
|
||
.gesture i{display:block;width:96px;height:4px;border-radius:2px;background:#3a423a}
|
||
|
||
/* m3-bitar */
|
||
.m3-greet{padding:6px 4px 0}
|
||
.m3-greet b{font-size:21px;font-weight:700;display:block}
|
||
.m3-greet span{color:var(--m3-dim);font-size:12.5px}
|
||
.card{background:var(--m3-surf);border-radius:16px;padding:13px 14px}
|
||
.card.tonal{background:var(--m3-surf2)}
|
||
.rowline{display:flex;align-items:center;gap:10px}
|
||
.rowline .grow{flex:1;min-width:0}
|
||
.btn-filled{background:var(--m3-pri);color:var(--m3-onpri);border-radius:999px;
|
||
padding:13px 18px;font-weight:700;font-size:14.5px;text-align:center;
|
||
display:flex;align-items:center;justify-content:center;gap:8px}
|
||
.seclabel{display:flex;justify-content:space-between;align-items:baseline;padding:2px 4px 0}
|
||
.seclabel b{font-size:13.5px;font-weight:700}
|
||
.seclabel a{font-size:11.5px;color:var(--m3-pri);text-decoration:none;font-weight:600}
|
||
.hscroll{display:flex;gap:10px;overflow:hidden}
|
||
.favcard{background:var(--m3-surf2);border-radius:16px;padding:12px;min-width:150px;flex:0 0 auto}
|
||
.favcard .nm{font-weight:700;font-size:13.5px;display:flex;gap:6px;align-items:center}
|
||
.favcard .muscles{color:var(--m3-dim);font-size:10.5px;margin:3px 0 8px}
|
||
.favcard .go{margin-top:6px;background:var(--m3-pri);color:var(--m3-onpri);border-radius:999px;
|
||
font-size:11.5px;font-weight:700;padding:6px 0;text-align:center}
|
||
.star{color:#ffd977;font-size:12px}
|
||
.listrow{display:flex;gap:11px;align-items:center;padding:9px 4px;border-bottom:1px solid #202820}
|
||
.listrow:last-child{border-bottom:0}
|
||
.listrow .t{font-weight:600;font-size:13px}
|
||
.listrow .s{color:var(--m3-dim);font-size:11px}
|
||
.mchip{width:34px;height:34px;border-radius:50%;background:var(--m3-surf3);
|
||
display:flex;align-items:center;justify-content:center;flex:0 0 auto}
|
||
.mchip svg{width:19px;height:19px;stroke:var(--m3-pri);fill:none;stroke-width:1.7;
|
||
stroke-linecap:round;stroke-linejoin:round}
|
||
.badge{font-size:9.5px;font-weight:700;background:var(--m3-surf3);color:var(--m3-dim);
|
||
border-radius:5px;padding:2px 5px;letter-spacing:.03em}
|
||
.searchbar{background:var(--m3-surf2);border-radius:999px;padding:10px 15px;color:var(--m3-dim);
|
||
display:flex;gap:9px;align-items:center;font-size:13px}
|
||
.chiprow{display:flex;gap:7px;overflow:hidden;padding:1px}
|
||
.chip{border:1px solid var(--m3-outline);border-radius:9px;padding:6px 11px;font-size:11.5px;
|
||
font-weight:600;color:var(--m3-dim);display:inline-flex;gap:6px;align-items:center;flex:0 0 auto}
|
||
.chip svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:1.8;
|
||
stroke-linecap:round;stroke-linejoin:round}
|
||
.chip.sel{background:var(--m3-seccont);color:var(--m3-onsec);border-color:transparent}
|
||
.chip.small{padding:4px 10px;font-size:10.5px;border-radius:999px}
|
||
.topbar-menu{display:flex;justify-content:space-between;align-items:center;padding:2px 4px}
|
||
.topbar-menu b{font-size:16px}
|
||
|
||
/* passläget */
|
||
.sess-top{display:flex;justify-content:space-between;align-items:center;padding:2px 4px}
|
||
.sess-top b{font-size:15.5px}
|
||
.timerchip{background:var(--m3-seccont);color:var(--m3-onsec);border-radius:999px;
|
||
padding:4px 11px;font:700 12px/1.4 ui-monospace,monospace}
|
||
.pagerdots{display:flex;gap:5px;align-items:center;padding:0 4px}
|
||
.pagerdots i{height:4px;border-radius:2px;background:var(--m3-surf3);flex:1}
|
||
.pagerdots i.done{background:var(--m3-pri);opacity:.45}
|
||
.pagerdots i.cur{background:var(--m3-pri)}
|
||
.exhead{padding:2px 4px}
|
||
.exhead b{font-size:19px;font-weight:750;display:block}
|
||
.exhead span{color:var(--m3-dim);font-size:11.5px}
|
||
.setdone{display:flex;align-items:center;gap:10px;padding:7px 10px;border-radius:11px;
|
||
background:var(--m3-surf);color:var(--m3-dim);font-size:12.5px}
|
||
.setdone .ck{color:var(--m3-pri);font-weight:800}
|
||
.setactive{background:var(--m3-surf2);border-radius:16px;padding:13px;display:flex;
|
||
flex-direction:column;gap:11px}
|
||
.steppers{display:flex;gap:9px}
|
||
.stepper{flex:1;background:var(--m3-bg);border-radius:13px;padding:8px 9px;
|
||
display:flex;align-items:center;justify-content:space-between}
|
||
.stepper .pm{width:30px;height:30px;border-radius:50%;background:var(--m3-surf3);
|
||
color:var(--m3-on);font:700 16px/30px sans-serif;text-align:center}
|
||
.stepper .val{text-align:center}
|
||
.stepper .val b{font-size:17px;font-variant-numeric:tabular-nums}
|
||
.stepper .val span{display:block;font-size:9.5px;color:var(--m3-dim);letter-spacing:.08em;text-transform:uppercase}
|
||
.rpe{display:flex;gap:6px;align-items:center;font-size:10.5px;color:var(--m3-dim)}
|
||
.rpe i{font-style:normal;border:1px solid var(--m3-outline);border-radius:7px;
|
||
padding:3px 9px;font-weight:700;font-size:11px}
|
||
.rpe i.sel{background:var(--m3-seccont);color:var(--m3-onsec);border-color:transparent}
|
||
.nextup{display:flex;align-items:center;gap:9px;color:var(--m3-dim);font-size:11.5px;padding:0 4px}
|
||
|
||
/* vilo-overlay */
|
||
.rest{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px}
|
||
.ring{width:190px;height:190px;border-radius:50%;position:relative;
|
||
background:conic-gradient(var(--m3-pri) 74%,var(--m3-surf3) 0)}
|
||
.ring::after{content:"";position:absolute;inset:12px;border-radius:50%;background:var(--m3-bg)}
|
||
.ring .mid{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;
|
||
justify-content:center;z-index:1}
|
||
.ring .mid b{font:800 40px/1 ui-monospace,monospace;font-variant-numeric:tabular-nums}
|
||
.ring .mid span{color:var(--m3-dim);font-size:11px;letter-spacing:.1em;text-transform:uppercase}
|
||
.restbtns{display:flex;gap:10px}
|
||
.restbtns .btn-tonal{background:var(--m3-surf3);color:var(--m3-on);border-radius:999px;
|
||
padding:9px 16px;font-weight:700;font-size:12.5px}
|
||
.restnext{color:var(--m3-dim);font-size:12px;text-align:center}
|
||
.restnext b{color:var(--m3-on)}
|
||
|
||
/* strips: minispelare + notis */
|
||
.strips{display:flex;flex-direction:column;gap:18px;min-width:280px;flex:1 1 340px}
|
||
.striplabel{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--dim);font-weight:700;margin-bottom:7px}
|
||
.stripbar{background:var(--m3-surf2);border:1px solid var(--line);border-radius:14px;
|
||
padding:10px 13px;display:flex;align-items:center;gap:11px;max-width:340px}
|
||
.stripbar .grow{flex:1;min-width:0}
|
||
.stripbar .t{font-weight:700;font-size:12.5px;color:var(--m3-on)}
|
||
.stripbar .s{font-size:10.5px;color:var(--m3-dim)}
|
||
.stripbar .act{color:var(--m3-pri);font-weight:800;font-size:11px}
|
||
.noti{background:#181d18;border:1px solid var(--line);border-radius:18px;padding:13px 15px;max-width:340px}
|
||
.noti .approw{display:flex;gap:7px;align-items:center;font-size:10px;color:var(--m3-dim);margin-bottom:7px}
|
||
.noti .approw i{width:13px;height:13px;border-radius:4px;background:var(--m3-pri);display:inline-block}
|
||
.noti b{font-size:13px;color:var(--m3-on)}
|
||
.noti p{font-size:12px;color:var(--m3-dim);margin:2px 0 9px}
|
||
.noti .actions{display:flex;gap:16px;font-weight:700;font-size:12px;color:var(--m3-pri)}
|
||
|
||
/* skivkalkylator */
|
||
.sheet{background:var(--m3-surf);border-radius:20px 20px 14px 14px;padding:16px;max-width:340px;border:1px solid var(--line)}
|
||
.sheet .grab{width:36px;height:4px;border-radius:2px;background:var(--m3-outline);margin:0 auto 12px}
|
||
.sheet h4{font-size:14px;margin-bottom:2px}
|
||
.sheet .sub{color:var(--m3-dim);font-size:11.5px;margin-bottom:13px}
|
||
.bar{display:flex;align-items:center;height:64px;margin:4px 0 12px}
|
||
.bar .shaft{height:7px;background:#5a635a;flex:1;border-radius:3px}
|
||
.bar .collar{width:9px;height:22px;background:#788078;border-radius:2px}
|
||
.plate{border-radius:4px;margin:0 1.5px;box-shadow:inset 0 0 0 1.5px rgba(0,0,0,.35)}
|
||
.p20{width:13px;height:62px;background:#3f6fb5}
|
||
.p10{width:11px;height:46px;background:#4d9b57}
|
||
.p5{width:10px;height:34px;background:#d7d7cf}
|
||
.p25{width:9px;height:26px;background:#c05252}
|
||
.sheet .plates-txt{font-size:12.5px;color:var(--m3-dim)}
|
||
.sheet .plates-txt b{color:var(--m3-on)}
|
||
|
||
/* widget */
|
||
.widget{background:linear-gradient(145deg,#1c231c,#141a14);border:1px solid var(--line);
|
||
border-radius:22px;padding:14px 16px;max-width:340px}
|
||
.widget .wt{display:flex;justify-content:space-between;align-items:center;margin-bottom:11px}
|
||
.widget .wt b{font-size:12.5px;color:var(--m3-on)}
|
||
.widget .wt span{font-size:10px;color:var(--m3-dim)}
|
||
.widget .wbtns{display:flex;gap:8px}
|
||
.widget .wb{flex:1;border-radius:12px;padding:10px 8px;font-size:11.5px;font-weight:700;text-align:center}
|
||
.widget .wb.pri{background:var(--m3-pri);color:var(--m3-onpri)}
|
||
.widget .wb.ton{background:var(--m3-surf3);color:var(--m3-on)}
|
||
|
||
/* kroppskarta */
|
||
.bodymaps{display:flex;gap:34px;flex-wrap:wrap;align-items:flex-start}
|
||
.bodycard{background:var(--panel);border:1px solid var(--line);border-radius:18px;padding:22px 26px;display:flex;gap:26px}
|
||
.bodycard figure{text-align:center}
|
||
.bodycard figcaption{font-size:11px;color:var(--dim);margin-top:8px;letter-spacing:.08em;text-transform:uppercase;font-weight:700}
|
||
.heatlegend{display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--dim);margin-top:16px}
|
||
.heatlegend i{width:22px;height:10px;border-radius:3px;display:inline-block}
|
||
|
||
/* layout runt telefoner */
|
||
.phones{display:flex;gap:26px;flex-wrap:wrap;align-items:flex-start}
|
||
.duo{display:flex;gap:40px;flex-wrap:wrap;align-items:flex-start}
|
||
.notes{flex:1 1 340px;min-width:280px;display:flex;flex-direction:column;gap:16px}
|
||
.note{display:flex;gap:13px;align-items:flex-start}
|
||
.note .dot{width:24px;height:24px;border-radius:50%;background:var(--accent);
|
||
color:#0a2e10;font:700 12.5px/24px ui-monospace,monospace;text-align:center;flex:0 0 auto}
|
||
.note p{color:var(--dim);font-size:14.5px}
|
||
.note b{color:var(--ink)}
|
||
.phcaption{font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--dim);
|
||
font-weight:700;text-align:center;margin-top:12px}
|
||
|
||
table{border-collapse:collapse;width:100%;font-size:13.5px;margin-top:22px}
|
||
th,td{text-align:left;padding:9px 12px;border-bottom:1px solid var(--line);vertical-align:top}
|
||
th{color:var(--dim);font-size:11px;text-transform:uppercase;letter-spacing:.1em}
|
||
td:first-child{font-weight:600;white-space:nowrap;color:var(--ink)}
|
||
td{color:var(--dim)}
|
||
.tablewrap{overflow-x:auto}
|
||
.pill-sm{display:inline-block;font-size:10px;font-weight:800;border-radius:5px;padding:2px 7px;
|
||
letter-spacing:.06em}
|
||
.pill-sm.s{background:var(--accent-deep);color:var(--accent)}
|
||
.pill-sm.m{background:#4a3f22;color:#e8c96e}
|
||
|
||
.decide{background:var(--panel);border:1px solid var(--line);border-radius:16px;
|
||
padding:22px 24px;margin-top:44px}
|
||
.decide h2{font-size:19px;margin:0 0 10px}
|
||
.decide ol{margin:0;padding-left:20px;color:var(--dim);display:flex;flex-direction:column;gap:8px;font-size:14.5px}
|
||
.decide b{color:var(--ink)}
|
||
</style>
|
||
|
||
<div class="wrap">
|
||
<header class="top">
|
||
<div class="eyebrow">FitnessDroid · Milstolpe 2 · Designförslag v2</div>
|
||
<h1>En passpilot i fickan — inte webben i mindre format</h1>
|
||
<p class="lede">Nytt tänk: appen byggs runt <b>själva gympasset</b>, inte runt flikar.
|
||
Mellan seten har du svettiga händer och 90 sekunder — allt i passläget är därför
|
||
stora tryckytor, förifyllda värden och en vilotimer som sköter sig själv, även på
|
||
låsskärmen. Runt det: en hemskärm som startar pass på ett tryck, och Android-ytor
|
||
som webben aldrig kan nå.</p>
|
||
<div class="modes">
|
||
<div class="mode"><span class="k">LÄGE 1 · STARTA</span><b>Hemskärmen</b>
|
||
<span>Favoritpass, fritt pass, widget och appgenvägar — max två tryck till första setet.</span></div>
|
||
<div class="mode"><span class="k">LÄGE 2 · KÖR</span><b>Passläget</b>
|
||
<span>En övning i taget, set loggas med ett tryck, vilotimern tar över — appen coachar, du lyfter.</span></div>
|
||
<div class="mode"><span class="k">LÄGE 3 · FÖLJ UPP</span><b>Statistik & PB</b>
|
||
<span>Kroppskarta som visar var veckans volym hamnat, trender och PB-historik.</span></div>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- ============ 1. PASSLÄGET ============ -->
|
||
<section>
|
||
<div class="secnum">1 / 6</div>
|
||
<h2>Passläget — en övning i taget, ett tryck per set</h2>
|
||
<p class="secintro">Hela skärmen ägnas åt övningen du står vid. Svep i sidled mellan
|
||
övningarna i passet. Värdena är alltid förifyllda från förra passet plus
|
||
progressionsregeln — stämmer allt trycker du bara på gröna knappen.</p>
|
||
|
||
<div class="duo">
|
||
<div>
|
||
<div class="phone"><div class="screen">
|
||
<div class="statusbar"><span>19:24</span><span class="sb-ic">▲ ▮</span></div>
|
||
<div class="content">
|
||
<div class="sess-top">
|
||
<span style="display:flex;align-items:center;gap:9px">
|
||
<svg width="18" height="18" viewBox="0 0 24 24" style="stroke:var(--m3-on);fill:none;stroke-width:1.8;stroke-linecap:round"><path d="M15 5l-7 7 7 7"/></svg>
|
||
<b>Push A</b></span>
|
||
<span class="timerchip">24:31</span>
|
||
</div>
|
||
<div class="pagerdots"><i class="done"></i><i class="done"></i><i class="cur"></i><i></i><i></i><i></i><i></i><i></i></div>
|
||
<div class="exhead"><b>Bänkpress</b>
|
||
<span>Övning 3 av 8 · Bröst, triceps · Förra passet: 4×8 @ 77,5 kg</span></div>
|
||
|
||
<div class="setdone"><span class="ck">✓</span>Set 1 · 80,0 kg × 8 · RPE 7</div>
|
||
<div class="setdone"><span class="ck">✓</span>Set 2 · 80,0 kg × 8 · RPE 8</div>
|
||
|
||
<div class="setactive">
|
||
<div style="font-size:11px;color:var(--m3-dim);font-weight:700;letter-spacing:.08em">SET 3 AV 4</div>
|
||
<div class="steppers">
|
||
<div class="stepper"><span class="pm">−</span>
|
||
<span class="val"><b>80,0</b><span>kg · ±2,5</span></span><span class="pm">+</span></div>
|
||
<div class="stepper"><span class="pm">−</span>
|
||
<span class="val"><b>8</b><span>reps</span></span><span class="pm">+</span></div>
|
||
</div>
|
||
<div class="rpe">RPE <i>7</i><i class="sel">8</i><i>9</i><i>10</i></div>
|
||
<div class="btn-filled">✓ Logga set — vilan startar</div>
|
||
</div>
|
||
|
||
<div class="nextup">
|
||
<svg width="14" height="14" viewBox="0 0 24 24" style="stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round"><path d="M5 12h14m-6-6 6 6-6 6"/></svg>
|
||
Nästa: Lutande hantelpress · 3×10 @ 28 kg</div>
|
||
</div>
|
||
<div class="gesture"><i></i></div>
|
||
</div></div>
|
||
<div class="phcaption">Passläget · aktivt set</div>
|
||
</div>
|
||
|
||
<div>
|
||
<div class="phone"><div class="screen">
|
||
<div class="statusbar"><span>19:26</span><span class="sb-ic">▲ ▮</span></div>
|
||
<div class="content">
|
||
<div class="sess-top"><b style="font-size:14px">Vila</b><span class="timerchip">Push A · 26:04</span></div>
|
||
<div class="rest">
|
||
<div class="ring"><div class="mid"><b>1:07</b><span>av 1:30</span></div></div>
|
||
<div class="restbtns">
|
||
<span class="btn-tonal">−15 s</span>
|
||
<span class="btn-tonal">+15 s</span>
|
||
<span class="btn-tonal">Hoppa över</span>
|
||
</div>
|
||
<div class="restnext">Härnäst: <b>Set 4 av 4 · 80,0 kg × 8</b><br>
|
||
Sista setet på bänken — sen lutande hantelpress</div>
|
||
</div>
|
||
</div>
|
||
<div class="gesture"><i></i></div>
|
||
</div></div>
|
||
<div class="phcaption">Vilan tar över skärmen</div>
|
||
</div>
|
||
|
||
<div class="notes">
|
||
<div class="note"><div class="dot">1</div><p><b>Ett tryck per set.</b> Vikt och
|
||
reps förifylls från förra passet + progressionsregeln (API:t har redan
|
||
<i>lastExercisePerformance</i>). Stämmer det: tryck ✓. Annars ±-knappar —
|
||
aldrig tangentbord för standardfallet.</p></div>
|
||
<div class="note"><div class="dot">2</div><p><b>Vilan sköter sig själv.</b> Loggat
|
||
set → timern startar, skärmen växlar till ringen, telefonen vibrerar när det
|
||
är dags. Längden hämtas per övning (litet API-tillägg, se sist).</p></div>
|
||
<div class="note"><div class="dot">3</div><p><b>Svep = nästa övning.</b> Ingen
|
||
lista att scrolla i mitt i passet. Prickraden överst visar var i passet du är;
|
||
långtryck öppnar överblicken där du kan ändra ordning eller lägga till övningar.</p></div>
|
||
<div class="note"><div class="dot">4</div><p><b>PB firas direkt</b> — slår du
|
||
ett personbästa på ett set får du konfetti och en 🏆-notis i samma sekund,
|
||
inte när passet är slut.</p></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="margin-top:38px" class="duo">
|
||
<div class="strips">
|
||
<div><div class="striplabel">Minispelare — passet följer med i hela appen (som Spotify)</div>
|
||
<div class="stripbar">
|
||
<svg width="18" height="18" viewBox="0 0 24 24" style="fill:var(--m3-pri)"><path d="M8 5v14l11-7z"/></svg>
|
||
<div class="grow"><div class="t">Push A · Bänkpress</div><div class="s">Vila 0:47 kvar · set 4 av 4</div></div>
|
||
<span class="act">ÖPPNA</span>
|
||
</div></div>
|
||
<div><div class="striplabel">Notis på låsskärmen — timern utan att ta upp telefonen ur fickan</div>
|
||
<div class="noti">
|
||
<div class="approw"><i></i> FitnessDroid · pågår</div>
|
||
<b>Vila 0:47 — sen set 4 av 4</b>
|
||
<p>Bänkpress 80,0 kg × 8 · Push A 26:04</p>
|
||
<div class="actions"><span>+15 s</span><span>LOGGA SET</span><span>PAUSA PASS</span></div>
|
||
</div></div>
|
||
</div>
|
||
<div class="notes" style="justify-content:center">
|
||
<div class="note"><div class="dot">5</div><p><b>Lämna passläget utan att tappa
|
||
passet.</b> Kollar du statistik mitt i passet ligger minispelaren kvar ovanför
|
||
navigeringen. Notisen med timer-åtgärder gör att telefonen kan ligga kvar i
|
||
fickan mellan seten — <b>det här är appens största övertag över webben.</b></p></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ 2. HEMSKÄRM ============ -->
|
||
<section>
|
||
<div class="secnum">2 / 6</div>
|
||
<h2>Hemskärmen — startmotorn</h2>
|
||
<p class="secintro">Öppnar du appen med ett pass igång åker du rakt in i passläget.
|
||
Annars: starta på ett eller två tryck.</p>
|
||
|
||
<div class="duo">
|
||
<div>
|
||
<div class="phone"><div class="screen">
|
||
<div class="statusbar"><span>19:24</span><span class="sb-ic">▲ ▮</span></div>
|
||
<div class="content">
|
||
<div class="m3-greet"><b>Tjena Björn</b><span>Vecka 30 · 2 pass · 3 veckors streak 🔥</span></div>
|
||
<div class="btn-filled" style="padding:15px 18px"><svg width="18" height="18" viewBox="0 0 24 24" style="fill:currentColor"><path d="M8 5v14l11-7z"/></svg> Starta fritt pass</div>
|
||
<div class="seclabel"><b>Favoritpass</b><a>Alla mallar</a></div>
|
||
<div class="hscroll">
|
||
<div class="favcard">
|
||
<div class="nm"><span class="star">★</span>Push A</div>
|
||
<div class="muscles">Bröst · Axlar · Triceps</div>
|
||
<div class="go">▶ Starta</div>
|
||
</div>
|
||
<div class="favcard">
|
||
<div class="nm"><span class="star">★</span>Ben & core</div>
|
||
<div class="muscles">Ben · Mage</div>
|
||
<div class="go">▶ Starta</div>
|
||
</div>
|
||
<div class="favcard">
|
||
<div class="nm"><span class="star">★</span>Rygg</div>
|
||
<div class="muscles">Rygg · Biceps</div>
|
||
<div class="go">▶ Starta</div>
|
||
</div>
|
||
</div>
|
||
<div class="card tonal rowline">
|
||
<div class="mchip"><svg viewBox="0 0 24 24"><path d="M4 19V9m6 10V5m6 14v-7"/></svg></div>
|
||
<div class="grow"><div style="font-weight:700;font-size:12.5px">Veckans muskler</div>
|
||
<div style="font-size:10.5px;color:var(--m3-dim)">Mest bröst & triceps — benen släpar efter</div></div>
|
||
<svg width="30" height="44" viewBox="0 0 30 46" aria-hidden="true">
|
||
<circle cx="15" cy="5" r="4" fill="#3d5c42"/>
|
||
<rect x="7" y="11" width="16" height="15" rx="5" fill="#8fd694"/>
|
||
<rect x="2" y="12" width="4.5" height="12" rx="2" fill="#5f8f60"/>
|
||
<rect x="23.5" y="12" width="4.5" height="12" rx="2" fill="#5f8f60"/>
|
||
<rect x="8" y="27" width="6" height="16" rx="2.6" fill="#233026"/>
|
||
<rect x="16" y="27" width="6" height="16" rx="2.6" fill="#233026"/>
|
||
</svg>
|
||
</div>
|
||
<div class="seclabel"><b>Senaste pass</b><a>Historik</a></div>
|
||
<div>
|
||
<div class="listrow"><div class="mchip"><svg viewBox="0 0 24 24"><path d="M4 12h16M7 8v8m10-8v8M4 10v4m16-4v4"/></svg></div>
|
||
<div class="grow"><div class="t">Push A</div><div class="s">mån 21/7 · 52 min · 4 890 kg</div></div>
|
||
<span class="badge">2 PB</span></div>
|
||
</div>
|
||
</div>
|
||
<div class="gesture"><i></i></div>
|
||
</div></div>
|
||
<div class="phcaption">Hemskärmen · inget pass igång</div>
|
||
</div>
|
||
|
||
<div class="notes">
|
||
<div class="note"><div class="dot">1</div><p><b>Fritt pass = ett tryck.</b>
|
||
Passet skapas direkt och övningsväljaren öppnas. Namn kan sättas efteråt —
|
||
inga formulär mellan dig och första setet.</p></div>
|
||
<div class="note"><div class="dot">2</div><p><b>Favoritpass = två tryck.</b>
|
||
API:ts favoritpass + mallar, med auto-progressionen förifylld.</p></div>
|
||
<div class="note"><div class="dot">3</div><p><b>Veckans muskler</b> — en liten
|
||
kroppskarta som teaser för statistiken, och en knuff om vad som är underjobbat.
|
||
Trycker du på kortet öppnas hela kartan (sektion 5).</p></div>
|
||
<div class="note"><div class="dot">4</div><p><b>Pågår ett pass öppnas appen
|
||
direkt i passläget</b> — hemskärmen visas bara när inget är igång. Därför
|
||
behövs inget "fortsätt"-kort: appen minns åt dig.</p></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ 3. ÖVNINGSVÄLJAREN ============ -->
|
||
<section>
|
||
<div class="secnum">3 / 6</div>
|
||
<h2>Övningsväljaren — sök, muskelfilter, favoriter först</h2>
|
||
<p class="secintro">Muskelgrupper som chips med ikoner; vald grupp fäller ut sina
|
||
muskler som en andra rad. Brickorna (KG/REPS/TID/M) kommer från övningens
|
||
tracks-flaggor och styr sedan set-loggningens fält.</p>
|
||
|
||
<div class="duo">
|
||
<div>
|
||
<div class="phone"><div class="screen">
|
||
<div class="statusbar"><span>19:24</span><span class="sb-ic">▲ ▮</span></div>
|
||
<div class="content">
|
||
<div class="topbar-menu"><span style="display:flex;align-items:center;gap:10px">
|
||
<svg width="20" height="20" viewBox="0 0 24 24" style="stroke:var(--m3-on);fill:none;stroke-width:1.8;stroke-linecap:round"><path d="M15 5l-7 7 7 7"/></svg>
|
||
<b>Lägg till övning</b></span></div>
|
||
<div class="searchbar"><svg width="15" height="15" viewBox="0 0 24 24" style="stroke:currentColor;fill:none;stroke-width:1.8"><circle cx="11" cy="11" r="6"/><path d="m20 20-4-4"/></svg> Sök övning …</div>
|
||
<div class="chiprow">
|
||
<span class="chip">Alla</span>
|
||
<span class="chip"><svg viewBox="0 0 24 24"><path d="M6 4h12l-1.5 8a4.5 4.5 0 0 1-9 0z"/><path d="M12 12v8"/></svg>Bröst</span>
|
||
<span class="chip sel"><svg viewBox="0 0 24 24"><path d="M7 4v7l5 9 5-9V4"/><path d="M7 8h10"/></svg>Rygg</span>
|
||
<span class="chip"><svg viewBox="0 0 24 24"><path d="M9 4v6l-2.5 9h4L12 13l1.5 6h4L15 10V4"/></svg>Ben</span>
|
||
<span class="chip"><svg viewBox="0 0 24 24"><path d="M4 12a8 8 0 0 1 16 0"/><circle cx="4" cy="14" r="2"/><circle cx="20" cy="14" r="2"/></svg>Axlar</span>
|
||
<span class="chip"><svg viewBox="0 0 24 24"><path d="M5 18l5-5m0 0 5-8 4 3-5 7-4-2z"/><circle cx="5" cy="19" r="2"/></svg>Armar</span>
|
||
</div>
|
||
<div class="chiprow">
|
||
<span class="chip small sel">Alla i Rygg</span>
|
||
<span class="chip small">Latsen</span>
|
||
<span class="chip small">Trapezius</span>
|
||
<span class="chip small">Ländrygg</span>
|
||
</div>
|
||
<div style="flex:1">
|
||
<div class="listrow"><div class="mchip"><svg viewBox="0 0 24 24"><path d="M4 12h16M7 8v8m10-8v8M4 10v4m16-4v4"/></svg></div>
|
||
<div class="grow"><div class="t">Marklyft <span class="star">★</span></div><div class="s">Rygg · Ben · senast 77,5 kg</div></div>
|
||
<span class="badge">KG</span><span class="badge">REPS</span></div>
|
||
<div class="listrow"><div class="mchip"><svg viewBox="0 0 24 24"><path d="M7 4v7l5 9 5-9V4"/><path d="M7 8h10"/></svg></div>
|
||
<div class="grow"><div class="t">Latsdrag <span class="star">★</span></div><div class="s">Latsen · senast 65 kg</div></div>
|
||
<span class="badge">KG</span><span class="badge">REPS</span></div>
|
||
<div class="listrow"><div class="mchip"><svg viewBox="0 0 24 24"><path d="M7 4v7l5 9 5-9V4"/><path d="M7 8h10"/></svg></div>
|
||
<div class="grow"><div class="t">Skivstångsrodd</div><div class="s">Rygg · Biceps</div></div>
|
||
<span class="badge">KG</span><span class="badge">REPS</span></div>
|
||
<div class="listrow"><div class="mchip"><svg viewBox="0 0 24 24"><path d="M4 6h16M8 6v4a4 4 0 0 0 8 0V6"/><path d="M12 14v6"/></svg></div>
|
||
<div class="grow"><div class="t">Pullups</div><div class="s">Latsen · kroppsvikt</div></div>
|
||
<span class="badge">REPS</span></div>
|
||
<div class="listrow"><div class="mchip"><svg viewBox="0 0 24 24"><path d="M7 4v7l5 9 5-9V4"/><path d="M7 8h10"/></svg></div>
|
||
<div class="grow"><div class="t">Ryggresning</div><div class="s">Ländrygg</div></div>
|
||
<span class="badge">REPS</span><span class="badge">TID</span></div>
|
||
</div>
|
||
</div>
|
||
<div class="gesture"><i></i></div>
|
||
</div></div>
|
||
<div class="phcaption">Övningsväljaren · Rygg valt</div>
|
||
</div>
|
||
|
||
<div class="notes">
|
||
<div class="note"><div class="dot">★</div><p><b>Favoriter alltid överst</b>
|
||
(API:ts favoritövningar), med senaste vikten som förhandsinfo så du slipper
|
||
minnas var du låg.</p></div>
|
||
<div class="note"><div class="dot">◐</div><p><b>Ikoner istället för foton:</b>
|
||
API:t saknar övningsbilder, så appen buntar vektorikoner per muskelgrupp —
|
||
offline, blixtsnabba, temafärgade. Vill du hellre ha en <b>kroppskarta där
|
||
vald muskel tänds</b> som filter är det samma dataunderlag — säg till vilken
|
||
du föredrar (kartan finns i sektion 5).</p></div>
|
||
<div class="note"><div class="dot">+</div><p><b>Ny övning på plats:</b> hittas
|
||
inte övningen visas "Skapa övningen ‹sökordet›" längst ned — grunddatan
|
||
behöver aldrig besökas mitt i ett pass.</p></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ 4. ANDROID-YTOR ============ -->
|
||
<section>
|
||
<div class="secnum">4 / 6</div>
|
||
<h2>Utanför appen — noll tryck innan gymmet</h2>
|
||
<p class="secintro">Det webben aldrig kan: starta och styra pass utan att ens öppna appen.</p>
|
||
<div class="duo">
|
||
<div class="strips">
|
||
<div><div class="striplabel">Hemskärms-widget (4×2)</div>
|
||
<div class="widget">
|
||
<div class="wt"><b>FitnessDroid</b><span>3 v streak · 2 pass denna vecka</span></div>
|
||
<div class="wbtns">
|
||
<span class="wb pri">▶ Push A</span>
|
||
<span class="wb ton">▶ Ben & core</span>
|
||
<span class="wb ton">Fritt pass</span>
|
||
</div>
|
||
</div></div>
|
||
<div><div class="striplabel">Långtryck på appikonen — genvägar</div>
|
||
<div class="noti" style="padding:9px 0;max-width:250px">
|
||
<div style="font-size:12.5px;font-weight:700;color:var(--m3-on);padding:6px 16px">▶ Starta Push A</div>
|
||
<div style="font-size:12.5px;font-weight:700;color:var(--m3-on);padding:6px 16px;border-top:1px solid var(--line)">▶ Starta fritt pass</div>
|
||
<div style="font-size:12.5px;font-weight:700;color:var(--m3-on);padding:6px 16px;border-top:1px solid var(--line)">📊 Veckans statistik</div>
|
||
</div></div>
|
||
</div>
|
||
<div class="strips">
|
||
<div><div class="striplabel">Skivkalkylatorn — tryck på vikten i passläget</div>
|
||
<div class="sheet">
|
||
<div class="grab"></div>
|
||
<h4>80,0 kg på stången</h4>
|
||
<div class="sub">Stång 20 kg · per sida:</div>
|
||
<div class="bar">
|
||
<span class="plate p5"></span><span class="plate p25"></span><span class="plate p10"></span><span class="plate p20"></span>
|
||
<span class="collar"></span><span class="shaft"></span><span class="collar"></span>
|
||
<span class="plate p20"></span><span class="plate p10"></span><span class="plate p25"></span><span class="plate p5"></span>
|
||
</div>
|
||
<div class="plates-txt">Per sida: <b>20 + 10 + 2,5 + 5</b> — dina skivor
|
||
ställs in en gång under Profil. Räknar även ut närmsta möjliga vikt.</div>
|
||
</div></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ 5. KROPPSKARTAN ============ -->
|
||
<section>
|
||
<div class="secnum">5 / 6</div>
|
||
<h2>Kroppskartan — var hamnade veckans volym?</h2>
|
||
<p class="secintro">Statistikens signaturvy: en stiliserad figur där varje muskelgrupp
|
||
färgas efter träningsvolymen i perioden (datat finns redan i API:ts workoutStats).
|
||
Samma karta kan återanvändas som muskelväljare i övningsfiltret om du hellre vill
|
||
det än chips.</p>
|
||
|
||
<div class="bodymaps">
|
||
<div class="bodycard">
|
||
<figure>
|
||
<svg width="150" height="290" viewBox="0 0 100 195" role="img" aria-label="Kroppskarta framsida">
|
||
<circle cx="50" cy="12" r="9" fill="#233026"/>
|
||
<rect x="43" y="22" width="14" height="7" rx="3" fill="#233026"/>
|
||
<ellipse cx="35" cy="36" rx="9" ry="7" fill="#5f8f60"/>
|
||
<ellipse cx="65" cy="36" rx="9" ry="7" fill="#5f8f60"/>
|
||
<rect x="33" y="34" width="15" height="14" rx="6" fill="#8fd694"/>
|
||
<rect x="52" y="34" width="15" height="14" rx="6" fill="#8fd694"/>
|
||
<rect x="36" y="50" width="28" height="26" rx="8" fill="#3d5c42"/>
|
||
<rect x="22" y="40" width="8" height="24" rx="4" fill="#d3f0c9"/>
|
||
<rect x="70" y="40" width="8" height="24" rx="4" fill="#d3f0c9"/>
|
||
<rect x="21" y="66" width="7" height="20" rx="3.5" fill="#3d5c42"/>
|
||
<rect x="72" y="66" width="7" height="20" rx="3.5" fill="#3d5c42"/>
|
||
<rect x="34" y="80" width="13" height="42" rx="6" fill="#233026"/>
|
||
<rect x="53" y="80" width="13" height="42" rx="6" fill="#233026"/>
|
||
<rect x="36" y="126" width="10" height="30" rx="5" fill="#233026"/>
|
||
<rect x="54" y="126" width="10" height="30" rx="5" fill="#233026"/>
|
||
</svg>
|
||
<figcaption>Framsida</figcaption>
|
||
</figure>
|
||
<figure>
|
||
<svg width="150" height="290" viewBox="0 0 100 195" role="img" aria-label="Kroppskarta baksida">
|
||
<circle cx="50" cy="12" r="9" fill="#233026"/>
|
||
<rect x="40" y="22" width="20" height="10" rx="4" fill="#5f8f60"/>
|
||
<rect x="34" y="33" width="32" height="22" rx="8" fill="#3d5c42"/>
|
||
<rect x="38" y="57" width="24" height="18" rx="7" fill="#233026"/>
|
||
<rect x="22" y="40" width="8" height="24" rx="4" fill="#3d5c42"/>
|
||
<rect x="70" y="40" width="8" height="24" rx="4" fill="#3d5c42"/>
|
||
<rect x="21" y="66" width="7" height="20" rx="3.5" fill="#233026"/>
|
||
<rect x="72" y="66" width="7" height="20" rx="3.5" fill="#233026"/>
|
||
<rect x="35" y="77" width="30" height="14" rx="6" fill="#233026"/>
|
||
<rect x="34" y="93" width="13" height="32" rx="6" fill="#233026"/>
|
||
<rect x="53" y="93" width="13" height="32" rx="6" fill="#233026"/>
|
||
<rect x="36" y="128" width="10" height="28" rx="5" fill="#3d5c42"/>
|
||
<rect x="54" y="128" width="10" height="28" rx="5" fill="#3d5c42"/>
|
||
</svg>
|
||
<figcaption>Baksida</figcaption>
|
||
</figure>
|
||
</div>
|
||
<div class="notes" style="justify-content:center">
|
||
<div class="note"><div class="dot">→</div><p><b>Färgskalan är volym i perioden</b>
|
||
— här syns direkt att bröst/underarmar fått mest och att ben & mage släpar.
|
||
Tryck på en muskel → övningarna och seten bakom siffran.</p></div>
|
||
<div class="heatlegend">Mindre
|
||
<i style="background:var(--heat0)"></i><i style="background:var(--heat1)"></i>
|
||
<i style="background:var(--heat2)"></i><i style="background:var(--heat3)"></i>
|
||
<i style="background:var(--heat4)"></i> Mer volym</div>
|
||
<div class="note" style="margin-top:10px"><div class="dot">✎</div><p>Figuren är
|
||
medvetet stiliserad (byggd av former, inte anatomisk) — den blir tydlig i litet
|
||
format, temafärgas och kräver inga bildlicenser. Vill du ha en mer anatomisk
|
||
siluett går det, men liten och skarp slår detaljerad och grötig på en telefon.</p></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ 6. NAVIGERING + API ============ -->
|
||
<section>
|
||
<div class="secnum">6 / 6</div>
|
||
<h2>Navigeringen — chrome runt tre lägen</h2>
|
||
<p class="secintro">Med passläge + minispelare behövs färre flikar än webben har:
|
||
<b>Hem · Historik · Statistik · Profil</b> med startknappen i mitten (förslag B
|
||
från förra rundan). PB och kroppskartan bor i Statistik, grunddata och
|
||
skivinställningar under Profil. Fritt pass, favoriter, widget och appgenvägar
|
||
gör att flikarna nästan aldrig behövs på väg <i>in</i> i ett pass — de är för
|
||
uppföljningen.</p>
|
||
|
||
<h2 style="margin-top:36px">Små API-tillägg som lyfter appen</h2>
|
||
<p class="secintro">Inget av detta blockerar bygget — appen kan falla tillbaka på
|
||
vettiga defaultvärden tills de finns.</p>
|
||
<div class="tablewrap"><table>
|
||
<tr><th>Tillägg</th><th>Vad det ger</th><th>Storlek</th></tr>
|
||
<tr><td>MuscleGroup.iconKey</td>
|
||
<td>Servern pekar ut vilken ikon en muskelgrupp har istället för att appen
|
||
gissar på namnsträngar ("Bröst" vs "Chest"). En kolumn + fält i GraphQL.</td>
|
||
<td><span class="pill-sm s">LITEN</span></td></tr>
|
||
<tr><td>ExerciseType.defaultRestSeconds</td>
|
||
<td>Auto-vilotimern vet hur länge just den övningen vilar (90 s bänk, 180 s
|
||
marklyft). Fallback i appen: 90 s. Kolumn + fält + med i mallexport.</td>
|
||
<td><span class="pill-sm s">LITEN</span></td></tr>
|
||
<tr><td>Lift/Set: clientId (UUID)</td>
|
||
<td>Offline-läge på gymmet: appen kan köa set lokalt och synka i efterhand utan
|
||
dubbletter när samma mutation skickas om. Unik kolumn + upsert-logik.</td>
|
||
<td><span class="pill-sm m">MEDEL · roadmap</span></td></tr>
|
||
<tr><td>ExerciseType.imageUrl</td>
|
||
<td>Frivillig påbyggnad om du senare vill ha riktiga foton/anatomibilder per
|
||
övning — appen visar dem när de finns, ikoner annars.</td>
|
||
<td><span class="pill-sm s">LITEN · valfri</span></td></tr>
|
||
</table></div>
|
||
|
||
<div class="decide">
|
||
<h2>Det jag behöver från dig</h2>
|
||
<ol>
|
||
<li><b>Passläget:</b> köper du "en övning i taget + svep + vilo-takeover", eller
|
||
vill du hellre se hela passet som scrollbar lista med allt synligt?</li>
|
||
<li><b>Muskelfiltret:</b> chips med ikoner (sektion 3) eller kroppskartan
|
||
(sektion 5) som väljare — eller båda (chips snabbt, karta bakom en knapp)?</li>
|
||
<li><b>Android-ytorna:</b> vilka vill du ha i första versionen — notistimer,
|
||
widget, appgenvägar, skivkalkylator? (Notistimern föreslår jag ingår direkt,
|
||
resten kan komma stegvis.)</li>
|
||
<li><b>API-tilläggen:</b> ok att jag gör iconKey + defaultRestSeconds i
|
||
gym-API:t (byggs och rullas ut via befintliga CI:t)?</li>
|
||
</ol>
|
||
</div>
|
||
</div>
|