No dejés que la IA piense por vos — Guía para aprender a programar en la era de la IA
| <!doctype html> | |
| <html lang="es"> | |
| <head> | |
| No dejés que la IA piense por vos · video explicativo | |
| /* Gentleman-Cute palette (themes/Gentleman-Cute.json) */ | |
| :root { | |
| --bg: #060407; | |
| --panel: #100A0F; | |
| --user: #2A1523; | |
| --border: #563040; | |
| --border-subtle: #2A1720; | |
| --text: #F6EFF3; | |
| --muted: #A78E9B; | |
| --dim: #76616B; | |
| --accent: #F095C8; | |
| --deep-pink: #C96AA2; | |
| --active-pink: #FFB1DD; | |
| --champagne: #E0C27A; | |
| --pearl: #D2CBD0; | |
| --soft-rose: #D7A0B8; | |
| --powder-blue: #A9C7EE; | |
| --mint: #B4E7C7; | |
| --peach: #F2B86D; | |
| --sky: #C4DAF6; | |
| --error: #FF718F; | |
| --sans: "Inter", "SF Pro Display", -apple-system, "Segoe UI", system-ui, sans-serif; | |
| --mono: "JetBrains Mono", "Iosevka", "SF Mono", ui-monospace, Menlo, monospace; | |
| } | |
| * { box-sizing: border-box; margin: 0; padding: 0; } | |
| html, body { height: 100%; background: var(--bg); color: var(--text); font-family: var(--sans); overflow: hidden; } | |
| /* stage: one absolutely positioned scene per storyboard beat */ | |
| .stage { position: relative; width: 100vw; height: 100vh; height: 100dvh; cursor: pointer; } | |
| .scene { | |
| position: absolute; inset: 0; | |
| display: flex; flex-direction: column; justify-content: flex-start; | |
| overflow: hidden; | |
| padding: 6vh 7vw 170px; | |
| opacity: 0; pointer-events: none; | |
| transform: translateY(14px) scale(.99); | |
| transition: opacity .45s ease, transform .45s ease; | |
| background: | |
| radial-gradient(1200px 600px at 110% -10%, rgba(240,149,200,.13), transparent 60%), | |
| radial-gradient(900px 500px at -10% 120%, rgba(169,199,238,.08), transparent 60%), | |
| var(--bg); | |
| } | |
| .scene.active { opacity: 1; pointer-events: auto; transform: none; } | |
| .scene::before { content: ""; margin-top: auto; } | |
| .scene::after { content: ""; margin-bottom: auto; } | |
| .scene > * { flex-shrink: 0; } | |
| /* typography */ | |
| .kicker { font-family: var(--mono); font-size: 1.05rem; letter-spacing: .18em; text-transform: uppercase; color: var(--accent); margin-bottom: 1.4vh; } | |
| .kicker::before { content: "✿ "; color: var(--soft-rose); } | |
| h1 { font-size: clamp(2.6rem, 6vw, 5.6rem); line-height: 1.02; font-weight: 800; letter-spacing: -.03em; } | |
| h2 { font-size: clamp(2rem, 3.4vw, 3.2rem); line-height: 1.08; font-weight: 750; letter-spacing: -.02em; margin-bottom: 3vh; } | |
| h3 { font-size: 1.3rem; color: var(--champagne); margin-bottom: .6rem; font-weight: 700; } | |
| p, li { font-size: clamp(1.05rem, 1.4vw, 1.4rem); line-height: 1.5; color: var(--pearl); } | |
| .lead { font-size: clamp(1.2rem, 1.8vw, 1.7rem); color: var(--muted); max-width: 62ch; margin-top: 2.4vh; } | |
| .pink { color: var(--accent); } .gold { color: var(--champagne); } .mint { color: var(--mint); } | |
| .blue { color: var(--powder-blue); } .rose { color: var(--soft-rose); } .peach { color: var(--peach); } | |
| .red { color: var(--error); } | |
| .muted { color: var(--muted); } .dim { color: var(--dim); } | |
| .grad { background: linear-gradient(90deg, var(--active-pink), var(--accent) 45%, var(--champagne)); -webkit-background-clip: text; background-clip: text; color: transparent; } | |
| code, .mono { font-family: var(--mono); } | |
| code { background: var(--user); color: var(--champagne); padding: .1em .4em; border-radius: 6px; font-size: .9em; } | |
| .sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; } | |
| /* layout helpers */ | |
| .grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 3vw; align-items: center; } | |
| .grid-2:has(> .card) { align-items: stretch; } | |
| .grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2vw; } | |
| .grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.6vw; } | |
| .split { display: grid; grid-template-columns: 5fr 7fr; gap: 3.5vw; align-items: center; } | |
| .card { | |
| background: linear-gradient(180deg, rgba(42,21,35,.55), rgba(16,10,15,.9)); | |
| border: 1px solid var(--border-subtle); border-radius: 18px; padding: 2.6vh 1.6vw; | |
| box-shadow: 0 0 0 1px rgba(240,149,200,.04), 0 18px 40px -24px rgba(240,149,200,.35); | |
| } | |
| .card p, .card li { font-size: clamp(.95rem, 1.2vw, 1.2rem); } | |
| .card .icon { font-size: 2rem; margin-bottom: .8rem; display: block; } | |
| .card.accent { border-color: var(--border); } | |
| .quote { border-left: 4px solid var(--deep-pink); padding: 1.2vh 1.4vw; background: rgba(42,21,35,.45); border-radius: 0 14px 14px 0; font-size: clamp(1.15rem, 1.6vw, 1.5rem); color: var(--text); margin-top: 3vh; } | |
| .pill { display: inline-block; font-family: var(--mono); font-size: .85rem; padding: .25em .8em; border-radius: 999px; border: 1px solid var(--border); color: var(--active-pink); background: rgba(240,149,200,.07); margin: 0 .4em .4em 0; } | |
| /* terminal */ | |
| .term { background: var(--panel); border: 1px solid var(--border); border-radius: 14px; overflow: hidden; font-family: var(--mono); box-shadow: 0 30px 60px -30px rgba(240,149,200,.4); } | |
| .term .bar { display: flex; gap: 8px; padding: 10px 14px; border-bottom: 1px solid var(--border-subtle); background: #0b070a; align-items: center; } | |
| .term .bar i { width: 12px; height: 12px; border-radius: 50%; background: var(--border); } | |
| .term .bar i:nth-child(1) { background: var(--error); } .term .bar i:nth-child(2) { background: var(--peach); } .term .bar i:nth-child(3) { background: var(--mint); } | |
| .term .bar span { margin-left: auto; color: var(--dim); font-size: .85rem; } | |
| .term pre { padding: 2.2vh 1.6vw; font-size: clamp(.9rem, 1.2vw, 1.15rem); line-height: 1.7; color: var(--text); white-space: pre-wrap; } | |
| .term .c { color: var(--dim); } .term .p { color: var(--accent); } .term .k { color: var(--champagne); } .term .s { color: var(--mint); } .term .e { color: var(--error); } | |
| /* steps */ | |
| .steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.2vw; margin-top: 2vh; } | |
| .step { background: var(--panel); border: 1px solid var(--border-subtle); border-radius: 14px; padding: 2.4vh 1.2vw; } | |
| .step b { display: block; font-family: var(--mono); color: var(--accent); font-size: 1.5rem; } | |
| .step span { display: block; color: var(--champagne); font-weight: 700; margin: .5rem 0 .6rem; font-size: 1.15rem; } | |
| .step small { color: var(--pearl); font-size: clamp(.9rem, 1.1vw, 1.08rem); line-height: 1.45; display: block; } | |
| .step.hl { border-color: var(--accent); background: linear-gradient(180deg, rgba(240,149,200,.14), var(--panel)); } | |
| .step.bad { border-color: #6a2b3a; } | |
| /* table */ | |
| table { width: 100%; border-collapse: collapse; font-size: clamp(.95rem, 1.2vw, 1.15rem); } | |
| th { text-align: left; color: var(--champagne); font-weight: 700; padding: 1.2vh .8vw; border-bottom: 1px solid var(--border); } | |
| td { padding: 1.1vh .8vw; border-bottom: 1px solid var(--border-subtle); color: var(--pearl); vertical-align: top; } | |
| td:first-child { font-family: var(--mono); color: var(--accent); white-space: nowrap; } | |
| /* petals */ | |
| .petals { position: absolute; inset: 0; pointer-events: none; overflow: hidden; } | |
| .petals span { position: absolute; top: -5vh; font-size: 1.4rem; color: var(--soft-rose); opacity: .35; animation: fall linear infinite; } | |
| @keyframes fall { to { transform: translateY(115vh) rotate(360deg); } } | |
| /* ------------------------------------------------------------------ | |
| Timed builds. Every element with data-t gets .on while the scene clock | |
| is past its cue. Base styles are the END state; :not(.on) holds the | |
| start state, and .on plays a "from" animation, so reduced motion (no | |
| animations, every cue on) lands directly on the static end state. | |
| ------------------------------------------------------------------ */ | |
| .fx-fade:not(.on) { opacity: 0; transform: translateY(16px); } | |
| .fx-fade.on { animation: fadeUp .6s ease both; } | |
| @keyframes fadeUp { from { opacity: 0; transform: translateY(16px); } } | |
| .fx-right:not(.on) { opacity: 0; transform: translateX(60px); } | |
| .fx-right.on { animation: fromRight .6s cubic-bezier(.2,.9,.3,1.15) both; } | |
| @keyframes fromRight { from { opacity: 0; transform: translateX(60px); } } | |
| .fx-pop:not(.on) { opacity: 0; transform: scale(.6); } | |
| .fx-pop.on { animation: pop .45s cubic-bezier(.2,1.5,.4,1) both; } | |
| @keyframes pop { from { opacity: 0; transform: scale(.6); } } | |
| .fx-slam:not(.on) { opacity: 0; transform: scale(1.7) rotate(-4deg); } | |
| .fx-slam.on { animation: slam .55s cubic-bezier(.2,1.4,.4,1) both; } | |
| @keyframes slam { 0% { opacity: 0; transform: scale(1.7) rotate(-4deg); } 60% { opacity: 1; transform: scale(.95); } } | |
| .fx-zoom { transform: scale(1.07); } | |
| .fx-zoom:not(.on) { opacity: 0; transform: scale(1.9) rotate(3deg); } | |
| .fx-zoom.on { animation: zoomSlam 1s cubic-bezier(.2,1.4,.4,1) both; } | |
| @keyframes zoomSlam { 0% { opacity: 0; transform: scale(1.9) rotate(3deg); } 35% { opacity: 1; transform: scale(.96); } 55% { transform: scale(1); } 75% { transform: scale(1.12); } } | |
| .fx-type { display: inline-block; overflow: hidden; white-space: nowrap; vertical-align: bottom; width: calc(var(--n) * 1ch); } | |
| .fx-type:not(.on) { width: 0; } | |
| .fx-type.on { animation: type calc(var(--n) * .055s) steps(var(--n)) both; } | |
| @keyframes type { from { width: 0; } } | |
| .fx-strike { position: relative; display: inline-block; } | |
| .fx-strike::after { content: ""; position: absolute; left: -2px; right: -2px; top: 52%; height: 3px; border-radius: 2px; background: var(--error); transform-origin: left; } | |
| .fx-strike:not(.on)::after { transform: scaleX(0); } | |
| .fx-strike.on::after { animation: strike .5s ease both; } | |
| @keyframes strike { from { transform: scaleX(0); } } | |
| .fx-dim.on { opacity: .38; filter: grayscale(.75); transform: scale(.97); animation: dim .9s ease both; } | |
| @keyframes dim { from { opacity: 1; filter: none; transform: none; } } | |
| .hl { transition: background .35s ease, box-shadow .35s ease, color .35s ease; } | |
| /* growth vs wither motif (from the gym scene, reused later) */ | |
| .meter { display: inline-block; width: 120px; height: 8px; border-radius: 99px; background: var(--panel); border: 1px solid var(--border-subtle); overflow: hidden; vertical-align: middle; } | |
| .meter i { display: block; height: 100%; border-radius: 99px; } | |
| .meter.grow i { width: 92%; background: linear-gradient(90deg, #6fbf92, var(--mint)); } | |
| .meter.wither i { width: 10%; background: linear-gradient(90deg, #c94a66, var(--error)); } | |
| .scene.active .meter.grow i { animation: growMotif 7s ease-in-out infinite; } | |
| .scene.active .meter.wither i { animation: witherMotif 7s ease-in-out infinite; } | |
| @keyframes growMotif { 0% { width: 12%; } 70%, 100% { width: 92%; } } | |
| @keyframes witherMotif { 0% { width: 85%; } 70%, 100% { width: 10%; } } | |
| .motif { display: inline-flex; align-items: center; gap: .6em; font-family: var(--mono); font-size: .9rem; color: var(--muted); } | |
| /* ---------- scene 1: hook ---------- */ | |
| .placas { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.6vw; margin-top: 4vh; } | |
| .placa { border: 1px solid var(--border); border-radius: 16px; padding: 2.4vh 1.4vw; background: linear-gradient(180deg, rgba(42,21,35,.8), rgba(16,10,15,.95)); box-shadow: 0 20px 50px -25px rgba(255,113,143,.5); } | |
| .placa .who { font-family: var(--mono); color: var(--champagne); letter-spacing: .12em; text-transform: uppercase; font-size: .95rem; } | |
| .placa .what { display: block; font-size: clamp(1.3rem, 2vw, 1.9rem); font-weight: 800; color: var(--text); margin-top: .4rem; } | |
| .placa .ico { font-size: 1.8rem; float: right; } | |
| .middle { display: flex; align-items: center; justify-content: center; gap: 1.6vw; margin-top: 4vh; } | |
| .middle svg { width: 74px; height: 110px; } | |
| .middle .yv { font-size: clamp(2rem, 3.6vw, 3.4rem); font-weight: 800; letter-spacing: -.02em; } | |
| .tag-bad { font-family: var(--mono); font-size: 1.1rem; color: var(--error); border: 1px solid #6a2b3a; border-radius: 999px; padding: .3em .9em; background: rgba(255,113,143,.08); } | |
| .scene.active .tag-bad.on { animation: pop .45s cubic-bezier(.2,1.5,.4,1) both, shake 4s ease-in-out 1s infinite; } | |
| @keyframes shake { 0%, 90%, 100% { transform: none; } 92% { transform: translateX(-4px); } 94% { transform: translateX(4px); } 96% { transform: translateX(-3px); } } | |
| .stick line, .stick circle { stroke: var(--accent); stroke-width: 5; stroke-linecap: round; fill: none; } | |
| .scene.active .stick { animation: breathe 3s ease-in-out infinite; transform-origin: 50% 100%; } | |
| @keyframes breathe { 50% { transform: scaleY(1.03); } } | |
| /* ---------- scene 2: gym ---------- */ | |
| .gym-panel { display: grid; grid-template-columns: 1fr; gap: 1.2vh; } | |
| .gym-panel h3 { display: flex; align-items: center; gap: .5em; } | |
| .gym-panel.good { border-color: rgba(180,231,199,.35); } | |
| .gym-panel.bad { border-color: #6a2b3a; } | |
| .gym { width: 100%; height: 200px; } | |
| .gym .frame { fill: none; stroke: var(--border); stroke-width: 3; } | |
| .gym .plate { fill: var(--user); stroke: var(--border); stroke-width: 2; } | |
| .gym .lift .plate { fill: var(--deep-pink); } | |
| .gym .fig line, .gym .fig circle { stroke-linecap: round; fill: none; } | |
| .gym .fig rect { fill: var(--champagne); } | |
| .gym .gear { font-size: 22px; fill: var(--muted); transform-box: fill-box; transform-origin: center; } | |
| .good .gym .fig line, .good .gym .fig circle { stroke: var(--mint); stroke-width: 9; } | |
| .bad .gym .fig line, .bad .gym .fig circle { stroke: var(--error); stroke-width: 2.5; } | |
| .bad .gym .fig { opacity: .5; transform-origin: 90px 192px; transform: rotate(7deg) translateY(4px); } | |
| .gym .arm { transform-origin: 90px 76px; } | |
| .scene.active .gym .arm.l { animation: repL 2.4s ease-in-out infinite; } | |
| .scene.active .gym .arm.r { animation: repR 2.4s ease-in-out infinite; } | |
| .scene.active .gym .lift { animation: liftStack 2.4s ease-in-out infinite; } | |
| .scene.active .good .gym .fig line, .scene.active .good .gym .fig circle { animation: buff 18s ease-out infinite; } | |
| .scene.active .bad .gym .fig line, .scene.active .bad .gym .fig circle { animation: atrophy 18s ease-in infinite; } | |
| .scene.active .bad .gym .fig { animation: droop 18s ease-in infinite; } | |
| .scene.active .good .gym .gear { animation: spin 6s linear infinite; } | |
| .scene.active .bad .gym .gear { animation: spin .8s linear infinite; } | |
| @keyframes repL { 50% { transform: rotate(58deg); } } | |
| @keyframes repR { 50% { transform: rotate(-58deg); } } | |
| @keyframes liftStack { 50% { transform: translateY(-46px); } } | |
| @keyframes buff { 0% { stroke-width: 3.5; } 75%, 100% { stroke-width: 9; } } | |
| @keyframes atrophy { 0% { stroke-width: 7; } 75%, 100% { stroke-width: 2.5; } } | |
| @keyframes droop { 0% { opacity: 1; transform: none; } 75%, 100% { opacity: .5; transform: rotate(7deg) translateY(4px); } } | |
| @keyframes spin { to { transform: rotate(360deg); } } | |
| .strength { display: grid; grid-template-columns: auto 1fr; gap: .8vw; align-items: center; font-family: var(--mono); font-size: .95rem; color: var(--muted); } | |
| .strength .meter { width: 100%; height: 14px; } | |
| .scene.active .good .strength .meter i { animation: growMotif 18s ease-out infinite; } | |
| .scene.active .bad .strength .meter i { animation: witherMotif 18s ease-in infinite; } | |
| .pips { display: inline-flex; gap: .5vw; margin-left: 1vw; vertical-align: middle; } | |
| .pips i { width: 22px; height: 22px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 14px rgba(240,149,200,.6); display: inline-block; } | |
| /* ---------- scene 3: timeline ---------- */ | |
| .timeline { display: grid; grid-template-columns: 1fr 1fr 1fr; position: relative; margin-top: 1vh; } | |
| .tl-track { position: absolute; left: 16.66%; right: 16.66%; top: 48px; height: 4px; background: var(--border-subtle); border-radius: 4px; display: grid; grid-template-columns: 1fr 1fr; } | |
| .tl-track i { display: block; height: 100%; background: linear-gradient(90deg, var(--deep-pink), var(--accent)); transform-origin: left; } | |
| .tl-track i:not(.on) { transform: scaleX(0); } | |
| .tl-track i.on { animation: strike .8s ease both; } | |
| .tl-step { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 1.2vh; position: relative; } | |
| .tl-node { width: 96px; height: 96px; border-radius: 50%; display: grid; place-items: center; font-size: 2.4rem; background: var(--panel); border: 2px solid var(--accent); box-shadow: 0 0 34px rgba(240,149,200,.45); } | |
| .tl-node:not(.on) { border-color: var(--border-subtle); box-shadow: none; filter: grayscale(1) brightness(.5); } | |
| .tl-node.on { animation: lightUp .7s ease both; } | |
| @keyframes lightUp { 0% { border-color: var(--border-subtle); box-shadow: none; filter: grayscale(1) brightness(.5); transform: scale(.8); } 60% { transform: scale(1.12); } } | |
| .tl-year { font-family: var(--mono); font-weight: 800; font-size: 1.6rem; color: var(--champagne); } | |
| .tl-what { font-size: 1.15rem; color: var(--pearl); } | |
| .tl-tags { display: flex; flex-direction: column; gap: .6vh; align-items: center; min-height: 128px; } | |
| .tag { font-family: var(--mono); font-size: 1rem; padding: .25em .9em; border-radius: 999px; border: 1px solid; } | |
| .tag.t1 { color: var(--error); border-color: #6a2b3a; background: rgba(255,113,143,.08); } | |
| .tag.t2 { color: var(--peach); border-color: #6b4a22; background: rgba(242,184,109,.08); } | |
| .tag.t3 { color: var(--mint); border-color: #2f5a42; background: rgba(180,231,199,.08); } | |
| .scene.active .tl-step:last-child .tag.t3.on { animation: pop .45s cubic-bezier(.2,1.5,.4,1) both, glowMint 2.2s ease-in-out 1s infinite; } | |
| @keyframes glowMint { 50% { box-shadow: 0 0 18px rgba(180,231,199,.55); } } | |
| .fixes { display: flex; gap: 1vw; flex-wrap: wrap; margin-top: 2vh; } | |
| .fixes .pill { font-size: 1rem; padding: .4em 1em; } | |
| /* ---------- scene 4: four steps ---------- */ | |
| .rule-card h3 { font-size: 1.2rem; } | |
| .rule-card p { color: var(--text); font-weight: 600; font-size: clamp(1.1rem, 1.45vw, 1.4rem); } | |
| .rule-card.hl.on { border-color: var(--accent); box-shadow: 0 0 0 1px rgba(240,149,200,.35), 0 18px 40px -20px rgba(240,149,200,.6); } | |
| .seq { grid-template-columns: repeat(4, 1fr); } | |
| .seq .step { position: relative; overflow: hidden; transition: border-color .3s ease, background .3s ease; } | |
| .seq .step .fill { position: absolute; left: 0; bottom: 0; height: 4px; width: 100%; background: linear-gradient(90deg, var(--deep-pink), var(--accent), var(--champagne)); } | |
| .seq .step:not(.on) { border-color: var(--border-subtle); } | |
| .seq .step:not(.on) b { color: var(--dim); } | |
| .seq .step:not(.on) span { color: var(--muted); } | |
| .seq .step:not(.on) .fill { width: 0; } | |
| .seq .step.on { border-color: var(--accent); background: linear-gradient(180deg, rgba(240,149,200,.14), var(--panel)); } | |
| .seq .step.on .fill { animation: fillX 1.4s ease both; } | |
| @keyframes fillX { from { width: 0; } } | |
| .seq-meta { display: flex; justify-content: space-between; align-items: center; margin-top: 2vh; } | |
| .seg { display: inline-flex; gap: 4px; } | |
| .seg i { width: 34px; height: 12px; border-radius: 3px; background: var(--mint); display: inline-block; } | |
| .seg i:not(.on) { background: var(--panel); outline: 1px solid var(--border-subtle); } | |
| /* ---------- scene 5: two prompts ---------- */ | |
| .term.bad-t { border-color: #6a2b3a; } | |
| .term.good-t { border-color: rgba(180,231,199,.45); } | |
| .term .tline { display: block; } | |
| .term .res { display: block; margin-top: 1.4vh; font-family: var(--sans); font-size: clamp(1rem, 1.25vw, 1.2rem); } | |
| .term pre { min-height: 190px; } | |
| .caret { display: inline-block; width: .6ch; height: 1.1em; background: var(--mint); vertical-align: text-bottom; margin-left: 2px; } | |
| .scene.active .caret { animation: blink 1s step-end infinite; } | |
| @keyframes blink { 50% { opacity: 0; } } | |
| .term.good-t.glow.on { box-shadow: 0 0 0 1px rgba(180,231,199,.5), 0 0 50px -10px rgba(180,231,199,.45); } | |
| .scene.active .term.good-t.glow.on { animation: glowPulse 2.6s ease-in-out infinite; } | |
| @keyframes glowPulse { 50% { box-shadow: 0 0 0 1px rgba(180,231,199,.8), 0 0 70px -6px rgba(180,231,199,.6); } } | |
| .verdict { display: flex; justify-content: space-between; align-items: center; margin-top: 1.6vh; } | |
| /* ---------- scene 6: checks + delegation table ---------- */ | |
| .checks { list-style: none; display: grid; gap: 2vh; } | |
| .chk { display: grid; grid-template-columns: 34px 1fr; gap: .9vw; align-items: center; } | |
| .chk .box { width: 30px; height: 30px; border-radius: 8px; border: 2px solid var(--mint); background: rgba(180,231,199,.14); display: grid; place-items: center; color: var(--mint); font-weight: 800; font-size: 1.1rem; } | |
| .chk .box i { font-style: normal; } | |
| .chk span { color: var(--text); } | |
| .chk:not(.on) .box { border-color: var(--border); background: transparent; } | |
| .chk:not(.on) .box i { opacity: 0; transform: scale(0); display: inline-block; } | |
| .chk:not(.on) span { color: var(--muted); } | |
| .chk.on .box i { display: inline-block; animation: pop .4s cubic-bezier(.2,1.6,.4,1) both; } | |
| .deleg th.more { color: var(--mint); } .deleg th.less { color: var(--error); } | |
| .deleg td { font-family: var(--sans) !important; white-space: normal !important; color: var(--pearl) !important; border-radius: 8px; } | |
| .deleg td.hl.on.m { background: rgba(180,231,199,.14); box-shadow: inset 3px 0 0 var(--mint); color: var(--text) !important; } | |
| .deleg td.hl.on.l { background: rgba(255,113,143,.14); box-shadow: inset 3px 0 0 var(--error); color: var(--text) !important; } | |
| .gradient-axis { display: flex; justify-content: space-between; font-family: var(--mono); font-size: .9rem; margin-bottom: 1vh; } | |
| .gradient-axis + .axis { height: 6px; border-radius: 6px; background: linear-gradient(90deg, var(--mint), var(--peach), var(--error)); margin-bottom: 1.4vh; } | |
| /* ---------- scene 7: notes + calendar ---------- */ | |
| .notes pre { min-height: 250px; } | |
| .notes .nl { display: block; } | |
| .cal { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.2vw 1vw; } | |
| .month b { display: block; font-family: var(--mono); font-size: .8rem; color: var(--muted); letter-spacing: .1em; margin-bottom: .4vh; } | |
| .days { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; } | |
| .days i { aspect-ratio: 1; border-radius: 3px; background: var(--border-subtle); display: block; } | |
| .days i.pick { background: var(--accent); box-shadow: 0 0 10px rgba(240,149,200,.7); } | |
| .days i.pick:not(.on) { background: var(--border-subtle); box-shadow: none; } | |
| .days i.pick.on { animation: pop .4s cubic-bezier(.2,1.6,.4,1) both; } | |
| .scene.active .days i.pick.on { animation: pop .4s cubic-bezier(.2,1.6,.4,1) both, dayPulse 1.6s ease-in-out .4s infinite; } | |
| @keyframes dayPulse { 50% { transform: scale(1.5); box-shadow: 0 0 16px rgba(240,149,200,1); } } | |
| /* ---------- scene 8: five cards ---------- */ | |
| .five { display: grid; gap: 1.3vh; } | |
| .five .card { display: grid; grid-template-columns: 64px 1fr; gap: 1.2vw; align-items: center; padding: 1.5vh 1.4vw; transition: border-color .4s ease; } | |
| .five .num { font-family: var(--mono); font-weight: 800; font-size: 2rem; color: var(--accent); text-align: center; } | |
| .five strong { display: block; color: var(--text); font-size: clamp(1.1rem, 1.45vw, 1.4rem); } | |
| .five small { color: var(--muted); font-size: clamp(.92rem, 1.1vw, 1.05rem); } | |
| .five .card.now.on { border-color: var(--accent); } | |
| .five .now-wrap { position: relative; } | |
| /* ---------- scene 9: cycle + checklist ---------- */ | |
| .cycle { position: relative; width: 360px; height: 360px; margin: 0 auto; } | |
| .cycle svg { position: absolute; inset: 0; } | |
| .cycle circle { fill: none; stroke: var(--border); stroke-width: 2; stroke-dasharray: 6 8; } | |
| .node { position: absolute; transform: translate(-50%, -50%); font-family: var(--mono); font-weight: 700; font-size: 1rem; padding: .45em .9em; border-radius: 999px; background: var(--panel); border: 1px solid var(--accent); color: var(--active-pink); white-space: nowrap; z-index: 2; } | |
| .node small { display: block; font-size: .7rem; color: inherit; opacity: .75; font-weight: 400; text-align: center; } | |
| .node.n1 { left: 180px; top: 30px; } .node.n2 { left: 330px; top: 180px; } .node.n3 { left: 180px; top: 330px; } .node.n4 { left: 30px; top: 180px; } | |
| /* each node lights from just before the traveling dot arrives until just after it leaves */ | |
| .scene.active .node { animation: nodeLit 8s linear -.4s infinite; } | |
| .scene.active .node.n2 { animation-delay: 1.6s; } .scene.active .node.n3 { animation-delay: 3.6s; } .scene.active .node.n4 { animation-delay: 5.6s; } | |
| @keyframes nodeLit { 0%, 14% { background: var(--accent); color: var(--bg); box-shadow: 0 0 26px rgba(240,149,200,.8); } 20%, 100% { background: var(--panel); color: var(--active-pink); box-shadow: none; } } | |
| .dot-travel { position: absolute; left: 0; top: 0; width: 18px; height: 18px; border-radius: 50%; background: var(--champagne); box-shadow: 0 0 18px var(--champagne); offset-path: path("M180,30 A150,150 0 1 1 179.99,30"); offset-rotate: 0deg; offset-distance: 0%; z-index: 1; } | |
| .scene.active .dot-travel { animation: travel 8s linear infinite; } | |
| @keyframes travel { to { offset-distance: 100%; } } | |
| .cycle .center { position: absolute; inset: 0; display: grid; place-items: center; text-align: center; font-family: var(--mono); color: var(--muted); font-size: .95rem; line-height: 1.5; } | |
| .cycle .center b { color: var(--champagne); display: block; font-size: 1.1rem; } | |
| .crit .checks { gap: 1.4vh; } | |
| .crit .chk span { font-size: clamp(.95rem, 1.2vw, 1.15rem); } | |
| /* ---------- scene 10: close ---------- */ | |
| .close h1 { font-size: clamp(2.6rem, 5.4vw, 5.2rem); } | |
| .close h1:not(.on) { opacity: 0; transform: scale(.55); filter: blur(8px); } | |
| .close h1.on { animation: bigIn 1.4s cubic-bezier(.2,1.2,.3,1) both; } | |
| @keyframes bigIn { from { opacity: 0; transform: scale(.55); filter: blur(8px); } } | |
| .close h1 { transform-origin: left center; } | |
| .gist-url { font-family: var(--mono); font-size: clamp(1rem, 1.4vw, 1.35rem); color: var(--champagne); margin-top: 3vh; display: inline-block; border: 1px solid var(--border); border-radius: 12px; padding: .5em 1em; background: rgba(42,21,35,.5); text-decoration: none; } | |
| .close-row { display: grid; grid-template-columns: 1fr 1fr; gap: 3vw; align-items: end; margin-top: 3vh; } | |
| .close .term pre { font-size: clamp(.85rem, 1.05vw, 1.05rem); min-height: 0; } | |
| /* ---------- player chrome ---------- */ | |
| .brand { position: fixed; left: 2vw; top: 2vh; font-family: var(--mono); color: var(--dim); font-size: .9rem; z-index: 10; } | |
| .brand b { color: var(--accent); font-weight: 600; } | |
| .hint { position: fixed; top: 2vh; right: 2vw; font-family: var(--mono); color: var(--dim); font-size: .8rem; z-index: 10; transition: opacity 1s; } | |
| #pause-badge { position: fixed; top: 2vh; left: 50%; transform: translateX(-50%); z-index: 12; font-family: var(--mono); font-weight: 800; letter-spacing: .3em; color: var(--bg); background: var(--accent); padding: .35em 1.1em; border-radius: 999px; font-size: .95rem; box-shadow: 0 0 30px rgba(240,149,200,.5); } | |
| body:not(.paused) #pause-badge { display: none; } | |
| #big-play { position: fixed; inset: 0; margin: auto; width: 220px; height: 220px; border-radius: 50%; z-index: 13; border: 2px solid var(--accent); background: rgba(16,10,15,.92); color: var(--active-pink); font: 700 1.25rem/1.3 var(--sans); cursor: pointer; display: grid; place-items: center; box-shadow: 0 0 60px rgba(240,149,200,.35); } | |
| #big-play span span { display: block; font-size: 3rem; line-height: 1; margin-bottom: .3rem; } | |
| #big-play[hidden] { display: none; } | |
| #caption { position: fixed; left: 50%; bottom: 82px; transform: translateX(-50%); width: min(1100px, 86vw); text-align: center; z-index: 9; font-size: clamp(1rem, 1.3vw, 1.25rem); line-height: 1.45; color: var(--text); background: rgba(6,4,7,.82); border: 1px solid var(--border-subtle); border-radius: 12px; padding: .55em 1.1em; min-height: 2.9em; display: flex; align-items: center; justify-content: center; } | |
| body.no-cc #caption { display: none; } | |
| .controls { position: fixed; left: 0; right: 0; bottom: 0; height: 66px; z-index: 11; display: flex; align-items: center; gap: 12px; padding: 0 18px; background: linear-gradient(180deg, rgba(6,4,7,.4), rgba(6,4,7,.95)); border-top: 1px solid var(--border-subtle); font-family: var(--mono); } | |
| .controls button { background: transparent; border: 1px solid var(--border); color: var(--active-pink); border-radius: 10px; height: 38px; min-width: 38px; padding: 0 10px; font: 700 1rem/1 var(--mono); cursor: pointer; } | |
| .controls button:hover, .controls button:focus-visible { background: var(--user); outline: none; border-color: var(--accent); } | |
| #play { min-width: 46px; font-size: 1.1rem; } | |
| #time { color: var(--pearl); font-size: .95rem; white-space: nowrap; min-width: 12ch; } | |
| #progress-track { position: relative; flex: 1; height: 26px; cursor: pointer; touch-action: none; } | |
| #progress-track::before { content: ""; position: absolute; left: 0; right: 0; top: 10px; height: 6px; border-radius: 6px; background: var(--border-subtle); } | |
| #progress-track:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; } | |
| #progress { position: absolute; left: 0; top: 10px; height: 6px; border-radius: 6px; background: linear-gradient(90deg, var(--deep-pink), var(--accent), var(--champagne)); width: 0; pointer-events: none; } | |
| #progress::after { content: ""; position: absolute; right: -7px; top: -4px; width: 14px; height: 14px; border-radius: 50%; background: var(--active-pink); box-shadow: 0 0 10px rgba(240,149,200,.8); } | |
| .mark { position: absolute; top: 7px; width: 2px; height: 12px; background: var(--border); pointer-events: none; } | |
| #dots { display: flex; gap: 6px; } | |
| #dots button { width: 12px; min-width: 12px; height: 12px; padding: 0; border-radius: 50%; background: var(--border-subtle); border: 1px solid var(--border); } | |
| #dots button.cur { background: var(--accent); border-color: var(--accent); } | |
| #counter { color: var(--muted); font-size: .95rem; white-space: nowrap; } | |
| #scene-label { color: var(--champagne); font-size: .9rem; white-space: nowrap; max-width: 22ch; overflow: hidden; text-overflow: ellipsis; } | |
| @media (max-width: 1100px) { #dots, #scene-label, .brand { display: none; } } | |
| /* reduced motion: no ambient loops, every build lands on its static end state */ | |
| @media (prefers-reduced-motion: reduce) { | |
| .scene, .scene *, .scene *::before, .scene *::after { animation: none !important; transition: none !important; } | |
| .petals, .dot-travel { display: none; } | |
| .scene .node.n1 { background: var(--accent); color: var(--bg); } | |
| } | |
| body.paused .scene *, body.paused .scene *::before, body.paused .scene *::after { animation-play-state: paused !important; } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- 1. Gancho --> | |
| La universidad te prohíbe usar IA. Y el que te aprueba el TP es un profesor que lee diapositivas de hace seis años. Tu empresa te mete un agente en la notebook el lunes. Y vos en el medio, sin criterio. | |
| Gentleman Programming · guía | |
No dejés que la IA piense por vos | |
| 🏛️UniversidadIA prohibida | |
| 📽️Profesorleyendo diapositivas | |
| 💼Empresaagente instalado el lunes | |
| </div> | |
| y vos en el medio | |
| sin criterio | |
| </div> | |
| Hoy: las reglas para que la IA trabaje para vos y no piense por vos. Todo está publicado en un gist. | |
| </section> | |
| <!-- 2. Tesis: la máquina con asistencia --> | |
| Misma máquina, resultados opuestos. Uno usa la máquina para aprender el movimiento y se hace fuerte. El otro deja que la máquina haga todo y se atrofia. La herramienta no decide tu nivel: tu criterio decide tu nivel. | |
| La tesis | |
Misma máquina, resultados opuestos | |
↗ aprende el movimiento | |
| ⚙ | |
| </svg> | |
| fuerza | |
| Siente el músculo, corrige la técnica. A los seis meses levanta solo. | |
| </div> | |
↘ deja que la máquina haga todo | |
| ⚙ | |
| </svg> | |
| fuerza | |
| Asistencia al cien por ciento: la máquina hace el recorrido entero y vos te atrofiás. | |
| </div> | |
| </div> | |
| La herramienta no decide tu nivel. Tu criterio decide tu nivel, y la IA solo lo hace visible. | |
| ¿Cómo se entrena eso? Con reglas. Siete. | |
| </p> | |
| </section> | |
| <!-- 3. Universidad --> | |
| Calculadora en 1985, compilador en 2000, IA en 2026: primero se prohíbe, después se tolera, al final se exige. Se evalúa el producto y no el proceso. Evaluá la defensa. | |
| A la universidad | |
Prohibir no funciona | |
| 🧮 | |
| 1985calculadora | |
| prohibidatoleradaexigida | |
| </div> | |
| ⚙️ | |
| 2000compilador | |
| prohibidatoleradaexigida | |
| </div> | |
| 🤖 | |
| 2026IA | |
| prohibidatoleradaexigida | |
| </div> | |
| </div> | |
| El problema no es la herramienta. Se evalúa el producto final y no el proceso. | |
| 1 · evaluá la defensa, no el texto | |
| 2 · enseñá a usarla adentro del aula | |
| 3 · exigí el cómo, no solo el qué | |
| aprobalo, pero no lo confundas con aprender | |
| </div> | |
| </section> | |
| <!-- 4. Reglas 1 y 2 --> | |
| Regla 1: nunca entregues código que no podés explicar. Regla 2: primero intentá solo. La secuencia: intento, hipótesis, pregunta, comparación. | |
| Reglas 1 y 2 | |
El músculo crece en el intento | |
Regla 1Nunca entregues código que no podés explicar. | |
Regla 2Primero intentá solo. Después pedile a la IA. | |
| </div> | |
| 1IntentoSolo, aunque sea feo. Peleá veinte minutos. | |
| 2Hipótesis"Creo que falla porque..." | |
| 3PreguntaRecién ahí le preguntás a la IA. | |
| 4ComparaciónTu hipótesis contra su respuesta. | |
| </div> | |
| músculo | |
| La hipótesis previa convierte una respuesta en una lección. | |
| </div> | |
| </div> | |
| </section> | |
| <!-- 5. Regla 3 --> | |
| Prompt malo: haceme el TP de listas enlazadas. Prompt bueno: explicame por qué mi lista pierde memoria, haceme 3 preguntas antes de darme la solución. | |
| Regla 3 | |
Pedile que te explique, no que resuelva | |
| atajo | |
✗ haceme el TP de listas enlazadas→ un entregable que no entendés | |
| </div> | |
| clase particular | |
✓ explicame por qué mi lista pierde memoria. Haceme 3 preguntas antes de darme la solución→ un tutor infinito, a las tres de la mañana, que no te juzga | |
| </div> | |
| </div> | |
| atajo | |
| clase | |
| </div> | |
| </div> | |
| La misma IA, dos destinos. Todo depende de cómo le pedís las cosas. | |
| </section> | |
| <!-- 6. Reglas 4 y 5 --> | |
| Regla 4: verificá todo, la IA se equivoca con total confianza. Regla 5: cuanto más crítico es el código, menos delegás. | |
| Reglas 4 y 5 | |
Verificá todo. Dosificá la delegación. | |
Regla 4: la IA se equivoca con total confianza | |
| | |
| | |
| | |
| | |
| </ul> | |
| </div> | |
Regla 5: cuanto más crítico, menos delegás | |
| menos críticomás crítico | |
| Podés delegar másPodés delegar menos | |
| Un script de una sola vezMigraciones de datos | |
| Un componente visual aisladoAutenticación y permisos | |
| Datos de pruebaLógica que mueve dinero | |
| CSS, copy, namingConcurrencia y locks | |
| "¿Cómo se hacía esto?"Lo que otros sistemas consumen | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| En lo crítico, la IA te ayuda a entender, no a escribir. | |
| </section> | |
| <!-- 7. Reglas 6 y 7 --> | |
| Regla 6: anotá lo que aprendés con tus palabras. Regla 7: el test de la muleta, una vez por mes cerrás la IA y programás algo mediano solo, para medir. | |
| Reglas 6 y 7 | |
Cerrá el círculo y medí tu nivel | |
Regla 6: anotá lo que aprendés | |
| aprendizajes.md | |
# lo que aprendí, con mis palabras- useMemo: solo si el cálculo es caro- mi lista perdía memoria: no soltaba el nodo- el test falla si el input viene vacío- por qué el índice va en ese orden# dos semanas: tu propia documentación | |
| </div> | |
| "Usé IA" contra "aprendí". | |
| </div> | |
Regla 7: el test de la muleta | |
| Un día por mes, IA cerrada, algo mediano solo. Para medir. | |
| </div> | |
| </div> | |
| Lo que no podés hacer solo es tu plan de estudio, escrito por la realidad. | |
| </section> | |
| <!-- 8. Trabajo --> | |
| Cinco reglas para el trabajo: tu nombre va en el PR, nada de código de la empresa en chats públicos, los tests son tu seguro de vida, preguntale lo que no le preguntás a un humano, velocidad no es valor. | |
| Al que le metieron IA en el trabajo | |
Respirá. Cinco cosas. | |
| 1Tu nombre va en el PR, no el de la IA.Revisá el diff como si lo hubiera escrito el becario más nuevo del mundo. | |
| 2Cero código de la empresa en chats públicos.Credenciales, datos de clientes, esquemas de base de datos: afuera. | |
| 3Los tests son tu seguro de vida.Escribilos como primera prioridad. | |
| 4Preguntale lo que no le preguntás a un humano.¿Qué haría un senior acá? ¿Qué se rompe si toco esto? | |
| 5Velocidad no es valor.Dos horas que queman tres semanas de guardia son deuda con tu nombre. | |
| </div> | |
| </section> | |
| <!-- 9. Criticidad --> | |
| El criterio se entrena con un ciclo: hipótesis, predicción, intento, verificación. Checklist antes de dar algo por terminado. Si respondés no a más de dos, no está terminado: está entregado. | |
| Construir criticidad | |
El criterio es un ciclo | |
| hipótesisqué creés que pasa | |
| predicciónverificable | |
| intentoejecutá | |
| verificación¿pasó? | |
| la brechaentre predicción y realidad = aprendizaje | |
| </div> | |
Checklist antes de dar algo por terminado | |
| | |
| | |
| | |
| | |
| | |
| | |
| </ul> | |
| </div> | |
| </div> | |
| ¿"No" a más de dos? No está terminado. Está entregado. No es lo mismo. | |
| </section> | |
| <!-- 10. Cierre --> | |
| No dejés que la IA piense por vos. Dejala trabajar para vos. Todo está en el gist. | |
| Cierre | |
No dejés que la IA piense por vos. | |
| Las siete reglas, la tabla de qué delegar y el checklist. vos | |
| Nos vemos, mis locuritas cósmicas ✿ | |
| </div> | |
| terminal | |
$ gh gist view f9ea4c592d06556ed3b9445bf19dd9dc --filesindex.htmlno-dejes-que-la-ia-piense-por-vos.md | |
| </div> | |
| </div> | |
| </section> | |
| </main> | |
| gentleman programming · no dejés que la IA piense por vos | |
| Espacio reproducir/pausar · ← → escenas · F pantalla completa · C subtítulos | |
| ❚❚ PAUSA | |
| 00:00 / 08:15 | |
| 1 / 10 | |
| </div> | |
| // Per-beat durations from the storyboard, in seconds. Total 495 s = 08:15. | |
| const DUR = [35, 55, 60, 50, 50, 50, 50, 50, 50, 45]; | |
| const TOTAL = DUR.reduce((a, b) => a + b, 0); | |
| const START = DUR.map((_, k) => DUR.slice(0, k).reduce((a, b) => a + b, 0)); | |
| const TITLES = ['Gancho', 'La tesis', 'A la universidad', 'Reglas 1 y 2', 'Regla 3', 'Reglas 4 y 5', 'Reglas 6 y 7', 'En el trabajo', 'Criticidad', 'Cierre']; | |
| const VOICE = [ | |
| 'La universidad te prohíbe usar IA. Y el que te aprueba el TP es un profesor que lee diapositivas de hace seis años. Mientras tanto, tu empresa te mete un agente en la notebook el lunes y te espera productivo el martes. Y vos en el medio, sin criterio. Hoy no vengo a llorar por eso. Vengo a darte las reglas para que la IA trabaje para vos y no piense por vos. Todo esto ya está publicado en un gist que te dejo abajo.', | |
| 'Primero la tesis, porque si te la llevás, el video ya valió. En el gimnasio existen las máquinas con asistencia. Y hay dos tipos de persona. Uno usa la máquina para aprender el movimiento: siente el músculo, corrige la técnica, y a los seis meses levanta solo. El otro se sube, deja que la máquina haga el recorrido entero, y se atrofia. Misma máquina, resultados opuestos. La IA es esa máquina. La herramienta no decide tu nivel. Tu criterio decide tu nivel, y la IA solo lo hace visible. La pregunta entonces no es si usar IA. Es cómo usarla sin atrofiarte. ¿Y cómo se entrena eso? Con reglas. Siete, exactamente.', | |
| 'A la universidad le tengo que decir algo directo. Prohibir la IA en 2026 es como prohibir la calculadora en los 80. Primero se prohíbe, después se tolera, y al final la exige la oferta laboral. Ya vimos esa película tres veces. El problema real no es la herramienta. Es que se evalúa el producto final y no el proceso. Si el TP se entrega en un PDF que nadie defiende, da igual de dónde salió. Evaluá la defensa: si el pibe explica cada línea en diez minutos, la IA trabajó para él, no en su lugar. Y ojo: si tu profesor lee diapositivas y no puede evaluar tu proceso, ese curso no te está formando. Aprobalo, pasalo, pero no lo confundas con aprender.', | |
| 'Regla uno, la madre de todas: nunca entregues código que no podés explicar. Si en una entrevista te preguntan por qué pusiste ese useMemo ahí y respondés "lo sugirió la IA", no aprobaron vos. Aprobaron un ticket de lotería. La IA puede escribir el noventa por ciento del código. El diez por ciento restante, entender qué hace y cuándo se rompe, es lo que te pagan por saber. Y regla dos: primero intentá solo. El músculo crece en el intento, no en la respuesta. Peleá veinte minutos con el problema, escribí tu hipótesis, y recién ahí preguntale a la IA. Esa hipótesis previa convierte una respuesta en una lección.', | |
| 'Este es el tema: la diferencia entre un atajo y una clase particular. Mirá los dos prompts. Uno dice: haceme el TP de listas enlazadas. Eso te da un entregable que no entendés, y en la defensa te cose a preguntas. El otro dice: explicame por qué mi lista pierde memoria, y haceme tres preguntas antes de darme la solución. Eso no es una respuesta. Es un tutor infinito, disponible a las tres de la mañana, que no te juzga por preguntar. ¿Se entiende? La misma IA, dos destinos. Todo depende de cómo le pedís las cosas.', | |
| 'Regla cuatro: verificá todo. La IA se equivoca con total confianza. Nunca dice "no estoy seguro" con la misma soltura con la que dice algo incorrecto. Entonces: corré el código, siempre. Probá con el input raro, no solo el obvio. Rompelo a propósito. Y si no sabés cómo romperlo, no sabés qué protege. Regla cinco: cuanto más crítico es el código, menos delegás. Un script de una sola vez, delegalo tranquilo. Migraciones de datos, autenticación, lógica que mueve dinero: ahí la IA te ayuda a entender, no a escribir. Ojo: si un error ahí borra datos de alguien, el último que escribe tiene que ser alguien que entiende.', | |
| 'Regla seis: anotá lo que aprendés, con tus palabras. Cuando la IA te resuelva algo que no sabías, cerrá el círculo en un archivo. En dos semanas tenés tu propia documentación de todo lo que te enseñó. Eso es la diferencia entre "usé IA" y "aprendí". Y regla siete, mi favorita: el test de la muleta. Una vez al mes, cerrás la IA y programás algo mediano solo. No por romanticismo. Para medir. Lo que no podés hacer solo es una lista concreta de fundamentos que te faltan. Es la información más valiosa que te puede dar esta época: tu plan de estudio, escrito por la realidad.', | |
| 'Ahora, si estás en un trabajo y te tiraron un agente encima sin explicarte nada, respirá. Cinco cosas. Tu nombre va en el pull request, no el de la IA: revisá ese código como el becario más nuevo del mundo. Nada de código de la empresa en chats públicos, jamás. Los tests son tu único dios: escribilos como primera prioridad, que son tu seguro de vida. Preguntale a la IA lo que te da vergüenza preguntar a un humano: qué haría un senior acá, qué se rompe si toco esto. Y velocidad no es valor: terminar en dos horas algo que quema tres semanas de guardia es deuda con tu nombre.', | |
| '¿Y de dónde sale el criterio? No nacés con él. Se entrena con un ciclo. Antes de actuar, decí en voz alta qué creés que va a pasar. Hacé la predicción verificable: si toco esto, el test falla. Ejecutá. Y comprobá. El aprendizaje real vive en la brecha entre lo que predijiste y lo que pasó. La IA es el mejor sparring para ese ciclo: mil repeticiones sin que nadie se canse de vos. Y antes de dar por terminado cualquier trabajo, el checklist: puedo explicar por qué funciona, probé el input raro, sé quién más consume esto, existe el test. Si respondés que no a más de dos, no está terminado. Está entregado. No es lo mismo.', | |
| 'Te dejo una sola frase para llevarte. La IA no te va a quitar el trabajo. Te lo va a quitar alguien que la usa mejor que vos. Y usarla mejor no es delegar más: es entender más, verificar más, y saber cuándo poner la respuesta de la máquina a prueba con tu propio criterio. No dejés que la IA piense por vos. Dejala trabajar para vos. Todo esto, las siete reglas, la tabla de qué delegar y el checklist, está en el gist de la descripción. Se lo pasás a ese compañero que entrega TPs que no entiende, o a ese junior que se está hundiendo solo. Nos vemos, mis locuritas cósmicas.' | |
| ]; | |
| const RM = matchMedia('(prefers-reduced-motion: reduce)').matches; | |
| const $ = (id) => document.getElementById(id); | |
| const scenes = [...document.querySelectorAll('.scene')]; | |
| const track = $('progress-track'), bar = $('progress'), timeEl = $('time'), counter = $('counter'); | |
| const label = $('scene-label'), caption = $('caption'), playBtn = $('play'), bigPlay = $('big-play'); | |
| // Scene 7 calendar: twelve mini months, one marked day per month, marked in sequence. | |
| const MONTHS = ['ENE', 'FEB', 'MAR', 'ABR', 'MAY', 'JUN', 'JUL', 'AGO', 'SEP', 'OCT', 'NOV', 'DIC']; | |
| MONTHS.forEach((m, k) => { | |
| const box = document.createElement('div'); | |
| box.className = 'month'; | |
| box.innerHTML = `${m}`; | |
| const pick = 12 + (k * 3) % 9; | |
| for (let d = 0; d < 35; d++) { | |
| const day = document.createElement('i'); | |
| if (d === pick) { day.className = 'pick'; day.dataset.t = String(22 + k * 1.2); } | |
| box.lastChild.appendChild(day); | |
| } | |
| $('cal').appendChild(box); | |
| }); | |
| // Falling petals on the closing scene. | |
| document.querySelectorAll('.petals').forEach((box) => { | |
| for (let k = 0; k < 16; k++) { | |
| const p = document.createElement('span'); | |
| p.textContent = k % 3 ? '❀' : '✿'; | |
| p.style.left = `${Math.random() * 100}%`; | |
| p.style.animationDuration = `${9 + Math.random() * 10}s`; | |
| p.style.animationDelay = `${-Math.random() * 18}s`; | |
| p.style.fontSize = `${0.9 + Math.random() * 1.2}rem`; | |
| box.appendChild(p); | |
| } | |
| }); | |
| // Cue table: every [data-t] element, with the loop window of its nearest [data-loop] box. | |
| const cues = scenes.map((s) => [...s.querySelectorAll('[data-t]')].map((el) => { | |
| const box = el.closest('[data-loop]'); | |
| const loop = box && s.contains(box) ? box : null; | |
| return { | |
| el, | |
| t: +el.dataset.t, | |
| until: el.dataset.until != null ? +el.dataset.until : null, | |
| loop: loop ? +loop.dataset.loop : 0, | |
| from: loop ? +(loop.dataset.from || 0) : 0 | |
| }; | |
| })); | |
| // Captions: split narration by sentence, timed proportionally to length. | |
| const captions = VOICE.map((text, k) => { | |
| const parts = text.match(/[^.?!]+[.?!]+["»]?/g) || [text]; | |
| const span = DUR[k] - 0.8; | |
| const total = parts.reduce((a, p) => a + p.trim().length, 0); | |
| let at = 0.3; | |
| return parts.map((p) => { | |
| const c = { start: at, text: p.trim() }; | |
| at += span * p.trim().length / total; | |
| return c; | |
| }); | |
| }); | |
| // Scrubber marks and scene dots. | |
| START.slice(1).forEach((s) => { | |
| const m = document.createElement('i'); | |
| m.className = 'mark'; | |
| m.style.left = `${(s / TOTAL) * 100}%`; | |
| track.appendChild(m); | |
| }); | |
| const dots = TITLES.map((title, k) => { | |
| const b = document.createElement('button'); | |
| b.type = 'button'; | |
| b.setAttribute('aria-label', `Ir a la escena ${k + 1}: ${title}`); | |
| b.addEventListener('click', (e) => { jump(k); if (e.detail) b.blur(); }); | |
| $('dots').appendChild(b); | |
| return b; | |
| }); | |
| let t = 0, playing = false, cur = -1, capIdx = -1, lastSec = -1, started = false; | |
| let last = performance.now(); | |
| const fmt = (s) => { s = Math.floor(s); return `${String(Math.floor(s / 60)).padStart(2, '0')}:${String(s % 60).padStart(2, '0')}`; }; | |
| const sceneAt = (time) => { let k = 0; while (k < DUR.length - 1 && time >= START[k + 1]) k++; return k; }; | |
| function activate(k) { | |
| if (cur >= 0 && cur !== k) { scenes[cur].classList.remove('active'); scenes[cur].inert = true; } | |
| const s = scenes[k]; | |
| // Reset every build, drop .active, force a style flush, then re-add: | |
| // CSS animations restart from frame zero whether we arrive forwards, backwards or by restart. | |