> Idea: A live regex tester: type a pattern and flags in one box and sample text in another; matches highlight in real time as you type, a match list shows captured groups, and a panel explains each token of the pattern in plain English. Includes a few example patterns to load.

Build a single-page, zero-build "Regex Lab" — a live regular-expression tester that highlights matches in real time, lists every match with its captured groups, and explains each token of the pattern in plain English. The whole thing must run by opening one HTML file (no server, no bundler, no install step). Treat this as a polished, production-grade developer tool, not a toy demo.

## Goal
Create a fast, beautiful, entirely client-side regex playground that a developer can open instantly and trust. The user types a JavaScript regular-expression pattern and a set of flags into one panel and arbitrary sample text into another. As they type — with no "Run" button — the app:

- Compiles the pattern with the chosen flags and runs it against the sample text.
- Renders the sample text with every match visually highlighted in place; when multiple capture groups exist, sub-highlights distinguish the groups inside each match.
- Lists every match in a results panel: the matched substring, its start/end index, and a breakdown of each numbered and named capture group.
- Parses the pattern itself and produces a plain-English explanation, token by token, so a learner understands *why* the pattern matches.
- Surfaces clear, friendly error states when the pattern is invalid (e.g. unbalanced parentheses) without crashing or freezing.
- Ships with a small library of example patterns (email, URL, hex color, ISO date, US phone, IPv4, etc.) that load pattern + flags + sample text in one click.

The bar: it should feel like a tool a developer would bookmark. Instant feedback, no jank, no broken states, looks like a premium dark-mode product.

## Tech stack
- A single `index.html` with no build step. Pure HTML + CSS + vanilla JavaScript (ES2019+). No frameworks, no bundlers, no package manager.
- No external network requests whatsoever: no CDNs, no web fonts, no remote images, no analytics. Everything is self-contained and works fully offline / from `file://`.
- Use the browser-native `RegExp` engine for matching (this is a JavaScript-regex tester, and using the real engine is the honest, correct choice). Do **not** pull in a third-party regex library.
- Hand-write a small, dependency-free pattern tokenizer/explainer in vanilla JS for the "plain English" panel. It does not need to cover 100% of PCRE; it must robustly cover the common JavaScript regex surface and degrade gracefully on anything exotic.
- System font stack only (e.g. `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif`) for UI; a monospace stack (`ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace`) for code/regex surfaces. No webfonts.
- All logic lives in an external same-origin script file referenced with a relative path so it works whether served from a subpath or a subdomain. Wire every interaction with `addEventListener` — no inline event-handler attributes.
- Persist the current pattern, flags, and sample text to `localStorage` so a reload restores the session; fail silently if storage is unavailable.

## File layout
Keep it lean and obvious:

- `index.html` — semantic markup for the whole UI, an inline `<style>` block (or a sibling `styles.css` referenced relatively) containing all CSS using CSS custom properties for the theme, and a relative `<script src="./main.js" defer></script>` tag. No inline scripts, no inline event handlers.
- `main.js` — ALL JavaScript: state, debounced live evaluation, match-running, the highlight renderer, the match-list renderer, the pattern explainer/tokenizer, the examples data + loader, error handling, and localStorage persistence.
- `styles.css` — optional; only if styles are split out of `index.html`. If used, reference it with a relative path.

No other files. No assets that require a network. Any icons are inline SVG or unicode glyphs.

## Behavior
Describe the runtime behavior precisely.

**Inputs**
- **Pattern field** — a monospace text input/textarea for the raw regex source (the part between the slashes). Do not require the user to type the slashes.
- **Flags field** — a short input (or a row of toggle chips) for the standard JS flags: `g`, `i`, `m`, `s`, `u`, `y`. If presented as chips, each chip toggles a single flag and shows its active state; if a text field, validate that only legal flag characters are entered and that none repeat. Always evaluate as if `g` is present for the purpose of enumerating *all* matches in the list and highlight layer, but reflect the user's chosen flags faithfully in the "constructed regex" display.
- **Sample-text field** — a large monospace textarea for the text to search.

**Live evaluation loop**
- Recompute on every input event, debounced by ~120–180ms so typing stays smooth on large inputs.
- Build the `RegExp` from the pattern + flags inside a `try/catch`. On `SyntaxError`, enter the error state (see below) and leave the last good highlight/match list dimmed or cleared — never throw to the console.
- When valid, run the regex globally over the sample text and collect all matches with their indices and capture groups. Guard against zero-width / empty matches causing an infinite loop (advance `lastIndex` by at least one when a match is empty). Cap total matches at a sane number (e.g. 5,000) and show a "showing first N" note if exceeded, to keep the UI responsive.

**Highlight renderer**
- Render the sample text into a results/preview area with each match wrapped in a highlight. Matches must align exactly with the source text (preserve whitespace and newlines — use `white-space: pre-wrap`).
- Escape all HTML from the user's sample text so it can never inject markup.
- When a match contains capture groups, visually nest/sub-tint the captured spans within the match so the user can see which part each group caught. Alternate or index-based tints for adjacent matches so neighbors are distinguishable.
- Hovering a match in the preview highlights the corresponding row in the match list and vice-versa (shared hover/active state by match index). This is a nice-to-have but should be implemented if it doesn't compromise stability.

**Match list**
- Below or beside the preview, render one row per match: match number, the matched text (truncated with title tooltip if very long), and `index`–`index+length`.
- For each match, list capture groups: `Group 1`, `Group 2`, … and any **named** groups as `name`. Show `undefined`/non-participating groups explicitly (e.g. greyed "—") rather than hiding them.
- If there are no matches but the pattern is valid, show a friendly empty state ("No matches. Try adjusting your pattern or sample text.").

**Pattern explainer (plain English)**
- Parse the pattern into a linear list of tokens and render a human-readable explanation for each, in order. Cover at minimum:
  - Literal characters and escaped literals (`\.`, `\/`, `\+`, etc.).
  - Character classes `[...]`, negated classes `[^...]`, and ranges (`a-z`, `0-9`).
  - Predefined classes: `\d \D \w \W \s \S` and `.` — each with its plain meaning.
  - Anchors `^ $` and word boundaries `\b \B`.
  - Quantifiers `* + ? {n} {n,} {n,m}` including lazy variants (`*?`, `+?`, `??`) — explain "zero or more", "one or more", "optional", "exactly n", "n or more", "between n and m", and note laziness.
  - Groups: capturing `( )`, non-capturing `(?: )`, named `(?<name> )`, alternation `|`, lookahead `(?= )` / `(?! )`, lookbehind `(?<= )` / `(?<! )`, and backreferences `\1`, `\k<name>`.
  - Escaped metacharacters and common escapes (`\n \t \r`).
- Each explained token should show the raw token text (monospace) next to its description. Group/nesting can be shown with indentation or subtle connective styling.
- The explainer must never throw: anything it can't classify falls back to "matches the literal/sequence `…`" so the panel always renders.
- Reflect the active flags in a short, separate line of prose (e.g. "Flags: global, case-insensitive — search the whole string, ignoring letter case.").

**Examples library**
- Provide at least six ready-to-load examples, each with a friendly name, the pattern, sensible flags, and a matching sample text. Suggested set: Email address, URL/link, Hex color, ISO 8601 date, US phone number, IPv4 address, and a "Named groups (date parts)" example to show off named captures.
- Render them as clickable chips/cards. Clicking one loads its pattern, flags, and sample text into the inputs and immediately re-evaluates.

**Quality-of-life**
- A "Copy regex" action copies the fully-constructed literal (e.g. `/pattern/flags`) to the clipboard with a brief confirmation.
- A "Clear" action empties the inputs and resets to the empty state.
- A live match-count indicator (e.g. "12 matches") updates with each evaluation.
- Restore the last session from `localStorage` on load; if none, preload a gentle default (a simple example) so the app is never blank on first open.

## UX & visual design
Modern, dark, polished, calm — a focused developer tool.

- **Layout**: mobile-first and responsive. On wide screens, a two-or-three-region layout: a top control bar (title + examples + copy/clear + match count), a left "Pattern / Flags / Sample text" input column, and a right "Preview + Matches + Explanation" column (the explanation can be a third stacked region or a tab). On narrow screens everything stacks vertically with comfortable touch targets (min 40px). Use CSS grid/flex; no horizontal scrolling of the page itself.
- **Color palette (dark, hex)**:
  - Background base `#0b0f14`, raised surface `#121821`, panel border `#1e2733`.
  - Primary text `#e6edf3`, secondary/muted text `#8b97a7`.
  - Accent (interactive, focus rings, primary actions) `#6ea8fe` with hover `#8cbcff`.
  - Match highlight base `#234` tint behind text, with an accent underline/edge in `#6ea8fe`; capture-group sub-tints from a small cohesive palette such as `#3fb950` (green), `#d29922` (amber), `#bc8cff` (violet), `#f778ba` (pink), cycling per group index at low opacity so text stays readable.
  - Success `#3fb950`, warning `#d29922`, error/invalid `#f85149`.
- **Typography**: system UI font for chrome; monospace for the pattern, flags, sample text, match text, and token chips. Establish a small type scale (e.g. 12 / 13 / 14 / 16 / 20 / 28px) and use it consistently. Comfortable line-height (~1.5) in the sample/preview.
- **Spacing scale**: 4 / 8 / 12 / 16 / 24 / 32px. Generous padding inside panels; consistent gaps in grids.
- **Surfaces**: rounded corners (~10–12px), 1px subtle borders, soft shadow on raised panels. Inputs have clear focus rings using the accent color (visible, accessible). Use subtle inner contrast so the monospace fields read as "code".
- **Motion**: keep it tasteful and quick (120–180ms ease). Fade/slide-in match rows, a soft pulse or background flash when a new match set lands, a quick checkmark confirmation on copy, and smooth color transitions on hover/focus. Respect `prefers-reduced-motion` and disable non-essential animation when set.
- **Error state**: when the pattern is invalid, outline the pattern field in the error color, show the engine's message in a small inline banner near the field (human-friendly, e.g. "Invalid pattern: unterminated group"), and keep the rest of the UI calm rather than blowing away the whole screen.
- **Accessibility**: real `<label>`s for every input, sufficient contrast, keyboard-operable chips/buttons, visible focus, and ARIA live region announcing match count / error changes. Highlight colors must not be the *only* signal (also use borders/underlines).
- **Footer**: include a small, tasteful footer link reading "Built with a one-shot prompt from 1ShotGen" pointing to https://1shotgen.com.

## Definition of done
- [ ] Opening `index.html` directly (no server) renders the full UI with zero console errors or warnings.
- [ ] Typing a pattern + flags evaluates live (debounced) with no "Run" button; the highlight layer, match list, count, and explanation all update together.
- [ ] Matches highlight exactly in place over the sample text, preserving whitespace and newlines, with user text HTML-escaped (no injection possible).
- [ ] Capture groups (numbered AND named) are sub-highlighted within matches and itemized per match in the list, with non-participating groups shown explicitly.
- [ ] Invalid patterns produce a friendly inline error state and never throw to the console, freeze the tab, or wipe the UI.
- [ ] Zero-width/empty matches and pathological inputs do not cause infinite loops; total matches are capped with a "showing first N" note when exceeded.
- [ ] The plain-English explainer renders a token-by-token breakdown covering literals, classes, predefined classes, anchors, boundaries, quantifiers (incl. lazy), groups (capturing/non-capturing/named), alternation, lookaround, and backreferences — and never throws on unknown tokens.
- [ ] At least six example patterns load pattern + flags + sample text in one click and immediately re-evaluate.
- [ ] "Copy regex" copies `/pattern/flags` with a confirmation; "Clear" resets cleanly; match count is always accurate.
- [ ] Session (pattern, flags, sample text) persists across reloads via localStorage, failing silently when unavailable; first open is never blank.
- [ ] Fully responsive from ~320px to wide desktop with no horizontal page scroll; touch targets are comfortable.
- [ ] Dark theme matches the specified palette; focus states are visible; `prefers-reduced-motion` is respected.
- [ ] No external network requests, no CDNs, no web fonts — fully self-contained and offline-capable; all JS is in an external same-origin file referenced by a relative path; no inline event handlers.
- [ ] The 1ShotGen footer link is present and points to https://1shotgen.com.
