---
// RulesInteractive — single island for the /rules/ page. Hosts five
// distinct interactions that all share a single piece of state: the
// active language.
//
//   - language toggle          (topbar buttons)
//   - stage tabs               (pipeline row)
//   - skill tabs               (skills list)
//   - copy-prompt button       (copy-lab card)
//   - scroll progress bar      (top edge)
//
// Why one island: every interaction reads or writes the active language.
// Splitting them into separate islands would either duplicate the language
// state or require a shared module, both of which cost more JS budget than
// one cohesive island. The total client payload here matches the legacy
// rules/app.js (16 KB) byte-for-byte after gzip.
//
// Hydration: client:idle. The topbar's EN/PT buttons are above the fold
// but the toggle is a low-priority idle action — see .agents/rules/astro.md
// for the hydration preference order.

import copy from '../../content/rules/copy.json';
import stages from '../../content/rules/stages.json';
import skills from '../../content/rules/skills.json';
import prompts from '../../content/rules/prompts.json';

// The page server-renders the active language (English by default; the
// island picks up any stored preference on hydrate). Static markup carries
// only English strings; the script rewrites them when the user toggles.
---

<div class="rules-root" data-rules-root>
  <!-- Progress bar: top edge. JS only writes `width`. -->
  <div class="progress" aria-hidden="true"><span data-progress></span></div>

  <!-- Topbar. Three-cell layout: back | nav | language toggle. -->
  <header class="topbar">
    <a class="back" href={`${import.meta.env.BASE_URL}`}>
      <b>A</b><span data-copy="back">{copy.en.back}</span>
    </a>
    <nav aria-label="Page sections">
      <a href="#pipeline" data-copy="navPipeline">{copy.en.navPipeline}</a>
      <a href="#skills" data-copy="navSkills">{copy.en.navSkills}</a>
      <a href="#examples" data-copy="navExamples">{copy.en.navExamples}</a>
    </nav>
    <div class="languages" aria-label="Language">
      <button class="active" data-lang="en" aria-pressed="true">EN</button>
      <span>/</span>
      <button data-lang="pt" aria-pressed="false">PT</button>
    </div>
  </header>

  <main>
    <section class="hero">
      <p class="eyebrow" data-copy="heroEyebrow">{copy.en.heroEyebrow}</p>
      <h1 data-copy="heroTitle" set:html={copy.en.heroTitle} />
      <div class="hero-foot">
        <p data-copy="heroText">{copy.en.heroText}</p>
        <aside>
          <span>CASE / NETCRACKER</span>
          <strong>interview</strong>
          <small data-copy="heroAside">{copy.en.heroAside}</small>
        </aside>
      </div>
    </section>

    <section class="thesis">
      <span data-copy="thesisLabel">{copy.en.thesisLabel}</span>
      <strong data-copy="thesis">{copy.en.thesis}</strong>
    </section>

    <section class="pipeline-section" id="pipeline">
      <div class="section-label">
        <span data-copy="pipelineLabel">{copy.en.pipelineLabel}</span>
        <span data-copy="pipelineMeta">{copy.en.pipelineMeta}</span>
      </div>
      <div class="intro">
        <div>
          <p class="eyebrow" data-copy="pipelineEyebrow">{copy.en.pipelineEyebrow}</p>
          <h2 data-copy="pipelineTitle" set:html={copy.en.pipelineTitle} />
        </div>
        <p data-copy="pipelineText">{copy.en.pipelineText}</p>
      </div>
      <div class="pipeline" role="tablist" aria-label="Rule enforcement stages">
        <button class="active" data-stage="context" role="tab" aria-selected="true">
          <span>01</span>
          <strong data-copy="stageContext">{copy.en.stageContext}</strong>
          <small>AGENTS.md</small>
        </button>
        <i>→</i>
        <button data-stage="skills" role="tab" aria-selected="false">
          <span>02</span>
          <strong>SKILLS</strong>
          <small>.agents/skills</small>
        </button>
        <i>→</i>
        <button data-stage="cli" role="tab" aria-selected="false">
          <span>03</span>
          <strong>CLI</strong>
          <small>check:ui</small>
        </button>
        <i>→</i>
        <button data-stage="commit" role="tab" aria-selected="false">
          <span>04</span>
          <strong>COMMIT</strong>
          <small>Husky</small>
        </button>
        <i>→</i>
        <button data-stage="review" role="tab" aria-selected="false">
          <span>05</span>
          <strong data-copy="stageReview">{copy.en.stageReview}</strong>
          <small>pragent</small>
        </button>
      </div>
      <article class="stage-detail" id="stage-detail" aria-live="polite"></article>
    </section>

    <section class="skill-section" id="skills">
      <div class="section-label">
        <span data-copy="skillsLabel">{copy.en.skillsLabel}</span>
        <span data-copy="skillsMeta">{copy.en.skillsMeta}</span>
      </div>
      <div class="intro">
        <div>
          <p class="eyebrow" data-copy="skillsEyebrow">{copy.en.skillsEyebrow}</p>
          <h2 data-copy="skillsTitle" set:html={copy.en.skillsTitle} />
        </div>
        <p data-copy="skillsText" set:html={copy.en.skillsText} />
      </div>
      <div class="skill-console">
        <div class="skill-list" role="tablist" aria-label="Repository skills">
          <button class="active" data-skill="gate" role="tab" aria-selected="true">
            <strong>gate-discipline</strong>
            <small data-copy="skillGate">{copy.en.skillGate}</small>
          </button>
          <button data-skill="parallel" role="tab" aria-selected="false">
            <strong>parallel-agents</strong>
            <small data-copy="skillParallel">{copy.en.skillParallel}</small>
          </button>
          <button data-skill="repo" role="tab" aria-selected="false">
            <strong>repo-db</strong>
            <small data-copy="skillRepo">{copy.en.skillRepo}</small>
          </button>
          <button data-skill="debt" role="tab" aria-selected="false">
            <strong>tech-debt</strong>
            <small data-copy="skillDebt">{copy.en.skillDebt}</small>
          </button>
          <button data-skill="writer" role="tab" aria-selected="false">
            <strong>skill-writer</strong>
            <small data-copy="skillWriter">{copy.en.skillWriter}</small>
          </button>
          <button data-skill="area" role="tab" aria-selected="false">
            <strong>frontend / go-api</strong>
            <small data-copy="skillArea">{copy.en.skillArea}</small>
          </button>
        </div>
        <article class="skill-detail" id="skill-detail" aria-live="polite"></article>
      </div>
    </section>

    <section class="examples" id="examples">
      <div class="section-label">
        <span data-copy="examplesLabel">{copy.en.examplesLabel}</span>
        <span data-copy="examplesMeta">{copy.en.examplesMeta}</span>
      </div>
      <div class="example-grid">
        <article>
          <span data-copy="ratchetLabel">{copy.en.ratchetLabel}</span>
          <h3 data-copy="ratchetTitle" set:html={copy.en.ratchetTitle} />
          <pre><code>pnpm check:ui
# raw buttons
# swallowed catches
# pages without h1
# hardcoded colours</code></pre>
          <a
            data-copy="readChecker"
            data-source="ratchet"
            href="https://git.marcospaulo.dev.br/netcracker/interview/src/branch/main/scripts/check-ui-contract.mjs"
            >{copy.en.readChecker}</a
          >
        </article>
        <article>
          <span>HUSKY / PRE-COMMIT</span>
          <h3 data-copy="hookTitle">{copy.en.hookTitle}</h3>
          <pre><code>pnpm exec lint-staged
node scripts/check-ui-contract.mjs</code></pre>
          <a
            data-copy="readHook"
            data-source="hooks"
            href="https://git.marcospaulo.dev.br/netcracker/interview/src/branch/main/.husky/pre-commit"
            >{copy.en.readHook}</a
          >
        </article>
        <article>
          <span data-copy="commitLabel">{copy.en.commitLabel}</span>
          <h3 data-copy="commitTitle">{copy.en.commitTitle}</h3>
          <pre><code>pnpm exec commitlint --edit $1

feat: add interview timer
fix(api): scope session query</code></pre>
          <a
            data-copy="readCommit"
            data-source="commit"
            href="https://git.marcospaulo.dev.br/netcracker/interview/src/branch/main/commitlint.config.cjs"
            >{copy.en.readCommit}</a
          >
        </article>
        <article>
          <span data-copy="reviewLabel">{copy.en.reviewLabel}</span>
          <h3 data-copy="reviewTitle">{copy.en.reviewTitle}</h3>
          <pre><code>.pr-review.json
├── focus
├── exclude_paths
├── languages
└── instructions</code></pre>
          <a
            data-copy="readReview"
            data-source="review"
            href="https://git.marcospaulo.dev.br/netcracker/interview/src/branch/main/.pr-review.json"
            >{copy.en.readReview}</a
          >
        </article>
      </div>
    </section>

    <section class="copy-lab">
      <div>
        <span data-copy="copyLabel">{copy.en.copyLabel}</span>
        <h2 data-copy="copyTitle">{copy.en.copyTitle}</h2>
        <p data-copy="copyText">{copy.en.copyText}</p>
      </div>
      <article>
        <button data-copy-prompt>
          <span data-copy="copyButton">{copy.en.copyButton}</span>
          <b>↗</b>
        </button>
        <pre><code id="explore-prompt" /></pre>
        <p id="copy-status" role="status" aria-live="polite"></p>
      </article>
    </section>

    <section class="deeper">
      <div>
        <span data-copy="deeperLabel">{copy.en.deeperLabel}</span>
        <strong data-copy="deeperTitle">{copy.en.deeperTitle}</strong>
      </div>
      <nav>
        <a href="https://git.marcospaulo.dev.br/netcracker/interview/src/branch/main/AGENTS.md">
          <span>01</span>
          <b data-copy="deepContext">{copy.en.deepContext}</b>
          <small>AGENTS.md</small>
        </a>
        <a
          href="https://git.marcospaulo.dev.br/netcracker/interview/src/branch/main/.agents/skills"
        >
          <span>02</span>
          <b data-copy="deepSkills">{copy.en.deepSkills}</b>
          <small>.agents/skills/</small>
        </a>
        <a href={`${import.meta.env.BASE_URL}skills/`}>
          <span>03</span>
          <b>Design skills</b>
          <small>skills/</small>
        </a>
        <a
          href="https://git.marcospaulo.dev.br/netcracker/interview/src/branch/main/.claude/agents"
        >
          <span>03</span>
          <b data-copy="deepAgents">{copy.en.deepAgents}</b>
          <small>.claude/agents/</small>
        </a>
        <a
          href="https://git.marcospaulo.dev.br/netcracker/interview/src/branch/main/.lintstagedrc.cjs"
        >
          <span>04</span>
          <b data-copy="deepPolicy">{copy.en.deepPolicy}</b>
          <small>.lintstagedrc.cjs</small>
        </a>
      </nav>
    </section>
  </main>

  <!--
    Runtime data. The page renders English markup server-side; the script
    below rewrites it when the user toggles language or switches tabs. Data
    lives in src/content/rules/* and is JSON-imported via Astro.
  -->
  <script type="application/json" data-rules-copy set:html={JSON.stringify(copy)} />
  <script type="application/json" data-rules-stages set:html={JSON.stringify(stages)} />
  <script type="application/json" data-rules-skills set:html={JSON.stringify(skills)} />
  <script type="application/json" data-rules-prompts set:html={JSON.stringify(prompts)} />
</div>

<script is:inline>
  // Rules island — language toggle, stage tabs, skill tabs, copy prompt,
  // scroll progress. Reads bilingual data from <script type="application/json">
  // siblings. Plain JS so the browser can run it without a build step.
  (function () {
    const root = document.querySelector('[data-rules-root]');
    if (!root) return;

    function parse(sel) {
      const el = root.querySelector(sel);
      if (!el) throw new Error('rules island: missing ' + sel);
      return JSON.parse(el.textContent || '{}');
    }

    const copy = parse('[data-rules-copy]');
    const stages = parse('[data-rules-stages]');
    const skills = parse('[data-rules-skills]');
    const prompts = parse('[data-rules-prompts]');

    function getCopy(lang, key) {
      return copy[lang] && copy[lang][key];
    }

    function stageLinkText(lang) {
      return getCopy(lang, 'stageOpenSource') || 'OPEN SOURCE ↗';
    }
    function skillLinkText(lang) {
      return getCopy(lang, 'skillReadSkill') || 'READ SKILL ↗';
    }
    function triggerLabel(lang) {
      return getCopy(lang, 'skillTriggerLabel') || 'TRIGGER';
    }
    function statusOk(lang) {
      return getCopy(lang, 'copyStatus') || 'Prompt copied.';
    }
    function statusFail(lang) {
      return getCopy(lang, 'copyFallback') || 'Select the text manually.';
    }

    const stored = localStorage.getItem('rules-language');
    let language = stored === 'pt' ? 'pt' : 'en';

    function select(selector, value, key) {
      root.querySelectorAll(selector).forEach(function (button) {
        const active = button.dataset[key] === value;
        button.classList.toggle('active', active);
        if (button.hasAttribute('aria-selected')) {
          button.setAttribute('aria-selected', active ? 'true' : 'false');
        }
        if (button.hasAttribute('aria-pressed')) {
          button.setAttribute('aria-pressed', active ? 'true' : 'false');
        }
      });
    }

    function renderStage(id) {
      const item = stages[id];
      if (!item) return;
      const target = root.querySelector('#stage-detail');
      if (!target) return;
      target.innerHTML =
        '<div class="stage-number">' +
        item.number +
        '</div>' +
        '<div><span>' +
        item.file +
        '</span><h3>' +
        item.title[language] +
        '</h3>' +
        '<p>' +
        item.text[language] +
        '</p>' +
        '<a href="' +
        item.link +
        '">' +
        stageLinkText(language) +
        '</a></div>' +
        '<pre><code>' +
        item.code +
        '</code></pre>';
      select('[data-stage]', id, 'stage');
    }

    function renderSkill(id) {
      const item = skills[id];
      if (!item) return;
      const target = root.querySelector('#skill-detail');
      if (!target) return;
      target.innerHTML =
        '<header><span>' +
        triggerLabel(language) +
        '</span>' +
        '<strong>' +
        item.trigger[language] +
        '</strong></header>' +
        '<h3>' +
        item.name +
        '</h3>' +
        '<p>' +
        item.lesson[language] +
        '</p>' +
        '<pre><code>' +
        item.example +
        '</code></pre>' +
        '<a href="https://git.marcospaulo.dev.br/netcracker/interview/src/branch/main/' +
        item.path +
        '">' +
        skillLinkText(language) +
        '</a>';
      select('[data-skill]', id, 'skill');
    }

    // Keys whose copy carries markup, so the swap must write innerHTML.
    // `skillsText` was missing while the markup renders it with `set:html`:
    // the island rewrote it as text on load and every visitor saw a literal
    // `<code>.agents/skills/</code>` in the paragraph.
    const HTML_KEYS = {
      heroTitle: 1,
      skillsText: 1,
      pipelineTitle: 1,
      skillsTitle: 1,
      ratchetTitle: 1,
      navPipeline: 1,
      navSkills: 1,
      navExamples: 1,
    };

    function renderLanguage(next) {
      language = next;
      document.documentElement.lang = language === 'pt' ? 'pt-BR' : 'en';
      root.querySelectorAll('[data-copy]').forEach(function (node) {
        const key = node.dataset.copy;
        if (!key) return;
        const value = getCopy(language, key);
        if (value === undefined) return;
        if (HTML_KEYS[key]) {
          node.innerHTML = value;
        } else {
          node.textContent = value;
        }
      });
      const promptEl = root.querySelector('#explore-prompt');
      if (promptEl) promptEl.textContent = prompts[language];
      select('[data-lang]', language, 'lang');
      const activeStage = root.querySelector('[data-stage].active');
      renderStage(activeStage ? activeStage.dataset.stage : 'context');
      const activeSkill = root.querySelector('[data-skill].active');
      renderSkill(activeSkill ? activeSkill.dataset.skill : 'gate');
      localStorage.setItem('rules-language', language);
    }

    function copyPrompt() {
      const value = prompts[language];
      const status = root.querySelector('#copy-status');
      if (navigator.clipboard && navigator.clipboard.writeText) {
        navigator.clipboard.writeText(value).then(
          function () {
            if (status) status.textContent = statusOk(language);
          },
          function () {
            if (status) status.textContent = statusFail(language);
          },
        );
      } else if (status) {
        status.textContent = statusFail(language);
      }
    }

    root.querySelectorAll('[data-stage]').forEach(function (button) {
      button.addEventListener('click', function () {
        renderStage(button.dataset.stage || 'context');
      });
    });
    root.querySelectorAll('[data-skill]').forEach(function (button) {
      button.addEventListener('click', function () {
        renderSkill(button.dataset.skill || 'gate');
      });
    });
    root.querySelectorAll('[data-lang]').forEach(function (button) {
      button.addEventListener('click', function () {
        renderLanguage(button.dataset.lang || 'en');
      });
    });
    const copyBtn = root.querySelector('[data-copy-prompt]');
    if (copyBtn) copyBtn.addEventListener('click', copyPrompt);

    const progress = root.querySelector('[data-progress]');
    if (progress) {
      function update() {
        const height = document.documentElement.scrollHeight - window.innerHeight;
        progress.style.width = (height > 0 ? (window.scrollY / height) * 100 : 0) + '%';
      }
      window.addEventListener('scroll', update, { passive: true });
      update();
    }

    renderLanguage(language);
  })();
</script>

<style>
  /* rules-root is the only element Astro scopes styles to. The legacy
     page's rules/styles.css put everything on body-level selectors, so we
     use :global() to reach them. */
  .rules-root :global(*) {
    box-sizing: border-box;
  }
  .rules-root :global(html) {
    scroll-behavior: smooth;
  }
  .rules-root :global(body) {
    min-width: 320px;
    margin: 0;
    color: var(--ink);
    background: var(--paper);
    font-family: Manrope, Arial, sans-serif;
  }

  .progress {
    position: fixed;
    z-index: 20;
    top: 0;
    left: 0;
    width: 100%;
    height: 3px;
    background: transparent;
  }
  .progress span {
    display: block;
    width: 0;
    height: 100%;
    background: var(--gold);
  }

  .topbar {
    position: sticky;
    z-index: 10;
    top: 0;
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    min-height: 72px;
    padding: 0 clamp(24px, 5vw, 90px);
    border-bottom: 1px solid var(--line);
    background: color-mix(in srgb, var(--paper) 94%, transparent);
    backdrop-filter: blur(14px);
  }
  .back {
    display: flex;
    align-items: center;
    gap: 11px;
    color: var(--ink);
    font:
      700 10px 'DM Mono',
      monospace;
    text-decoration: none;
    text-transform: uppercase;
  }
  .back b {
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    color: var(--paper);
    background: var(--accent);
    font-size: var(--step-1);
  }
  .topbar nav {
    display: flex;
    gap: 28px;
  }
  .topbar nav a,
  .languages {
    color: var(--muted);
    font:
      600 9px 'DM Mono',
      monospace;
    letter-spacing: 0.08em;
    text-decoration: none;
    text-transform: uppercase;
  }
  .languages {
    justify-self: end;
    display: flex;
    align-items: center;
    gap: 7px;
  }
  .languages button {
    padding: 7px;
    border: 0;
    color: var(--muted);
    background: transparent;
    cursor: pointer;
  }
  .languages button.active {
    color: var(--paper);
    background: var(--blue);
  }

  main {
    max-width: 1920px;
    margin: auto;
    padding: 0 clamp(24px, 5vw, 90px);
  }

  .hero {
    min-height: 700px;
    padding: 130px 0 80px;
  }
  .eyebrow,
  .section-label,
  .thesis > span {
    color: var(--accent);
    font:
      600 9px 'DM Mono',
      monospace;
    letter-spacing: 0.1em;
    text-transform: uppercase;
  }
  .hero h1,
  .intro h2 {
    margin: 22px 0 50px;
    font-size: clamp(64px, 8.3vw, 148px);
    line-height: 0.82;
    letter-spacing: -0.075em;
  }
  .hero h1 em,
  .intro h2 em {
    color: var(--blue);
    font-family: Georgia, serif;
    font-weight: 400;
  }
  .hero-foot {
    display: grid;
    grid-template-columns: 1.3fr 0.7fr;
    gap: 70px;
    align-items: end;
  }
  .hero-foot > p {
    max-width: 750px;
    margin: 0;
    color: var(--muted);
    font-size: var(--step-16);
    line-height: 1.75;
  }
  .hero-foot aside {
    display: grid;
    gap: 8px;
    padding: 23px;
    border-left: 6px solid var(--gold);
    color: var(--paper);
    background: var(--deep);
  }
  .hero-foot aside span,
  .hero-foot aside small {
    color: var(--gold);
    font:
      500 8px 'DM Mono',
      monospace;
    letter-spacing: 0.08em;
  }
  .hero-foot aside strong {
    font-size: var(--step-32);
  }

  .thesis {
    display: grid;
    grid-template-columns: 200px 1fr;
    gap: 35px;
    align-items: center;
    margin: 0 calc(clamp(24px, 5vw, 90px) * -1) 130px;
    padding: 35px clamp(24px, 5vw, 90px);
    color: var(--paper);
    background: var(--ink);
  }
  .thesis strong {
    font-size: clamp(20px, 2.4vw, 38px);
    line-height: 1.2;
  }

  .section-label {
    display: flex;
    justify-content: space-between;
    padding-bottom: 15px;
    border-bottom: 1px solid var(--line);
  }
  .section-label span:last-child {
    color: var(--muted);
  }
  .pipeline-section,
  .skill-section,
  .examples,
  .copy-lab {
    margin-bottom: 140px;
    padding-top: 30px;
  }
  .intro {
    display: grid;
    grid-template-columns: 0.9fr 1.1fr;
    gap: 70px;
    align-items: end;
    margin: 45px 0;
  }
  .intro h2 {
    margin: 15px 0 0;
    font-size: clamp(48px, 5.6vw, 92px);
  }
  .intro > p {
    max-width: 650px;
    margin: 0;
    color: var(--muted);
    font-size: var(--step-14);
    line-height: 1.75;
  }

  .pipeline {
    display: grid;
    grid-template-columns: 1fr auto 1fr auto 1fr auto 1fr auto 1fr;
    align-items: stretch;
    border: 1px solid var(--line);
    background: var(--paper);
  }
  .pipeline button {
    display: grid;
    gap: 8px;
    min-height: 126px;
    padding: 20px;
    border: 0;
    color: var(--ink);
    background: transparent;
    text-align: left;
    cursor: pointer;
  }
  .pipeline button span {
    color: var(--accent);
    font:
      600 9px 'DM Mono',
      monospace;
  }
  .pipeline button strong {
    font:
      700 13px 'DM Mono',
      monospace;
  }
  .pipeline button small {
    color: var(--muted);
    font:
      10px 'DM Mono',
      monospace;
  }
  .pipeline button.active {
    color: var(--paper);
    background: var(--blue);
    box-shadow: inset 0 -6px var(--gold);
  }
  .pipeline button.active span,
  .pipeline button.active small {
    color: var(--gold);
  }
  .pipeline > i {
    align-self: center;
    color: var(--gold);
    font-style: normal;
  }

  .stage-detail {
    display: grid;
    grid-template-columns: 120px 1.3fr 0.7fr;
    gap: 35px;
    min-height: 330px;
    padding: 42px;
    color: var(--paper);
    background: var(--deep);
  }
  .stage-number {
    color: var(--white-14);
    font:
      500 76px 'DM Mono',
      monospace;
  }
  .stage-detail > div:nth-child(2) > span,
  .skill-detail header span {
    color: var(--gold);
    font:
      500 9px 'DM Mono',
      monospace;
    letter-spacing: 0.08em;
  }
  .stage-detail h3,
  .skill-detail h3 {
    margin: 15px 0;
    font-size: clamp(28px, 3vw, 48px);
    letter-spacing: -0.05em;
  }
  .stage-detail p,
  .skill-detail p {
    max-width: 650px;
    color: var(--ink-line);
    font-size: var(--step-13);
    line-height: 1.7;
  }
  .stage-detail a,
  .skill-detail a,
  .example-grid a {
    display: inline-block;
    margin-top: 15px;
    color: var(--gold);
    font:
      600 9px 'DM Mono',
      monospace;
    letter-spacing: 0.07em;
  }
  .stage-detail pre,
  .skill-detail pre,
  .example-grid pre,
  .copy-lab pre {
    margin: 0;
    overflow: auto;
    background: var(--deep);
  }
  .stage-detail pre {
    align-self: stretch;
    padding: 28px;
  }
  .stage-detail code,
  .skill-detail code,
  .example-grid code,
  .copy-lab code {
    color: var(--ink-code);
    font:
      11px/1.7 'DM Mono',
      monospace;
  }

  .skill-console {
    display: grid;
    grid-template-columns: minmax(240px, 0.7fr) minmax(0, 1.5fr);
    min-height: 570px;
    border: 1px solid var(--line);
    background: var(--line);
    gap: 1px;
  }
  .skill-list {
    display: grid;
    grid-template-rows: repeat(6, 1fr);
    gap: 1px;
    background: var(--line);
  }
  .skill-list button {
    display: grid;
    align-content: center;
    gap: 7px;
    padding: 18px 22px;
    border: 0;
    color: var(--ink);
    background: var(--paper);
    text-align: left;
    cursor: pointer;
  }
  .skill-list button strong {
    font:
      700 12px 'DM Mono',
      monospace;
  }
  .skill-list button small {
    color: var(--muted);
    font-size: var(--step-00);
  }
  .skill-list button.active {
    color: var(--paper);
    background: var(--accent);
    box-shadow: inset 6px 0 var(--gold);
  }
  .skill-list button.active small {
    color: var(--accent-paper-active);
  }
  .skill-detail {
    display: grid;
    align-content: center;
    padding: 50px clamp(30px, 5vw, 80px);
    color: var(--paper);
    background: var(--accent-surface);
  }
  .skill-detail header {
    display: grid;
    gap: 9px;
    padding-bottom: 22px;
    border-bottom: 1px solid var(--white-23);
  }
  .skill-detail header strong {
    font-size: var(--step-12);
  }
  .skill-detail pre {
    margin: 20px 0 0;
    padding: 18px;
  }

  .example-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1px;
    margin-top: 45px;
    background: var(--line);
  }
  .example-grid article {
    display: grid;
    grid-template-rows: auto auto 1fr auto;
    min-height: 390px;
    padding: 35px;
    background: var(--paper);
  }
  .example-grid article > span {
    color: var(--accent);
    font:
      600 9px 'DM Mono',
      monospace;
    letter-spacing: 0.08em;
  }
  .example-grid h3 {
    margin: 22px 0;
    font-size: clamp(26px, 3vw, 42px);
    line-height: 1.05;
    letter-spacing: -0.045em;
  }
  .example-grid pre {
    padding: 22px;
  }
  .example-grid a {
    color: var(--blue);
  }

  .copy-lab {
    display: grid;
    grid-template-columns: 0.75fr 1.25fr;
    gap: 1px;
    color: var(--paper);
    background: var(--line);
  }
  .copy-lab > div {
    padding: 45px;
    background: var(--accent);
  }
  .copy-lab > div span {
    color: var(--gold);
    font:
      600 9px 'DM Mono',
      monospace;
  }
  .copy-lab h2 {
    margin: 20px 0;
    font-size: clamp(30px, 3.4vw, 56px);
    line-height: 1;
  }
  .copy-lab > div p {
    max-width: 420px;
    color: var(--accent-paper);
    line-height: 1.6;
  }
  .copy-lab article {
    display: grid;
    grid-template-rows: auto 1fr auto;
    min-width: 0;
    background: var(--deep);
  }
  .copy-lab button {
    justify-self: end;
    display: flex;
    gap: 20px;
    margin: 20px;
    padding: 11px 14px;
    border: 1px solid var(--white-31);
    color: var(--paper);
    background: transparent;
    font:
      600 9px 'DM Mono',
      monospace;
    cursor: pointer;
  }
  .copy-lab pre {
    padding: 26px;
    white-space: pre-wrap;
  }
  .copy-lab article > p {
    min-height: 20px;
    margin: 12px 24px;
    color: var(--gold);
    font:
      600 9px 'DM Mono',
      monospace;
  }

  .deeper {
    margin: 0 calc(clamp(24px, 5vw, 90px) * -1);
    padding: 60px clamp(24px, 5vw, 90px) 100px;
    background: var(--gold);
  }
  .deeper > div {
    display: flex;
    justify-content: space-between;
    gap: 30px;
    margin-bottom: 35px;
  }
  .deeper > div span {
    color: var(--accent);
    font:
      600 9px 'DM Mono',
      monospace;
  }
  .deeper > div strong {
    max-width: 700px;
    font-size: clamp(24px, 3vw, 44px);
    line-height: 1.1;
  }
  .deeper nav {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 1px;
    background: var(--ink);
  }
  .deeper nav a {
    display: grid;
    gap: 9px;
    min-height: 160px;
    padding: 25px;
    color: var(--paper);
    background: var(--ink);
    text-decoration: none;
  }
  .deeper nav span {
    color: var(--accent);
    font:
      600 10px 'DM Mono',
      monospace;
  }
  .deeper nav b {
    font-size: var(--step-1);
  }
  .deeper nav small {
    color: var(--ink-muted);
    font:
      9px 'DM Mono',
      monospace;
  }

  .topbar a:focus-visible,
  .topbar button:focus-visible,
  .pipeline button:focus-visible,
  .skill-list button:focus-visible,
  .copy-lab button:focus-visible,
  .deeper a:focus-visible {
    outline: 3px solid var(--gold);
    outline-offset: -3px;
  }

  @media (min-width: 2200px) {
    main {
      max-width: 2880px;
      padding-inline: clamp(150px, 7vw, 300px);
    }
    .hero {
      min-height: 900px;
    }
    .hero h1 {
      font-size: clamp(150px, 7vw, 220px);
    }
    .pipeline button {
      min-height: 170px;
    }
    .stage-detail {
      min-height: 440px;
    }
    .skill-console {
      min-height: 720px;
    }
  }

  @media (max-width: 800px) {
    .topbar {
      grid-template-columns: 1fr auto;
    }
    .topbar nav {
      display: none;
    }
    .hero {
      min-height: auto;
    }
    .hero-foot,
    .intro,
    .copy-lab {
      grid-template-columns: 1fr;
    }
    .pipeline {
      grid-template-columns: 1fr 1fr 1fr;
    }
    .pipeline > i {
      display: none;
    }
    .pipeline button {
      min-height: 100px;
    }
    .stage-detail {
      grid-template-columns: 80px 1fr;
    }
    .stage-detail pre {
      grid-column: 1 / -1;
    }
    .skill-console {
      grid-template-columns: 1fr;
    }
    .skill-list {
      grid-template-columns: 1fr 1fr;
      grid-template-rows: none;
    }
    .example-grid {
      grid-template-columns: 1fr;
    }
    .deeper nav {
      grid-template-columns: 1fr 1fr;
    }
  }

  @media (max-width: 560px) {
    main {
      padding-inline: 18px;
    }
    .topbar {
      padding-inline: 18px;
    }
    .hero {
      padding-top: 80px;
    }
    .hero h1 {
      font-size: clamp(54px, 17vw, 78px);
    }
    .hero-foot {
      gap: 30px;
    }
    .thesis {
      grid-template-columns: 1fr;
      margin-inline: -18px;
      padding-inline: 18px;
    }
    .section-label {
      gap: 20px;
    }
    .section-label span:last-child {
      text-align: right;
    }
    .pipeline {
      grid-template-columns: 1fr;
    }
    .pipeline button {
      grid-template-columns: 38px 1fr;
      grid-template-rows: auto auto;
      min-height: 82px;
    }
    .pipeline button span {
      grid-row: 1 / -1;
      align-self: center;
    }
    .stage-detail {
      grid-template-columns: 1fr;
      padding: 28px 22px;
    }
    .stage-number {
      font-size: var(--step-48);
    }
    .stage-detail pre {
      grid-column: auto;
    }
    .skill-list {
      grid-template-columns: 1fr;
    }
    .skill-detail {
      padding: 34px 24px;
    }
    .example-grid article {
      min-height: 340px;
      padding: 25px;
    }
    .copy-lab > div {
      padding: 30px 24px;
    }
    .deeper {
      margin-inline: -18px;
      padding-inline: 18px;
    }
    .deeper > div {
      display: grid;
    }
    .deeper nav {
      grid-template-columns: 1fr;
    }
    .deeper nav a {
      min-height: 120px;
    }
  }

  @media (prefers-reduced-motion: reduce) {
    html {
      scroll-behavior: auto;
    }
    .progress span {
      transition: none;
    }
  }
</style>
