Article 75QMW The ultimate tool for playing GM and building a Cowboys roster

The ultimate tool for playing GM and building a Cowboys roster

by
from on (#75QMW)
7b53a46be99d06a0d3d3f12dd7ab4d80A chess board.

Many of us take great pleasure in playing GM, constructing our own roster, and making calls on who stays and who goes. Now, you can do just that with our 2026 Dallas Cowboys Roster Builder.

With the tool embedded below, whittle down the roster from 90 to 53 players, build a practice squad, change player positions, see the dead money pile up, agonize over the last cuts, and have fun doing it!

And then delete it and start over again. And again. And again.

Here's how it works:

  • You can cut players by dragging them into the red Cut Players" box at the bottom. The dead money tally at the bottom tells you how much dead money you have accrued with your cuts.
  • You can also move up to 16 players to the practice squad by dragging them to the practice squad box at the bottom of the tool. Technically, you're allowed a maximum of six veterans on the PS, but the tool will let you place whoever you want on the PS.
  • The player count gives you an always up-to-date number of players you still have on the roster.
  • You don't like the pre-configured ranking of the players in the position groups? Simply drag and drop them until you have them in the order you like.
  • You think some players are listed in the wrong position groups? You can change that as well. Within the secondary (S/CB/NB), the front seven (ILB/Edge/DT), and the O-Line (OT/G/C) you can move players around as you see fit, but you won't ever be able to make a wide receiver out of a running back.
  • DT Adedayo Odeleye is an IPP player with roster exemptions: If you keep him on the roster, you're allowed 54 players in total, if you put him on the practice squad, you're allowed 17 players in total on the PS.
  • If you click on the View Roster Snapshot" Button, you'll open an extra window with a clean version of your roster on one page.

You'll find that the cuts get progressively tougher, and that you'll have to make some really hard choices as you get to your final three or four cuts.

Discuss your choices in the comments section below and let us know who ended up being your hardest cuts.

Have fun!

Cowboys 2026 - Build Your 53 :root { --navy: #09243F; --silver: #869397; --silver-light: #c8d0d4; --white: #ffffff; --cut-border: #4a4a6a; --green: #1a7a3a; --green-light: #d4edda; --red: #c0392b; --red-light: #fde8e6; --col-default: #e8ecee; --col-default-text: #1a1a1a; --col-fa: #cce0f5; --col-fa-text: #09243F; --col-draft: #c8ecd4; --col-draft-text: #1a5c2a; --col-udfa: #fef9c3; --col-udfa-text: #7a5f00; } *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: 'DM Sans', sans-serif; background: #0d1117; color: var(--white); min-height: 100vh; user-select: none; } /* HEADER */ header { background: var(--navy); border-bottom: 3px solid #b8a04a; padding: 14px 24px; display: flex; align-items: center; gap: 20px; position: sticky; top: 0; z-index: 100; } /* Star is always white */ .star-logo { width: 44px; height: 44px; background: #ffffff; flex-shrink: 0; clip-path: polygon(50% 0%,61% 35%,98% 35%,68% 57%,79% 91%,50% 70%,21% 91%,32% 57%,2% 35%,39% 35%); } header h1 { font-family: 'Bebas Neue', sans-serif; font-size: 1.7rem; letter-spacing: 2px; line-height: 1; } header h1 span { color: #b8a04a; } .header-sub { font-size: 0.7rem; color: var(--silver-light); letter-spacing: 1px; text-transform: uppercase; } .legend { display: flex; gap: 14px; margin-left: auto; align-items: center; flex-wrap: wrap; } .legend-item { display: flex; align-items: center; gap: 5px; font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.5px; color: var(--silver-light); } .legend-swatch { width: 13px; height: 13px; border-radius: 3px; border: 1px solid rgba(255,255,255,0.2); } /* LAYOUT */ .app-body { display: grid; grid-template-columns: 1fr 1fr; gap: 0; height: calc(100vh - 75px); } .panel { display: flex; flex-direction: column; border: 1px solid rgba(255,255,255,0.06); overflow: hidden; } .panel-header { background: rgba(255,255,255,0.04); border-bottom: 1px solid rgba(255,255,255,0.08); padding: 8px 14px; display: flex; align-items: center; gap: 10px; } .panel-title { font-family: 'Bebas Neue', sans-serif; font-size: 0.95rem; letter-spacing: 2px; color: #b8a04a; } .panel-count { margin-left: auto; font-size: 0.7rem; color: var(--silver); background: rgba(255,255,255,0.06); padding: 2px 8px; border-radius: 20px; } .panel-body { flex: 1; overflow-y: auto; padding: 10px; scrollbar-width: thin; scrollbar-color: rgba(255,255,255,0.15) transparent; } .panel-body::-webkit-scrollbar { width: 4px; } .panel-body::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.15); border-radius: 2px; } /* POSITION GROUPS */ .pos-group { margin-bottom: 8px; } .pos-label { font-family: 'Bebas Neue', sans-serif; font-size: 0.75rem; letter-spacing: 2px; color: var(--silver); padding: 3px 0; border-bottom: 1px solid rgba(255,255,255,0.08); margin-bottom: 3px; } .pos-drop-zone { min-height: 28px; border-radius: 5px; transition: background 0.2s; } .pos-drop-zone.drag-over { background: rgba(9,36,63,0.35); outline: 2px dashed rgba(9,36,63,0.7); } /* PLAYER CHIP */ .player { display: flex; align-items: center; gap: 7px; padding: 4px 7px; border-radius: 5px; margin-bottom: 2px; cursor: grab; transition: transform 0.15s, opacity 0.2s; border: 1px solid rgba(0,0,0,0.1); font-size: 0.78rem; font-weight: 500; position: relative; } .player:active { cursor: grabbing; } .player.dragging { opacity: 0.3; transform: scale(0.97); } .player.drag-ghost { opacity: 0.95; box-shadow: 0 8px 24px rgba(0,0,0,0.5); transform: rotate(1.5deg) scale(1.04); pointer-events: none; } .player:hover { transform: translateX(2px); } .cat-default { background: var(--col-default); color: var(--col-default-text); } .cat-fa { background: var(--col-fa); color: var(--col-fa-text); } .cat-draft { background: var(--col-draft); color: var(--col-draft-text); } .cat-udfa { background: var(--col-udfa); color: var(--col-udfa-text); } .player-pos-badge { font-family: 'Bebas Neue', sans-serif; font-size: 0.62rem; letter-spacing: 1px; color: rgba(0,0,0,0.35); min-width: 26px; } .player-name { flex: 1; } .drag-handle { color: rgba(0,0,0,0.2); font-size: 0.75rem; } /* TOOLTIP */ .tooltip { display: none; position: fixed; z-index: 9998; background: #1a1f2e; border: 1px solid rgba(184,160,74,0.4); border-radius: 8px; padding: 10px 12px; width: 240px; box-shadow: 0 8px 24px rgba(0,0,0,0.6); pointer-events: none; } .tooltip.visible { display: block; } .tooltip-name { font-family: 'Bebas Neue', sans-serif; font-size: 0.9rem; letter-spacing: 1.5px; color: #b8a04a; border-bottom: 1px solid rgba(255,255,255,0.08); padding-bottom: 5px; margin-bottom: 7px; } .tooltip-section { margin-bottom: 6px; } .tooltip-section:last-child { margin-bottom: 0; } .tooltip-label { font-size: 0.6rem; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; margin-bottom: 2px; } .tooltip-label.keep { color: #4caf7d; } .tooltip-label.cut { color: #e87060; } .tooltip-text { font-size: 0.72rem; color: #c8d0d4; line-height: 1.4; } /* DROP / CUT ZONES */ .cut-zone { min-height: 36px; border: 2px dashed var(--cut-border); border-radius: 7px; padding: 6px; display: flex; flex-direction: column; gap: 2px; transition: border-color 0.2s, background 0.2s; } .cut-zone.drag-over { border-color: var(--red); background: rgba(192,57,43,0.08); } .cut-zone .player { background: rgba(255,255,255,0.06); color: var(--silver-light); border-color: rgba(255,255,255,0.1); } .cut-placeholder { text-align: center; color: var(--cut-border); font-size: 0.7rem; padding: 8px; pointer-events: none; } /* BOTTOM ROW: 3 columns - ST | Practice Squad | Cut */ .bottom-row { grid-column: 1 / -1; display: grid; grid-template-columns: 1fr 1fr 1fr; border-top: 2px solid #b8a04a; height: 260px; } .bottom-row .panel { overflow: hidden; min-width: 0; } .bottom-row .panel-body { overflow-y: auto; height: calc(100% - 37px); } .bottom-row .cut-zone { min-height: 50px; } .st-row { display: flex; flex-direction: column; gap: 2px; } /* ROSTER COUNTER BAR */ .roster-counter { display: flex; align-items: center; gap: 12px; padding: 7px 16px; background: rgba(255,255,255,0.03); border-top: 1px solid rgba(255,255,255,0.08); justify-content: center; flex-wrap: wrap; } .counter-label { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 1px; color: var(--silver); } .counter-badge { font-family: 'Bebas Neue', sans-serif; font-size: 1.5rem; padding: 2px 16px; border-radius: 7px; transition: background 0.4s, color 0.4s; min-width: 60px; text-align: center; } .counter-badge.green { background: var(--green-light); color: var(--green); } .counter-badge.red { background: var(--red-light); color: var(--red); } .counter-hint { font-size: 0.68rem; color: var(--silver); } .dead-cap-row { width: 100%; display: flex; align-items: center; justify-content: center; gap: 10px; padding-top: 4px; border-top: 1px solid rgba(255,255,255,0.05); margin-top: 2px; } .dead-cap-label { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 1px; color: var(--silver); } .snapshot-btn { margin-left: 20px; background: #b8a04a; color: #0a0a0a; border: none; padding: 6px 16px; border-radius: 6px; font-family: 'Bebas Neue', sans-serif; font-size: 0.95rem; letter-spacing: 1.5px; cursor: pointer; transition: background 0.2s; } .snapshot-btn:hover { background: #d4b85a; } /* DEAD MONEY */ .dead-money-label { font-size: 0.6rem; font-weight: 700; color: #c0392b; white-space: nowrap; letter-spacing: 0.3px; margin-left: 2px; } .cat-default .dead-money-label { color: #c0392b; } .cat-fa .dead-money-label { color: #c0392b; } .cat-draft .dead-money-label { color: #c0392b; } .cat-udfa .dead-money-label { color: #9b2820; } .cut-zone .dead-money-label { color: #e87060; } .dead-badge { font-family: 'Bebas Neue', sans-serif; font-size: 1.5rem; padding: 2px 14px; border-radius: 7px; min-width: 80px; text-align: center; transition: background 0.4s, color 0.4s; } .dead-badge.none { background: rgba(255,255,255,0.06); color: var(--silver); } .dead-badge.some { background: var(--red-light); color: var(--red); } @media (max-width: 900px) { .app-body { grid-template-columns: 1fr; height: auto; } .bottom-row { grid-template-columns: 1fr; grid-template-rows: auto auto auto; height: auto; } } Dallas Cowboys 2026Build Your 53-Man RosterReturningFree Agent / TradeDraft PickUDFARed = Dead Money if Cut Offense- Defense- Special Teams Practice Squad0 / 16Drag here (max 10) Cut Players0 cutDrag players here to cutActive Roster90/ 53 target - green when at limit (54 if Odeleye on roster) View Roster Snapshot Total Accrued Dead Money:$0 Why Keep Why Cut// DATA const ROSTER = [ {name:'Dak Prescott', pos:'QB', zone:'offense', cluster:'QB', cat:'default'}, {name:'Joe Milton III', pos:'QB', zone:'offense', cluster:'QB', cat:'default'}, {name:'Sam Howell', pos:'QB', zone:'offense', cluster:'QB', cat:'fa'}, {name:'Javonte Williams', pos:'RB', zone:'offense', cluster:'RB', cat:'default'}, {name:'Hunter Luepke', pos:'FB', zone:'offense', cluster:'RB', cat:'default'}, {name:'Malik Davis', pos:'RB', zone:'offense', cluster:'RB', cat:'default'}, {name:'Jaydon Blue', pos:'RB', zone:'offense', cluster:'RB', cat:'default'}, {name:'Phil Mafah', pos:'RB', zone:'offense', cluster:'RB', cat:'default'}, {name:'Israel Abanikanda', pos:'RB', zone:'offense', cluster:'RB', cat:'default'}, {name:'Dominic Richardson', pos:'RB', zone:'offense', cluster:'RB', cat:'udfa'}, {name:'CeeDee Lamb', pos:'WR', zone:'offense', cluster:'WR', cat:'default'}, {name:'George Pickens', pos:'WR', zone:'offense', cluster:'WR', cat:'default'}, {name:'Ryan Flournoy', pos:'WR', zone:'offense', cluster:'WR', cat:'default'}, {name:'KaVontae Turpin', pos:'WR', zone:'offense', cluster:'WR', cat:'default'}, {name:'Jonathan Mingo', pos:'WR', zone:'offense', cluster:'WR', cat:'default'}, {name:'Anthony Smith', pos:'WR', zone:'offense', cluster:'WR', cat:'draft'}, {name:'Traeshon Holden', pos:'WR', zone:'offense', cluster:'WR', cat:'default'}, {name:'Marquez Valdes-Scantling', pos:'WR', zone:'offense', cluster:'WR', cat:'fa'}, {name:'Tyler Johnson', pos:'WR', zone:'offense', cluster:'WR', cat:'fa'}, {name:'Parris Campbell', pos:'WR', zone:'offense', cluster:'WR', cat:'default'}, {name:'Camden Brown', pos:'WR', zone:'offense', cluster:'WR', cat:'udfa'}, {name:'Jordan Hudson', pos:'WR', zone:'offense', cluster:'WR', cat:'udfa'}, {name:'Jake Ferguson', pos:'TE', zone:'offense', cluster:'TE', cat:'default'}, {name:'Luke Schoonmaker', pos:'TE', zone:'offense', cluster:'TE', cat:'default'}, {name:'Brevyn Spann-Ford', pos:'TE', zone:'offense', cluster:'TE', cat:'default'}, {name:'Princeton Fant', pos:'TE', zone:'offense', cluster:'TE', cat:'default'}, {name:'Michael Trigg', pos:'TE', zone:'offense', cluster:'TE', cat:'udfa'}, {name:'DJ Rogers', pos:'TE', zone:'offense', cluster:'TE', cat:'udfa'}, {name:'Tyler Guyton', pos:'OT', zone:'offense', cluster:'OL', cat:'default'}, {name:'Terence Steele', pos:'OT', zone:'offense', cluster:'OL', cat:'default'}, {name:'Nate Thomas', pos:'OT', zone:'offense', cluster:'OL', cat:'default'}, {name:'Drew Shelton', pos:'OT', zone:'offense', cluster:'OL', cat:'draft'}, {name:'Ajani Cornelius', pos:'OT', zone:'offense', cluster:'OL', cat:'default'}, {name:'Marcellus Johnson', pos:'OT', zone:'offense', cluster:'OL', cat:'default'}, {name:'Shiyazh Pete', pos:'OT', zone:'offense', cluster:'OL', cat:'udfa'}, {name:'Tyler Smith', pos:'G', zone:'offense', cluster:'OL', cat:'default'}, {name:'Tyler Booker', pos:'G', zone:'offense', cluster:'OL', cat:'default'}, {name:'Cooper Beebe', pos:'C', zone:'offense', cluster:'OL', cat:'default'}, {name:'T.J. Bass', pos:'G', zone:'offense', cluster:'OL', cat:'default'}, {name:'Matt Hennessy', pos:'C', zone:'offense', cluster:'OL', cat:'fa'}, {name:'Trevor Keegan', pos:'G', zone:'offense', cluster:'OL', cat:'default'}, {name:'Nick Leverett', pos:'G', zone:'offense', cluster:'OL', cat:'default'}, {name:'Sidney Fugar', pos:'OT', zone:'offense', cluster:'OL', cat:'udfa'}, {name:'DJ Wingfield', pos:'C', zone:'offense', cluster:'OL', cat:'udfa'}, {name:'Jalen Thompson', pos:'S', zone:'defense', cluster:'DB', cat:'fa'}, {name:'Malik Hooker', pos:'S', zone:'defense', cluster:'DB', cat:'default'}, {name:'Markquese Bell', pos:'S', zone:'defense', cluster:'DB', cat:'default'}, {name:'P.J. Locke', pos:'S', zone:'defense', cluster:'DB', cat:'fa'}, {name:'Julius Wood', pos:'S', zone:'defense', cluster:'DB', cat:'default'}, {name:'Alijah Clark', pos:'S', zone:'defense', cluster:'DB', cat:'default'}, {name:'DaRon Bland', pos:'CB', zone:'defense', cluster:'DB', cat:'default'}, {name:'Cobie Durant', pos:'CB', zone:'defense', cluster:'DB', cat:'fa'}, {name:'Shavon Revel Jr.', pos:'CB', zone:'defense', cluster:'DB', cat:'default'}, {name:'Devin Moore', pos:'CB', zone:'defense', cluster:'DB', cat:'draft'}, {name:'Caelen Carson', pos:'CB', zone:'defense', cluster:'DB', cat:'default'}, {name:'Trikweze Bridges', pos:'CB', zone:'defense', cluster:'DB', cat:'default'}, {name:'Derion Kendrick', pos:'CB', zone:'defense', cluster:'DB', cat:'fa'}, {name:'Josh Butler', pos:'CB', zone:'defense', cluster:'DB', cat:'default'}, {name:'Caleb Downs', pos:'NB', zone:'defense', cluster:'DB', cat:'draft'}, {name:'Reddy Steward', pos:'NB', zone:'defense', cluster:'DB', cat:'default'}, {name:'Corey Ballentine', pos:'NB', zone:'defense', cluster:'DB', cat:'default'}, {name:'Zion Childress', pos:'NB', zone:'defense', cluster:'DB', cat:'default'}, {name:'DeMarvion Overshown', pos:'ILB', zone:'defense', cluster:'DL', cat:'default'}, {name:'Dee Winters', pos:'ILB', zone:'defense', cluster:'DL', cat:'fa'}, {name:'Jaishawn Barham', pos:'ILB', zone:'defense', cluster:'DL', cat:'draft'}, {name:'Shemar James', pos:'ILB', zone:'defense', cluster:'DL', cat:'default'}, {name:'Curtis Robinson', pos:'ILB', zone:'defense', cluster:'DL', cat:'fa'}, {name:'Justin Barron', pos:'ILB', zone:'defense', cluster:'DL', cat:'default'}, {name:'Langston Patterson', pos:'ILB', zone:'defense', cluster:'DL', cat:'udfa'}, {name:'Rashan Gary', pos:'Edge', zone:'defense', cluster:'DL', cat:'fa'}, {name:'Donovan Ezeiruaku', pos:'Edge', zone:'defense', cluster:'DL', cat:'default'}, {name:'Malachi Lawrence', pos:'Edge', zone:'defense', cluster:'DL', cat:'draft'}, {name:'James Houston', pos:'Edge', zone:'defense', cluster:'DL', cat:'default'}, {name:'Marist Liufau', pos:'Edge', zone:'defense', cluster:'DL', cat:'default'}, {name:'Sam Williams', pos:'Edge', zone:'defense', cluster:'DL', cat:'default'}, {name:'Tyrus Wheat', pos:'Edge', zone:'defense', cluster:'DL', cat:'fa'}, {name:'Isaiah Land', pos:'Edge', zone:'defense', cluster:'DL', cat:'default'}, {name:'Quinnen Williams', pos:'DT', zone:'defense', cluster:'DL', cat:'default'}, {name:'Kenny Clark', pos:'DT', zone:'defense', cluster:'DL', cat:'default'}, {name:'Otito Ogbonnia', pos:'DT', zone:'defense', cluster:'DL', cat:'fa'}, {name:'Jonathan Bullard', pos:'DT', zone:'defense', cluster:'DL', cat:'fa'}, {name:'LT Overton', pos:'DT', zone:'defense', cluster:'DL', cat:'draft'}, {name:'Jay Toia', pos:'DT', zone:'defense', cluster:'DL', cat:'default'}, {name:'Adedayo Odeleye', pos:'DT', zone:'defense', cluster:'DL', cat:'default'}, {name:'Tommy Dunn', pos:'DT', zone:'defense', cluster:'DL', cat:'udfa'}, {name:'Kelvin Gilliam', pos:'DT', zone:'defense', cluster:'DL', cat:'udfa'}, {name:'DJ Withers', pos:'DT', zone:'defense', cluster:'DL', cat:'udfa'}, {name:'Brandon Aubrey', pos:'K', zone:'st', cluster:'ST', cat:'default'}, {name:'Bryan Anger', pos:'P', zone:'st', cluster:'ST', cat:'default'}, {name:'Trent Sieg', pos:'LS', zone:'st', cluster:'ST', cat:'default'},];const OFF_GROUPS = [ {label:'QB', positions:['QB']}, {label:'RB / FB', positions:['RB','FB']}, {label:'WR', positions:['WR']}, {label:'TE', positions:['TE']}, {label:'OT', positions:['OT']}, {label:'G / C', positions:['G','C']},];const DEF_GROUPS = [ {label:'S', positions:['S']}, {label:'CB', positions:['CB']}, {label:'NB', positions:['NB']}, {label:'ILB', positions:['ILB']}, {label:'Edge', positions:['Edge']}, {label:'DT', positions:['DT']},];ROSTER.forEach(p => { p.location = 'roster'; });// BUILD PANELS function buildPanel(containerEl, groups, zone) { containerEl.innerHTML = ''; groups.forEach(g => { const gDiv = document.createElement('div'); gDiv.className = 'pos-group'; const label = document.createElement('div'); label.className = 'pos-label'; label.textContent = g.label; gDiv.appendChild(label); const dz = document.createElement('div'); dz.className = 'pos-drop-zone'; dz.dataset.positions = g.positions.join(','); dz.dataset.zone = zone; gDiv.appendChild(dz); containerEl.appendChild(gDiv); });}buildPanel(document.getElementById('offenseBody'), OFF_GROUPS, 'offense');buildPanel(document.getElementById('defenseBody'), DEF_GROUPS, 'defense');// RENDER function makePlayerEl(player) { const el = document.createElement('div'); el.className = `player cat-${player.cat}`; el.dataset.name = player.name; const dead = DEAD_MONEY[player.name]; const deadHtml = dead ? `${fmtDead(dead)}` : ''; el.innerHTML = `${player.pos}${player.name}${deadHtml}`; return el;}function render() { document.querySelectorAll('.pos-drop-zone').forEach(dz => dz.innerHTML = ''); ['cutZone','psZone'].forEach(id => { const z = document.getElementById(id); if (!z) return; z.innerHTML = ''; const ph = document.createElement('div'); ph.className = 'cut-placeholder'; ph.textContent = id === 'cutZone' ? 'Drag players here to cut' : 'Drag here (max 10)'; z.appendChild(ph); }); const stBody = document.getElementById('stBody'); stBody.innerHTML = ''; const stDz = document.createElement('div'); stDz.className = 'pos-drop-zone st-row'; stDz.dataset.positions = 'K,P,LS'; stDz.dataset.zone = 'st'; stBody.appendChild(stDz); ROSTER.forEach(p => { const el = makePlayerEl(p); if (p.location === 'roster') { if (p.zone === 'st') { document.querySelector('[data-zone="st"]').appendChild(el); } else { let placed = false; document.querySelectorAll(`.pos-drop-zone[data-zone="${p.zone}"]`).forEach(dz => { if (!placed && dz.dataset.positions.split(',').includes(p.pos)) { dz.appendChild(el); placed = true; } }); } } else { const zoneEl = document.getElementById(p.location + 'Zone'); if (zoneEl) { const ph = zoneEl.querySelector('.cut-placeholder'); if (ph) ph.remove(); zoneEl.appendChild(el); } } attachDrag(el, p); }); updateCounts();}function updateCounts() { const roster = ROSTER.filter(p => p.location === 'roster'); const cut = ROSTER.filter(p => p.location === 'cut'); const ps = ROSTER.filter(p => p.location === 'ps'); // IPP exception: Adedayo Odeleye doesn't count against roster/PS limits const odeleye = ROSTER.find(p => p.name === 'Adedayo Odeleye'); const odOnRoster = odeleye && odeleye.location === 'roster'; const odOnPS = odeleye && odeleye.location === 'ps'; const rosterLimit = odOnRoster ? 54 : 53; const psLimit = odOnPS ? 17 : 16; // Active roster count excludes Odeleye if he's on roster (he's exempt) const activeCount = odOnRoster ? roster.length - 1 : roster.length; document.getElementById('offCount').textContent = `${roster.filter(p=>p.zone==='offense').length} players`; document.getElementById('defCount').textContent = `${roster.filter(p=>p.zone==='defense').length} players`; document.getElementById('cutCount').textContent = `${cut.length} cut`; document.getElementById('psCount').textContent = `${ps.length} / ${psLimit}`; const badge = document.getElementById('rosterBadge'); badge.textContent = roster.length; badge.className = `counter-badge ${activeCount sum + (DEAD_MONEY[p.name] || 0), 0); const deadBadge = document.getElementById('deadBadge'); deadBadge.textContent = totalDead > 0 ? fmtDead(totalDead) : '$0'; deadBadge.className = `dead-badge ${totalDead > 0 ? 'some' : 'none'}`;}// DRAG & DROP let dragPlayer = null;const ghostEl = document.getElementById('dragGhost');// DEAD MONEY DATA const DEAD_MONEY = { 'Dak Prescott': 174989996, 'Sam Howell': 2500000, 'Javonte Williams': 16000000, 'Hunter Luepke': 3500000, 'Jaydon Blue': 320301, 'Phil Mafah': 83649, 'Dominic Richardson': 50000, 'CeeDee Lamb': 75123140, 'George Pickens': 27298000, 'KaVontae Turpin': 2400000, 'Anthony Smith': 180860, 'Marquez Valdes-Scantling': 187500, 'Camden Brown': 105000, 'Jordan Hudson': 105000, 'Jake Ferguson': 9600000, 'Luke Schoonmaker': 389396, 'Brevyn Spann-Ford': 6667, 'Michael Trigg': 280000, 'DJ Rogers': 200000, 'Tyler Guyton': 7773885, 'Terence Steele': 34125000, 'Nate Thomas': 52986, 'Drew Shelton': 1195428, 'Ajani Cornelius': 160482, 'Shiyazh Pete': 3000, 'Tyler Smith': 49342300, 'Tyler Booker': 18309189, 'Cooper Beebe': 569898, 'Matt Hennessy': 1262500, 'Sidney Fugar': 3000, 'Jalen Thompson': 22000000, 'Malik Hooker': 5500000, 'Markquese Bell': 3666668, 'P.J. Locke': 1500000, 'DaRon Bland': 30254904, 'Cobie Durant': 1500000, 'Shavon Revel Jr.': 1029132, 'Devin Moore': 1189532, 'Caelen Carson': 127138, 'Caleb Downs': 28951992, 'DeMarvion Overshown': 230005, 'Jaishawn Barham': 1416980, 'Shemar James': 317577, 'Langston Patterson': 50000, 'Rashan Gary': 16000000, 'Donovan Ezeiruaku': 6929340, 'Marist Liufau': 479642, 'Sam Williams': 2000000, 'Tyrus Wheat': 100000, 'Quinnen Williams': 7656000, 'Kenny Clark': 11000000, 'Otito Ogbonnia': 500000, 'Jonathan Bullard': 1500000, 'LT Overton': 789036, 'Jay Toia': 114837, 'Tommy Dunn': 50000, 'Kelvin Gilliam': 50000, 'DJ Withers': 3000, 'Brandon Aubrey': 6750000, 'Bryan Anger': 1000000, 'Trent Sieg': 1666668,};function fmtDead(n) { if (!n || n === 0) return ''; if (n >= 1000000) return '$' + (n / 1000000).toFixed(1) + 'M'; if (n >= 1000) return '$' + (n / 1000).toFixed(0) + 'K'; return '$' + n;}// PLAYER SCOUTING DATA const SCOUT = { // QBs 'Dak Prescott': { keep: "He IS the Cowboys.", cut: "Leave this website if you're actually thinking about cutting Dak Prescott." }, 'Joe Milton III': { keep: "Big arm, big frame, legit upside as a developmental QB2. Made strides operating Schottenheimer's system in 2025.", cut: "Accuracy issues are real and persistent. If Sam Howell outplays him in camp, the math gets ugly with three QBs." }, 'Sam Howell': { keep: "Showed starter-level moments in Washington. Smart, quick release, good fit for this offense as a backup insurance policy.", cut: "Has started 18 NFL games and gone 5-13. The definition of 'he's fine... probably.'" }, // RBs/FB 'Javonte Williams': { keep: "A true workhorse back who posted 1,200+ yards in 2025. Strong between the tackles, reliable pass protector. The Cowboys' bell cow.", cut: "Wore down late in the season. At 26 with a rebuilt knee history, the durability question never fully goes away." }, 'Hunter Luepke': { keep: "One of the best blocking fullbacks in the NFL. Makes the entire run game better. Special teams ace. A roster lock every year.", cut: "Fullbacks are perpetually one roster crunch away from extinction. His resume is blocking and... blocking." }, 'Malik Davis': { keep: "Proved he belongs in 2025 with reliable hands and smart routes out of the backfield. Coaches love him. A keep-the-peace roster decision.", cut: "Doesn't profile as a featured back at any level. If a cheaper UDFA exceeds him in camp, he's the odd man out." }, 'Jaydon Blue': { keep: "Explosive speed that changes games in the open field. Big-play threat on screens and sweeps. The 'splash play' option in the room.", cut: "Draft pedigree can only carry you so far. Still a work in progress." }, 'Phil Mafah': { keep: "Was a training camp standout in 2025 and gives the Cowboys a physical, downhill option who won't ask for carries - just give them.", cut: "The numbers just don't add up for Mafah in the RB room." }, 'Israel Abanikanda': { keep: "Tremendous athleticism and burst. Could be the mystery weapon this offense needs if he puts it all together. High ceiling.", cut: "Has yet to put it all together at the NFL level. At some point 'ceiling' stops being a reason to keep someone." }, 'Dominic Richardson': { keep: "A UDFA with size and contact balance who could sneak onto the practice squad and develop into something real.", cut: "Last man in at a crowded position. Practice squad is his realistic ambition, not the 53." }, // WRs 'CeeDee Lamb': { keep: "Not cutting CeeDee Lamb is basically a prerequisite to existing as an NFL franchise.", cut: "Stop it! You're not cutting CeeDee Lamb." }, 'George Pickens': { keep: "1,429 yards, 9 TDs, and 137 targets in his first season in Dallas. On the franchise tag for a reason - possibly the best WR duo in football alongside Lamb.", cut: "Purportedly a drama magnet. Also costs $27.3M on the tag." }, 'Ryan Flournoy': { keep: "Established himself as a legitimate WR3 and proven red zone threat. Slot ace.", cut: "Go away with this nonsense." }, 'KaVontae Turpin': { keep: "The most electric returner in Cowboys history with some versatility as a gadget weapon.", cut: "His role as a 'returner who might catch a pass' is roster-spot expensive on a crowded roster." }, 'Jonathan Mingo': { keep: "The Cowboys gave up a 4th-round pick for him, so there's organizational pride involved.", cut: "His path to meaningful snaps is nearly gone with Lamb, Pickens, and Flournoy locked in. The investment hasn't paid off." }, 'Anthony Smith': { keep: "4.40 speed out of ECU with 1,000+ yard senior season. A 3rd-round pick who can stretch the field and contribute on special teams immediately.", cut: "As a rookie, he needs to prove he's more than a track star in cleats. Camp and preseason performance will tell the real story." }, 'Traeshon Holden': { keep: "Reliable depth option with good hands. A low-risk, low-cost roster or practice squad piece that gives the team emergency WR depth.", cut: "Unlikely to make the 53 with six receivers ahead of him. Practice squad is the ceiling barring a major injury wave." }, 'Marquez Valdes-Scantling': { keep: "Veteran savvy and a clear downfield threat. Gives Dak a genuine deep ball option on a relatively affordable deal.", cut: "Career catch rate is... not great. At this stage of his career, he may not even make it out of camp." }, 'Tyler Johnson': { keep: "A reliable veteran slot option who has been productive when healthy. Good hands, smart routes, familiar with multiple offenses.", cut: "Injury history and the crowded WR room make his roster spot precarious. Camp has to go perfectly for him." }, 'Parris Campbell': { keep: "Adds a legitimate speed dimension to the room as veteran depth when healthy.", cut: "The phrase 'when healthy' is doing so much work in that keep column." }, 'Camden Brown': { keep: "A UDFA who adds speed and a willingness to do the dirty work on special teams. Practice squad candidate with upside.", cut: "At this stage, he's fighting to even make the practice squad." }, 'Jordan Hudson': { keep: "UDFA with good hands and solid production in college. Special teams value could keep him on the roster bubble.", cut: "Faces an uphill battle against established veterans. Will likely need a standout preseason just to stay in the conversation." }, // TEs 'Jake Ferguson': { keep: "The Cowboys' clear TE1. Over 700 yards in 2025 and Dak's security blanket in the middle of the field.", cut: "You keep Jake Ferguson. That's it. That's the entire analysis." }, 'Luke Schoonmaker': { keep: "Athletic blocker who flashed real receiving ability in Year 2. Likely keeps his spot with effort and versatility.", cut: "Inconsistency as a receiver limits his ceiling. He needs a strong 2026 to cement his role before other TEs push him down the depth chart." }, 'Brevyn Spann-Ford': { keep: "An excellent blocker who makes the run game tick. If the Cowboys want a true Y tight end, he's the guy. Special teams ace.", cut: "Limited receiving upside makes him vulnerable if the team wants more pass-catching from the TE position." }, 'Princeton Fant': { keep: "Veteran depth who gives the team a third TE capable of lining up in multiple spots. Insurance policy for Ferguson.", cut: "At this stage, he's depth behind depth. If the Cowboys trim the TE room to two, he's first to go." }, 'Michael Trigg': { keep: "UDFA with some buzz from his college tape. Raw but athletic, could develop into a genuine pass-catching TE with time.", cut: "Cut if you don't believe the hype, or you're still pissed at the Rico Gathers pick." }, 'DJ Rogers': { keep: "UDFA who adds depth at a critical position. Blocking ability may give him a leg up on the practice squad bubble.", cut: "Will need a miraculous preseason to crack the 53." }, // OL 'Tyler Guyton': { keep: "Year 3 should see a big leap from the 2024 first-rounder. Coaches are excited.", cut: "Still learning the nuances of NFL pass protection. Got beat more than the Cowboys would like in 2025. But you keep him." }, 'Terence Steele': { keep: "A veteran anchor at right tackle entering his 7th year in Dallas. Restructured his deal to stay.", cut: "Coaches openly discussed whether Tyler Smith should kick out to tackle, which tells you something about long-term security here." }, 'Nate Thomas': { keep: "A swing tackle who provides valuable insurance for both sides. Coaches trust him. Versatility is everything on the OL.", cut: "Depth designation is hard to hold when younger, cheaper options are pushing up. Solid but not spectacular." }, 'Drew Shelton': { keep: "A 4th-round pick in 2026 with the upside to be a starter. Long arms, physical tools, and the Cowboys' investment means he'll get every chance.", cut: "As a rookie tackle, the learning curve is steep. He'll likely start as a backup while he develops NFL-caliber technique." }, 'Ajani Cornelius': { keep: "A developmental OT with size and athleticism. Could develop into a quality starter with the right coaching.", cut: "Still raw. Competing for the last OL spots on the depth chart against veterans with more NFL polish." }, 'Marcellus Johnson': { keep: "Experienced swing tackle who has been in the system. Gives the team a known quantity as emergency depth.", cut: "The 'he's been here before' factor only carries so much weight when the depth chart is filled with younger options." }, 'Shiyazh Pete': { keep: "UDFA with the frame to develop as an OT. Long project, but the Cowboys' OL coaching is among the best in developing raw linemen.", cut: "Roster long shot. Practice squad is the goal." }, 'Tyler Smith': { keep: "A cornerstone of the Cowboys' OL and one of the best guards in football. The coaches keep debating if he should kick to tackle - a sign of his value.", cut: "What are you, an Eagles fan? One does not cut Tyler Smith." }, 'Tyler Booker': { keep: "Already looking like a star in the making. A 2025 Day 1 pick who stepped in and played like a starter immediately at RG.", cut: "The only reason to cut Tyler Booker is if you have lost your mind." }, 'Cooper Beebe': { keep: "One of the better centers in the NFC. Intelligent, anchor-strong, and the glue of this offensive line. Extension candidate.", cut: "Nobody is cutting Cooper Beebe." }, 'T.J. Bass': { keep: "Quality interior depth who can play both guard spots. A trusted backup who can step in without the offense missing a beat.", cut: "With Booker and Smith locked in at guard, Bass is essentially playing for the 6th-OL spot. Camp battle is real." }, 'Matt Hennessy': { keep: "Veteran backup center and interior lineman who gives the team a capable emergency starter. Insurance for Beebe.", cut: "Behind Beebe at center and competing with Bass and others for depth snaps. The numbers may not work out." }, 'Trevor Keegan': { keep: "A versatile interior lineman who can play multiple spots. Special teams contributions make him a viable 53-man candidate.", cut: "On the fringe. If the Cowboys decide to carry fewer linemen, he's one of the first to go." }, 'Nick Leverett': { keep: "Experienced veteran who can step in at center or guard. FA signing suggests the coaches wanted proven depth on the interior.", cut: "Competing for the same spots as Bass, Hennessy, and Keegan. Not everyone can survive the cuts." }, 'Sidney Fugar': { keep: "UDFA tackle who adds depth to the room. Size and length are intriguing at the next level.", cut: "Practice squad is the realistic target. The 53 would be a surprise." }, 'DJ Wingfield': { keep: "UDFA center who gives the Cowboys interior OL depth behind Beebe. Smart player who understood the game at the college level.", cut: "Long shot for the 53. The Cowboys have better options in front of him." }, // DBs 'Jalen Thompson': { keep: "Experienced FS who instantly upgrades the back end. A savvy veteran communicator who makes everyone around him better.", cut: "You don't cut the Cowboys' biggest free agent signing since Brandon Carr in 2012." }, 'Malik Hooker': { keep: "A proven NFL starter. Brings leadership, ball-hawking instincts, and a championship pedigree.", cut: "Age and injury history are real. Caleb Downs' versatility means Hooker's role may shrink faster than expected." }, 'Markquese Bell': { keep: "One of the Cowboys' best special teams players. A core ST ace who makes the roster on those contributions alone.", cut: "Limited role as a defensive starter with Thompson, Hooker, and Downs ahead of him. His fate is likely tied to special teams value." }, 'P.J. Locke': { keep: "A versatile safety who can play in the box, deep, or in the slot. Leadership and positional flexibility are invaluable.", cut: "On a one-year deal and entering a crowded safety room with Thompson, Hooker, Bell, and the great Caleb Downs. The math is tight." }, 'Julius Wood': { keep: "A 2024 UDFA with athleticism and instincts to develop at safety. The Cowboys invested in him - they'll give him every chance.", cut: "He's likely not cracking the 53. Practice squad is the expectation." }, 'Alijah Clark': { keep: "A legitimate 53-man roster candidate. Versatile and physical - coaches like what they see.", cut: "Might be the final cut to get to 53. The secondary is simply too deep." }, 'DaRon Bland': { keep: "A borderline All-Pro corner with repeated injury issues. When healthy, one of the best corners in the NFC.", cut: "Nobody is taking a $30.2 million dead money hit for cutting Bland. Not even you." }, 'Cobie Durant': { keep: "A physical press corner on a one-year deal who instantly upgrades the outside CB depth. Competed in a tough Rams secondary.", cut: "On a one-year prove-it deal. Has to outperform younger options in camp or his tenure ends quickly." }, 'Shavon Revel Jr.': { keep: "If healthy, he has legitimate CB1 upside opposite DaRon Bland.", cut: "Health is the entire conversation - the talent is undeniable when he's on the field." }, 'Devin Moore': { keep: "A 2026 draft pick who gives the Cowboys a long-term answer at cornerback. Physical tools and instincts to be a starter.", cut: "As a rookie corner, Year 1 is about development. With Bland, Durant, Revel, and Kendrick ahead, snaps may be limited." }, 'Caelen Carson': { keep: "Smart, instinctive, ready to contribute.", cut: "Still establishing himself as a consistent starter." }, 'Trikweze Bridges': { keep: "Solid depth cornerback who brings NFL starting experience. A quiet professional who understands his role perfectly.", cut: "With so many CBs on the roster, he's fighting for the last spot. Special teams value will determine his fate." }, 'Derion Kendrick': { keep: "A physical, experienced cornerback who brings starting-quality depth. Coaches have confidence in him as a contributor.", cut: "Acquired as a FA, meaning the contract has to make sense. In a deep CB room, he might be the odd man out." }, 'Josh Butler': { keep: "A depth corner who brings physicality and special teams value. Could make the 53 as the last corner in a big CB group.", cut: "On the absolute bubble. Any underperformance in camp or preseason and he's packing his playbook." }, 'Caleb Downs': { keep: "THE pick of the 2026 draft, Cowboys had him at #4 on their board. A generational safety who can play nickel, LB, and everywhere in between.", cut: "Don't be silly." }, 'Reddy Steward': { keep: "A developmental NB/S hybrid who fits perfectly in a Christian Parker defense. Great instincts and playmaking ability.", cut: "Behind Downs, Thompson, and others in the pecking order. Proving himself on special teams is his path to the 53." }, 'Corey Ballentine': { keep: "A reliable veteran who can play corner or nickel in a pinch. Special teams value keeps him relevant.", cut: "Roster math may not work in his favor." }, 'Zion Childress': { keep: "A UDFA nickel/safety hybrid with the athleticism to contribute on special teams. Intriguing developmental piece.", cut: "Long shot for the 53. Practice squad is the optimistic outcome." }, // LBs 'DeMarvion Overshown': { keep: "Finally healthy. High motor, sideline-to-sideline range, and the Cowboys' most talented homegrown LB. Huge year coming.", cut: "When you're always 'finally healthy' until you're not. Camp health will tell everything." }, 'Dee Winters': { keep: "Acquired via trade from San Francisco to give the Cowboys a plug-and-play ILB starter. Instantly the most reliable linebacker on the roster.", cut: "It's a one-year arrangement, and if he doesn't produce, the Cowboys won't overpay to keep him. Prove-it season." }, 'Jaishawn Barham': { keep: "A 3rd-round pick who brings sideline-to-sideline athleticism and pass-rush upside. The Cowboys' LB of the future alongside Overshown.", cut: "As a rookie in a new defensive system, patience will be required. He may not start immediately but will be a key piece quickly." }, 'Shemar James': { keep: "A versatile linebacker with experience in multiple defensive systems. Smart, instinctive, and a strong locker room presence.", cut: "Depth behind Winters, Overshown, and Barham. Roster spot is not guaranteed in a competitive LB room." }, 'Curtis Robinson': { keep: "A veteran ILB who has earned his place through special teams contributions. Reliable depth that coaches can count on.", cut: "Veteran presence is valued, but in a new defensive system, youth wins. He's a camp body competing for the last LB spot." }, 'Justin Barron': { keep: "Developmental LB who adds depth and special teams value. A low-cost insurance policy behind the starters.", cut: "On the outside looking in with Winters, Overshown, Barham, and James all ahead of him. The math is brutal." }, 'Langston Patterson': { keep: "A UDFA with the energy and motor to make a case on special teams. Underdogs are always worth watching.", cut: "Extremely long shot for the 53. But hey, someone has to surprise us every training camp." }, // Edge/DL 'Rashan Gary': { keep: "A Pro Bowl pass rusher who gives the Cowboys strong edge presence. Veteran tone-setter.", cut: "Coming off a 2025 season where his pressure rate dipped slightly. At 28 on a one-year deal, he has to deliver or it's over." }, 'Donovan Ezeiruaku': { keep: "A 2025 2nd-round pick who showed legitimate NFL pass-rush ability in Year 1. With Gary as a mentor, Year 2 should see a big leap.", cut: "His 2 sacks as a rookie were below expectations. He needs to take the next step in 2026." }, 'Malachi Lawrence': { keep: "The #23 overall pick in 2026. UCF product with more speed than DeMarcus Lawrence had according to Cowboys brass. A star in the making.", cut: "Every Cowboys fan who just read 'more speed than DeMarcus Lawrence' has already refused to cut him." }, 'James Houston': { keep: "5.5 sacks and a 15% pressure rate in limited action in 2025. An absolute steal.", cut: "'This is James Houston! This is James Houston!'" }, 'Marist Liufau': { keep: "Depth at edge rusher is never a bad thing. Physical tools and a willingness to compete on special teams keep him relevant.", cut: "A man must find his place on a roster." }, 'Sam Williams': { keep: "If he recaptures his pre-injury form, he'll be part of the rotation.", cut: "Lawrence's arrival pushes him further down the depth chart. Two years removed from the injury, he has to produce NOW." }, 'Tyrus Wheat': { keep: "A familiar face the Cowboys brought back, maybe that's enough?", cut: "On a one-year deal, competing against a much younger edge group. He needs an elite camp just to survive to Week 1." }, 'Isaiah Land': { keep: "A pass-rush specialist with legitimate bend and quickness. If he can contribute in third-down packages, he earns his roster spot.", cut: "Limited snap role limits his value in a 53-man calculation. Special teams contributions are his insurance policy." }, 'Quinnen Williams': { keep: "An All-Pro DT who immediately became the Cowboys' best defensive player after the trade. The anchor of Christian Parker's new 3-4. A cornerstone.", cut: "Worth every penny. Not cutting Quinnen Williams." }, 'Kenny Clark': { keep: "A three-time Pro Bowl DT who gives the Cowboys arguably the best interior defensive line duo in football alongside Williams.", cut: "Turns 31 in October. Age and a significant contract means the Cowboys need him to stay healthy. But he stays." }, 'Otito Ogbonnia': { keep: "A young DT who may earn a role as a key rotational piece.", cut: "Not a starter, but is that really enough of a reason to cut him?" }, 'Jonathan Bullard': { keep: "A reliable veteran defensive tackle who provides capable rotation behind Williams and Clark. Does the dirty work without complaint.", cut: "Veteran depth is only so valuable when younger, cheaper options are pushing up. His roster spot is year-to-year." }, 'LT Overton': { keep: "The frame is there to develop into a starter.", cut: "The learning curve is steep. Patience required." }, 'Jay Toia': { keep: "A solid rotational defensive tackle who provides reliable depth behind the starters. Coaches trust him in key situations.", cut: "With Overton, Bullard, and others in the mix, his roster spot is not guaranteed. Camp competition will be fierce." }, 'Adedayo Odeleye': { keep: "Depth DT who can play multiple spots along the interior line. A low-cost piece that adds competition and depth, and as an IPP player, he gets a roster exemption.", cut: "On the roster bubble. The Cowboys have better options ahead of him at every DT spot." }, 'Tommy Dunn': { keep: "A UDFA defensive tackle who impressed enough to get signed. Physical and relentless - the type who might surprise in camp.", cut: "Long shot for the 53. But if Overton struggles in the transition, Dunn's a name to watch on the practice squad." }, 'Kelvin Gilliam': { keep: "UDFA with good size who can contribute in a rotation. Development piece with some upside.", cut: "Practice squad candidate if he can beat out similar profiles." }, 'DJ Withers': { keep: "UDFA DT who adds bodies to a defensive line that lost Odighizuwa. Gives Dallas extra competition in training camp.", cut: "Almost certainly a practice squad or cut candidate." }, // Special Teams 'Brandon Aubrey': { keep: "Is this the year he kicks a 70-yarder?", cut: "Not cutting Brandon Aubrey. Not now. Not ever." }, 'Bryan Anger': { keep: "A consistent, quality punter who pins opponents deep and wins the field position battle. Underrated part of this team's success.", cut: "No reason to cut a punter this reliable. You'd only do it if a UDFA punter showed up and averaged 60 yards per kick. Which won't happen." }, 'Trent Sieg': { keep: "Long snappers are among the most undervalued roster spots in football. Sieg is reliable, quiet, and does his job perfectly every single snap.", cut: "If he snaps one ball over Aubrey's head, the entire Cowboys fanbase will remember his name forever. Until then, he's safe." },};// TOOLTIP LOGIC const tooltip = document.getElementById('tooltip');const ttName = document.getElementById('tt-name');const ttKeep = document.getElementById('tt-keep');const ttCut = document.getElementById('tt-cut');let tooltipTimer = null;function showTooltip(e, player) { const data = SCOUT[player.name]; if (!data) return; ttName.textContent = player.name; ttKeep.textContent = data.keep; ttCut.textContent = data.cut; positionTooltip(e); tooltip.classList.add('visible');}function positionTooltip(e) { const tw = 240, th = 120; let x = e.clientX + 14; let y = e.clientY + 14; if (x + tw > window.innerWidth - 10) x = e.clientX - tw - 14; if (y + th > window.innerHeight - 10) y = e.clientY - th - 14; tooltip.style.left = x + 'px'; tooltip.style.top = y + 'px';}function hideTooltip() { tooltip.classList.remove('visible');}function canDropInZone(player, targetZone, targetPositions) { if (['cut','ps'].includes(targetZone)) return true; const tPos = targetPositions ? targetPositions.split(',') : []; if (tPos.includes(player.pos)) return true; const tCluster = ROSTER.find(r => tPos.includes(r.pos))?.cluster; return player.cluster && tCluster && player.cluster === tCluster;}function attachDrag(el, player) { // Tooltip el.addEventListener('mouseenter', e => { showTooltip(e, player); }); el.addEventListener('mousemove', e => { positionTooltip(e); }); el.addEventListener('mouseleave', () => { hideTooltip(); }); // Mouse drag el.addEventListener('mousedown', e => { hideTooltip(); if (e.button !== 0) return; dragPlayer = player; el.classList.add('dragging'); ghostEl.className = `player cat-${player.cat} drag-ghost`; ghostEl.innerHTML = el.innerHTML; ghostEl.style.display = 'block'; moveGhost(e); document.addEventListener('mousemove', onMouseMove); document.addEventListener('mouseup', onMouseUp); e.preventDefault(); }); el.addEventListener('touchstart', e => { dragPlayer = player; el.classList.add('dragging'); ghostEl.className = `player cat-${player.cat} drag-ghost`; ghostEl.innerHTML = el.innerHTML; ghostEl.style.display = 'block'; const t = e.touches[0]; moveGhost({clientX: t.clientX, clientY: t.clientY}); }, {passive:true}); el.addEventListener('touchmove', e => { const t = e.touches[0]; moveGhost({clientX: t.clientX, clientY: t.clientY}); document.querySelectorAll('.drag-over').forEach(x => x.classList.remove('drag-over')); const tgt = getDropTarget(t.clientX, t.clientY); if (tgt) tgt.classList.add('drag-over'); e.preventDefault(); }, {passive:false}); el.addEventListener('touchend', e => { const t = e.changedTouches[0]; onMouseUp({clientX: t.clientX, clientY: t.clientY}); });}function moveGhost(e) { ghostEl.style.left = (e.clientX + 12) + 'px'; ghostEl.style.top = (e.clientY - 12) + 'px';}function getDropTarget(x, y) { // Use elementsFromPoint to get ALL elements under cursor, then find the first valid zone const els = document.elementsFromPoint(x, y); for (const el of els) { if (el.classList.contains('pos-drop-zone') || el.classList.contains('cut-zone')) return el; // Also accept clicks on player chips inside a cut-zone - return the parent zone if (el.classList.contains('player') || el.classList.contains('player-name') || el.classList.contains('player-pos-badge') || el.classList.contains('drag-handle') || el.classList.contains('dead-money-label')) { const zone = el.closest('.cut-zone') || el.closest('.pos-drop-zone'); if (zone) return zone; } } return null;}function onMouseMove(e) { moveGhost(e); document.querySelectorAll('.drag-over').forEach(el => el.classList.remove('drag-over')); const tgt = getDropTarget(e.clientX, e.clientY); if (tgt) tgt.classList.add('drag-over');}function onMouseUp(e) { document.removeEventListener('mousemove', onMouseMove); document.removeEventListener('mouseup', onMouseUp); ghostEl.style.display = 'none'; document.querySelectorAll('.drag-over').forEach(el => el.classList.remove('drag-over')); if (!dragPlayer) return; const target = getDropTarget(e.clientX, e.clientY); if (target) { const zone = target.dataset.zone || ''; const positions = target.dataset.positions ? target.dataset.positions.split(',') : []; if (zone === 'cut') { dragPlayer.location = 'cut'; } else if (zone === 'ps') { const psCount = ROSTER.filter(p => p.location === 'ps').length; const odeleye = ROSTER.find(p => p.name === 'Adedayo Odeleye'); // If Odeleye is already on PS, limit is 17; otherwise 16 // Also: if we're moving Odeleye himself to PS, check against base limit of 16 const odOnPS = odeleye && odeleye.location === 'ps' && dragPlayer.name !== 'Adedayo Odeleye'; const psLimit = odOnPS ? 17 : 16; if (dragPlayer.location !== 'ps' && psCount >= psLimit) { showToast(`Practice Squad is full (max ${psLimit} players)`); } else { dragPlayer.location = 'ps'; } } else if (zone === 'st' || positions.length) { // Returning from cut/ps back to roster if (['cut','ps'].includes(dragPlayer.location)) { dragPlayer.location = 'roster'; if (zone === 'st') dragPlayer.zone = 'st'; } else if (canDropInZone(dragPlayer, zone, target.dataset.positions)) { // Update zone dragPlayer.zone = zone === 'st' ? 'st' : (target.closest('[data-zone]')?.dataset.zone || dragPlayer.zone); // If dropping into a same-cluster but different position group, // update pos to match the target group's primary position if (zone !== 'st' && positions.length && !positions.includes(dragPlayer.pos)) { // Assign the first position of the target group dragPlayer.pos = positions[0]; } // Reorder within zone: find insert index based on Y position const siblings = Array.from(target.children).filter(c => c.classList.contains('player')); let insertBefore = null; for (const sib of siblings) { const sibRect = sib.getBoundingClientRect(); if (e.clientY p.name === sibName); ROSTER.splice(toIdx, 0, dragPlayer); } else { // Drop at end of this group: find last player in target zone+positions let lastIdx = -1; ROSTER.forEach((p, i) => { if (p.location === 'roster' && p.zone === dragPlayer.zone && positions.includes(p.pos)) lastIdx = i; }); ROSTER.splice(lastIdx + 1, 0, dragPlayer); } } } } document.querySelector('.player.dragging')?.classList.remove('dragging'); dragPlayer = null; render();}function showToast(msg) { const t = document.createElement('div'); t.textContent = msg; Object.assign(t.style, { position:'fixed', bottom:'80px', left:'50%', transform:'translateX(-50%)', background:'#c0392b', color:'#fff', padding:'10px 20px', borderRadius:'8px', fontWeight:'600', zIndex:'9999', fontSize:'0.85rem', boxShadow:'0 4px 16px rgba(0,0,0,0.4)' }); document.body.appendChild(t); setTimeout(() => t.remove(), 2500);}// SNAPSHOT function openSnapshot() { const roster = ROSTER.filter(p => p.location === 'roster'); const ps = ROSTER.filter(p => p.location === 'ps'); const CAT = { default: {bg:'#e8ecee', color:'#1a1a1a'}, fa: {bg:'#cce0f5', color:'#09243F'}, draft: {bg:'#c8ecd4', color:'#1a5c2a'}, udfa: {bg:'#fef9c3', color:'#7a5f00'}, }; // Render one position column: header with count + names stacked below function posCol(label, positions) { const players = roster.filter(p => positions.includes(p.pos)); const count = players.length; const names = players.map(p => { const c = CAT[p.cat] || CAT.default; return `${p.name}`; }).join(''); return `${label} (${count}) ${names || '-'} `; } // Render one reserve column (PS / PUP / IR) with colored header function reserveCol(label, players, maxStr, headerColor) { const countStr = maxStr ? `${players.length}/${maxStr}` : `${players.length}`; const names = players.map(p => { const c = CAT[p.cat] || CAT.default; return `${p.pos} ${p.name}`; }).join('') || '-'; return `${label} (${countStr}) ${names} `; } // ST: flat name list, no sub-headers function stCol() { const players = roster.filter(p => p.zone === 'st'); const names = players.map(p => { const c = CAT[p.cat] || CAT.default; return `${p.name}`; }).join('') || '-'; return `Special Teams (${players.length}) ${names} `; } const total = roster.length; const badgeColor = total <= 55 ? '#1a7a3a' : '#c0392b'; const badgeBg = total <= 55 ? '#d4edda' : '#fde8e6'; const now = new Date().toLocaleDateString('en-US',{month:'short',day:'numeric',year:'numeric'}); // Build the two main bands as flex rows of position columns const offenseRow = ` ${posCol('QB', ['QB'])} ${posCol('RB/FB', ['RB','FB'])} ${posCol('WR', ['WR'])} ${posCol('TE', ['TE'])} ${posCol('OT', ['OT'])} ${posCol('OG/C', ['G','C'])} `; const defenseRow = ` ${posCol('S', ['S'])} ${posCol('CB', ['CB'])} ${posCol('NB', ['NB'])} ${posCol('ILB', ['ILB'])} ${posCol('DE', ['Edge'])} ${posCol('DT', ['DT'])} `; const bottomRow = ` ${stCol()} ${reserveCol('Practice Squad', ps, '10', '#5a5a8a')} `; const bandStyle = `display:flex;gap:12px;padding:10px 14px;border-radius:6px;margin-bottom:10px;align-items:flex-start;`; const html = `Cowboys 2026 - Roster Snapshot * { box-sizing:border-box; margin:0; padding:0; } body { font-family:'DM Sans',sans-serif; background:#fff; color:#1a1a1a; padding:12px 16px; } .hdr { background:#09243F; color:#fff; padding:10px 16px; border-radius:7px; display:flex; align-items:center; gap:12px; margin-bottom:10px; border-bottom:3px solid #b8a04a; } .star { width:30px;height:30px;background:#ffffff;flex-shrink:0;clip-path:polygon(50% 0%,61% 35%,98% 35%,68% 57%,79% 91%,50% 70%,21% 91%,32% 57%,2% 35%,39% 35%); } .hdr-title { font-family:'Bebas Neue',sans-serif;font-size:1.25rem;letter-spacing:2px;line-height:1; } .hdr-title span { color:#b8a04a; } .hdr-sub { font-size:0.58rem;color:#c8d0d4;letter-spacing:1px;text-transform:uppercase;margin-top:2px; } .badge-wrap { margin-left:auto;text-align:center; } .badge { font-family:'Bebas Neue',sans-serif;font-size:1.5rem;background:${badgeBg};color:${badgeColor};padding:2px 12px;border-radius:6px; } .badge-lbl { font-size:0.52rem;color:${badgeColor};font-weight:700;letter-spacing:1px;text-transform:uppercase; } .legend { display:flex;gap:8px;flex-wrap:wrap;margin-bottom:8px;padding:4px 10px;background:#f8f9fa;border-radius:5px;border:1px solid #e0e6ea;align-items:center; } .leg-item { display:flex;align-items:center;gap:4px;font-size:0.6rem;color:#555; } .leg-sw { width:10px;height:10px;border-radius:2px;border:1px solid rgba(0,0,0,0.1); } .band-label { font-family:'Bebas Neue',sans-serif;font-size:0.75rem;letter-spacing:2px;color:#fff;background:#09243F;display:inline-block;padding:2px 8px;border-radius:3px;margin-bottom:6px; } @media print { body{padding:8px;} }Dallas Cowboys 2026Roster Snapshot ${now}${total}Active RosterLegend:ReturningFA/TradeDraft PickUDFAOffense ${offenseRow}Defense ${defenseRow} ${bottomRow}

Ctrl/Cmd+P to print or screenshot Blogging The Boys

`; const w = window.open('', '_blank', 'width=1050,height=820,scrollbars=yes'); w.document.write(html); w.document.close();}// INIT render();
External Content
Source RSS or Atom Feed
Feed Location http://sports.yahoo.com/nfl/rss.xml
Feed Title
Feed Link https://sports.yahoo.com/nfl/
Feed Copyright Copyright (c) 2026 Yahoo! Inc. All rights reserved.
Reply 0 comments