/* ============================================================
   ContentVeda UI — Documentation Site Styles
   Light and dark, sidebar layout, reader-controlled text size
   ============================================================ */

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap');

/* ── Design Tokens ─────────────────────────────────────────
   The ContentVeda palette from src/styles/theme.css, in both themes. :root is
   light and :root[data-theme='dark'] is dark — the same attribute, the same
   default (follow the OS, dark unless it asks for light) and the same
   localStorage key the docs site uses. Both are served from
   docs.contentveda.com, so that shared key means a visitor who picked a theme
   over there still has it when they land on /ui/.

   Three accent tokens, because one value cannot carry the brand across both
   themes:
     --accent       solid fills that carry white text (buttons, active tabs)
     --accent-text  accent-coloured text and borders on the page surface
     --accent-deep  the darker end of the brand, for gradients and hovers
   In light mode --accent-text is the brand teal itself; in dark it has to be a
   light tint of it, since #245066 on #0b1120 measures 2.16:1 and fails
   outright. */
:root {
  --bg-base:        #ffffff;
  --bg-surface:     #f8fafc;
  --bg-elevated:    #f1f5f9;
  --bg-hover:       #e9eff5;
  --border:         #e2e8f0;
  --border-accent:  rgba(36,80,102,0.35);

  --text-primary:   #0f172a;
  --text-secondary: #475569;
  --text-muted:     #64748b;
  --text-code:      #245066;

  --accent:         #245066;
  --accent-deep:    #1a3f52;
  --accent-text:    #245066;
  --accent-glow:    rgba(36,80,102,0.10);
  --accent-alt:     #2c6480;
  --link-hover:     #1a3f52;

  /* Code surfaces stay dark in both themes. That is the usual docs convention
     (GitHub, Stripe, and this project's own Content API pages all do it): it
     reads as "code" at a glance, and it means one syntax palette is legible
     everywhere instead of two that have to be kept in step. */
  --code-bg:          #0b1120;
  --code-border:      rgba(255,255,255,0.08);
  --code-text:        #e2e8f0;
  --code-chrome:      rgba(255,255,255,0.08);
  --code-chrome-text: #94a3b8;

  /* Status hues. Light-mode values are dark enough to read as text on their
     own 8-10% tint; the dark block below swaps in the light equivalents. */
  --ok:       #15803d;
  --info:     #1d4ed8;
  --warn:     #b45309;
  --danger:   #dc2626;
  --ty:       #047857;  /* prop types, in the props table rather than a code block */
  --required: #be123c;
  --react:    #0e7490;
  --svelte:   #c2410c;
  --wc:       #15803d;

  --sidebar-w:      260px;
  --topbar-h:       60px;
  --radius-sm:      6px;
  --radius-md:      12px;
  --radius-lg:      18px;
  --shadow-md:      0 4px 24px rgba(15,23,42,0.08);
  --shadow-lift:    0 12px 40px rgba(15,23,42,0.14);
  --shadow-drawer:  0 0 60px rgba(15,23,42,0.25);
  --shadow-icon:    0 4px 12px rgba(15,23,42,0.18);
  --shadow-glow:    0 0 40px var(--accent-glow);
  --scroll-thumb:       #cbd5e1;
  --scroll-thumb-hover: #94a3b8;

  --font-sans:      'Inter', system-ui, sans-serif;
  --font-mono:      'JetBrains Mono', 'Fira Code', monospace;

  --transition:     0.2s ease;
}

:root[data-theme='dark'] {
  --bg-base:        #0b1120;
  --bg-surface:     #111a2e;
  --bg-elevated:    #16213a;
  --bg-hover:       #1e2b45;
  --border:         rgba(255,255,255,0.07);
  --border-accent:  rgba(127,196,222,0.45);

  --text-primary:   #e2e8f0;
  --text-secondary: #94a3b8;
  --text-muted:     #64748b;
  --text-code:      #7fc4de;

  /* --accent lightens here: #245066 as a button fill on a near-black page
     reads as a hole rather than a control. Only as light as AAA allows though
     — it carries white text (Sign in, the active tab), and #2c6480, the
     obvious next step up, drops that to 6.48:1. */
  --accent:         #2a5c76;
  --accent-deep:    #245066;
  --accent-text:    #7fc4de;
  --accent-glow:    rgba(127,196,222,0.18);
  --accent-alt:     #4d8ba6;
  --link-hover:     #ffffff;

  --ok:       #4ade80;
  --info:     #60a5fa;
  --warn:     #fbbf24;
  --danger:   #f87171;
  --ty:       #34d399;
  --required: #fda4af;
  --react:    #61dafb;
  --svelte:   #ff7750;
  --wc:       #4ade80;

  --shadow-md:      0 4px 24px rgba(0,0,0,0.4);
  --shadow-lift:    0 12px 40px rgba(0,0,0,0.4);
  --shadow-drawer:  0 0 60px rgba(0,0,0,0.7);
  --shadow-icon:    0 4px 12px rgba(0,0,0,0.5);
  --scroll-thumb:       #22304a;
  --scroll-thumb-hover: #2f4160;
}

/*
 * Text size. Set as a percentage of whatever the browser's own base size is,
 * never as a px value — a reader who has raised their default should keep that
 * increase and have this scale on top of it, not have it overwritten. Almost
 * every length in this file is in rem, so the whole page scales with it; the
 * few px values that do not (sidebar width, header height, the logo lockup)
 * are the ones that should stay put.
 */
:root                  { font-size: 100%; }
:root[data-font='sm']  { font-size: 87.5%; }
:root[data-font='lg']  { font-size: 112.5%; }
:root[data-font='xl']  { font-size: 125%; }

/* ── Reset ─────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }

body {
  font-family: var(--font-sans);
  background: var(--bg-base);
  color: var(--text-primary);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent-text); text-decoration: none; }
a:hover { color: var(--link-hover); }
img, video { max-width: 100%; }

/* ── Site Header ────────────────────────────────────────────
   The docs site's DocsNav, reproduced: same height, same lockup, same links,
   same Sign in button, so /ui/ does not read as a different site to someone
   who arrived from docs.contentveda.com. Colours come from the tokens above,
   which is why it is dark here and light there. */
.cv-nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: var(--topbar-h);
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding: 0 1.25rem;
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border);
  z-index: 200;
}

.cv-brand {
  display: flex;
  align-items: center;
  gap: 0.34em;
  text-decoration: none;
  color: inherit;
}

/* Sized in px on the element as well as here, so the mark holds its space
   before the stylesheet or the webfont land and the bar cannot reflow.

   The three fills are custom properties because the artwork cannot serve both
   themes as-is: the C is near-black, and the V's darkest facet measures about
   1.9:1 against the dark page. */
.cv-brand-mark {
  display: block;
  flex-shrink: 0;
  width: 49px;
  height: 30px;
  --m-ink: #010101;
  --m-v: #164f69;
  --m-vd: #0f374e;
}

:root[data-theme='dark'] .cv-brand-mark {
  --m-ink: #e8eef2;
  --m-v: #7fc4de;
  --m-vd: #4d8ba6;
}

/* Live text in Inter, not the lettering outlined in the logo artwork — that
   face is not Inter, and Inter is the brand guideline. */
.cv-brand-word {
  font-size: 17px;
  font-weight: 500;
  letter-spacing: -0.022em;
  line-height: 1;
  color: var(--accent-text);
  white-space: nowrap;
}

.cv-brand-word b { font-weight: 700; }

/* Sits beside the wordmark, so it is deliberately lighter and smaller —
   matching its weight would read as part of the logo. */
.cv-brand-sub {
  color: var(--text-muted);
  font-weight: 400;
  font-size: 0.95rem;
  padding-left: 0.35rem;
}

.cv-links {
  display: flex;
  gap: 0.25rem;
  margin-left: auto;
}

.cv-links a {
  padding: 0.45rem 0.75rem;
  border-radius: var(--radius-sm);
  text-decoration: none;
  font-size: 0.9rem;
  color: var(--text-secondary);
}

.cv-links a:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.cv-links a.active {
  color: var(--accent-text);
  font-weight: 600;
}

.cv-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.cv-signin {
  padding: 0.45rem 0.9rem;
  border-radius: 8px;
  background: var(--accent);
  color: #fff;
  text-decoration: none;
  font-size: 0.875rem;
  font-weight: 500;
  white-space: nowrap;
}

.cv-signin:hover { background: var(--accent-alt); color: #fff; }

/* Theme toggle — the docs site's button, down to the 34px square and the
   sun/moon glyph showing the theme you would switch *to*. */
.cv-theme-toggle {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: transparent;
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
  color: var(--text-primary);
  transition: background var(--transition), border-color var(--transition);
}

.cv-theme-toggle:hover { background: var(--bg-hover); border-color: var(--border-accent); }

/* Text size. Two steps rather than a slider or a menu: the range is only four
   sizes wide, so anything richer costs more clicks than it saves. */
.cv-fontsize {
  display: inline-flex;
  align-items: stretch;
  height: 34px;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}

.cv-fontsize button {
  width: 30px;
  border: none;
  background: transparent;
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  transition: background var(--transition);
}

.cv-fontsize button + button { border-left: 1px solid var(--border); }
.cv-fontsize button:hover:not(:disabled) { background: var(--bg-hover); }

/* Disabled at the ends of the range, so the control says where you are without
   needing a separate readout. */
.cv-fontsize button:disabled {
  color: var(--text-muted);
  opacity: 0.5;
  cursor: default;
}

/* ── Layout Shell ───────────────────────────────────────── */
.docs-shell {
  display: flex;
  min-height: 100vh;
  padding-top: var(--topbar-h); /* offset the fixed header */
}

/* ── Sidebar ────────────────────────────────────────────── */
.docs-sidebar {
  position: fixed;
  top: var(--topbar-h); left: 0;
  width: var(--sidebar-w);
  height: calc(100vh - var(--topbar-h));
  background: var(--bg-surface);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  z-index: 100;
  transition: transform var(--transition);
}

/* The brand lockup lives in .cv-nav now, not at the top of the sidebar — one
   lockup per page, in the same place the docs site puts it. */

.sidebar-version {
  font-size: 0.65rem;
  color: var(--text-muted);
  font-family: var(--font-mono);
  margin-left: auto;
  background: var(--bg-elevated);
  padding: 2px 6px;
  border-radius: 4px;
}

.sidebar-nav {
  padding: 1rem 0;
  flex: 1;
}

.sidebar-section-label {
  font-size: 0.65rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 0.5rem 1.5rem 0.25rem;
}

.sidebar-link {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0.45rem 1.5rem;
  font-size: 0.875rem;
  color: var(--text-secondary);
  transition: all var(--transition);
  border-left: 2px solid transparent;
  text-decoration: none;
}

.sidebar-link:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
  border-left-color: var(--border-accent);
}

.sidebar-link.active {
  color: var(--accent-text);
  background: var(--accent-glow);
  border-left-color: var(--accent);
  font-weight: 500;
}

.sidebar-link-icon {
  font-size: 14px;
  width: 18px;
  text-align: center;
  flex-shrink: 0;
}

.sidebar-footer {
  padding: 1rem 1.5rem;
  border-top: 1px solid var(--border);
  display: flex;
  gap: 0.75rem;
}

.sidebar-footer a {
  font-size: 0.75rem;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 4px;
  transition: color var(--transition);
}

.sidebar-footer a:hover { color: var(--text-primary); }

/* ── Main Content ───────────────────────────────────────── */
.docs-main {
  margin-left: var(--sidebar-w);
  flex: 1;
  min-width: 0;
}

/* The per-page topbar (breadcrumb + action) is gone: .cv-nav carries the
   action, and the sidebar's active item says where you are, which is what the
   breadcrumb was for. */

.btn-github {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  color: var(--text-secondary);
  font-size: 0.8rem;
  font-weight: 500;
  cursor: pointer;
  transition: all var(--transition);
  text-decoration: none;
}

.btn-github:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
  border-color: var(--border-accent);
}

/* ── Page Content ───────────────────────────────────────── */
.docs-content {
  max-width: 900px;
  margin: 0 auto;
  padding: 3rem 2rem 6rem;
}

/* ── Page Header ────────────────────────────────────────── */
.page-header {
  margin-bottom: 3rem;
}

.page-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--accent-glow);
  border: 1px solid var(--border-accent);
  color: var(--accent-text);
  font-size: 0.75rem;
  font-weight: 600;
  padding: 4px 10px;
  border-radius: 20px;
  margin-bottom: 1rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.page-title {
  font-size: 2.5rem;
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 1.1;
  margin-bottom: 0.75rem;
  background: linear-gradient(135deg, var(--text-primary) 50%, var(--accent-text));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.page-description {
  font-size: 1.1rem;
  color: var(--text-secondary);
  max-width: 600px;
  line-height: 1.7;
}

/* ── Section Heading ────────────────────────────────────── */
.section-heading {
  font-size: 1rem;
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 1rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 8px;
}

.section-heading::before {
  content: '';
  width: 3px;
  height: 16px;
  background: linear-gradient(to bottom, var(--accent-text), var(--accent));
  border-radius: 2px;
  flex-shrink: 0;
}

/* ── Preview Card ───────────────────────────────────────── */
.preview-card {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  margin-bottom: 2rem;
  box-shadow: var(--shadow-md);
}

.preview-toolbar {
  display: flex;
  align-items: center;
  padding: 0.75rem 1.25rem;
  background: var(--bg-elevated);
  border-bottom: 1px solid var(--border);
  gap: 0.5rem;
}

.preview-dot { width: 10px; height: 10px; border-radius: 50%; }
.preview-dot.red   { background: #ff5f57; }
.preview-dot.amber { background: #ffbd2e; }
.preview-dot.green { background: #28c840; }

.preview-url {
  margin-left: 0.75rem;
  font-size: 0.75rem;
  color: var(--text-muted);
  font-family: var(--font-mono);
  background: var(--bg-base);
  padding: 3px 12px;
  border-radius: 4px;
  border: 1px solid var(--border);
  flex: 1;
}

.preview-body {
  padding: 2rem;
  background: var(--bg-base);
  min-height: 120px;
}

.preview-body-flush {
  padding: 0;
  background: var(--bg-base);
  min-height: 120px;
}

/* ── Framework Tabs ─────────────────────────────────────── */
.tabs-bar {
  display: flex;
  gap: 0;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 4px;
  margin-bottom: 1rem;
  width: fit-content;
}

.tab-btn {
  padding: 6px 16px;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  font-family: var(--font-sans);
  font-size: 0.8rem;
  font-weight: 500;
  cursor: pointer;
  border-radius: calc(var(--radius-md) - 4px);
  transition: all var(--transition);
  white-space: nowrap;
}

.tab-btn:hover { color: var(--text-primary); background: var(--bg-hover); }

.tab-btn.active {
  background: var(--accent);
  color: #fff;
  box-shadow: 0 2px 8px var(--accent-glow);
}

.tab-panel { display: none; }
.tab-panel.active { display: block; }

/* ── Code Block ─────────────────────────────────────────── */
.code-block {
  position: relative;
  margin-bottom: 2rem;
}

.code-block pre {
  background: var(--code-bg);
  border: 1px solid var(--code-border);
  border-radius: var(--radius-md);
  padding: 1.25rem 1.5rem;
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: 0.82rem;
  line-height: 1.7;
  color: var(--code-text);
}

.code-block code {
  font-family: inherit;
}

/* Syntax colouring (minimal, css-only) */
.kw  { color: #7fc4de; }  /* keywords */
.str { color: #86efac; }  /* strings */
.cm  { color: #64748b; font-style: italic; }  /* comments */
.fn  { color: #93c5fd; }  /* function names */
.num { color: #fbbf24; }  /* numbers */
.tag { color: #f472b6; }  /* HTML/JSX tags */
.at  { color: #a5b4fc; }  /* attributes */
.ty  { color: #34d399; }  /* types */

/* Sits on the code surface, so it takes the code tokens rather than the page
   ones — otherwise it turns into a pale chip on a near-black block in light
   mode. */
.copy-btn {
  position: absolute;
  top: 10px; right: 10px;
  background: var(--code-chrome);
  border: 1px solid var(--code-border);
  color: var(--code-chrome-text);
  font-family: var(--font-sans);
  font-size: 0.75rem;
  padding: 4px 10px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all var(--transition);
}

.copy-btn:hover { color: var(--code-text); border-color: rgba(255,255,255,0.2); }
/* Fixed green, not var(--ok): this button sits on the always-dark code
   surface, so it does not follow the page theme. */
.copy-btn.copied { color: #4ade80; border-color: #4ade80; }

/* ── Props Table ────────────────────────────────────────── */
.props-table-wrap {
  overflow-x: auto;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  margin-bottom: 2rem;
}

.props-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}

.props-table thead tr {
  background: var(--bg-elevated);
}

.props-table th {
  padding: 0.75rem 1rem;
  text-align: left;
  font-weight: 600;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
}

.props-table td {
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border);
  color: var(--text-secondary);
  vertical-align: top;
}

.props-table tbody tr:last-child td { border-bottom: none; }

.props-table tbody tr:hover td { background: var(--bg-hover); }

.prop-name {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--text-code);
  font-weight: 500;
}

.prop-type {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--ty);
}

.prop-default {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--text-muted);
}

.prop-required {
  display: inline-block;
  background: rgba(251,113,133,0.15);
  color: var(--required);
  font-size: 0.65rem;
  font-weight: 600;
  padding: 1px 6px;
  border-radius: 4px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* ── Install Banner ─────────────────────────────────────── */
.install-banner {
  background: linear-gradient(135deg, var(--accent-glow), transparent);
  border: 1px solid var(--border-accent);
  border-radius: var(--radius-md);
  padding: 1.25rem 1.5rem;
  margin-bottom: 2rem;
  display: flex;
  align-items: center;
  gap: 1rem;
}

.install-banner code {
  font-family: var(--font-mono);
  font-size: 0.9rem;
  color: var(--accent-text);
  flex: 1;
}

/* ── Alert Boxes ────────────────────────────────────────── */
.alert {
  padding: 1rem 1.25rem;
  border-radius: var(--radius-md);
  border-left: 3px solid;
  margin-bottom: 1.5rem;
  font-size: 0.875rem;
}

.alert-tip  { background: rgba(52,211,153,0.10); border-color: var(--ok);    color: var(--ok); }
.alert-info { background: rgba(96,165,250,0.10); border-color: var(--info);  color: var(--info); }
.alert-warn { background: rgba(251,191,36,0.10); border-color: var(--warn);  color: var(--warn); }

/* ── Landing Hero ───────────────────────────────────────── */
.landing-hero {
  text-align: center;
  padding: 5rem 2rem 3rem;
  max-width: 760px;
  margin: 0 auto;
}

.hero-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--accent-glow);
  border: 1px solid var(--border-accent);
  color: var(--accent-text);
  font-size: 0.75rem;
  font-weight: 600;
  padding: 5px 14px;
  border-radius: 20px;
  margin-bottom: 1.5rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.hero-title {
  font-size: clamp(2.5rem, 6vw, 4rem);
  font-weight: 800;
  letter-spacing: -0.05em;
  line-height: 1.08;
  margin-bottom: 1.25rem;
}

.hero-gradient {
  background: linear-gradient(135deg, var(--accent-text), var(--accent-alt));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.hero-subtitle {
  font-size: 1.15rem;
  color: var(--text-secondary);
  max-width: 560px;
  margin: 0 auto 2rem;
  line-height: 1.7;
}

.hero-actions {
  display: flex;
  gap: 1rem;
  justify-content: center;
  flex-wrap: wrap;
  margin-bottom: 3rem;
}

.btn-primary {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: linear-gradient(135deg, var(--accent), var(--accent-deep));
  color: #fff;
  padding: 12px 28px;
  border-radius: var(--radius-md);
  font-weight: 600;
  font-size: 0.95rem;
  text-decoration: none;
  box-shadow: 0 4px 20px var(--accent-glow);
  transition: all var(--transition);
}

.btn-primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 30px var(--accent-glow);
  color: #fff;
}

.btn-secondary {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  color: var(--text-primary);
  padding: 12px 28px;
  border-radius: var(--radius-md);
  font-weight: 600;
  font-size: 0.95rem;
  text-decoration: none;
  transition: all var(--transition);
}

.btn-secondary:hover {
  background: var(--bg-hover);
  border-color: var(--border-accent);
  transform: translateY(-2px);
}

/* ── Feature Pills ──────────────────────────────────────── */
.feature-pills {
  display: flex;
  gap: 0.5rem;
  justify-content: center;
  flex-wrap: wrap;
  margin-bottom: 4rem;
}

.feature-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 20px;
  font-size: 0.8rem;
  color: var(--text-secondary);
}

.feature-pill .dot { width: 6px; height: 6px; border-radius: 50%; }
.dot-react  { background: #61dafb; }
.dot-svelte { background: #ff3e00; }
.dot-wc     { background: #4ade80; }
.dot-ts     { background: #3b82f6; }
.dot-css    { background: #7fc4de; }

/* ── Component Grid ─────────────────────────────────────── */
.component-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 1.25rem;
  max-width: 960px;
  margin: 0 auto;
  padding: 0 2rem 6rem;
}

.component-card {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  text-decoration: none;
  transition: all 0.25s ease;
  display: flex;
  flex-direction: column;
}

.component-card:hover {
  border-color: var(--border-accent);
  transform: translateY(-4px);
  box-shadow: var(--shadow-lift), var(--shadow-glow);
  color: inherit;
}

.card-preview {
  height: 140px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 3rem;
  position: relative;
  overflow: hidden;
}

.card-preview-bg {
  position: absolute;
  inset: 0;
  opacity: 0.15;
}

.card-preview-icon {
  position: relative;
  z-index: 1;
  filter: drop-shadow(var(--shadow-icon));
}

.card-body {
  padding: 1.25rem;
  flex: 1;
}

.card-name {
  font-size: 1rem;
  font-weight: 700;
  color: var(--text-primary);
  margin-bottom: 0.375rem;
  display: flex;
  align-items: center;
  gap: 8px;
}

.card-desc {
  font-size: 0.82rem;
  color: var(--text-secondary);
  line-height: 1.6;
  margin-bottom: 1rem;
}

.card-footer {
  display: flex;
  gap: 0.5rem;
  padding: 0.75rem 1.25rem;
  border-top: 1px solid var(--border);
  background: var(--bg-elevated);
}

.card-tag {
  font-size: 0.65rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 3px 8px;
  border-radius: 4px;
}

.tag-react  { background: rgba(97,218,251,0.12); color: var(--react); }
.tag-svelte { background: rgba(255,62,0,0.12);   color: var(--svelte); }
.tag-wc     { background: rgba(74,222,128,0.12); color: var(--wc); }

/* ── Stats Bar ──────────────────────────────────────────── */
.stats-bar {
  display: flex;
  gap: 3rem;
  justify-content: center;
  padding: 2.5rem;
  background: var(--bg-surface);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  margin-bottom: 4rem;
}

.stat-item { text-align: center; }

.stat-value {
  font-size: 2rem;
  font-weight: 800;
  letter-spacing: -0.04em;
  background: linear-gradient(135deg, var(--accent-text), var(--accent-alt));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.stat-label {
  font-size: 0.8rem;
  color: var(--text-muted);
  margin-top: 2px;
}

/* ── Mobile Sidebar Toggle ──────────────────────────────── */
.sidebar-toggle {
  display: none;
  background: none;
  border: none;
  color: var(--text-primary);
  cursor: pointer;
  font-size: 1.25rem;
  padding: 4px;
}

/* Backdrop overlay for mobile drawer. docs.js creates the element, so it is
   styled here rather than in the generated markup. */
.sidebar-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(4px);
  z-index: 90;
}

.sidebar-backdrop.open {
  display: block;
}

/* ── Scrollbar ──────────────────────────────────────────── */
::-webkit-scrollbar       { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: var(--bg-base); }
::-webkit-scrollbar-thumb { background: var(--scroll-thumb); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: var(--scroll-thumb-hover); }

/* ── Responsive ─────────────────────────────────────────── */
@media (max-width: 768px) {
  .docs-sidebar {
    transform: translateX(-100%);
  }

  .docs-sidebar.open {
    transform: translateX(0);
    box-shadow: var(--shadow-drawer);
  }

  .docs-main {
    margin-left: 0;
  }

  .sidebar-toggle {
    display: block;
  }

  .hero-title { font-size: 2rem; }

  .stats-bar { gap: 1.5rem; flex-wrap: wrap; }

  .landing-hero { padding: 3rem 1rem 2rem; }

  .docs-content { padding: 1.5rem 1rem 4rem; }
  .preview-body { padding: 1rem; }
  .controls-body { padding: 1rem; }
  .controls-body form#playground-form { grid-template-columns: 1fr; }
  .tabs-bar { overflow-x: auto; max-width: 100%; -webkit-overflow-scrolling: touch; }
}

/* Matches the breakpoint above, where .docs-sidebar becomes a drawer and
   .sidebar-toggle appears. The two have to be the same number: docs.js moves
   the .cv-links destinations into that drawer, so if the links were dropped at
   a narrower width than the drawer appears, the range in between would show
   the hamburger and the links at once — and dropping them later would leave
   them with nowhere to go. The brand, the toggle and Sign in stay;
   "Star on GitHub" / "View Source" go, since the same links are in the
   drawer. */
@media (max-width: 768px) {
  .cv-nav { gap: 0.75rem; }
  .cv-links { display: none; }
  /* .cv-links carried the margin-left:auto that right-aligns everything after
     the brand, so the actions have to take it over when the links go. */
  .cv-actions { margin-left: auto; }
  .cv-actions .btn-github { display: none; }
  .cv-brand-sub { display: none; }

  /* Even with the links gone the bar did not fit a phone: the brand lockup,
     the A−/A+ pair, the theme toggle and Sign in together measure past 375px,
     so the row overflowed and "Sign in" broke onto two lines.

     The text-size control is the one to drop. It is an addition this tree
     makes for its long prop tables; the docs site's nav has no equivalent, so
     removing it here is also what brings the two bars back into line. Pinch
     zoom still works, and the reader's own browser text-size setting is
     honoured because the pages size in rem. */
  .cv-fontsize { display: none; }

  /* Belt and braces: nothing in this bar may wrap. If a future addition
     overflows again it should be visibly clipped rather than silently
     reflowing the header to two lines. */
  .cv-nav { flex-wrap: nowrap; }
  .cv-brand { min-width: 0; flex-shrink: 1; }
  .cv-brand-word { overflow: hidden; text-overflow: ellipsis; }
  .cv-actions { flex-shrink: 0; }
}

/* Narrow phones. Measured rather than guessed: with the text-size control gone
   the bar needs about 320px, so it still fits a 360px phone with the wordmark
   intact. Only below that does the wordmark have to go, leaving the mark alone
   to carry the brand — it is the recognisable part at this size, and it stays
   a link home. */
@media (max-width: 340px) {
  .cv-nav { gap: 0.5rem; padding: 0 0.75rem; }
  .cv-brand-word { display: none; }
  .cv-signin { padding: 0.45rem 0.7rem; }
}

/* ── Interactive Playground Layout ─────────────────────── */
.playground-container {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  margin-bottom: 3rem;
}

.preview-column {
  width: 100%;
}

.controls-column {
  width: 100%;
}

.controls-card {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-md);
  height: 100%;
}

.controls-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0.75rem 1.25rem;
  background: var(--bg-elevated);
  border-bottom: 1px solid var(--border);
}

.controls-icon {
  font-size: 1rem;
}

.controls-title {
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-primary);
}

.controls-body {
  padding: 1.25rem 1.5rem;
  overflow: visible;
}

.controls-body form#playground-form {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 1rem 1.5rem;
}

/* Full-width controls (JSON textarea, content areas) span all columns */
.controls-body .control-group:has(.json-textarea),
.controls-body .control-group:has(textarea[name="content"]),
.controls-body .control-group:has(textarea[name="initialContent"]) {
  grid-column: 1 / -1;
}

/* ── Playground Inputs ────────────────────────────────── */
.control-group {
  margin-bottom: 0;
}

.control-group:last-child {
  margin-bottom: 0;
}

.control-label {
  display: block;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-secondary);
  margin-bottom: 6px;
}

.control-type-badge {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  color: var(--accent-text);
  background: var(--accent-glow);
  padding: 2px 6px;
  border-radius: 4px;
  margin-left: 6px;
}

.control-input, .control-select {
  width: 100%;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  color: var(--text-primary);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  font-family: var(--font-sans);
  font-size: 0.8rem;
  outline: none;
  transition: border-color var(--transition), box-shadow var(--transition);
}

.control-input:focus, .control-select:focus {
  border-color: var(--border-accent);
  box-shadow: 0 0 0 2px rgba(127, 196, 222, 0.15);
}

.json-textarea {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  min-height: 90px;
  resize: vertical;
  line-height: 1.5;
}

.json-error-msg {
  display: none;
  font-size: 0.7rem;
  color: var(--danger);
  margin-top: 4px;
  font-weight: 500;
}

.json-textarea.invalid {
  border-color: var(--danger) !important;
  box-shadow: 0 0 0 2px rgba(248, 113, 113, 0.15) !important;
}

.json-textarea.invalid + .json-error-msg {
  display: block;
}

.control-desc {
  font-size: 0.7rem;
  color: var(--text-muted);
  margin-top: 4px;
  line-height: 1.4;
}

/* Checkbox */
.control-checkbox-label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--text-secondary);
  user-select: none;
}

.control-checkbox-label input {
  display: none;
}

.control-checkbox-custom {
  width: 16px;
  height: 16px;
  border: 1px solid var(--border);
  background: var(--bg-elevated);
  border-radius: 4px;
  position: relative;
  transition: all var(--transition);
}

.control-checkbox-label input:checked + .control-checkbox-custom {
  background: var(--accent);
  border-color: var(--accent);
}

.control-checkbox-label input:checked + .control-checkbox-custom::after {
  content: '';
  position: absolute;
  left: 5px;
  top: 2px;
  width: 4px;
  height: 8px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* Slider */
.control-slider-wrap {
  display: flex;
  align-items: center;
  gap: 12px;
}

.control-slider {
  flex: 1;
  height: 6px;
  background: var(--bg-elevated);
  border-radius: 3px;
  outline: none;
  accent-color: var(--accent);
  cursor: pointer;
}

.control-slider-val {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--accent-text);
  font-weight: 700;
  min-width: 20px;
  text-align: right;
}

/* Color Picker */
.control-color-wrap {
  display: flex;
  align-items: center;
  gap: 10px;
}

.control-color-picker {
  -webkit-appearance: none;
  border: 1px solid var(--border);
  background: transparent;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  padding: 0;
}

.control-color-picker::-webkit-color-swatch-wrapper {
  padding: 0;
}

.control-color-picker::-webkit-color-swatch {
  border: none;
  border-radius: calc(var(--radius-sm) - 1px);
}
