Moving the current line up and down in Visual Studio using a keyboard shortcut

๐Ÿ“ฆ Key shortcuts
โœจ The Prompt Phrase
What keyboard shortcut moves the current line up or down in Visual Studio, depending on the arrow key you press?

 ~alt + (Air-up/air-down)~

๐Ÿ’ป Code Preview

๐Ÿ“ฆ All-in-One Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Moving the current line up and down in Visual Studio using a keyboard shortcut - Interactive Tutorial</title>
<style>
:root{
  --bg:#0b0b1a; --bg2:#14142b; --card:rgba(255,255,255,.06); --border:rgba(255,255,255,.14);
  --text:#e8e8f5; --muted:#a3a3c2; --purple:#8b5cf6; --blue:#3b82f6; --green:#22c55e; --pink:#ec4899;
  --grad:linear-gradient(135deg,var(--purple),var(--blue) 55%,var(--green));
  --code:#0a0a16; --shadow:0 20px 40px rgba(0,0,0,.35);
}
body.light{
  --bg:#f4f4ff; --bg2:#e8e8fb; --card:rgba(255,255,255,.75); --border:rgba(80,70,160,.2);
  --text:#1e1b3a; --muted:#55527a; --code:#1e1b3a; --shadow:0 20px 40px rgba(80,70,160,.15);
}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{font-family:'Segoe UI',system-ui,sans-serif;background:radial-gradient(circle at 20% 0%,var(--bg2),var(--bg) 60%);color:var(--text);line-height:1.7;min-height:100vh}
a{color:inherit}
.progress{position:fixed;top:0;left:0;height:5px;width:0;background:var(--grad);z-index:100;transition:width .2s}
nav{position:sticky;top:5px;z-index:50;display:flex;gap:6px;align-items:center;justify-content:center;flex-wrap:wrap;padding:10px;margin:10px auto;max-width:1000px;background:var(--card);backdrop-filter:blur(14px);border:1px solid var(--border);border-radius:18px}
nav a{text-decoration:none;font-size:.82rem;padding:6px 12px;border-radius:999px;color:var(--muted);transition:.2s}
nav a:hover,nav a:focus-visible{background:var(--grad);color:#fff;outline:none}
.icon-btn{background:var(--card);border:1px solid var(--border);color:var(--text);border-radius:999px;padding:6px 12px;cursor:pointer;font-size:.85rem}
main{max-width:900px;margin:0 auto;padding:0 18px 60px}
section{margin:34px 0}
.glass{background:var(--card);backdrop-filter:blur(14px);border:1px solid var(--border);border-radius:24px;padding:28px;box-shadow:var(--shadow)}
.reveal{opacity:0;transform:translateY(26px);transition:opacity .7s,transform .7s}
.reveal.show{opacity:1;transform:none}
h2{font-size:1.6rem;margin-bottom:14px}
h2 .grad,.grad{background:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent}
p{margin-bottom:12px}
/* hero */
.hero{text-align:center;padding:50px 20px 30px}
.hero h1{font-size:clamp(1.8rem,5vw,3rem);line-height:1.2;margin-bottom:16px}
.hero .sub{color:var(--muted);max-width:640px;margin:0 auto 22px}
.keys{display:flex;justify-content:center;gap:10px;align-items:center;flex-wrap:wrap;margin:22px 0}
kbd{display:inline-block;min-width:44px;text-align:center;padding:8px 16px;border-radius:10px;font-family:Consolas,monospace;font-weight:700;background:linear-gradient(#2b2b4d,#1b1b34);color:#fff;border:1px solid rgba(255,255,255,.25);border-bottom-width:4px;box-shadow:0 6px 14px rgba(0,0,0,.3)}
.keys kbd{animation:float 3s ease-in-out infinite}
.keys kbd:nth-child(3){animation-delay:.5s}
@keyframes float{50%{transform:translateY(-8px)}}
.plus{font-size:1.4rem;color:var(--muted)}
.badges{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;margin-top:18px}
.badge{padding:6px 14px;border-radius:999px;border:1px dashed var(--border);color:var(--muted);font-size:.85rem;filter:grayscale(1);opacity:.55;transition:.4s}
.badge.on{filter:none;opacity:1;color:#fff;background:var(--grad);border-style:solid;transform:scale(1.06)}
.btn{background:var(--grad);color:#fff;border:none;border-radius:12px;padding:10px 18px;font-weight:600;cursor:pointer;transition:.2s;font-size:.95rem}
.btn:hover{transform:translateY(-2px);box-shadow:0 8px 20px rgba(139,92,246,.4)}
.btn.ghost{background:var(--card);border:1px solid var(--border);color:var(--text)}
:focus-visible{outline:3px solid var(--green);outline-offset:2px}
/* quote */
.quote{border-left:4px solid var(--purple);padding:12px 16px;background:rgba(139,92,246,.12);border-radius:0 12px 12px 0;margin:12px 0}
.tip{border-bottom:1px dotted var(--green);cursor:help;position:relative}
.tip::after{content:attr(data-tip);position:absolute;left:50%;bottom:130%;transform:translateX(-50%);width:max-content;max-width:240px;background:#111;color:#fff;padding:8px 12px;border-radius:10px;font-size:.8rem;opacity:0;pointer-events:none;transition:.2s;z-index:10;line-height:1.4}
.tip:hover::after,.tip:focus::after{opacity:1}
ul.list{padding-left:20px}
ul.list li{margin-bottom:8px}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:14px}
.mini{background:var(--card);border:1px solid var(--border);border-radius:16px;padding:16px;transition:.25s}
.mini:hover{transform:translateY(-5px) rotate(-.5deg);border-color:var(--purple)}
.mini .e{font-size:1.8rem}
/* steps */
.steps{list-style:none;counter-reset:s}
.steps li{counter-increment:s;display:flex;gap:14px;margin-bottom:14px;align-items:flex-start;cursor:pointer;padding:10px;border-radius:14px;transition:.2s;border:1px solid transparent}
.steps li:hover{background:var(--card)}
.steps li::before{content:counter(s);flex:none;width:34px;height:34px;border-radius:50%;background:var(--grad);color:#fff;display:grid;place-items:center;font-weight:700}
.steps li.done{border-color:var(--green)}
.steps li.done::before{content:"โœ“";background:var(--green)}
/* demo */
.editor{background:var(--code);border-radius:16px;border:1px solid var(--border);padding:10px 0;font-family:Consolas,'Courier New',monospace;font-size:.95rem;color:#e6e6f5;outline:none;overflow:hidden}
.editor:focus{border-color:var(--green);box-shadow:0 0 0 3px rgba(34,197,94,.25)}
.line{display:flex;padding:3px 14px;cursor:pointer;transition:background .15s,transform .2s;white-space:pre}
.line .n{width:32px;color:#6b6b8f;flex:none;user-select:none}
.line.sel{background:rgba(139,92,246,.35);border-left:3px solid var(--green);padding-left:11px}
.line.moved{animation:pop .3s}
@keyframes pop{50%{transform:scale(1.02);background:rgba(34,197,94,.3)}}
.controls{display:flex;gap:10px;flex-wrap:wrap;margin-top:14px;align-items:center}
.status{margin-top:10px;color:var(--muted);font-size:.9rem;min-height:1.5em}
/* code */
.tabs{display:flex;gap:8px;margin-bottom:12px;flex-wrap:wrap}
.tab{background:var(--card);border:1px solid var(--border);color:var(--muted);padding:8px 14px;border-radius:12px;cursor:pointer}
.tab[aria-selected="true"]{background:var(--grad);color:#fff;border-color:transparent}
.codebox{position:relative;background:var(--code);border-radius:16px;padding:18px;font-family:Consolas,monospace;font-size:.92rem;overflow-x:auto;color:#e6e6f5;white-space:pre;border:1px solid var(--border)}
.k{color:#c4a5ff}.s{color:#7ee787}.c{color:#7c7ca3;font-style:italic}.t{color:#79c0ff}.hl{background:rgba(236,72,153,.25);border-radius:4px;padding:0 4px}
.copy{position:absolute;top:10px;right:10px;font-size:.78rem;padding:5px 10px}
.anno{margin-top:12px;padding:12px 16px;border-radius:12px;background:rgba(59,130,246,.12);border:1px solid rgba(59,130,246,.3);white-space:normal;font-family:'Segoe UI',sans-serif}
/* accordion */
details{background:var(--card);border:1px solid var(--border);border-radius:16px;margin-bottom:10px;overflow:hidden}
summary{cursor:pointer;padding:14px 18px;font-weight:600;list-style:none}
summary::-webkit-details-marker{display:none}
summary::after{content:"๏ผ‹";float:right;color:var(--green)}
details[open] summary::after{content:"๏ผ"}
details .body{padding:0 18px 14px}
.bad{color:#fb7185}.good{color:var(--green)}
/* quiz */
.q{margin-bottom:22px}
.opts{display:grid;gap:8px;margin-top:10px}
.opt{text-align:left;background:var(--card);border:1px solid var(--border);color:var(--text);padding:12px 14px;border-radius:12px;cursor:pointer;font-size:.95rem;transition:.2s}
.opt:hover:not(:disabled){border-color:var(--purple);transform:translateX(4px)}
.opt.right{background:rgba(34,197,94,.25);border-color:var(--green)}
.opt.wrong{background:rgba(251,113,133,.2);border-color:#fb7185;animation:shake .35s}
@keyframes shake{25%{transform:translateX(-6px)}75%{transform:translateX(6px)}}
.fb{margin-top:8px;min-height:1.5em;font-size:.9rem}
.score{font-weight:700;font-size:1.1rem}
/* cheat */
.cheat{border:2px solid transparent;background:linear-gradient(var(--bg2),var(--bg2)) padding-box,var(--grad) border-box}
body.light .cheat{background:linear-gradient(#fff,#fff) padding-box,var(--grad) border-box}
table{width:100%;border-collapse:collapse;margin-top:10px}
td,th{padding:10px;border-bottom:1px solid var(--border);text-align:left;font-size:.92rem}
footer{text-align:center;color:var(--muted);padding:30px 18px 50px;font-size:.9rem}
.confetti{position:fixed;top:-20px;font-size:1.4rem;pointer-events:none;z-index:200;animation:fall linear forwards}
@keyframes fall{to{transform:translateY(110vh) rotate(720deg);opacity:.8}}
@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}.reveal{opacity:1;transform:none}}
@media(max-width:600px){.glass{padding:18px}}
</style>
</head>
<body>
<div class="progress" id="progress" role="progressbar" aria-label="Reading progress" aria-valuemin="0" aria-valuemax="100"></div>

<nav aria-label="Tutorial sections">
  <a href="#what">What</a><a href="#why">Why</a><a href="#how">How</a><a href="#demo">Demo</a>
  <a href="#code">Code</a><a href="#mistakes">Mistakes</a><a href="#tips">Tips</a><a href="#quiz">Quiz</a><a href="#summary">Cheat Sheet</a>
  <button class="icon-btn" id="theme" aria-label="Toggle dark or light theme">๐ŸŒ™ / โ˜€๏ธ</button>
</nav>

<main>
  <!-- 1. HERO -->
  <header class="hero reveal" id="top">
    <p>๐ŸŽฎ Level 1 ยท Beginner ยท ~7 minutes</p>
    <h1><span class="grad">Moving the current line up and down in Visual Studio</span> using a keyboard shortcut</h1>
    <p class="sub">Imagine you could pick up a line of code like a Lego brick and slide it anywhere, with no cutting and no pasting. โœจ Let's learn the trick.</p>
    <div class="keys" aria-label="Alt plus Up Arrow or Down Arrow">
      <kbd>Alt</kbd><span class="plus">+</span><kbd>โ†‘</kbd><span class="plus">/</span><kbd>โ†“</kbd>
    </div>
    <div class="quote"><strong>Question:</strong> What keyboard shortcut moves the current line up or down in Visual Studio, depending on the arrow key you press?<br><strong>Answer:</strong> <code>Alt + โ†‘ / โ†“</code> (Alt plus the Up or Down <em>Arrow</em> key).</div>
    <div class="badges" aria-live="polite">
      <span class="badge" id="b1">๐Ÿ” Explorer</span>
      <span class="badge" id="b2">๐Ÿ•น๏ธ Line Mover</span>
      <span class="badge" id="b3">๐Ÿง  Quiz Master</span>
      <span class="badge" id="b4">๐Ÿ† Shortcut Hero</span>
    </div>
  </header>

  <!-- 2. WHAT -->
  <section id="what" class="glass reveal">
    <h2>๐Ÿค” What Is It?</h2>
    <p>Once upon a time, a young coder named Sam wanted to move one line of code above another. Sam selected it, pressed <kbd>Ctrl</kbd>+<kbd>X</kbd>, clicked somewhere else, and pressed <kbd>Ctrl</kbd>+<kbd>V</kbd>. It took forever. ๐Ÿ˜ฉ</p>
    <p>Then Sam discovered the shortcut:</p>
    <ul class="list">
      <li><kbd>Alt</kbd> + <kbd>โ†‘</kbd> moves the line your <span class="tip" tabindex="0" data-tip="The blinking vertical bar that shows where you are typing.">cursor</span> is on <strong>up</strong>.</li>
      <li><kbd>Alt</kbd> + <kbd>โ†“</kbd> moves the line <strong>down</strong>.</li>
    </ul>
    <p>The line goes up or down depending on which <span class="tip" tabindex="0" data-tip="The keys with arrows on your keyboard, usually near the bottom right.">arrow key</span> you press. In Visual Studio this command is named <code>Edit.MoveSelectedLinesUp</code> or <code>Edit.MoveSelectedLinesDown</code>.</p>
    <p><em>Note:</em> some people write "Air-up" or "Air-down" by mistake. The word is <strong>Arrow</strong>. ๐Ÿน</p>
  </section>

  <!-- 3. WHY -->
  <section id="why" class="glass reveal">
    <h2>๐Ÿš€ Why Use It?</h2>
    <div class="grid">
      <div class="mini"><div class="e">โšก</div><strong>Fast</strong><p>One quick key combo instead of cut, click, and paste.</p></div>
      <div class="mini"><div class="e">๐ŸŽฏ</div><strong>Precise</strong><p>The line moves one row at a time, so you can't paste in the wrong place.</p></div>
      <div class="mini"><div class="e">๐Ÿ“‹</div><strong>Clipboard-safe</strong><p>It doesn't touch your clipboard, so whatever you copied earlier is still there.</p></div>
      <div class="mini"><div class="e">๐Ÿงน</div><strong>Great for tidying</strong><p>Reorder <code>using</code> statements, list items, or the order of steps.</p></div>
    </div>
  </section>

  <!-- 4. HOW -->
  <section id="how" class="glass reveal">
    <h2>๐Ÿ› ๏ธ How Does It Work?</h2>
    <p>Click each step as you read it. โœ…</p>
    <ol class="steps" id="steps">
      <li><div><strong>Open a file</strong> in the Visual Studio code editor.</div></li>
      <li><div><strong>Click on any line</strong> to place the cursor there. You don't need to select the whole line.</div></li>
      <li><div><strong>Hold <kbd>Alt</kbd></strong> with your left thumb.</div></li>
      <li><div><strong>Tap <kbd>โ†‘</kbd> or <kbd>โ†“</kbd></strong>. The line swaps places with its neighbor.</div></li>
      <li><div><strong>Keep tapping</strong> to move it further. ๐ŸŽข Select several lines first and the whole block moves together.</div></li>
    </ol>
  </section>

  <!-- 5. DEMO -->
  <section id="demo" class="glass reveal">
    <h2>๐Ÿ•น๏ธ Live Demo: Try It!</h2>
    <p>Click a line to select it. Then click the editor and press <kbd>Alt</kbd>+<kbd>โ†‘</kbd> / <kbd>โ†“</kbd> on your keyboard, or use the buttons below. Put the lines in the right order: <strong>1, 2, 3, Go!</strong> ๐Ÿ</p>
    <div class="editor" id="editor" tabindex="0" role="application" aria-label="Practice editor. Select a line and press Alt plus Up or Down arrow to move it."></div>
    <div class="controls">
      <button class="btn" id="up">โฌ†๏ธ Alt + โ†‘</button>
      <button class="btn" id="down">โฌ‡๏ธ Alt + โ†“</button>
      <button class="btn ghost" id="reset">๐Ÿ”„ Shuffle</button>
      <span id="moves" aria-live="polite">Moves: 0</span>
    </div>
    <div class="status" id="status" aria-live="polite">Click a line to start.</div>
  </section>

  <!-- 6. CODE -->
  <section id="code" class="glass reveal">
    <h2>๐Ÿงฉ Code Breakdown</h2>
    <div class="tabs" role="tablist" aria-label="Examples">
      <button class="tab" role="tab" aria-selected="true" data-i="0">Single line</button>
      <button class="tab" role="tab" aria-selected="false" data-i="1">Many lines</button>
      <button class="tab" role="tab" aria-selected="false" data-i="2">Inside a method</button>
    </div>
    <div class="codebox" id="codebox" role="tabpanel"></div>
    <div class="anno" id="anno"></div>
  </section>

  <!-- 7. MISTAKES -->
  <section id="mistakes" class="glass reveal">
    <h2>โš ๏ธ Common Mistakes</h2>
    <details open><summary>โŒ Using Ctrl or Shift instead of Alt</summary><div class="body">
      <p><span class="bad">Wrong:</span> <kbd>Ctrl</kbd>+<kbd>โ†‘</kbd> only scrolls the view. <kbd>Shift</kbd>+<kbd>โ†‘</kbd> selects text.</p>
      <p><span class="good">Right:</span> <kbd>Alt</kbd>+<kbd>โ†‘</kbd>/<kbd>โ†“</kbd>.</p></div></details>
    <details><summary>โŒ Writing "Air" instead of "Arrow"</summary><div class="body"><p>It's an <strong>arrow</strong> key. Searching for "air-up" won't help you. ๐Ÿ˜„</p></div></details>
    <details><summary>โŒ Expecting it to work while the focus is elsewhere</summary><div class="body"><p>Click inside the code editor first. If the focus is in the Solution Explorer or the Output window, nothing will move.</p></div></details>
    <details><summary>โŒ Thinking it copies the line</summary><div class="body"><p>It <em>moves</em> the line. It doesn't duplicate it. To duplicate a line in Visual Studio 2022, try <kbd>Ctrl</kbd>+<kbd>D</kbd>.</p></div></details>
    <details><summary>โŒ Moving code out of its brackets by accident</summary><div class="body"><p>A line can move across <code>{ }</code> boundaries. Check that your code still makes sense, and press <kbd>Ctrl</kbd>+<kbd>Z</kbd> to undo.</p></div></details>
  </section>

  <!-- 8. TIPS -->
  <section id="tips" class="glass reveal">
    <h2>๐Ÿ’Ž Pro Tips</h2>
    <ul class="list">
      <li>๐Ÿงฑ <strong>Select multiple lines</strong> (<kbd>Shift</kbd>+<kbd>โ†‘</kbd>/<kbd>โ†“</kbd>), then use <kbd>Alt</kbd>+<kbd>โ†‘</kbd>/<kbd>โ†“</kbd> to move the whole block.</li>
      <li>โ†ฉ๏ธ <strong>Made a mess?</strong> <kbd>Ctrl</kbd>+<kbd>Z</kbd> undoes the move.</li>
      <li>โš™๏ธ <strong>Shortcut not working?</strong> Open <em>Tools โ†’ Options โ†’ Environment โ†’ Keyboard</em> and search for <code>MoveSelectedLines</code>.</li>
      <li>๐Ÿ†š <strong>Using VS Code?</strong> It uses the same <kbd>Alt</kbd>+<kbd>โ†‘</kbd>/<kbd>โ†“</kbd> shortcut. <kbd>Shift</kbd>+<kbd>Alt</kbd>+<kbd>โ†“</kbd> copies a line down there.</li>
      <li>๐ŸŽ <strong>On a Mac?</strong> Visual Studio Code uses <kbd>Option</kbd> in place of Alt.</li>
    </ul>
  </section>

  <!-- 9. QUIZ -->
  <section id="quiz" class="glass reveal">
    <h2>๐Ÿง  Practice Quiz</h2>
    <p class="score" id="score">Score: 0 / 3</p>
    <div id="quizBox"></div>
  </section>

  <!-- 10. SUMMARY -->
  <section id="summary" class="glass cheat reveal">
    <h2>๐Ÿ“Œ Summary Card</h2>
    <table>
      <tr><th>Goal</th><th>Shortcut</th></tr>
      <tr><td>Move current line up</td><td><kbd>Alt</kbd> + <kbd>โ†‘</kbd></td></tr>
      <tr><td>Move current line down</td><td><kbd>Alt</kbd> + <kbd>โ†“</kbd></td></tr>
      <tr><td>Move several lines</td><td>Select them, then <kbd>Alt</kbd> + <kbd>โ†‘</kbd>/<kbd>โ†“</kbd></td></tr>
      <tr><td>Undo a move</td><td><kbd>Ctrl</kbd> + <kbd>Z</kbd></td></tr>
    </table>
    <div class="controls"><button class="btn" id="copySummary">๐Ÿ“‹ Copy cheat sheet</button></div>
  </section>
</main>

<footer>Made with ๐Ÿ’œ ยท Generated by <strong>AI Prompt Dictionary</strong><br>Keep practicing. Every pro was once a beginner! ๐ŸŒŸ</footer>

<script>
(function(){
  var $=function(s){return document.querySelector(s)}, $$=function(s){return Array.prototype.slice.call(document.querySelectorAll(s))};
  var earned={};
  function badge(id){ if(earned[id])return; earned[id]=1; $('#'+id).classList.add('on'); if(Object.keys(earned).length===3) badge('b4'); }

  /* theme */
  $('#theme').onclick=function(){document.body.classList.toggle('light')};

  /* scroll progress + reveal */
  function onScroll(){
    var h=document.documentElement, p=h.scrollTop/(h.scrollHeight-h.clientHeight)*100||0;
    $('#progress').style.width=p+'%'; $('#progress').setAttribute('aria-valuenow',Math.round(p));
  }
  window.addEventListener('scroll',onScroll,{passive:true}); onScroll();
  var io=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting)e.target.classList.add('show')})},{threshold:.1});
  $$('.reveal').forEach(function(el){io.observe(el)});

  /* confetti */
  function confetti(){
    var em=['๐ŸŽ‰','โœจ','๐Ÿ’œ','๐Ÿ’š','โญ','๐ŸŽŠ'];
    for(var i=0;i<40;i++){
      var s=document.createElement('span'); s.className='confetti'; s.textContent=em[i%em.length];
      s.style.left=Math.random()*100+'vw'; s.style.animationDuration=(2+Math.random()*2)+'s'; s.style.animationDelay=Math.random()*.5+'s';
      document.body.appendChild(s); setTimeout(function(x){x.remove()},4800,s);
    }
  }

  /* steps */
  $$('#steps li').forEach(function(li){
    li.tabIndex=0;
    function t(){li.classList.toggle('done'); if($$('#steps li.done').length===5)badge('b1')}
    li.onclick=t; li.onkeydown=function(e){if(e.key==='Enter'||e.key===' '){e.preventDefault();t()}};
  });

  /* demo */
  var goal=['1','2','3','Go!'];
  var lines, sel=-1, moves=0, solvedOnce=false;
  var ed=$('#editor');
  function shuffle(){
    do{lines=goal.slice().sort(function(){return Math.random()-.5})}while(lines.join()===goal.join());
    sel=-1; moves=0; render(); $('#status').textContent='Click a line to start.';
  }
  function render(movedIdx){
    ed.innerHTML='';
    lines.forEach(function(t,i){
      var d=document.createElement('div'); d.className='line'+(i===sel?' sel':'')+(i===movedIdx?' moved':'');
      d.innerHTML='<span class="n">'+(i+1)+'</span>';
      d.appendChild(document.createTextNode('Console.WriteLine("'+t+'");'));
      d.onclick=function(){sel=i;render();ed.focus()};
      ed.appendChild(d);
    });
    $('#moves').textContent='Moves: '+moves;
  }
  function move(dir){
    if(sel<0){$('#status').textContent='๐Ÿ‘† Click a line first!';return}
    var j=sel+dir;
    if(j<0||j>=lines.length){$('#status').textContent='๐Ÿšง Can\'t go further that way.';return}
    var tmp=lines[sel]; lines[sel]=lines[j]; lines[j]=tmp; sel=j; moves++;
    render(sel); badge('b2');
    if(lines.join()===goal.join()){
      $('#status').textContent='๐ŸŽ‰ Perfect order in '+moves+' moves!'; if(!solvedOnce){solvedOnce=true;confetti()}
    } else $('#status').textContent='Nice! Line moved '+(dir<0?'up โฌ†๏ธ':'down โฌ‡๏ธ')+'.';
  }
  ed.addEventListener('keydown',function(e){
    if(e.altKey&&(e.key==='ArrowUp'||e.key==='ArrowDown')){e.preventDefault();move(e.key==='ArrowUp'?-1:1)}
    else if(e.key==='ArrowUp'&&sel>0){e.preventDefault();sel--;render()}
    else if(e.key==='ArrowDown'&&sel>=0&&sel<lines.length-1){e.preventDefault();sel++;render()}
  });
  $('#up').onclick=function(){move(-1)}; $('#down').onclick=function(){move(1)};
  $('#reset').onclick=function(){solvedOnce=false;shuffle()};
  shuffle();

  /* code tabs */
  var ex=[
    {code:'<span class="c">// Cursor is on the line marked below</span>\n<span class="t">int</span> a = <span class="s">1</span>;\n<span class="hl"><span class="t">int</span> b = <span class="s">2</span>;</span>   <span class="c">&larr; press Alt + &uarr;</span>\n<span class="t">int</span> c = <span class="s">3</span>;',
     note:'๐Ÿ” <strong>Alt</strong> is the modifier key and <strong>โ†‘</strong> is the direction. After the press, <code>int b = 2;</code> sits above <code>int a = 1;</code>. Only the two lines swap, and nothing else changes.'},
    {code:'<span class="c">// Select both lines with Shift + โ†“</span>\n<span class="hl"><span class="k">var</span> x = <span class="s">10</span>;\n<span class="k">var</span> y = <span class="s">20</span>;</span>\n<span class="k">var</span> z = <span class="s">30</span>;   <span class="c">&larr; Alt + &darr; moves the block past this line</span>',
     note:'๐Ÿงฑ With several lines selected, the whole block moves as one piece. It jumps over the line next to it.'},
    {code:'<span class="t">void</span> Greet()\n{\n    Console.WriteLine(<span class="s">"Hello"</span>);\n<span class="hl">    Console.WriteLine(<span class="s">"Welcome!"</span>);</span>  <span class="c">&larr; Alt + &uarr;</span>\n}',
     note:'๐Ÿ›ก๏ธ The line stays inside the braces <code>{ }</code>. Moving it past a brace would change which block it belongs to, so read your code after you move it.'}
  ];
  function showEx(i){
    $$('.tab').forEach(function(t){t.setAttribute('aria-selected',t.dataset.i==i)});
    $('#codebox').innerHTML='<button class="btn ghost copy" id="copyCode">Copy</button>'+ex[i].code;
    $('#anno').innerHTML=ex[i].note;
    $('#copyCode').onclick=function(){
      var tmp=document.createElement('div'); tmp.innerHTML=ex[i].code; copy(tmp.textContent,this);
    };
  }
  $$('.tab').forEach(function(t){t.onclick=function(){showEx(+t.dataset.i)}}); showEx(0);

  function copy(text,btn){
    function ok(){var o=btn.textContent;btn.textContent='Copied โœ“';setTimeout(function(){btn.textContent=o},1400)}
    if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(text).then(ok,function(){fb()})}else fb();
    function fb(){var a=document.createElement('textarea');a.value=text;document.body.appendChild(a);a.select();document.execCommand('copy');a.remove();ok()}
  }
  $('#copySummary').onclick=function(){
    copy('Visual Studio: Alt + Up Arrow = move line up | Alt + Down Arrow = move line down | Ctrl + Z = undo',this);
  };

  /* quiz */
  var quiz=[
    {q:'Which shortcut moves the current line UP in Visual Studio?',o:['Ctrl + โ†‘','Alt + โ†‘','Shift + โ†‘','Tab + โ†‘'],a:1,w:'Alt + โ†‘ moves the line up. Ctrl + โ†‘ just scrolls, and Shift + โ†‘ selects.'},
    {q:'You press Alt + โ†“. What happens to the line under your cursor?',o:['It is deleted','It is copied below','It moves down one row','Nothing, you need to select it first'],a:2,w:'It moves down one row. No selection is needed.'},
    {q:'Does the move shortcut change what is stored in your clipboard?',o:['Yes, it cuts the line','Yes, it copies the line','No, the clipboard is untouched'],a:2,w:'The move shortcut never uses the clipboard.'}
  ];
  var score=0,answered=0,box=$('#quizBox');
  quiz.forEach(function(item,qi){
    var d=document.createElement('div'); d.className='q';
    d.innerHTML='<strong>'+(qi+1)+'. '+item.q+'</strong><div class="opts"></div><div class="fb" aria-live="polite"></div>';
    var opts=d.querySelector('.opts'),fb=d.querySelector('.fb');
    item.o.forEach(function(txt,oi){
      var b=document.createElement('button'); b.className='opt'; b.textContent=txt;
      b.onclick=function(){
        var all=opts.querySelectorAll('.opt');
        if(oi===item.a){
          b.classList.add('right'); fb.textContent='โœ… Correct! Great job!'; score++; confetti();
          all.forEach(function(x){x.disabled=true}); answered++; finish();
        } else {
          b.classList.add('wrong'); b.disabled=true; fb.textContent='โŒ Not quite. Try again! ๐Ÿ’ช Hint: '+item.w;
        }
        $('#score').textContent='Score: '+score+' / 3';
      };
      opts.appendChild(b);
    });
    box.appendChild(d);
  });
  function finish(){
    if(answered===3){
      badge('b3');
      var m=document.createElement('p'); m.className='score grad'; m.textContent='๐Ÿ† Quiz complete! You are ready to move lines like a pro!';
      box.appendChild(m);
    }
  }
})();
</script>
</body>
</html>
Live Preview