// Career Progress — the 2-year 85+ LPA campaign (two-hop strategy)
// Content is data-driven below; milestone checks persist in state.career.ms

const CAREER = {
  startCTC: 15.6,
  goalCTC: 85,
  goalDate: '2028-07-01',
  // Validated categorical palette (dataviz-checked on surface #10151b):
  colors: {
    dsa: '#3987e5',      // blue
    design: '#199e70',   // aqua
    depth: '#c98500',    // yellow
    ai: '#9085e9',       // violet
    apps: '#e66767',     // red
  },
};

// ── Compensation trajectory (months from Jul 2026) ──────────────────────────
const TRAJ = {
  months: 27, // Jul '26 → Sep '28
  goal: 85,
  points: [
    { m: 0,  mid: 15.6, lo: 15.6, hi: 15.6, label: 'Now', sub: 'Jul 2026 · 3 YOE' },
    { m: 5,  mid: 38,   lo: 30,   hi: 45,   label: 'Hop 1 offer', sub: 'Dec 2026 · competing offers' },
    { m: 17, mid: 44,   lo: 40,   hi: 52,   label: 'Refresh + hike', sub: 'Dec 2027 · at new company' },
    { m: 25, mid: 88,   lo: 75,   hi: 105,  label: 'Hop 2 offer', sub: 'Aug 2028 · senior loops' },
  ],
  ticks: [
    { m: 0, t: "Jul'26" }, { m: 5, t: "Dec'26" }, { m: 11, t: "Jun'27" },
    { m: 17, t: "Dec'27" }, { m: 23, t: "Jun'28" }, { m: 27, t: "Sep'28" },
  ],
};

// ── Weekly 20h allocation per phase (hours) ──────────────────────────────────
const ALLOC_CATS = [
  { id: 'dsa', name: 'DSA' },
  { id: 'design', name: 'LLD + HLD' },
  { id: 'depth', name: 'Depth / projects' },
  { id: 'ai', name: 'AI-era skills' },
  { id: 'apps', name: 'Mocks + pipeline' },
];
const ALLOC = [
  { phase: 'Sprint (now → Aug 23)',        dsa: 8, design: 6, depth: 0, ai: 2, apps: 4 },
  { phase: 'Hop-1 campaign (Sep → Dec 26)', dsa: 6, design: 5, depth: 0, ai: 2, apps: 7 },
  { phase: 'Land & establish (H1 2027)',    dsa: 2, design: 2, depth: 8, ai: 6, apps: 2 },
  { phase: 'Depth year (H2 2027)',          dsa: 2, design: 2, depth: 8, ai: 6, apps: 2 },
  { phase: 'Hop-2 campaign (2028)',         dsa: 6, design: 6, depth: 1, ai: 1, apps: 6 },
];

// ── Readiness meters ─────────────────────────────────────────────────────────
const READINESS = [
  { skill: 'DSA speed & patterns', now: 65, hop1: 85, hop2: 80, note: 'Sprint covers this; hop-2 only needs a 3-week resharpen.' },
  { skill: 'LLD / machine coding', now: 55, hop1: 75, hop2: 80, note: 'Practice full working code under 90 min, not just class diagrams.' },
  { skill: 'HLD / system design', now: 40, hop1: 70, hop2: 90, note: 'The single biggest gap for hop 2 — senior loops are won here.' },
  { skill: 'Behavioral + stories', now: 45, hop1: 70, hop2: 90, note: 'Keep a weekly engineering-decision journal from today.' },
  { skill: 'AI fluency (build + judge)', now: 55, hop1: 60, hop2: 85, note: 'Already AI-heavy at work; formalize into evals, agents, MCP.' },
  { skill: 'Production ownership depth', now: 35, hop1: 40, hop2: 85, note: 'Comes from the depth year — own a service end to end.' },
];

// ── Company tiers (India, total comp LPA, 2026 market) ──────────────────────
const TIERS = [
  { tier: 'S', names: 'Google · Uber · LinkedIn · Atlassian · Rubrik · Databricks · Stripe-class · HFT platform teams', mid: [32, 60], sr: [60, 110],
    note: 'Where 85+ lives. Equity-heavy. Hop-2 primary targets; long-shot hop-1 applications still worth 2–3 tickets.' },
  { tier: 'A', names: 'Microsoft · Amazon · Adobe · Intuit · Salesforce · Oracle OCI · Walmart GT · Goldman/JPMC tech', mid: [26, 45], sr: [45, 75],
    note: 'Strong hop-1 targets. Brand compounds into hop-2 credibility.' },
  { tier: 'B', names: 'Flipkart · PhonePe · Razorpay · CRED · Swiggy · Meesho · Groww · Zepto · Navi', mid: [24, 42], sr: [40, 70],
    note: 'Fast loops, aggressive cash. Great hop-1 outcomes; some seniors do cross 70 here.' },
  { tier: 'C', names: 'Mid product / SaaS / GCCs (calibration tier)', mid: [18, 30], sr: [30, 45],
    note: 'Use for warm-up loops and backup offers that create negotiation leverage. Not the destination.' },
];

// ── The six levels ───────────────────────────────────────────────────────────
const LEVELS = [
  {
    id: 'L0', num: '00', name: 'Foundation Sprint', dates: 'Now → Aug 23, 2026', start: '2026-06-01', end: '2026-08-23',
    objective: 'Finish the 14-week sprint already running in this app. Nothing new — protect it.',
    boss: 'Self-mock gauntlet in the final sprint week',
    detail: [
      'Everything in the Calendar / DSA Rebuild / LLD / HLD views stays the plan of record. This page adds zero work before Aug 23.',
      'One addition, 10 min/week: start the engineering-decision journal now (what you decided at work, why, what broke). It feeds every behavioral round for the next two years.',
      'Resume rule for the ML work: describe it as systems engineering — "designed repo structure, training/scoring pipelines, and cross-system integration for two credit-risk models." Backend interviewers hire the platform builder, not the model tuner.',
    ],
    exit: [
      'Question bank finished per the sprint plan (78/78 coverage)',
      '8+ full mock interviews done with written post-mortems',
      '8 HLD designs practiced end-to-end (talk track, not just notes)',
      '8 STAR stories written, 2 of them about the ML platform work',
      'Resume v1 done: backend-SDE framed, quantified, one page',
    ],
  },
  {
    id: 'L1', num: '01', name: 'Hop-1 Campaign', dates: 'Aug 24 → Dec 2026', start: '2026-08-24', end: '2026-12-31',
    objective: 'Convert prep into a 30–45 LPA offer at the best brand you can reach. Brand beats +3 LPA — hop 2 is priced off where you work, not just what you make.',
    boss: 'Onsite loops · Waves B and C',
    detail: [
      'Weeks 1–3 (late Aug–mid Sep): referral farming. Target 15+ referrals — ex-colleagues, LinkedIn warm outreach, college network. A referral roughly triples callback rate vs cold apply. Update Naukri/LinkedIn with PBC keywords the same week.',
      'Wave A (mid–late Sep): 5–8 Tier-C/B warm-up companies. Purpose: calibration under real pressure, not offers. Expect to be rusty in loop #1 — that is the design.',
      'Wave B (Oct): the main assault — 12–15 Tier-B/A companies. Schedule loops close together so offers land in the same 3-week window.',
      'Wave C (Nov): 3–5 Tier-S/A stretch shots once you are loop-sharp. Even one Tier-S offer resets every negotiation.',
      'Negotiation (Nov–Dec): never share current CTC as an anchor if avoidable — quote expectations (:"late-30s total comp, and I have active processes"). Hold 2–3 offers simultaneously; every counter is asked from the highest one.',
      'Decision rule: brand tiebreak. A 34 LPA Tier-A offer beats a 38 LPA Tier-C offer for this plan — the hop-2 payoff difference is 15–20 LPA.',
    ],
    exit: [
      '15+ referrals secured before Wave B',
      '20+ applications across waves, 8+ loops reached',
      '3+ offers in hand in the same window',
      'Offer signed: ≥30 LPA at Tier-B or better (or ≥26 at Tier-S/A brand)',
      'Every rejected loop has a written post-mortem within 48h',
    ],
  },
  {
    id: 'L2', num: '02', name: 'Land & Establish', dates: 'Jan → Jun 2027', start: '2027-01-01', end: '2027-06-30',
    objective: 'First 90 days decide your internal trajectory and your hop-2 stories. Ship early, pick scope deliberately, drop prep to maintenance without going cold.',
    boss: 'First on-call / first production incident',
    detail: [
      'Days 0–30: ship something — any real merged, deployed change. Speed of first ship is the strongest early trust signal.',
      'Days 30–90: volunteer for one unowned, slightly scary thing (a flaky service, a migration, an observability gap — your Grafana/Kibana past makes this a cheat code). Ownership stories for hop-2 start here.',
      'Learn the comp machinery of the new company in month 1: refresh policy, promo cycle, rating system. You will exploit it in 2028.',
      'Maintenance prep, 4h/week floor: 3 DSA problems, 1 system-design read/watch with notes, journal entry. This floor is non-negotiable for two years — going fully cold costs 8+ weeks to recover.',
      'Bank the salary jump: from the first hiked month, save/invest the delta. A 6-month emergency fund is a strategic asset — it is what lets you reject lowball offers in 2028.',
    ],
    exit: [
      'Shipped to production within 30 days of joining',
      'Owning one service/component by day 90',
      'Comp machinery mapped (refresh, promo, ratings)',
      '4h/week maintenance streak held (track in Revision Lab)',
      '6-month emergency fund funded or on schedule',
    ],
  },
  {
    id: 'L3', num: '03', name: 'Depth Year', dates: 'Jul → Dec 2027', start: '2027-07-01', end: '2027-12-31',
    objective: 'Become the engineer senior loops are looking for: deep production ownership + the AI-integration skill stack. This level is where 85 is actually earned; 2028 just collects it.',
    boss: 'Lead one design end-to-end (doc → review → build → operate)',
    detail: [
      'Track A — Senior depth: go one level deeper than your job requires on the systems you own. DB internals (indexes, MVCC, locks), queue semantics (Kafka delivery guarantees, idempotency, DLQs), caching (invalidation, stampedes), migrations without downtime, incident command. Write 2+ real design docs and mentor at least one junior — that is the evidence pack for "senior".',
      'Track B — AI-era arsenal (see the AI-Proofing tab for the full stack): ship one production-grade AI feature at work or as a serious side project — LLM integration with structured outputs, tool calling, RAG where it fits, an eval harness, tracing, cost controls. This single artifact does double duty: hop-2 differentiation AND disruption insurance.',
      'Track C — Visibility: one artifact per quarter (internal talk, blog post, or OSS contribution). Every colleague and interviewer from 2026 is a 2028 referral — maintain the network deliberately, not desperately.',
      'Quarterly self-mock (one DSA + one design, recorded, scored). Keeps the 2028 resharpen at 8 weeks instead of 16.',
    ],
    exit: [
      'Own a service end-to-end incl. on-call and capacity/cost',
      '2+ design docs written and reviewed; 1+ junior mentored',
      'One production-grade AI feature shipped with evals + tracing',
      '2+ public/internal artifacts (talks, posts, OSS)',
      '4 quarterly self-mocks done and scored',
    ],
  },
  {
    id: 'L4', num: '04', name: 'Hop-2 Campaign', dates: 'Jan → Sep 2028', start: '2028-01-01', end: '2028-09-30',
    objective: 'Senior loops at Tier-S. Target 85+; the negotiation floor is 75 with a real equity path. Competing offers are mandatory — senior offers move 15–30% under competition.',
    boss: 'Tier-S senior onsite loops',
    detail: [
      'Jan–Mar: the resharpen. 3 weeks DSA back to speed (patterns return fast), 5 weeks senior system design (design FOR scale trade-offs, run the room, push back on requirements), 2 weeks staff-flavored behavioral (conflict, influence without authority, wrong-decision stories).',
      'The senior bar is different: they are buying judgment and ownership, not puzzle speed. Every answer should surface trade-offs, blast radius, migration paths, and cost. Your depth-year stories are the ammunition.',
      'Apr–Jul: waves again — warm-up loop first, then 8–10 Tier-S/A senior processes clustered tightly. Your 2026-era interviewer/recruiter contacts get pinged first.',
      'Position the AI artifact hard: "backend engineer who ships AI features with evals and observability" is the premium profile of 2028 — it commands the 30–50% skill premium the market already shows.',
      'Negotiate from strength: multiple offers + current Tier-A/B comp ≈ 45 + visible seniority. Ask for front-loaded equity and sign-on to bridge unvested refreshers.',
      'Decision rules at the finish: ≥85 → sign. 75–85 at Tier-S with refresh path crossing 85 within 12 months → sign (you hit the goal on trajectory, slightly late — that is a win, not a failure). <75 by Sep → extend max 2 quarters, re-run Wave with post-mortems; do not torch a 75 for pride.',
    ],
    exit: [
      'Resharpen block completed (10 weeks, scored mocks)',
      '8+ senior loops reached at Tier-S/A',
      '3+ senior offers in the same window',
      'Signed: ≥85 LPA total comp (or 75+ with ≤12-month path to 85)',
    ],
  },
  {
    id: 'L5', num: '05', name: 'Compound', dates: '2028 →', start: '2028-10-01', end: '2099-01-01',
    objective: 'The goal shifts from switching to compounding: refresh management, the staff track, and staying disruption-proof by habit.',
    boss: 'Staff promo case — or the next arbitrage',
    detail: [
      'Equity discipline: know your vest cliffs; interview externally every ~2 years even when happy — market price discovery is free and keeps you loop-warm.',
      'Choose the track deliberately: staff IC (deep technical leadership) vs EM. Both clear 1Cr+ at Tier-S; pick by energy, not title.',
      'Keep the 10% frontier habit from the AI-Proofing tab forever. The specific tech will change; the habit is the moat.',
    ],
    exit: [
      'Refresh/promo cycle mapped and exploited at new company',
      'Track chosen (staff IC vs EM) with a named 2-year target',
    ],
  },
];

// ── AI-proofing skill stack ──────────────────────────────────────────────────
const AI_ERODES = [
  ['Boilerplate CRUD & glue code', 'System boundaries, data modeling, API contracts'],
  ['Syntax knowledge, framework trivia', 'Debugging production under ambiguity'],
  ['Simple scripts & dashboards', 'Distributed correctness: idempotency, consistency, failure modes'],
  ['First-draft code generation', 'Judging generated code: security, cost, edge cases'],
  ['Routine test writing', 'Deciding WHAT to build, evals, and verification strategy'],
];
const AI_STACK = [
  { when: 'Now → Dec 2026 (alongside prep, ~2h/wk)', title: 'AI-assisted engineering mastery',
    body: 'Use an agentic coding tool daily at work (Claude Code / Cursor-class). Practice the loop that interviews now test: spec precisely → let AI draft → review like a hostile senior → verify with tests. Google is piloting Gemini-assisted coding rounds and Meta runs AI-enabled rounds — this workflow IS the interview now, so practicing it is prep, not extra.' },
  { when: 'H1 2027 (~6h/wk inside depth year)', title: 'LLM integration engineering',
    body: 'The backend skill that currently carries a 30–50% pay premium: provider APIs, structured outputs, tool/function calling, MCP, RAG done properly (chunking, hybrid search, reranking), streaming, caching and cost control, rate-limit/fallback design. This is 80% classic backend engineering — you are closer than most.' },
  { when: 'H2 2027', title: 'Agentic systems + evals + observability',
    body: 'Multi-step agents with guardrails, eval harnesses (golden sets, LLM-as-judge and its pitfalls), tracing (Langfuse-class), PII handling, human-in-the-loop design. Cap it with the one production-grade artifact from Level 3 — an AI feature with real evals and tracing is rarer than it sounds and interviews spectacularly.' },
  { when: '2028 → forever (10% time)', title: 'The frontier habit',
    body: 'Reserve ~2h/week for whatever is current — agent protocols, on-device models, whatever replaces them. The specific tech will be different by 2028; the habit of never being two waves behind is the actual insurance policy.' },
];

// ── Interview meta-shifts ────────────────────────────────────────────────────
const SHIFTS = [
  { title: 'AI-allowed coding rounds', likelihood: 'Already live',
    what: 'Google is piloting coding interviews with its own Gemini assistant; Meta rolled out an AI-enabled round from Oct 2025; Canva expects candidates to use Copilot/Cursor/Claude in technical rounds. Evaluation shifts from "can you produce code" to "can you judge code" — prompt precision, output validation, debugging of AI output.',
    guide: 'Practice solving LeetCode-class problems WITH an assistant, narrating: state the plan first, give the AI tight specs, then aggressively verify — walk the code, hunt edge cases aloud, fix its bugs on camera. The candidate who blindly accepts AI output fails; the one who catches its off-by-one wins. Do 1 in 4 of your mocks in this format from Wave A onward.' },
  { title: 'Debugging & production-scenario rounds', likelihood: 'Rising fast',
    what: 'Companies increasingly swap a puzzle round for a "here is a failing service / unfamiliar repo / bug trace — find it" round, because AI made puzzle output cheap but diagnosis is still human work.',
    guide: 'Drill the loop: reproduce → isolate → hypothesize → bisect → fix → add regression test. Practice on open-source issues (pick a bug label, time-box 45 min). Your Grafana/Kibana + on-call background is a genuine edge — say so in these rounds.' },
  { title: 'System design weight increasing at ALL levels', likelihood: 'High',
    what: 'As generated code commoditizes implementation, design judgment becomes the differentiator — mid-level loops now often include a design round that used to be senior-only.',
    guide: 'Treat HLD as a permanent skill, not interview cram: after the sprint, keep 1 design/week forever (read or practice). By hop 2 you want 50+ designs internalized — that is what "run the room" feels like.' },
  { title: 'Behavioral rounds going technical-deep', likelihood: 'Already live',
    what: 'Google\'s "Googleyness & Leadership" round now includes a technical design conversation grounded in the candidate\'s own past work — culture-fit questions are becoming engineering-decision interrogations.',
    guide: 'The weekly engineering-decision journal (Level 0) is the counter. Before each loop, pick 3 journal entries and rehearse them to 3 levels of "why": why this design, why not the alternative, what broke and what you changed. Vague stories die in this format; journaled ones thrive.' },
  { title: 'AI-resistant online assessments', likelihood: 'Medium',
    what: 'OAs are adding proctoring, novel problem banks, and in-browser AI restrictions to counter assisted cheating — expect harder, weirder screens.',
    guide: 'No shortcut exists or is worth it: fundamentals from the sprint carry you. Do OAs early in the day, treat flagged environments seriously (clean machine, no overlays), and never risk a ban on a Tier-S company for a screen you could pass legitimately.' },
];

// ── Contingencies ────────────────────────────────────────────────────────────
const SCENARIOS = [
  { name: 'Hop-1 offers cap below 28', sev: 'high',
    trigger: 'Best offer ≤28 LPA by mid-Dec 2026 after full waves.',
    response: 'If it is a Tier-S/A brand — take it; brand is the hop-2 multiplier and 26 at Microsoft beats 32 at a no-name for this plan. If only Tier-C offers: extend to Feb, run post-mortems (where do loops die? fix that stage specifically), get 5 fresh referrals, re-run Wave B. Do NOT accept a Tier-C lowball out of fatigue.',
    prevent: 'Wave structure + 15 referrals + clustered offers is the prevention. Most people fail this by applying scattershot with no competing offers.' },
  { name: 'Layoffs / market downturn mid-plan', sev: 'high',
    trigger: 'Layoff hits you, or hiring volume visibly drops (2027-style freeze).',
    response: 'The 6-month fund (Level 2) converts this from crisis to inconvenience. If laid off: you are never fully cold (4h/wk floor) — compress the resharpen to 3 weeks and run a full campaign immediately; severance + fund covers the runway. If frozen market: shift targets to fintech/GCC/HFT which hire counter-cyclically, and extend timeline one quarter rather than downgrading tiers permanently.',
    prevent: 'Emergency fund, maintenance floor, warm network. All three are already levels in this plan — that is why they are there.' },
  { name: 'Rejection wave (0 offers from 8+ loops)', sev: 'med',
    trigger: 'Eight loops reached, zero offers, in either campaign.',
    response: '48-hour rule: feel it for 48h, then post-mortem every loop — write where each died (screen / DSA / design / behavioral / culture). The failure stage is almost always consistent, and fixable: if design → 4 weeks of targeted mock designs; if behavioral → journal + story rework; if DSA speed → timed-set regimen. Respect 6–12 month cooldowns; rotate to fresh companies meanwhile.',
    prevent: 'Wave A exists precisely to burn the rust on companies you do not need.' },
  { name: 'Burnout / life event', sev: 'med',
    trigger: 'Two consecutive weeks below the floor, or life happens (health, family, wedding, anything real).',
    response: 'Drop to the Minimum Viable Week — 5h: 3 DSA problems, 1 design read, 1 journal entry — with zero guilt; it preserves ~90% of skill at 25% of cost. Slip the timeline, never delete the floor. A 3-month slip on a 24-month plan is noise; quitting is the only real failure mode.',
    prevent: 'Deload weeks are legal: after every intense 6 weeks, one deliberately light week. Sustainable beats heroic over 24 months.' },
  { name: 'Counteroffer trap at current company', sev: 'med',
    trigger: 'You resign with a 35 LPA offer; current employer counters near it.',
    response: 'Decline politely, 95% of the time. Counteroffers fix the number, not the trajectory: you stay off the PBC brand track that hop 2 is priced on, and you are first on the next layoff shortlist as a flight risk. The exception: a counter with a promotion + team change that materially improves your hop-2 story — rare, and even then get it in writing before withdrawing anything.',
    prevent: 'Decide this now, while calm — that is what this card is.' },
  { name: 'Pigeonholed as "the ML-ops person"', sev: 'low',
    trigger: 'Recruiters keep routing you to MLE/MLOps roles; backend interviewers discount the ML years.',
    response: 'Resume language is the fix: pipelines, repo architecture, system integration, throughput, reliability — the FSV/channel-prediction work described as the distributed system it is. In loops, lead with the platform story, mention models as the payload. If a great MLE offer appears anyway (they pay premiums in 2026+), it is a legitimate plan-B lane to 85 — judge it on comp + brand, not on lane purity.',
    prevent: 'Resume v1 rule in Level 0 exists for this.' },
  { name: 'AI disruption accelerates hiring cuts', sev: 'high',
    trigger: 'Mid-level backend openings visibly shrink through 2027 as AI tooling compresses teams.',
    response: 'This plan IS the hedge — the two profiles that keep commanding premiums in that world are (1) senior engineers who own production systems and (2) engineers who build AI features reliably. Levels 3A and 3B build exactly those. If it gets severe: lean harder into the AI-integration lane (go for AI-platform/LLM-infra roles — your MLE background becomes a moat, not a detour), and use the infra/SRE fallback (your 1.9y AWS/Linux/observability years) as a third employable lane.',
    prevent: 'The 70/20/10 split (core backend / AI stack / frontier) is the standing insurance premium.' },
  { name: 'Month 24 arrives at 75, not 85', sev: 'low',
    trigger: 'Sep 2028: best signed-able offer is 75–84.',
    response: 'Sign it if: Tier-S brand AND refresh/promo path crosses 85 within ~12 months (this is the goal achieved on trajectory, one year of patience attached). Keep hunting max 2 more quarters if: offers are sub-75 or at brands with weak equity paths. Never torch a 78 at Google-class for the symbolic difference — the 2-year number is a target, not a cliff.',
    prevent: 'Negotiation discipline in Level 4 (clustered competing offers) is what closes the 75→85 gap most reliably.' },
];

// ─────────────────────────────────────────────────────────────────────────────

function careerState(state) { return state.career || {}; }
function careerChecks(state) { return careerState(state).ms || {}; }

function levelStatus(level, TODAY, checks) {
  const done = level.exit.every((_, i) => checks[`${level.id}:${i}`]);
  if (done) return 'done';
  if (TODAY > level.end) return 'overdue';
  if (TODAY >= level.start) return 'active';
  return 'locked';
}

function CareerSection({ kicker, title, children, style }) {
  return (
    <div style={{ marginBottom: '44px', ...style }}>
      <div className="mono" style={{ fontSize: '10px', letterSpacing: '0.16em', color: 'var(--accent)', marginBottom: '6px' }}>{kicker}</div>
      <div style={{ fontFamily: 'var(--serif)', fontSize: '24px', letterSpacing: '-0.015em', marginBottom: '14px' }}>{title}</div>
      {children}
    </div>
  );
}

// ── Trajectory chart (single series + range band + goal line) ────────────────
function TrajectoryChart() {
  const [hover, setHover] = React.useState(null);
  const W = 760, H = 320, padL = 44, padR = 20, padT = 26, padB = 34;
  const iw = W - padL - padR, ih = H - padT - padB;
  const yMax = 110;
  const x = m => padL + (m / TRAJ.months) * iw;
  const y = v => padT + ih - (v / yMax) * ih;

  const line = TRAJ.points.map((p, i) => `${i ? 'L' : 'M'}${x(p.m)},${y(p.mid)}`).join(' ');
  const band = TRAJ.points.map(p => `${x(p.m)},${y(p.hi)}`).join(' ') + ' ' +
    [...TRAJ.points].reverse().map(p => `${x(p.m)},${y(p.lo)}`).join(' ');

  return (
    <div className="card" style={{ padding: '20px', overflowX: 'auto' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', flexWrap: 'wrap', gap: '8px' }}>
        <div style={{ fontSize: '14px', fontWeight: 600 }}>Planned compensation trajectory (total comp, LPA)</div>
        <div className="mono muted" style={{ fontSize: '10px' }}>SHADED = REALISTIC OFFER RANGE · DOTS = MILESTONES</div>
      </div>
      <svg viewBox={`0 0 ${W} ${H}`} style={{ width: '100%', minWidth: '560px', marginTop: '10px' }} onMouseLeave={() => setHover(null)}>
        {[0, 25, 50, 75, 100].map(v => (
          <g key={v}>
            <line x1={padL} x2={W - padR} y1={y(v)} y2={y(v)} stroke="var(--line-soft)" strokeWidth="1" />
            <text x={padL - 8} y={y(v) + 3} textAnchor="end" fill="var(--ink-3)" fontSize="10" fontFamily="var(--mono)">{v}</text>
          </g>
        ))}
        {TRAJ.ticks.map(t => (
          <text key={t.m} x={x(t.m)} y={H - 10} textAnchor="middle" fill="var(--ink-3)" fontSize="10" fontFamily="var(--mono)">{t.t}</text>
        ))}
        {/* goal line */}
        <line x1={padL} x2={W - padR} y1={y(TRAJ.goal)} y2={y(TRAJ.goal)} stroke="var(--warn)" strokeWidth="1.5" strokeDasharray="6 5" />
        <text x={W - padR} y={y(TRAJ.goal) - 6} textAnchor="end" fill="var(--warn)" fontSize="11" fontFamily="var(--mono)">GOAL 85</text>
        {/* offer range band + mid line */}
        <polygon points={band} fill="var(--accent)" opacity="0.10" />
        <path d={line} fill="none" stroke="var(--accent)" strokeWidth="2" strokeLinejoin="round" />
        {TRAJ.points.map((p, i) => (
          <g key={i} style={{ cursor: 'pointer' }}
             onMouseEnter={() => setHover(i)}>
            <circle cx={x(p.m)} cy={y(p.mid)} r="14" fill="transparent" />
            <circle cx={x(p.m)} cy={y(p.mid)} r={hover === i ? 6.5 : 5} fill="var(--accent)" stroke="var(--bg-2)" strokeWidth="2" />
            <text x={x(p.m)} y={y(p.hi) - 10} textAnchor={i === 0 ? 'start' : i === TRAJ.points.length - 1 ? 'end' : 'middle'}
                  fill="var(--ink)" fontSize="11.5" fontWeight="600">{p.label}</text>
            <text x={x(p.m)} y={y(p.mid) - 12} textAnchor={i === 0 ? 'start' : 'middle'} fill="var(--ink-2)" fontSize="10.5" fontFamily="var(--mono)">
              {p.lo === p.hi ? p.mid : `${p.lo}–${p.hi}`}
            </text>
          </g>
        ))}
        {hover != null && (() => {
          const p = TRAJ.points[hover];
          const tx = Math.min(Math.max(x(p.m) - 85, padL), W - padR - 190);
          const ty = Math.max(y(p.hi) - 66, 4);
          return (
            <g pointerEvents="none">
              <rect x={tx} y={ty} width="190" height="46" rx="6" fill="var(--bg-3)" stroke="var(--line)" />
              <text x={tx + 10} y={ty + 18} fill="var(--ink)" fontSize="11" fontWeight="600">{p.label} · {p.lo === p.hi ? `${p.mid} LPA` : `${p.lo}–${p.hi} LPA`}</text>
              <text x={tx + 10} y={ty + 34} fill="var(--ink-2)" fontSize="10" fontFamily="var(--mono)">{p.sub}</text>
            </g>
          );
        })()}
      </svg>
    </div>
  );
}

// ── Weekly allocation (stacked bars, validated palette) ─────────────────────
function AllocationChart() {
  const [hover, setHover] = React.useState(null); // {row, cat}
  const total = 20;
  return (
    <div className="card" style={{ padding: '20px' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', flexWrap: 'wrap', gap: '8px' }}>
        <div style={{ fontSize: '14px', fontWeight: 600 }}>Where the 20 hours/week go, by phase</div>
        <div className="mono muted" style={{ fontSize: '10px' }}>HOVER SEGMENTS FOR HOURS</div>
      </div>
      <div style={{ display: 'grid', gap: '14px', marginTop: '16px' }}>
        {ALLOC.map((row, ri) => (
          <div key={row.phase}>
            <div className="mono" style={{ fontSize: '10px', letterSpacing: '0.08em', color: 'var(--ink-2)', marginBottom: '5px' }}>{row.phase.toUpperCase()}</div>
            <div style={{ display: 'flex', gap: '2px', height: '26px', borderRadius: '5px', overflow: 'hidden' }}>
              {ALLOC_CATS.map(cat => {
                const h = row[cat.id];
                if (!h) return null;
                const on = hover && hover.row === ri && hover.cat === cat.id;
                return (
                  <div key={cat.id}
                       onMouseEnter={() => setHover({ row: ri, cat: cat.id })}
                       onMouseLeave={() => setHover(null)}
                       style={{
                         width: `${(h / total) * 100}%`, background: CAREER.colors[cat.id],
                         opacity: hover && !on ? 0.45 : 1, transition: 'opacity 0.12s',
                         display: 'flex', alignItems: 'center', justifyContent: 'center', position: 'relative', cursor: 'default',
                       }}>
                    {h >= 2 && <span style={{ fontSize: '10px', fontFamily: 'var(--mono)', color: '#08090c', fontWeight: 700 }}>{h}h</span>}
                    {on && (
                      <div style={{
                        position: 'absolute', bottom: '30px', left: '50%', transform: 'translateX(-50%)', whiteSpace: 'nowrap',
                        background: 'var(--bg-3)', border: '1px solid var(--line)', borderRadius: '5px', padding: '4px 9px',
                        fontSize: '11px', color: 'var(--ink)', zIndex: 5,
                      }}>{ALLOC_CATS.find(c => c.id === cat.id).name}: <b>{h}h</b> / 20h</div>
                    )}
                  </div>
                );
              })}
            </div>
          </div>
        ))}
      </div>
      <div style={{ display: 'flex', gap: '16px', flexWrap: 'wrap', marginTop: '14px' }}>
        {ALLOC_CATS.map(cat => (
          <div key={cat.id} style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
            <span style={{ width: '10px', height: '10px', borderRadius: '3px', background: CAREER.colors[cat.id], display: 'inline-block' }} />
            <span style={{ fontSize: '11.5px', color: 'var(--ink-2)' }}>{cat.name}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

// ── Readiness meters ─────────────────────────────────────────────────────────
function ReadinessMeters() {
  return (
    <div className="card" style={{ padding: '20px' }}>
      <div style={{ fontSize: '14px', fontWeight: 600 }}>Skill readiness — where you are vs the two bars you must clear</div>
      <div className="mono muted" style={{ fontSize: '10px', marginTop: '4px' }}>FILLED = TODAY (ESTIMATE) · ◇ = HOP-1 BAR · ● = HOP-2 SENIOR BAR</div>
      <div style={{ display: 'grid', gap: '14px', marginTop: '18px' }}>
        {READINESS.map(r => (
          <div key={r.skill}>
            <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '4px', gap: '10px', flexWrap: 'wrap' }}>
              <span style={{ fontSize: '12.5px', fontWeight: 600 }}>{r.skill}</span>
              <span className="mono" style={{ fontSize: '10px', color: 'var(--ink-3)' }}>{r.now} → {r.hop1} → {r.hop2}</span>
            </div>
            <div style={{ position: 'relative', height: '10px', background: 'var(--bg-3)', borderRadius: '5px' }}>
              <div style={{ position: 'absolute', inset: 0, width: `${r.now}%`, background: 'var(--accent)', borderRadius: '5px', opacity: 0.85 }} />
              <div title={`Hop-1 bar: ${r.hop1}`} style={{ position: 'absolute', left: `${r.hop1}%`, top: '-3px', width: '2px', height: '16px', background: 'var(--ink-2)' }} />
              <div title={`Hop-2 bar: ${r.hop2}`} style={{ position: 'absolute', left: `${r.hop2}%`, top: '-3px', width: '2px', height: '16px', background: 'var(--warn)' }} />
            </div>
            <div className="dim" style={{ fontSize: '11.5px', marginTop: '4px' }}>{r.note}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ── Tier table with range bars ───────────────────────────────────────────────
function RangeBar({ lo, hi, max = 110, color = '#3987e5' }) {
  return (
    <div style={{ position: 'relative', height: '8px', background: 'var(--bg-3)', borderRadius: '4px', minWidth: '120px' }}>
      <div style={{ position: 'absolute', left: `${(lo / max) * 100}%`, width: `${((hi - lo) / max) * 100}%`, top: 0, bottom: 0, background: color, borderRadius: '4px' }} />
    </div>
  );
}

function TierTable() {
  return (
    <div className="card" style={{ padding: '20px', overflowX: 'auto' }}>
      <div style={{ fontSize: '14px', fontWeight: 600, marginBottom: '4px' }}>Company tiers & realistic total-comp bands (India, 2026)</div>
      <div className="mono muted" style={{ fontSize: '10px', marginBottom: '14px' }}>MID = SDE-2 / ~3 YOE (HOP 1) · SENIOR = ~5 YOE (HOP 2) · BAR SCALE 0–110 LPA</div>
      <table style={{ width: '100%', borderCollapse: 'collapse', minWidth: '640px' }}>
        <thead>
          <tr>
            {['TIER', 'COMPANIES (EXAMPLES)', 'HOP-1 BAND', 'HOP-2 BAND'].map(h => (
              <th key={h} className="mono" style={{ textAlign: 'left', fontSize: '9.5px', letterSpacing: '0.12em', color: 'var(--ink-3)', padding: '6px 10px 8px 0', borderBottom: '1px solid var(--line-soft)', fontWeight: 500 }}>{h}</th>
            ))}
          </tr>
        </thead>
        <tbody>
          {TIERS.map(t => (
            <tr key={t.tier}>
              <td style={{ padding: '12px 10px 12px 0', borderBottom: '1px solid var(--line-soft)', verticalAlign: 'top' }}>
                <span style={{ fontFamily: 'var(--serif)', fontSize: '22px', fontStyle: 'italic', color: t.tier === 'S' ? 'var(--accent)' : 'var(--ink)' }}>{t.tier}</span>
              </td>
              <td style={{ padding: '12px 14px 12px 0', borderBottom: '1px solid var(--line-soft)', verticalAlign: 'top', maxWidth: '260px' }}>
                <div style={{ fontSize: '12px', lineHeight: 1.5 }}>{t.names}</div>
                <div className="dim" style={{ fontSize: '11px', marginTop: '4px', lineHeight: 1.45 }}>{t.note}</div>
              </td>
              <td style={{ padding: '12px 14px 12px 0', borderBottom: '1px solid var(--line-soft)', verticalAlign: 'top', width: '22%' }}>
                <RangeBar lo={t.mid[0]} hi={t.mid[1]} />
                <div className="mono" style={{ fontSize: '10px', color: 'var(--ink-2)', marginTop: '4px' }}>{t.mid[0]}–{t.mid[1]}</div>
              </td>
              <td style={{ padding: '12px 0 12px 0', borderBottom: '1px solid var(--line-soft)', verticalAlign: 'top', width: '22%' }}>
                <RangeBar lo={t.sr[0]} hi={t.sr[1]} color="#199e70" />
                <div className="mono" style={{ fontSize: '10px', color: 'var(--ink-2)', marginTop: '4px' }}>{t.sr[0]}–{t.sr[1]}</div>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

// ── Level card ───────────────────────────────────────────────────────────────
function LevelCard({ level, TODAY, checks, toggle }) {
  const status = levelStatus(level, TODAY, checks);
  const doneCount = level.exit.filter((_, i) => checks[`${level.id}:${i}`]).length;
  const [open, setOpen] = React.useState(status === 'active');
  const statusMeta = {
    done: { label: 'CLEARED', color: 'var(--accent)' },
    active: { label: 'ACTIVE QUEST', color: 'var(--accent)' },
    overdue: { label: 'PAST WINDOW', color: 'var(--warn)' },
    locked: { label: 'UPCOMING', color: 'var(--ink-3)' },
  }[status];

  return (
    <div className="card" style={{ padding: 0, overflow: 'hidden', borderColor: status === 'active' ? 'var(--accent)' : 'var(--line-soft)' }}>
      <button onClick={() => setOpen(v => !v)} style={{
        all: 'unset', boxSizing: 'border-box', display: 'flex', gap: '18px', alignItems: 'flex-start',
        width: '100%', padding: '20px 22px', cursor: 'pointer',
      }}>
        <div style={{ fontFamily: 'var(--serif)', fontSize: '40px', fontStyle: 'italic', lineHeight: 0.9, color: status === 'locked' ? 'var(--ink-3)' : 'var(--accent)' }}>{level.num}</div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: 'flex', gap: '10px', alignItems: 'baseline', flexWrap: 'wrap' }}>
            <span style={{ fontFamily: 'var(--serif)', fontSize: '20px', letterSpacing: '-0.01em' }}>{level.name}</span>
            <span className="mono" style={{ fontSize: '10px', letterSpacing: '0.1em', color: statusMeta.color }}>{statusMeta.label}</span>
          </div>
          <div className="mono muted" style={{ fontSize: '10px', marginTop: '4px', letterSpacing: '0.06em' }}>
            {level.dates} · BOSS: {level.boss.toUpperCase()} · {doneCount}/{level.exit.length} EXIT CRITERIA
          </div>
          <div style={{ fontSize: '13px', color: 'var(--ink-2)', marginTop: '8px', lineHeight: 1.55 }}>{level.objective}</div>
        </div>
        <div className="mono" style={{ fontSize: '12px', color: 'var(--ink-3)', paddingTop: '4px' }}>{open ? '−' : '+'}</div>
      </button>
      {open && (
        <div style={{ padding: '0 22px 22px 80px' }}>
          <div style={{ height: '1px', background: 'var(--line-soft)', marginBottom: '16px' }} />
          <div style={{ display: 'grid', gap: '10px', marginBottom: '18px' }}>
            {level.detail.map((d, i) => (
              <div key={i} style={{ display: 'flex', gap: '10px', fontSize: '12.5px', lineHeight: 1.6, color: 'var(--ink-2)' }}>
                <span style={{ color: 'var(--accent)', fontFamily: 'var(--mono)', fontSize: '10px', paddingTop: '4px' }}>▸</span>
                <span>{d}</span>
              </div>
            ))}
          </div>
          <div className="mono" style={{ fontSize: '9.5px', letterSpacing: '0.14em', color: 'var(--ink-3)', marginBottom: '10px' }}>EXIT CRITERIA — CHECK TO CLEAR THE LEVEL</div>
          <div style={{ display: 'grid', gap: '8px' }}>
            {level.exit.map((e, i) => {
              const k = `${level.id}:${i}`;
              return (
                <div key={k} style={{ display: 'flex', gap: '10px', alignItems: 'flex-start' }}>
                  <Check on={!!checks[k]} onClick={() => toggle(k)} />
                  <span style={{ fontSize: '12.5px', lineHeight: 1.5, color: checks[k] ? 'var(--ink-3)' : 'var(--ink)', textDecoration: checks[k] ? 'line-through' : 'none' }}>{e}</span>
                </div>
              );
            })}
          </div>
        </div>
      )}
    </div>
  );
}

// ── Main view ────────────────────────────────────────────────────────────────
function CareerView() {
  const { state, update } = useStore();
  const TODAY = todayStrFor(useToday());
  const checks = careerChecks(state);
  const [tab, setTab] = React.useState(() => {
    const t = new URLSearchParams(window.location.search).get('ctab');
    return ['overview', 'levels', 'ai', 'meta', 'risk'].includes(t) ? t : 'overview';
  });

  const toggle = (k) => {
    const next = { ...checks, [k]: !checks[k] };
    update({ career: { ...careerState(state), ms: next } });
  };

  const totalCriteria = LEVELS.reduce((n, l) => n + l.exit.length, 0);
  const doneCriteria = LEVELS.reduce((n, l) => n + l.exit.filter((_, i) => checks[`${l.id}:${i}`]).length, 0);
  const progress = Math.round((doneCriteria / totalCriteria) * 100);
  const activeLevel = LEVELS.find(l => levelStatus(l, TODAY, checks) === 'active') || LEVELS[0];
  const monthsLeft = Math.max(0, Math.round((Date.parse(CAREER.goalDate) - Date.parse(TODAY)) / (30.44 * 864e5)));

  const TABS = [
    { id: 'overview', label: 'Overview' },
    { id: 'levels', label: 'The 6 Levels' },
    { id: 'ai', label: 'AI-Proofing' },
    { id: 'meta', label: 'Interview Meta' },
    { id: 'risk', label: 'Contingencies' },
  ];

  return (
    <div className="fade-in">
      <div className="section-h">
        <div>
          <div className="kicker">The Campaign · 15.6 → 85+ LPA</div>
          <h1 className="h-title"><em>Two hops.</em><br/>Twenty-four months.</h1>
        </div>
      </div>

      {/* HUD */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(150px, 1fr))', gap: '12px', marginBottom: '26px' }}>
        <Stat label="Current CTC" value="15.6 LPA" sub="3 YOE · Jul 2026" />
        <Stat label="Target" value="85+ LPA" sub="total comp · by mid-2028" accent />
        <Stat label="Months on the clock" value={String(monthsLeft)} sub="to Jul 2028" />
        <Stat label="Active level" value={activeLevel.num} sub={activeLevel.name} accent />
        <Stat label="Quest progress" value={`${progress}%`} sub={`${doneCriteria}/${totalCriteria} criteria cleared`} />
      </div>

      {/* Tabs */}
      <div style={{ display: 'flex', gap: '6px', flexWrap: 'wrap', marginBottom: '30px' }}>
        {TABS.map(t => (
          <button key={t.id} onClick={() => setTab(t.id)} className="btn" style={{
            background: tab === t.id ? 'var(--accent)' : 'transparent',
            color: tab === t.id ? '#08090c' : 'var(--ink-2)',
            borderColor: tab === t.id ? 'var(--accent)' : 'var(--line)',
            fontWeight: tab === t.id ? 700 : 500,
          }}>{t.label}</button>
        ))}
      </div>

      {tab === 'overview' && (
        <div>
          <CareerSection kicker="THE HONEST MATH" title="Why this is a two-hop campaign">
            <div className="card" style={{ padding: '22px', marginBottom: '14px' }}>
              <div style={{ fontSize: '13px', lineHeight: 1.7, color: 'var(--ink-2)', display: 'grid', gap: '12px' }}>
                <p>85+ LPA from 15.6 is a <b style={{ color: 'var(--ink)' }}>5.4× jump</b>. No single switch delivers that: at 3 YOE the strongest realistic outcome is 30–45 LPA (a 2–2.9× hop, already top-percentile). The 85+ band in India lives almost exclusively in <b style={{ color: 'var(--ink)' }}>senior (~5 YOE) roles at Tier-S companies</b>, where equity makes up 30–50% of the package. So the campaign is: <b style={{ color: 'var(--ink)' }}>Hop 1 (Dec 2026)</b> to ~35–45 at the best brand reachable, a <b style={{ color: 'var(--ink)' }}>depth year (2027)</b> that manufactures genuine seniority plus the AI-integration premium, then <b style={{ color: 'var(--ink)' }}>Hop 2 (mid-2028)</b> into senior loops with competing offers.</p>
                <p>What this plan can and cannot promise: executed fully, the two-hop path reaches 85+ by month 24 in the base case and by month 27–30 in the slow case — and every failure mode short of quitting has a contingency card in the Contingencies tab. What no honest plan can promise is a guarantee; anyone selling one is lying. What is provable: this exact route (mid PBC → depth → senior Tier-S with competing offers) is the single most-travelled road to 85+ in the Indian market, and every input it needs is already in your hands — 20h/week, 3 YOE, systems background, and an ML story most backend candidates don't have.</p>
              </div>
            </div>
            <TrajectoryChart />
          </CareerSection>

          <CareerSection kicker="THE MARKET" title="Where 85+ actually lives">
            <TierTable />
          </CareerSection>

          <CareerSection kicker="THE INPUTS" title="Hours and skills, phase by phase">
            <div style={{ display: 'grid', gap: '14px' }}>
              <AllocationChart />
              <ReadinessMeters />
            </div>
          </CareerSection>

          <CareerSection kicker="STANDING ORDERS" title="Five rules that hold for all 24 months">
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))', gap: '12px' }}>
              {[
                ['Brand beats +3 LPA at hop 1', 'Hop 2 is priced off your employer\'s tier as much as your skill. A Tier-A badge at 34 outearns a Tier-C badge at 38 within 18 months.'],
                ['Never interview without competing offers', 'Cluster loops so offers land together. Solo offers get lowballed; competing offers move senior packages 15–30%.'],
                ['Never go fully cold', '4h/week floor forever: 3 problems, 1 design, 1 journal entry. Cold restarts cost 2+ months; the floor costs 4 hours.'],
                ['The journal is the behavioral engine', '10 min/week writing down real engineering decisions. Every 2026-28 behavioral round — increasingly technical — is answered from it.'],
                ['Save the delta', 'Every post-hop rupee above old lifestyle goes to the 6-month fund first. The fund is what makes "no" possible in a negotiation.'],
              ].map(([t, b], i) => (
                <div key={i} className="card" style={{ padding: '18px' }}>
                  <div style={{ fontFamily: 'var(--serif)', fontSize: '17px', marginBottom: '6px' }}>{t}</div>
                  <div className="dim" style={{ fontSize: '12px', lineHeight: 1.55 }}>{b}</div>
                </div>
              ))}
            </div>
          </CareerSection>
        </div>
      )}

      {tab === 'levels' && (
        <div>
          <CareerSection kicker="THE CAMPAIGN MAP" title="Six levels. Each has a boss, exit criteria, and a clock.">
            <div style={{ display: 'grid', gap: '12px' }}>
              {LEVELS.map(l => (
                <LevelCard key={l.id} level={l} TODAY={TODAY} checks={checks} toggle={toggle} />
              ))}
            </div>
          </CareerSection>
        </div>
      )}

      {tab === 'ai' && (
        <div>
          <CareerSection kicker="THE DISRUPTION HEDGE" title="What AI erodes vs what it amplifies">
            <div className="card" style={{ padding: '20px', overflowX: 'auto', marginBottom: '14px' }}>
              <table style={{ width: '100%', borderCollapse: 'collapse', minWidth: '520px' }}>
                <thead>
                  <tr>
                    <th className="mono" style={{ textAlign: 'left', fontSize: '9.5px', letterSpacing: '0.12em', color: 'var(--rose)', padding: '6px 12px 8px 0', borderBottom: '1px solid var(--line-soft)', fontWeight: 500, width: '50%' }}>COMMODITIZING — DON'T BUILD A CAREER HERE</th>
                    <th className="mono" style={{ textAlign: 'left', fontSize: '9.5px', letterSpacing: '0.12em', color: 'var(--accent)', padding: '6px 0 8px 0', borderBottom: '1px solid var(--line-soft)', fontWeight: 500 }}>DURABLE — WHERE YOUR VALUE COMPOUNDS</th>
                  </tr>
                </thead>
                <tbody>
                  {AI_ERODES.map(([bad, good], i) => (
                    <tr key={i}>
                      <td style={{ padding: '10px 12px 10px 0', borderBottom: '1px solid var(--line-soft)', fontSize: '12.5px', color: 'var(--ink-3)', lineHeight: 1.5 }}>{bad}</td>
                      <td style={{ padding: '10px 0', borderBottom: '1px solid var(--line-soft)', fontSize: '12.5px', color: 'var(--ink)', lineHeight: 1.5 }}>{good}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
              <div className="dim" style={{ fontSize: '12px', lineHeight: 1.6, marginTop: '14px' }}>
                The operating split for the whole plan: <b style={{ color: 'var(--ink)' }}>70% core backend depth · 20% AI-integration stack · 10% frontier awareness</b>. Engineers with GenAI/LLM + platform skills already command a 30–50% premium in the 2026 Indian market — and your MLE detour, framed right, is a head start on exactly that stack, not a deviation from backend.
              </div>
            </div>
          </CareerSection>

          <CareerSection kicker="THE STACK, SEQUENCED" title="Four layers, in the order you add them">
            <div style={{ display: 'grid', gap: '12px' }}>
              {AI_STACK.map((s, i) => (
                <div key={i} className="card" style={{ padding: '20px', display: 'grid', gridTemplateColumns: '44px 1fr', gap: '16px' }}>
                  <div style={{ fontFamily: 'var(--serif)', fontSize: '38px', fontStyle: 'italic', lineHeight: 0.9, color: '#9085e9' }}>{i + 1}</div>
                  <div>
                    <div style={{ display: 'flex', gap: '10px', alignItems: 'baseline', flexWrap: 'wrap' }}>
                      <span style={{ fontFamily: 'var(--serif)', fontSize: '18px' }}>{s.title}</span>
                      <span className="mono" style={{ fontSize: '9.5px', letterSpacing: '0.1em', color: 'var(--ink-3)' }}>{s.when.toUpperCase()}</span>
                    </div>
                    <div className="dim" style={{ fontSize: '12.5px', lineHeight: 1.6, marginTop: '8px' }}>{s.body}</div>
                  </div>
                </div>
              ))}
            </div>
          </CareerSection>

          <CareerSection kicker="INSURANCE POLICIES" title="If the wave hits harder than expected">
            <div className="card" style={{ padding: '22px' }}>
              <div style={{ fontSize: '13px', lineHeight: 1.7, color: 'var(--ink-2)', display: 'grid', gap: '10px' }}>
                <p><b style={{ color: 'var(--ink)' }}>Lane 1 — Senior backend:</b> the primary plan. Production ownership + design judgment stays scarce in every AI scenario short of full automation of engineering (in which case no plan survives, and savings — not skills — are the hedge; hence the fund).</p>
                <p><b style={{ color: 'var(--ink)' }}>Lane 2 — AI-platform engineering:</b> if backend hiring compresses, pivot toward LLM-infra/AI-platform roles. Your 7+ months of real MLE work becomes a moat here — most backend engineers can't tell a feature pipeline from a training pipeline.</p>
                <p><b style={{ color: 'var(--ink)' }}>Lane 3 — Infra/SRE/platform:</b> the fallback lane from your first 1.9 years (EC2 scaling, Linux, Grafana/Kibana). Ops-of-AI-systems is itself a growth area. Three employable lanes, one shared skill core — that is what "disruption-proof" actually means in practice.</p>
              </div>
            </div>
          </CareerSection>
        </div>
      )}

      {tab === 'meta' && (
        <div>
          <CareerSection kicker="GOOD TO KNOW · MID-2026 SIGNALS" title="How interviews are changing — and the counter for each">
            <div style={{ display: 'grid', gap: '12px' }}>
              {SHIFTS.map((s, i) => (
                <div key={i} className="card" style={{ padding: '20px' }}>
                  <div style={{ display: 'flex', gap: '10px', alignItems: 'baseline', flexWrap: 'wrap', marginBottom: '8px' }}>
                    <span style={{ fontFamily: 'var(--serif)', fontSize: '18px' }}>{s.title}</span>
                    <Pill kind={s.likelihood === 'Already live' ? 'accent' : ''}>{s.likelihood}</Pill>
                  </div>
                  <div className="dim" style={{ fontSize: '12.5px', lineHeight: 1.6 }}>{s.what}</div>
                  <div style={{ height: '1px', background: 'var(--line-soft)', margin: '12px 0' }} />
                  <div style={{ display: 'flex', gap: '10px' }}>
                    <span className="mono" style={{ fontSize: '9.5px', letterSpacing: '0.12em', color: 'var(--accent)', paddingTop: '3px', whiteSpace: 'nowrap' }}>IF YOU FACE IT →</span>
                    <span style={{ fontSize: '12.5px', lineHeight: 1.6, color: 'var(--ink)' }}>{s.guide}</span>
                  </div>
                </div>
              ))}
            </div>
            <div className="mono muted" style={{ fontSize: '10px', lineHeight: 1.8, marginTop: '14px' }}>
              SIGNALS FROM: GOOGLE GEMINI-ASSISTED CODING PILOT (2026) · META AI-ENABLED ROUNDS (OCT 2025 →) · CANVA AI-EXPECTED INTERVIEWS (JUN 2025 →) · GOOGLE G&L ROUND ADDING TECHNICAL-DESIGN DEPTH. RE-CHECK THIS TAB QUARTERLY — THE META MOVES FAST.
            </div>
          </CareerSection>
        </div>
      )}

      {tab === 'risk' && (
        <div>
          <CareerSection kicker="PRE-DECIDED, NOT IMPROVISED" title="Every failure mode gets a card: trigger → response → prevention">
            <div style={{ display: 'grid', gap: '12px' }}>
              {SCENARIOS.map((s, i) => (
                <div key={i} className="card" style={{ padding: '20px', borderLeft: `3px solid ${s.sev === 'high' ? 'var(--rose)' : s.sev === 'med' ? 'var(--warn)' : 'var(--ink-3)'}` }}>
                  <div style={{ display: 'flex', gap: '10px', alignItems: 'baseline', flexWrap: 'wrap', marginBottom: '10px' }}>
                    <span style={{ fontFamily: 'var(--serif)', fontSize: '18px' }}>{s.name}</span>
                    <span className="mono" style={{ fontSize: '9.5px', letterSpacing: '0.12em', color: s.sev === 'high' ? 'var(--rose)' : s.sev === 'med' ? 'var(--warn)' : 'var(--ink-3)' }}>
                      {s.sev === 'high' ? 'HIGH IMPACT' : s.sev === 'med' ? 'MEDIUM IMPACT' : 'LOW IMPACT'}
                    </span>
                  </div>
                  <div style={{ display: 'grid', gap: '8px', fontSize: '12.5px', lineHeight: 1.6 }}>
                    <div><span className="mono" style={{ fontSize: '9.5px', letterSpacing: '0.12em', color: 'var(--ink-3)' }}>TRIGGER · </span><span style={{ color: 'var(--ink-2)' }}>{s.trigger}</span></div>
                    <div><span className="mono" style={{ fontSize: '9.5px', letterSpacing: '0.12em', color: 'var(--accent)' }}>RESPONSE · </span><span style={{ color: 'var(--ink)' }}>{s.response}</span></div>
                    <div><span className="mono" style={{ fontSize: '9.5px', letterSpacing: '0.12em', color: 'var(--ink-3)' }}>PREVENTION · </span><span className="dim">{s.prevent}</span></div>
                  </div>
                </div>
              ))}
            </div>
          </CareerSection>

          <CareerSection kicker="THE FLOOR" title="The Minimum Viable Week (5 hours)">
            <div className="card" style={{ padding: '22px' }}>
              <div style={{ fontSize: '13px', lineHeight: 1.7, color: 'var(--ink-2)' }}>
                When everything goes sideways — crunch at work, illness, life — the plan degrades to exactly this, never to zero:
                <b style={{ color: 'var(--ink)' }}> 3 DSA problems (spaced-repetition picks from the Revision Lab) · 1 system-design read with 5 lines of notes · 1 journal entry.</b> That
                is ~5 hours and preserves roughly 90% of interview readiness. Two rules: the floor cannot be skipped two weeks running, and dropping to the floor
                requires no justification and carries no guilt — it is a designed mode, not a failure. Timelines slip; the campaign never stops.
              </div>
            </div>
          </CareerSection>
        </div>
      )}
    </div>
  );
}

window.CareerView = CareerView;
