#!/usr/bin/env python3
"""
Generate comprehensive HTML/CSS training data for Dev-AI.
Covers: semantic markup, accessibility, responsive design, CSS specificity,
layout patterns, modern CSS features, performance, and best practices.
Target: 100-120 high-quality entries.
"""
import json
import os
import random
from pathlib import Path

BASE = Path(__file__).parent.parent / "data" / "processed"

def g(issue, bad, good):
    return {
        "messages": [
            {"role": "user", "content": f"Review this HTML/CSS code:\n\n```html\n{bad}\n```"},
            {"role": "assistant", "content": f"**Issue: {issue}**\n\n**Fix:**\n```html\n{good}\n```"}
        ],
        "source": "html_css_training",
        "tags": ["html_css", issue.lower().replace(" ", "_")]
    }


entries = []

# =============================================================================
# SEMANTIC HTML (12 entries)
# =============================================================================

entries.append(g(
    "Div-based layout (div soup)",
    "<div class=\"header\">\n  <div class=\"logo\">...</div>\n  <div class=\"nav\">\n    <div class=\"nav-item\">Home</div>\n  </div>\n</div>\n<div class=\"main\">\n  <div class=\"article\">\n    <div class=\"title\">...</div>\n    <div class=\"content\">...</div>\n  </div>\n</div>\n<div class=\"footer\">...</div>",
    "<header>\n  <a href=\"/\" aria-label=\"Home\"><img src=\"logo.svg\" alt=\"Site logo\"></a>\n  <nav aria-label=\"Main\">\n    <a href=\"/\">Home</a>\n  </nav>\n</header>\n<main>\n  <article>\n    <h1>Title</h1>\n    <p>Content...</p>\n  </article>\n</main>\n<footer>...</footer>"
))

entries.append(g(
    "Missing lang attribute",
    "<!DOCTYPE html>\n<html>\n<head><title>Page</title></head>\n<body>...</body>\n</html>",
    "<!DOCTYPE html>\n<html lang=\"en\">\n<head><title>Page</title></head>\n<body>...</body>\n</html>\n// lang attribute is required for accessibility and SEO"
))

entries.append(g(
    "Using <b>/<i> instead of <strong>/<em>",
    "<b>Important warning</b>\n<i>Emphasized text</i>",
    "<strong>Important warning</strong>\n<em>Emphasized text</em>\n// strong/em convey meaning, not just style\n// b/i are for visual styling without semantic emphasis"
))

entries.append(g(
    "Missing heading hierarchy",
    "<h1>Page Title</h1>\n<h3>Section</h3>\n<h2>Subsection</h2>\n// Skips h2, goes h1 -> h3",
    "<h1>Page Title</h1>\n<h2>Section</h2>\n<h3>Subsection</h3>\n// Headings must follow sequential order\n// Screen readers use heading structure to navigate"
))

entries.append(g(
    "Table without semantic elements",
    "<table>\n  <tr><td>Name</td><td>Age</td></tr>\n  <tr><td>Alice</td><td>30</td></tr>\n</table>",
    "<table>\n  <thead>\n    <tr><th>Name</th><th>Age</th></tr>\n  </thead>\n  <tbody>\n    <tr><td>Alice</td><td>30</td></tr>\n  </tbody>\n</table>"
))

entries.append(g(
    "Using <br> for spacing",
    "<p>Line 1</p>\n<br><br>\n<p>Line 2</p>",
    "<p>Line 1</p>\n<p>Line 2</p>\n// Use CSS margin for spacing, not <br> tags\n// <br> is for line breaks within text (addresses, poetry)"
))

entries.append(g(
    "Missing alt text on images",
    "<img src=\"hero.jpg\">\n<img src=\"icon.png\">",
    "<img src=\"hero.jpg\" alt=\"Person planting seeds in garden\">\n<img src=\"icon.png\" alt=\"\"> // Decorative image - empty alt\n// All images need alt. Decorative images use alt=\"\""
))

entries.append(g(
    "Using <a> for non-navigation",
    "<a href=\"#\" onclick=\"openModal()\">Open Modal</a>\n// Not a navigation link",
    "<button type=\"button\" onclick=\"openModal()\">Open Modal</button>\n// Buttons for actions, links for navigation\n// <a> should have a real href for accessibility"
))

entries.append(g(
    "Missing form labels",
    "<form>\n  <input type=\"text\" placeholder=\"Name\">\n  <input type=\"email\" placeholder=\"Email\">\n  <button>Submit</button>\n</form>",
    "<form>\n  <label for=\"name\">Name</label>\n  <input type=\"text\" id=\"name\" required>\n  <label for=\"email\">Email</label>\n  <input type=\"email\" id=\"email\" required>\n  <button type=\"submit\">Submit</button>\n</form>"
))

entries.append(g(
    "Using <div> for text content",
    "<div class=\"paragraph\">This is a paragraph of text.</div>\n<div class=\"paragraph\">Another paragraph.</div>",
    "<p>This is a paragraph of text.</p>\n<p>Another paragraph.</p>\n// <p> is for paragraphs, <div> is for grouping"
))

entries.append(g(
    "Missing main landmark",
    "<div id=\"content\">\n  <h1>Title</h1>\n  <p>Content...</p>\n</div>",
    "<main id=\"content\">\n  <h1>Title</h1>\n  <p>Content...</p>\n</main>\n// <main> marks the primary content\n// Only one <main> per page"
))

entries.append(g(
    "Using abbreviations without definition",
    "<p>Use the API for integration.</p>\n// API is abbreviated, undefined",
    "<p>Use the <abbr title=\"Application Programming Interface\">API</abbr> for integration.</p>\n// <abbr> provides expanded text for accessibility"
))

# =============================================================================
# ACCESSIBILITY (12 entries)
# =============================================================================

entries.append(g(
    "Missing focus styles",
    "a:focus {\n  outline: none;\n}",
    "a:focus {\n  outline: 2px solid #0066cc;\n  outline-offset: 2px;\n}\n// Never remove outline without replacement\n// Focus indicators are essential for keyboard navigation"
))

entries.append(g(
    "Inline event handlers",
    "<button onclick=\"doSomething()\">Click</button>",
    "<button type=\"button\" id=\"action-btn\">Click</button>\n\n<script>\ndocument.getElementById('action-btn').addEventListener('click', doSomething);\n</script>\n// Separate structure from behavior"
))

entries.append(g(
    "Color-only information",
    "<p><span style=\"color: red;\">Error:</span> Invalid input</p>\n// Red color indicates error, no other indicator",
    "<p role=\"alert\">\n  <span aria-hidden=\"true\">⚠️</span>\n  <strong>Error:</strong> Invalid input\n</p>\n// Don't rely on color alone\n// Add text, icons, or ARIA roles"
))

entries.append(g(
    "Missing skip navigation link",
    "<nav>\n  <a href=\"/1\">One</a>\n  <a href=\"/2\">Two</a>\n  <a href=\"/3\">Three</a>\n  <!-- 50 more links -->\n</nav>",
    "<a href=\"#main\" class=\"skip-link\">Skip to main content</a>\n\n<style>\n.skip-link {\n  position: absolute;\n  left: -9999px;\n}\n.skip-link:focus {\n  left: 0;\n}\n</style>\n// Skip link lets keyboard users bypass navigation"
))

entries.append(g(
    "aria-label missing on icon button",
    "<button class=\"icon-btn\">\n  <svg>...</svg>\n</button>\n// Icon button with no text",
    "<button class=\"icon-btn\" aria-label=\"Close dialog\">\n  <svg aria-hidden=\"true\"><use href=\"#close-icon\"/></svg>\n</button>\n// aria-label describes the action\n// Decorative SVGs use aria-hidden"
))

entries.append(g(
    "Table without caption or scope",
    "<table>\n  <tr><td>Q1</td><td>$100</td></tr>\n  <tr><td>Q2</td><td>$150</td></tr>\n</table>",
    "<table>\n  <caption>Quarterly Revenue</caption>\n  <thead>\n    <tr><th scope=\"col\">Quarter</th><th scope=\"col\">Revenue</th></tr>\n  </thead>\n  <tbody>\n    <tr><td>Q1</td><td>$100</td></tr>\n    <tr><td>Q2</td><td>$150</td></tr>\n  </tbody>\n</table>"
))

entries.append(g(
    "Missing role on custom component",
    "<div class=\"dropdown\">\n  <div class=\"dropdown-toggle\" tabindex=\"0\">Menu</div>\n  <div class=\"dropdown-menu\">\n    <a href=\"/1\">One</a>\n  </div>\n</div>",
    "<div class=\"dropdown\" role=\"combobox\" aria-expanded=\"false\">\n  <div class=\"dropdown-toggle\" tabindex=\"0\" role=\"button\">Menu</div>\n  <div class=\"dropdown-menu\" role=\"listbox\">\n    <a href=\"/1\" role=\"option\">One</a>\n  </div>\n</div>\n// Use ARIA roles to convey semantics to screen readers"
))

entries.append(g(
    "Link text not descriptive",
    "<a href=\"/details\">Click here</a>\n<a href=\"/docs\">Read more</a>\n// Link text doesn't describe destination",
    "<a href=\"/details\">View order details</a>\n<a href=\"/docs\">Read API documentation</a>\n// Link text should be meaningful on its own"
))

entries.append(g(
    "Missing live region for dynamic content",
    "<div id=\"results\"></div>\n// Content updated dynamically, screen readers won't know",
    "<div id=\"results\" aria-live=\"polite\" aria-atomic=\"true\"></div>\n// aria-live announces changes to screen readers\n// polite = wait for pause, assertive = interrupt"
))

entries.append(g(
    "Form without error association",
    "<form>\n  <input type=\"email\" id=\"email\">\n  <span class=\"error\">Invalid email</span>\n</form>\n// Error not associated with input",
    "<form>\n  <label for=\"email\">Email</label>\n  <input type=\"email\" id=\"email\" aria-describedby=\"email-error\" aria-invalid=\"true\">\n  <span id=\"email-error\" class=\"error\">Invalid email</span>\n</form>"
))

entries.append(g(
    "Video without captions",
    "<video src=\"demo.mp4\" controls></video>",
    "<video src=\"demo.mp4\" controls>\n  <track src=\"captions.vtt\" kind=\"subtitles\" srclang=\"en\" label=\"English\">\n</video>\n// Captions are required for accessibility\n// <track> element provides subtitle/caption support"
))

entries.append(g(
    "Missing landmarks",
    "<div class=\"wrapper\">\n  <div class=\"header\">...</div>\n  <div class=\"nav\">...</div>\n  <div class=\"content\">...</div>\n  <div class=\"sidebar\">...</div>\n  <div class=\"footer\">...</div>\n</div>",
    "<div class=\"wrapper\">\n  <header>...</header>\n  <nav aria-label=\"Main\">...</nav>\n  <main>...</main>\n  <aside>...</aside>\n  <footer>...</footer>\n</div>\n// Semantic landmarks improve screen reader navigation"
))

# =============================================================================
# CSS SPECIFICITY & SELECTORS (10 entries)
# =============================================================================

entries.append(g(
    "Using !important",
    ".btn {\n  color: white;\n  background: blue;\n}\n.btn.primary {\n  background: red !important;\n}",
    ".btn {\n  color: white;\n  background: blue;\n}\n.btn--primary {\n  background: red;\n}\n// Fix specificity with better selectors, not !important\n// !important makes CSS unmaintainable"
))

entries.append(g(
    "Overly specific selectors",
    "div.container > ul.list > li.item > a.link {\n  color: blue;\n}\n// Specificity: 0,4,0 - hard to override",
    ".link {\n  color: blue;\n}\n// Use single-class selectors (0,1,0)\n// Keep specificity low and predictable"
))

entries.append(g(
    "ID selectors for styling",
    "#header {\n  background: #333;\n}\n#sidebar {\n  width: 300px;\n}\n// IDs have high specificity and can't be reused",
    ".header {\n  background: #333;\n}\n.sidebar {\n  width: 300px;\n}\n// Use classes for styling, IDs for JavaScript hooks"
))

entries.append(g(
    "Descendant selector abuse",
    ".nav .menu .item .link .icon {\n  color: red;\n}\n// Deep nesting - fragile and high specificity",
    ".icon--nav {\n  color: red;\n}\n// BEM-style: block__element--modifier\n// Or flat selectors with descriptive names"
))

entries.append(g(
    "Universal selector in performance-critical path",
    ".card * {\n  box-sizing: border-box;\n}\n// Matches every element inside .card",
    "* {\n  box-sizing: border-box;\n}\n// Apply universal reset once at the top level\n// Avoid * in component selectors for performance"
))

entries.append(g(
    "Adjacent sibling selector fragility",
    "h1 + p {\n  font-size: 1.2rem;\n}\n// Breaks if any element is inserted between h1 and p",
    ".lead {\n  font-size: 1.2rem;\n}\n// Use a class instead of structural selectors\n// Structural selectors break with DOM changes"
))

entries.append(g(
    "Attribute selector performance",
    "[class*=\"btn\"] {\n  padding: 8px 16px;\n}\n// Matches any element with \"btn\" in class",
    ".btn {\n  padding: 8px 16px;\n}\n// Class selectors are faster than attribute selectors\n// Attribute selectors are for dynamic/generated classes"
))

entries.append(g(
    "Missing CSS reset/normalize",
    "body {\n  font-family: sans-serif;\n}\n// Browser default styles vary",
    "/* Normalize.css or custom reset */\n*, *::before, *::after {\n  box-sizing: border-box;\n}\nhtml {\n  line-height: 1.5;\n  -webkit-text-size-adjust: 100%;\n}body {\n  margin: 0;\n  font-family: system-ui, sans-serif;\n}"
))

entries.append(g(
    "Chained class specificity war",
    ".container .main .content .card .btn {\n  background: red;\n}\n// Fighting another rule with more nesting",
    ".btn--danger {\n  background: red;\n}\n// Resolve specificity conflicts with clearer naming\n// Not by adding more selectors"
))

entries.append(g(
    "Type selector in component CSS",
    "div.card {\n  padding: 16px;\n}\n// Tied to element type",
    ".card {\n  padding: 16px;\n}\n// Don't tie styles to element types\n// Components should work on any element"
))

# =============================================================================
# LAYOUT (12 entries)
# =============================================================================

entries.append(g(
    "Float-based layout",
    ".sidebar {\n  float: left;\n  width: 250px;\n}\n.content {\n  margin-left: 270px;\n}\n// Float layout requires clearfix hacks",
    ".layout {\n  display: grid;\n  grid-template-columns: 250px 1fr;\n}\n// CSS Grid: clean, no clearfix needed\n// Or Flexbox for simpler layouts"
))

entries.append(g(
    "Fixed height containers",
    ".hero {\n  height: 500px;\n}\n// Breaks on small screens and with dynamic content",
    ".hero {\n  min-height: 500px;\n}\n// min-height allows content to expand\n// Fixed height causes overflow issues"
))

entries.append(g(
    "Margin collapse not handled",
    ".parent {\n  border: 1px solid #ccc;\n}\n.child {\n  margin-top: 20px;\n}\n// Child margin collapses with parent",
    ".parent {\n  border: 1px solid #ccc;\n  overflow: hidden;\n  /* Or: display: flow-root */\n}\n// Creates new block formatting context"
))

entries.append(g(
    "Using display: none for responsive hiding",
    "@media (max-width: 768px) {\n  .sidebar {\n    display: none;\n  }\n}\n// Removes from accessibility tree entirely",
    "@media (max-width: 768px) {\n  .sidebar {\n    display: none;\n  }\n}\n// OK for responsive, but consider:\n// .sidebar[aria-hidden=\"true\"] for programmatic hiding\n// Or reorder with CSS instead of hiding"
))

entries.append(g(
    "Centering with negative margins",
    ".modal {\n  position: fixed;\n  top: 50%;\n  left: 50%;\n  margin-top: -150px;\n  margin-left: -200px;\n}\n// Fragile - breaks if size changes",
    ".modal {\n  position: fixed;\n  inset: 0;\n  display: grid;\n  place-items: center;\n}\n// Grid centering: works regardless of size"
))

entries.append(g(
    "Holy grail layout with floats",
    ".header { height: 60px; }\n.sidebar { float: left; width: 200px; }\n.main { margin: 0 200px; }\n.footer { clear: both; height: 40px; }",
    ".page {\n  display: grid;\n  grid-template-areas:\n    \"header header\"\n    \"sidebar main\"\n    \"footer footer\";\n  grid-template-columns: 200px 1fr;\n  min-height: 100vh;\n}\n.header { grid-area: header; }\n.sidebar { grid-area: sidebar; }\n.main { grid-area: main; }\n.footer { grid-area: footer; }"
))

entries.append(g(
    "Flexbox with fixed widths",
    ".nav {\n  display: flex;\n}\n.nav-item {\n  width: 100px;\n}\n// Doesn't adapt to content",
    ".nav {\n  display: flex;\n  gap: 8px;\n}\n.nav-item {\n  flex: 1 1 auto;\n  min-width: 80px;\n}\n// flex: grow shrink basis\n// gap replaces margin for spacing"
))

entries.append(g(
    "Using tables for layout",
    "<table style=\"width:100%\">\n  <tr><td width=\"200\">Sidebar</td><td>Content</td></tr>\n</table>",
    "<div style=\"display: grid; grid-template-columns: 200px 1fr; gap: 16px;\">\n  <aside>Sidebar</aside>\n  <main>Content</main>\n</div>\n// Tables are for tabular data only"
))

entries.append(g(
    "Missing responsive images",
    "<img src=\"photo-2000.jpg\" style=\"width: 100%\">\n// Loads 2MB image on mobile",
    "<picture>\n  <source media=\"(max-width: 600px)\" srcset=\"photo-600.webp\">\n  <source media=\"(max-width: 1200px)\" srcset=\"photo-1200.webp\">\n  <img src=\"photo-2000.webp\" alt=\"Description\" loading=\"lazy\">\n</picture>"
))

entries.append(g(
    "Container not constraining max width",
    ".content {\n  padding: 0 16px;\n}\n// Content stretches to full viewport on wide screens",
    ".content {\n  max-width: 72rem;\n  margin: 0 auto;\n  padding: 0 16px;\n}\n// max-width + margin: auto centers and constrains"
))

entries.append(g(
    "Using px for typography",
    "body {\n  font-size: 16px;\n  line-height: 24px;\n}\nh1 {\n  font-size: 32px;\n}\n// Doesn't respect user browser settings",
    "body {\n  font-size: 1rem;\n  line-height: 1.5;\n}\nh1 {\n  font-size: 2rem;\n}\n// rem respects user font-size settings\n// unitless line-height inherits properly"
))

entries.append(g(
    "Position sticky not working",
    ".sidebar {\n  position: sticky;\n  top: 0;\n}\n// Not working - parent has overflow",
    ".parent {\n  overflow: visible; /* not hidden/auto/scroll */\n}\n.sidebar {\n  position: sticky;\n  top: 0;\n}\n// sticky is constrained by parent overflow"
))

# =============================================================================
# MODERN CSS FEATURES (12 entries)
# =============================================================================

entries.append(g(
    "Not using CSS custom properties",
    ".btn {\n  background: #0066cc;\n  color: #fff;\n  border-radius: 4px;\n}\n.btn--dark {\n  background: #333;\n}\n// Duplicated values",
    ":root {\n  --color-primary: #0066cc;\n  --color-text-light: #fff;\n  --radius-sm: 4px;\n}\n.btn {\n  background: var(--color-primary);\n  color: var(--color-text-light);\n  border-radius: var(--radius-sm);\n}\n.btn--dark {\n  --color-primary: #333;\n}"
))

entries.append(g(
    "Media query for mobile first",
    ".container {\n  width: 960px;\n}\n@media (max-width: 768px) {\n  .container {\n    width: 100%;\n  }\n}\n// Desktop-first - adds complexity",
    ".container {\n  width: 100%;\n  max-width: 960px;\n  margin: 0 auto;\n}\n@media (min-width: 768px) {\n  .container {\n    /* Add desktop enhancements */\n  }\n}\n// Mobile-first: base styles = mobile, min-width = larger screens"
))

entries.append(g(
    "Not using container queries",
    ".card {\n  display: block;\n}\n@media (min-width: 768px) {\n  .card {\n    display: flex;\n  }\n}\n// Component layout tied to viewport",
    ".card-container {\n  container-type: inline-size;\n}\n.card {\n  display: block;\n}\n@container (min-width: 400px) {\n  .card {\n    display: flex;\n  }\n}\n// Container queries: component responds to its container, not viewport"
))

entries.append(g(
    "Not using :has() selector",
    "// JavaScript needed to style parent based on child\ndocument.querySelectorAll('.form-group').forEach(group => {\n  if (group.querySelector('.error')) {\n    group.classList.add('has-error');\n  }\n});",
    ".form-group:has(.error) {\n  border-color: red;\n}\n// :has() styles parent based on child state\n// No JavaScript needed"
))

entries.append(g(
    "Not using CSS layers",
    "/* Third-party styles */\n.btn { padding: 8px; }\n/* Base styles */\n.btn { padding: 12px; }\n/* Component styles */\n.btn { padding: 16px; }\n// Specificity wars",
    "@layer reset, base, components, utilities;\n\n@layer reset { /* ... */ }\n@layer base { .btn { padding: 12px; } }\n@layer components { .btn { padding: 16px; } }\n// @layer controls cascade order regardless of specificity"
))

entries.append(g(
    "Not using subgrid",
    ".grid {\n  display: grid;\n  grid-template-columns: repeat(3, 1fr);\n}\n.card {\n  display: grid;\n  grid-template-columns: 1fr 2fr;\n  /* Doesn't align with parent grid */\n}",
    ".grid {\n  display: grid;\n  grid-template-columns: repeat(3, 1fr);\n}\n.card {\n  display: grid;\n  grid-template-columns: subgrid;\n  /* Inherits parent grid track sizes */\n}"
))

entries.append(g(
    "Not using aspect-ratio",
    ".image-container {\n  position: relative;\n  padding-top: 56.25%; /* 16:9 */\n}\n.image-container img {\n  position: absolute;\n  top: 0;\n  width: 100%;\n  height: 100%;\n  object-fit: cover;\n}\n// Padding hack for aspect ratio",
    ".image-container {\n  aspect-ratio: 16 / 9;\n}\n.image-container img {\n  width: 100%;\n  height: 100%;\n  object-fit: cover;\n}\n// aspect-ratio: native, clean"
))

entries.append(g(
    "Not using clamp() for responsive typography",
    "h1 { font-size: 2rem; }\n@media (min-width: 768px) { h1 { font-size: 3rem; } }\n@media (min-width: 1200px) { h1 { font-size: 4rem; } }",
    "h1 {\n  font-size: clamp(2rem, 5vw + 1rem, 4rem);\n}\n// clamp(min, preferred, max)\n// Fluid typography without media queries"
))

entries.append(g(
    "Not using logical properties",
    ".card {\n  margin-left: 16px;\n  padding-top: 8px;\n  padding-bottom: 8px;\n}\n// Breaks in RTL languages",
    ".card {\n  margin-inline-start: 16px;\n  padding-block: 8px;\n}\n// Logical properties adapt to writing direction\n// inline = horizontal, block = vertical"
))

entries.append(g(
    "Not using color-mix()",
    ".btn:hover {\n  background: #0055aa;\n}\n// Manual darker shade",
    ":root {\n  --color-primary: #0066cc;\n}\n.btn:hover {\n  background: color-mix(in srgb, var(--color-primary) 80%, black);\n}\n// color-mix: programmatic color manipulation"
))

entries.append(g(
    "Not using text-wrap: balance",
    "h1 {\n  /* Multi-line heading wraps awkwardly */\n}",
    "h1 {\n  text-wrap: balance;\n}\n// Balances line lengths in multi-line text\n// Also: text-wrap: pretty for paragraphs"
))

entries.append(g(
    "Not using @scope",
    ".modal .btn { color: white; }\n.modal .card .btn { color: blue; }\n// Global selectors can conflict",
    "@scope (.modal) {\n  .btn { color: white; }\n  .card :where(.btn) { color: blue; }\n}\n// @scope limits CSS to a subtree\n// Prevents global selector conflicts"
))

# =============================================================================
# RESPONSIVE DESIGN (8 entries)
# =============================================================================

entries.append(g(
    "Missing viewport meta tag",
    "<!DOCTYPE html>\n<html>\n<head>\n  <title>Page</title>\n</head>",
    "<!DOCTYPE html>\n<html>\n<head>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n  <title>Page</title>\n</head>\n// Required for mobile rendering"
))

entries.append(g(
    "Using rem without setting base",
    "body {\n  font-size: 1rem;\n}\n// 1rem = browser default (usually 16px)\n// Different browsers = different sizes",
    "html {\n  font-size: 100%; /* Respects user settings */\n}\nbody {\n  font-size: 1rem;\n}\n// Or set explicitly: html { font-size: 16px; }"
))

entries.append(g(
    "Breakpoint-based instead of content-based",
    "@media (min-width: 768px) { /* tablet */ }\n@media (min-width: 1024px) { /* desktop */ }\n@media (min-width: 1440px) { /* large desktop */ }\n// Device-based breakpoints",
    "// Break when the design breaks:\n@container (min-width: 300px) {\n  .card { display: flex; }\n}\n// Or viewport-based but content-driven:\n@media (min-width: 48em) {\n  .layout { display: grid; grid-template-columns: 1fr 1fr; }\n}\n// Use em for viewport breakpoints (scales with font-size)"
))

entries.append(g(
    "Fixed width container on mobile",
    ".container {\n  width: 960px;\n  margin: 0 auto;\n}\n// Horizontally scrollable on mobile",
    ".container {\n  width: min(960px, 100% - 32px);\n  margin: 0 auto;\n}\n// min() constrains to viewport\n// 32px = 16px padding on each side"
))

entries.append(g(
    "Not using prefers-reduced-motion",
    "@keyframes slide {\n  from { transform: translateX(-100%); }\n  to { transform: translateX(0); }\n}\n.element {\n  animation: slide 0.5s ease;\n}",
    "@keyframes slide {\n  from { transform: translateX(-100%); }\n  to { transform: translateX(0); }\n}\n.element {\n  animation: slide 0.5s ease;\n}\n@media (prefers-reduced-motion: reduce) {\n  .element {\n    animation: none;\n  }\n}"
))

entries.append(g(
    "Not using prefers-color-scheme",
    "body {\n  background: #fff;\n  color: #333;\n}",
    ":root {\n  --bg: #fff;\n  --text: #333;\n}\n@media (prefers-color-scheme: dark) {\n  :root {\n    --bg: #1a1a1a;\n    --text: #e0e0e0;\n  }\n}\nbody {\n  background: var(--bg);\n  color: var(--text);\n}"
))

entries.append(g(
    "Text sized with viewport units only",
    "h1 {\n  font-size: 8vw;\n}\n// Too large on desktop, too small on mobile",
    "h1 {\n  font-size: clamp(1.5rem, 8vw, 4rem);\n}\n// Clamp provides min and max bounds\n// 8vw is the ideal fluid size"
))

entries.append(g(
    "Image overflow on small screens",
    "<img src=\"photo.jpg\" style=\"width: 800px\">\n// Overflows viewport on mobile",
    "<img src=\"photo.jpg\" style=\"max-width: 100%; height: auto;\">\n// max-width: 100% prevents overflow\n// height: auto maintains aspect ratio"
))

# =============================================================================
# CSS PERFORMANCE (8 entries)
# =============================================================================

entries.append(g(
    "Loading CSS in body",
    "<body>\n  <link rel=\"stylesheet\" href=\"styles.css\">\n  <div>Content</div>\n</body>",
    "<head>\n  <link rel=\"stylesheet\" href=\"styles.css\">\n</head>\n<body>\n  <div>Content</div>\n</body>\n// CSS in <head> prevents FOUC"
))

entries.append(g(
    "Not using font-display swap",
    "@font-face {\n  font-family: 'Custom';\n  src: url('font.woff2') format('woff2');\n}\n// Invisible text while font loads",
    "@font-face {\n  font-family: 'Custom';\n  src: url('font.woff2') format('woff2');\n  font-display: swap;\n}\n// swap: show fallback immediately, swap when loaded\n// Also consider: optional, fallback"
))

entries.append(g(
    "Large CSS file not split",
    "<link rel=\"stylesheet\" href=\"all.css\">\n// 200KB single file with above/below fold styles",
    "<link rel=\"stylesheet\" href=\"critical.css\">\n<link rel=\"stylesheet\" href=\"components.css\" media=\"print\" onload=\"this.media='all'\">\n// Critical CSS inlined or loaded first\n// Non-critical deferred"
))

entries.append(g(
    "Using @import in CSS",
    "@import 'reset.css';\n@import 'base.css';\n@import 'components.css';\n// Each @import is a blocking request",
    "<link rel=\"stylesheet\" href=\"reset.css\">\n<link rel=\"stylesheet\" href=\"base.css\">\n<link rel=\"stylesheet\" href=\"components.css\">\n// <link> tags are parallel-loaded\n// @import in CSS is sequential"
))

entries.append(g(
    "Not preloading critical resources",
    "<head>\n  <link rel=\"stylesheet\" href=\"styles.css\">\n</head>",
    "<head>\n  <link rel=\"preload\" href=\"font.woff2\" as=\"font\" crossorigin>\n  <link rel=\"preload\" href=\"hero.webp\" as=\"image\">\n  <link rel=\"stylesheet\" href=\"styles.css\">\n</head>\n// Preload critical resources the browser might not discover"
))

entries.append(g(
    "Using box-shadow on large area",
    ".page {\n  box-shadow: 0 0 100px rgba(0,0,0,0.3);\n}\n// Large blur on full page is expensive",
    ".page {\n  background: radial-gradient(ellipse at center, transparent 0%, rgba(0,0,0,0.3) 100%);\n}\n// Gradient can be cheaper than large blur shadows\n// Or reduce blur radius: box-shadow: 0 4px 8px"
))

entries.append(g(
    "Not using will-change",
    ".modal {\n  transform: translateY(-100%);\n  transition: transform 0.3s;\n}\n// Repaints on every frame",
    ".modal {\n  transform: translateY(-100%);\n  transition: transform 0.3s;\n  will-change: transform;\n}\n// will-change promotes to compositor layer\n// Use sparingly - it consumes memory"
))

entries.append(g(
    "Using CSS expressions (legacy)",
    "width: expression(document.body.clientWidth > 800 ? '800px' : 'auto');\n// JavaScript in CSS - terrible performance",
    "width: min(800px, 100%);\n// Modern CSS function replaces expression()\n// expression() is removed from all modern browsers"
))

# =============================================================================
# CSS ARCHITECTURE (6 entries)
# =============================================================================

entries.append(g(
    "No naming convention",
    ".header {\n}\n.header-title {\n}\n.header-title-small {\n}\n.header-nav {\n}\n// Unclear relationships",
    "/* BEM: Block __ Element -- Modifier */\n.header {\n}\n.header__title {\n}\n.header__title--small {\n}\n.header__nav {\n}\n// Clear component hierarchy from names"
))

entries.append(g(
    "Utility class abuse",
    "<div class=\"d-flex align-center justify-between p-4 m-2 bg-white rounded shadow\">\n  Content\n</div>\n// CSS-in-HTML, hard to maintain",
    "<div class=\"card\">\n  Content\n</div>\n\n.card {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  padding: 1rem;\n  margin: 0.5rem;\n  background: white;\n  border-radius: 4px;\n  box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n}\n// Semantic class names, not utility soup\n// Utility-first (Tailwind) is fine as a system choice"
))

entries.append(g(
    "Global state dependency in CSS",
    ".sidebar .content .card .title {\n  color: red;\n}\n// Only works in this specific DOM structure",
    ".title--highlighted {\n  color: red;\n}\n// Component should be self-contained\n// Not dependent on parent structure"
))

entries.append(g(
    "Not using CSS modules or scoped CSS",
    ".button {\n  background: blue;\n}\n// Global class - name collision risk",
    "// CSS Modules (button.module.css)\n.button {\n  background: blue;\n}\n// Compiled to: .button___abc123\n// Scope isolation without global namespace"
))

entries.append(g(
    "Not using CSS cascade layers for theming",
    "/* Theme overrides scattered everywhere */\n.theme-dark .btn { background: #333; }\n.theme-dark .card { background: #222; }\n.theme-dark .header { background: #111; }\n// Hard to maintain",
    ":root {\n  --theme-bg: #fff;\n  --theme-text: #333;\n  --theme-accent: #0066cc;\n}\n[data-theme=\"dark\"] {\n  --theme-bg: #1a1a1a;\n  --theme-text: #e0e0e0;\n  --theme-accent: #6699ff;\n}\n.btn {\n  background: var(--theme-accent);\n}\n// Theme via CSS custom properties - single source"
))

entries.append(g(
    "Missing CSS linting",
    "// No CSS linting configured",
    "// .stylelintrc.json\n{\n  \"extends\": \"stylelint-config-recommended\",\n  \"rules\": {\n    \"no-descending-specificity\": true,\n    \"selector-class-pattern\": \"^[a-z][a-zA-Z0-9_-]*$\",\n    \"color-named\": \"never\",\n    \"no-invalid-position-at-import-rule\": true\n  }\n}"
))

# =============================================================================
# SAVE
# =============================================================================

random.seed(42)
random.shuffle(entries)

os.makedirs(BASE, exist_ok=True)
out = BASE / "dev_finetuning_html_css.json"
with open(out, 'w') as f:
    json.dump(entries, f, indent=2)

categories = {}
for e in entries:
    for tag in e['tags']:
        if tag != 'html_css':
            categories[tag] = categories.get(tag, 0) + 1

print(f"Total entries: {len(entries)}")
print(f"Categories:")
for cat, count in sorted(categories.items(), key=lambda x: -x[1]):
    print(f"  {cat}: {count}")
print(f"Saved: {out}")
