{"id":590,"date":"2025-12-22T18:09:14","date_gmt":"2025-12-22T18:09:14","guid":{"rendered":"https:\/\/studio1live.com\/picks\/?p=590"},"modified":"2025-12-23T05:01:11","modified_gmt":"2025-12-23T05:01:11","slug":"590-2","status":"publish","type":"post","link":"https:\/\/studio1live.com\/picks\/590-2\/","title":{"rendered":"Portal Vs Recruiting, what is King?"},"content":{"rendered":"<body>\n<h1 class=\"wp-block-heading\">From Canes Insight to Code: Finding College Football\u2019s Portal \u201cSweet Spot\u201d<\/h1>\n\n\n\n<p>I was watching <strong>Canes Insight<\/strong> the other day, listening to <strong>Steve Kim<\/strong>, when he said something that stuck with me.<\/p>\n\n\n\n<p>Paraphrasing, he wondered out loud if there was a <em>\u201csweet spot\u201d<\/em> in the transfer portal era \u2014 not too portal-heavy, not too old-school high-school recruiting \u2014 but a mix that actually correlates with winning. He also asked the natural follow-up: <em>has anyone already done this math?<\/em><\/p>\n\n\n\n<p>That question sent me down a rabbit hole.<\/p>\n\n\n\n<p>Because once you strip away the talking points, the portal debate is really a <strong>data problem<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>How much portal is too much?<\/li>\n\n\n\n<li>How much continuity matters?<\/li>\n\n\n\n<li>What happens when a team loads up one year\u2026 then loses those players the next?<\/li>\n<\/ul>\n\n\n\n<p>So I built a model. Then I built a tool.<\/p>\n\n\n\n<p>What you see below is the <strong>Portal Sweet Spot framework<\/strong> \u2014 the same logic powering the interactive widget under this article.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Measuring Roster Mix (Portal vs High School)<\/h2>\n\n\n\n<p>Let\u2019s start simple.<\/p>\n\n\n\n<p>Let:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>P<\/strong> = number of portal players added<\/li>\n\n\n\n<li><strong>H<\/strong> = number of high-school recruits signed<\/li>\n<\/ul>\n\n\n\n<p>There are two useful ways to express roster mix:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Portal Share (PS)<\/h3>\n\n\n\n<p>This is the cleanest headline number.<math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\" display=\"block\"><semantics><mrow><mi>P<\/mi><mi>S<\/mi><mo>=<\/mo><mfrac><mi>P<\/mi><mrow><mi>P<\/mi><mo>+<\/mo><mi>H<\/mi><\/mrow><\/mfrac><\/mrow><annotation encoding=\"application\/x-tex\">PS = \\frac{P}{P + H}<\/annotation><\/semantics><\/math>PS=P+HP\u200b<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>0.00<\/strong> \u2192 all high-school<\/li>\n\n\n\n<li><strong>0.40<\/strong> \u2192 40% portal<\/li>\n\n\n\n<li><strong>1.00<\/strong> \u2192 all portal<\/li>\n<\/ul>\n\n\n\n<p>This is the number fans intuitively understand.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Portal Ratio (PR)<\/h3>\n\n\n\n<p>For the math heads:<math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\" display=\"block\"><semantics><mrow><mi>P<\/mi><mi>R<\/mi><mo>=<\/mo><mfrac><mi>P<\/mi><mi>H<\/mi><\/mfrac><\/mrow><annotation encoding=\"application\/x-tex\">PR = \\frac{P}{H}<\/annotation><\/semantics><\/math>PR=HP\u200b<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>PR = 1.0<\/strong> \u2192 equal portal and HS<\/li>\n\n\n\n<li><strong>PR &gt; 1.0<\/strong> \u2192 portal-heavy<\/li>\n\n\n\n<li><strong>PR &lt; 1.0<\/strong> \u2192 HS-heavy<\/li>\n<\/ul>\n\n\n\n<p>In the tool, you\u2019ll see both \u2014 but <strong>Portal Share<\/strong> is what drives most of the analysis pasted.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Winning Still Matters (A Lot)<\/h2>\n\n\n\n<p>No advanced metric should ignore the obvious.<math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\" display=\"block\"><semantics><mrow><mi>W<\/mi><mi>i<\/mi><mi>n<\/mi><mtext>\u00a0<\/mtext><mi>P<\/mi><mi>e<\/mi><mi>r<\/mi><mi>c<\/mi><mi>e<\/mi><mi>n<\/mi><mi>t<\/mi><mi>a<\/mi><mi>g<\/mi><mi>e<\/mi><mo>=<\/mo><mfrac><mi>W<\/mi><mrow><mi>W<\/mi><mo>+<\/mo><mi>L<\/mi><\/mrow><\/mfrac><\/mrow><annotation encoding=\"application\/x-tex\">Win\\ Percentage = \\frac{W}{W + L}<\/annotation><\/semantics><\/math>Win\u00a0Percentage=W+LW\u200b<\/p>\n\n\n\n<p>Everything we do later is anchored to winning, not vibes.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: The Missing Piece \u2014 Retention &amp; Continuity<\/h2>\n\n\n\n<p>This is where the portal conversation usually breaks down.<\/p>\n\n\n\n<p>Steve Kim\u2019s point \u2014 whether explicitly or implicitly \u2014 was this:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Teams can win the portal one year\u2026 then get crushed when that class leaves.<\/p>\n<\/blockquote>\n\n\n\n<p>So we track <strong>portal retention<\/strong>.<\/p>\n\n\n\n<p>Let:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>P\u2080<\/strong> = portal players added in Year 0<\/li>\n\n\n\n<li><strong>S\u2081<\/strong> = how many are still on the roster the next year<\/li>\n\n\n\n<li><strong>S\u2082<\/strong>, <strong>S\u2083<\/strong> = still there two and three years later<\/li>\n<\/ul>\n\n\n\n<p>Retention rates:<math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\" display=\"block\"><semantics><mrow><msub><mi>R<\/mi><mn>1<\/mn><\/msub><mo>=<\/mo><mfrac><msub><mi>S<\/mi><mn>1<\/mn><\/msub><msub><mi>P<\/mi><mn>0<\/mn><\/msub><\/mfrac><mo separator=\"true\">,<\/mo><mspace width=\"1em\"><\/mspace><msub><mi>R<\/mi><mn>2<\/mn><\/msub><mo>=<\/mo><mfrac><msub><mi>S<\/mi><mn>2<\/mn><\/msub><msub><mi>P<\/mi><mn>0<\/mn><\/msub><\/mfrac><mo separator=\"true\">,<\/mo><mspace width=\"1em\"><\/mspace><msub><mi>R<\/mi><mn>3<\/mn><\/msub><mo>=<\/mo><mfrac><msub><mi>S<\/mi><mn>3<\/mn><\/msub><msub><mi>P<\/mi><mn>0<\/mn><\/msub><\/mfrac><\/mrow><annotation encoding=\"application\/x-tex\">R_1 = \\frac{S_1}{P_0}, \\quad R_2 = \\frac{S_2}{P_0}, \\quad R_3 = \\frac{S_3}{P_0}<\/annotation><\/semantics><\/math>R1\u200b=P0\u200bS1\u200b\u200b,R2\u200b=P0\u200bS2\u200b\u200b,R3\u200b=P0\u200bS3\u200b\u200b<\/p>\n\n\n\n<p>Then we combine them into a <strong>Roster Stability Score (RSS)<\/strong>:<math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\" display=\"block\"><semantics><mrow><mi>R<\/mi><mi>S<\/mi><mi>S<\/mi><mo>=<\/mo><mn>0.60<\/mn><msub><mi>R<\/mi><mn>1<\/mn><\/msub><mo>+<\/mo><mn>0.30<\/mn><msub><mi>R<\/mi><mn>2<\/mn><\/msub><mo>+<\/mo><mn>0.10<\/mn><msub><mi>R<\/mi><mn>3<\/mn><\/msub><\/mrow><annotation encoding=\"application\/x-tex\">RSS = 0.60R_1 + 0.30R_2 + 0.10R_3<\/annotation><\/semantics><\/math>RSS=0.60R1\u200b+0.30R2\u200b+0.10R3\u200b<\/p>\n\n\n\n<p>Why the weighting?<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Immediate continuity matters most<\/li>\n\n\n\n<li>Long-term retention still counts, just less<\/li>\n<\/ul>\n\n\n\n<p>Programs that cycle players every year get exposed here.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Penalizing Extremes (The \u201cSweet Spot\u201d Idea)<\/h2>\n\n\n\n<p>The core hypothesis is simple:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Too little portal = slow roster correction<br>Too much portal = instability<\/p>\n<\/blockquote>\n\n\n\n<p>So we define a <strong>target portal share<\/strong> \u2014 call it <strong>PS*<\/strong> (for example, 0.35).<\/p>\n\n\n\n<p>Then we reward balance:<math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\" display=\"block\"><semantics><mrow><mi>B<\/mi><mi>a<\/mi><mi>l<\/mi><mi>a<\/mi><mi>n<\/mi><mi>c<\/mi><mi>e<\/mi><mo>=<\/mo><mn>1<\/mn><mo>\u2212<\/mo><mi mathvariant=\"normal\">\u2223<\/mi><mi>P<\/mi><mi>S<\/mi><mo>\u2212<\/mo><mi>P<\/mi><msup><mi>S<\/mi><mo>\u2217<\/mo><\/msup><mi mathvariant=\"normal\">\u2223<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">Balance = 1 \u2013 |PS \u2013 PS^*|<\/annotation><\/semantics><\/math>Balance=1\u2212\u2223PS\u2212PS\u2217\u2223<\/p>\n\n\n\n<p>The closer you are to the sweet spot, the higher the balance score.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">Step 5: The Sweet Spot Score (SSS)<\/h2>\n\n\n\n<p>Now we combine everything into one number:<math xmlns=\"http:\/\/www.w3.org\/1998\/Math\/MathML\" display=\"block\"><semantics><mrow><mi>S<\/mi><mi>S<\/mi><mi>S<\/mi><mo>=<\/mo><mo stretchy=\"false\">(<\/mo><mn>0.50<\/mn><mo>\u00d7<\/mo><mi>W<\/mi><mi>i<\/mi><mi>n<\/mi><mi mathvariant=\"normal\">%<\/mi><mo stretchy=\"false\">)<\/mo><mo>+<\/mo><mo stretchy=\"false\">(<\/mo><mn>0.25<\/mn><mo>\u00d7<\/mo><mi>R<\/mi><mi>S<\/mi><mi>S<\/mi><mo stretchy=\"false\">)<\/mo><mo>+<\/mo><mo stretchy=\"false\">(<\/mo><mn>0.15<\/mn><mo>\u00d7<\/mo><mi>B<\/mi><mi>a<\/mi><mi>l<\/mi><mi>a<\/mi><mi>n<\/mi><mi>c<\/mi><mi>e<\/mi><mo stretchy=\"false\">)<\/mo><mo>+<\/mo><mo stretchy=\"false\">(<\/mo><mn>0.10<\/mn><mo>\u00d7<\/mo><mo stretchy=\"false\">(<\/mo><mn>1<\/mn><mo>\u2212<\/mo><mi>C<\/mi><mi>h<\/mi><mi>u<\/mi><mi>r<\/mi><mi>n<\/mi><mo stretchy=\"false\">)<\/mo><mo stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">SSS = (0.50 \\times Win\\%) + (0.25 \\times RSS) + (0.15 \\times Balance) + (0.10 \\times (1 \u2013 Churn))<\/annotation><\/semantics><\/math>SSS=(0.50\u00d7Win%)+(0.25\u00d7RSS)+(0.15\u00d7Balance)+(0.10\u00d7(1\u2212Churn))<\/p>\n\n\n\n<p>This score:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Rewards winning<\/li>\n\n\n\n<li>Rewards continuity<\/li>\n\n\n\n<li>Penalizes roster whiplash<\/li>\n\n\n\n<li>Penalizes extreme portal dependence<\/li>\n<\/ul>\n\n\n\n<p>It also explains <em>why<\/em> two teams with similar records can feel very different long-term.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">Why This Matters (Especially for Miami)<\/h2>\n\n\n\n<p>This model finally lets us test narratives we argue about every offseason:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Did a big portal year actually <em>sustain<\/em> success?<\/li>\n\n\n\n<li>Did losing portal starters show up in next year\u2019s record?<\/li>\n\n\n\n<li>Who builds reloadable rosters \u2014 not just one-year spikes?<\/li>\n<\/ul>\n\n\n\n<p>For Miami specifically, this helps separate:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u201cPortal hype\u201d<\/strong> from <strong>portal efficiency<\/strong><\/li>\n\n\n\n<li>Volume from value<\/li>\n\n\n\n<li>Short-term wins from program stability<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">What the Tool Below Does<\/h2>\n\n\n\n<p>The interactive widget below lets you:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Manually enter team-year data<\/li>\n\n\n\n<li>Paste or load CSVs (including Python-generated outputs)<\/li>\n\n\n\n<li>Compare teams across conferences<\/li>\n\n\n\n<li>Visualize multi-year trends with sparklines<\/li>\n\n\n\n<li>Rank programs by Sweet Spot Score<\/li>\n<\/ul>\n\n\n\n<p>No database. No login. Just math.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">Final Thought<\/h2>\n\n\n\n<p>Steve Kim asked the right question.<\/p>\n\n\n\n<p>This isn\u2019t about being <em>pro-portal<\/em> or <em>anti-portal<\/em>.<br>It\u2019s about <strong>how much<\/strong>, <strong>how well<\/strong>, and <strong>for how long<\/strong>.<\/p>\n\n\n\n<p>That\u2019s the sweet spot.<\/p>\n\n\n\n<p>\ud83d\udc47 <strong>Use the calculator below, plug in your teams, and see where the data lands.<\/strong><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<p><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\">\n\n\n\n<h2 class=\"wp-block-heading\">\ud83e\uddee Simple Sweet Spot Score (Public Formula)<\/h2>\n\n\n\n<p>This is intentionally <strong>short + explainable<\/strong>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>PAS = Portal_In \/ (Portal_In + HS_Signed)\n\nWin% = Wins \/ (Wins + Losses)\n\nSweet Spot Score =\n(Win% \u00d7 100)\n\u2212 |PAS \u2212 0.40| \u00d7 30\n\u2212 Churn \u00d7 15\n<\/code><\/pre>\n\n\n\n<p>Where:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>0.40<\/strong> = hypothesized portal sweet spot<\/li>\n\n\n\n<li><strong>Churn<\/strong> = (Portal In + Portal Out) \u00f7 Total Adds<\/li>\n<\/ul>\n\n\n\n<p>Score range (rough):<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>80\u2013100<\/strong> = Elite balance<\/li>\n\n\n\n<li><strong>65\u201379<\/strong> = Solid \/ sustainable<\/li>\n\n\n\n<li><strong>50\u201364<\/strong> = Volatile<\/li>\n\n\n\n<li><strong>&lt; 50<\/strong> = Roster risk<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">I\u2019M building The Full scale Here\u2026<a href=\"https:\/\/studio1live.com\/college-football-roster-sweetspot\/\">https:\/\/studio1live.com\/college-football-roster-sweetspot\/<\/a>  coming soon , a little scrape code build so it can be automatic \u2026<\/h2>\n\n\n\n<p>Check out the simple tool below <\/p>\n\n\n  <div id=\"s1l_ss_f0d321c2-6f85-47be-9f5e-d467254adae8\"\r\n       class=\"s1l-sweetspot-widget\"\r\n       data-target=\"\"\r\n       data-conference=\"\"\r\n       data-autoload-url=\"\"\r\n       style=\"max-width:1020px;margin:24px auto;padding:18px;border-radius:16px;\r\n       border:1px solid rgba(255,255,255,.15);\r\n       background:linear-gradient(180deg,#005035,#000);\r\n       color:#f3fff9;font-family:system-ui,Segoe UI,Roboto,Arial;\">\r\n\r\n    <div style=\"display:flex;gap:12px;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;\">\r\n      <div>\r\n        <h3 style=\"margin:0 0 6px;color:#ff7a21;\"><\/h3>\r\n        <div style=\"color:rgba(243,255,249,.9);line-height:1.4;\">\r\n          Enter team-year data (W\/L + HS + Portal In\/Out). Run scores to rank teams.\r\n          <span style=\"opacity:.9;\">No database required.<\/span>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <div style=\"display:flex;gap:10px;flex-wrap:wrap;align-items:center;\">\r\n        <label style=\"font-size:12px;color:rgba(243,255,249,.85);\">Sweet Spot Target (PAS)<\/label>\r\n        <input class=\"mixTarget\" type=\"number\" step=\"0.01\" min=\"0\" max=\"1\" value=\"\"\r\n          style=\"width:110px;padding:9px;border-radius:10px;border:1px solid rgba(255,255,255,.18);\r\n          background:rgba(0,0,0,.25);color:#f3fff9;\">\r\n        <button class=\"btnMiami\" type=\"button\"\r\n          style=\"padding:9px 12px;border-radius:10px;border:0;background:#ff7a21;color:#000;font-weight:900;cursor:pointer;\">\r\n          Load Miami Preset\r\n        <\/button>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <hr style=\"border:0;border-top:1px solid rgba(255,255,255,.14);margin:14px 0;\">\r\n\r\n    <div style=\"display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin-bottom:10px;\">\r\n      <div style=\"font-weight:800;color:#00d084;\">Conference Presets:<\/div>\r\n      <button class=\"btnConf\" type=\"button\" data-conf=\"ACC\"\r\n        style=\"padding:8px 10px;border-radius:10px;border:1px solid rgba(255,255,255,.18);\r\n        background:rgba(0,0,0,.25);color:#f3fff9;cursor:pointer;\">ACC<\/button>\r\n      <button class=\"btnConf\" type=\"button\" data-conf=\"SEC\"\r\n        style=\"padding:8px 10px;border-radius:10px;border:1px solid rgba(255,255,255,.18);\r\n        background:rgba(0,0,0,.25);color:#f3fff9;cursor:pointer;\">SEC<\/button>\r\n      <button class=\"btnConf\" type=\"button\" data-conf=\"B1G\"\r\n        style=\"padding:8px 10px;border-radius:10px;border:1px solid rgba(255,255,255,.18);\r\n        background:rgba(0,0,0,.25);color:#f3fff9;cursor:pointer;\">B1G<\/button>\r\n      <button class=\"btnConf\" type=\"button\" data-conf=\"B12\"\r\n        style=\"padding:8px 10px;border-radius:10px;border:1px solid rgba(255,255,255,.18);\r\n        background:rgba(0,0,0,.25);color:#f3fff9;cursor:pointer;\">Big 12<\/button>\r\n      <button class=\"btnConf\" type=\"button\" data-conf=\"PAC\"\r\n        style=\"padding:8px 10px;border-radius:10px;border:1px solid rgba(255,255,255,.18);\r\n        background:rgba(0,0,0,.25);color:#f3fff9;cursor:pointer;\">Pac<\/button>\r\n    <\/div>\r\n\r\n    <!-- Input table -->\r\n    <div style=\"overflow:auto;border:1px solid rgba(255,255,255,.14);border-radius:12px;\">\r\n      <table style=\"width:100%;border-collapse:collapse;font-size:13px;\">\r\n        <thead>\r\n          <tr style=\"background:rgba(255,255,255,.06);\">\r\n            <th style=\"padding:10px;text-align:left;\">Team<\/th>\r\n            <th style=\"padding:10px;text-align:left;\">Year<\/th>\r\n            <th style=\"padding:10px;text-align:left;\">W<\/th>\r\n            <th style=\"padding:10px;text-align:left;\">L<\/th>\r\n            <th style=\"padding:10px;text-align:left;\">HS Signed<\/th>\r\n            <th style=\"padding:10px;text-align:left;\">Portal In<\/th>\r\n            <th style=\"padding:10px;text-align:left;\">Portal Out<\/th>\r\n            <th style=\"padding:10px;text-align:left;\">Actions<\/th>\r\n          <\/tr>\r\n        <\/thead>\r\n        <tbody class=\"rows\"><\/tbody>\r\n      <\/table>\r\n    <\/div>\r\n\r\n    <!-- CSV paste import -->\r\n    <div style=\"margin-top:12px;display:grid;grid-template-columns:1fr;gap:8px;\">\r\n      <div style=\"font-weight:900;color:#ff7a21;\">Optional: Paste CSV (team,year,w,l,hs,pin,pout)<\/div>\r\n      <textarea class=\"csvPaste\" rows=\"4\" placeholder=\"Miami,2024,10,3,18,12,9\"\r\n        style=\"width:100%;padding:10px;border-radius:12px;border:1px solid rgba(255,255,255,.18);\r\n        background:rgba(0,0,0,.25);color:#f3fff9;\"><\/textarea>\r\n      <div style=\"display:flex;gap:10px;flex-wrap:wrap;\">\r\n        <button class=\"btnImport\" type=\"button\"\r\n          style=\"padding:9px 12px;border-radius:10px;border:1px solid rgba(255,255,255,.18);\r\n          background:rgba(0,0,0,.25);color:#f3fff9;cursor:pointer;\">Import CSV<\/button>\r\n        <button class=\"btnExample\" type=\"button\"\r\n          style=\"padding:9px 12px;border-radius:10px;border:1px solid rgba(255,255,255,.18);\r\n          background:rgba(0,0,0,.25);color:#f3fff9;cursor:pointer;\">Paste Example<\/button>\r\n      <\/div>\r\n      <!-- CSV URL load -->\r\n<div style=\"margin-top:12px;display:grid;grid-template-columns:1fr;gap:8px;\">\r\n  <div style=\"font-weight:900;color:#ff7a21;\">Load CSV from URL (Python output)<\/div>\r\n\r\n  <input class=\"csvUrl\" type=\"url\"\r\n    placeholder=\"https:\/\/studio1live.com\/college-football-roster-sweetspot\/data\/out\/teamyear_sweetspot_retention_2024.csv\"\r\n    style=\"width:100%;padding:10px;border-radius:12px;border:1px solid rgba(255,255,255,.18);\r\n    background:rgba(0,0,0,.25);color:#f3fff9;\">\r\n\r\n  <div style=\"display:flex;gap:10px;flex-wrap:wrap;align-items:center;\">\r\n    <button class=\"btnLoadUrl\" type=\"button\"\r\n      style=\"padding:9px 12px;border-radius:10px;border:0;background:#00d084;color:#000;font-weight:900;cursor:pointer;\">\r\n      Load From URL\r\n    <\/button>\r\n\r\n    <button class=\"btnUrlExample\" type=\"button\"\r\n      style=\"padding:9px 12px;border-radius:10px;border:1px solid rgba(255,255,255,.18);\r\n      background:rgba(0,0,0,.25);color:#f3fff9;cursor:pointer;\">\r\n      Use Example URL\r\n    <\/button>\r\n\r\n    <span class=\"urlStatus\" style=\"font-size:12px;opacity:.85;\"><\/span>\r\n  <\/div>\r\n\r\n  <div style=\"font-size:12px;opacity:.85;line-height:1.35;\">\r\n    Tip: If the load fails, it\u2019s usually CORS or the CSV isn\u2019t publicly accessible.\r\n    Best is to host the CSV on the same domain (studio1live.com).\r\n  <\/div>\r\n<\/div>\r\n\r\n    <\/div>\r\n\r\n    <div style=\"display:flex;gap:10px;flex-wrap:wrap;margin-top:12px;\">\r\n      <button class=\"btnAdd\" type=\"button\"\r\n        style=\"padding:9px 12px;border-radius:10px;border:1px solid rgba(255,255,255,.18);\r\n        background:rgba(0,0,0,.25);color:#f3fff9;cursor:pointer;\">+ Add Row<\/button>\r\n\r\n      <button class=\"btnRun\" type=\"button\"\r\n        style=\"padding:9px 12px;border-radius:10px;border:0;background:#00d084;color:#000;font-weight:900;cursor:pointer;\">\r\n        Run Scores\r\n      <\/button>\r\n\r\n      <button class=\"btnExport\" type=\"button\"\r\n        style=\"padding:9px 12px;border-radius:10px;border:1px solid rgba(255,255,255,.18);\r\n        background:rgba(0,0,0,.25);color:#f3fff9;cursor:pointer;\">Export CSV<\/button>\r\n\r\n      <button class=\"btnClear\" type=\"button\"\r\n        style=\"padding:9px 12px;border-radius:10px;border:0;background:#ff3f6c;color:#000;font-weight:900;cursor:pointer;\">\r\n        Clear \/ Reset\r\n      <\/button>\r\n    <\/div>\r\n\r\n    <div class=\"out\" style=\"margin-top:14px;\"><\/div>\r\n  <\/div>\r\n  \n\n\n\n<p><a href=\"https:\/\/studio1live.com\/college-football-roster-sweetspot\">https:\/\/studio1live.com\/college-football-roster-sweetspot<\/a><\/p>\n\n\n\n<p><\/p>\n<\/body>","protected":false},"excerpt":{"rendered":"<p>From Canes Insight to Code: Finding College Football\u2019s Portal \u201cSweet Spot\u201d I was watching Canes Insight the other day, listening to Steve Kim, when he said something that stuck with me. Paraphrasing, he wondered out loud if there was a \u201csweet spot\u201d in the transfer portal era \u2014 not too portal-heavy, not too old-school high-school [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-590","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"jetpack_featured_media_url":"","jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/studio1live.com\/picks\/wp-json\/wp\/v2\/posts\/590","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/studio1live.com\/picks\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/studio1live.com\/picks\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/studio1live.com\/picks\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/studio1live.com\/picks\/wp-json\/wp\/v2\/comments?post=590"}],"version-history":[{"count":5,"href":"https:\/\/studio1live.com\/picks\/wp-json\/wp\/v2\/posts\/590\/revisions"}],"predecessor-version":[{"id":601,"href":"https:\/\/studio1live.com\/picks\/wp-json\/wp\/v2\/posts\/590\/revisions\/601"}],"wp:attachment":[{"href":"https:\/\/studio1live.com\/picks\/wp-json\/wp\/v2\/media?parent=590"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/studio1live.com\/picks\/wp-json\/wp\/v2\/categories?post=590"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/studio1live.com\/picks\/wp-json\/wp\/v2\/tags?post=590"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}