/* ══════════════════════════════════════════════════════════════════════════
   TalkinQuantum Interface System
   TQ_INTERFACE_SYSTEM_FOUNDATION_2026_08_06.md

   The single authoritative interface layer: tokens, type scale, shared control
   variants, the tooltip primitive and the loading-state primitive.

   Rules for anyone editing this file:
     1. This is the ONLY place new interface tokens are declared. Do not start a
        second token system in a page <style> block or in styles.css.
     2. Everything here is namespaced `tq-`. It never restyles an existing app
        selector, so it can be loaded alongside styles.css with no specificity war.
     3. Legacy `--bg0 … --purple` variables in styles.css and their duplicates in
        landing.html are the pre-existing palette. The `--tq-*` tokens below alias
        those exact values so the two systems cannot drift apart in colour while the
        rest of the application is migrated surface by surface.
     4. No `!important`. If a rule does not win, fix the selector, not the weight.

   Load order: tq-system.css BEFORE styles.css (index.html) — tokens first.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── Colour: page backgrounds ─────────────────────────────────────────── */
  --tq-bg:            #04050a;   /* page floor                                */
  --tq-bg-raised:     #08090f;   /* alternating section band                  */
  --tq-surface:       #0d1018;   /* card / panel                              */
  --tq-surface-2:     #131720;   /* nested control on a card                  */

  /* ── Colour: borders ──────────────────────────────────────────────────── */
  --tq-border:        rgba(255,255,255,0.08);
  --tq-border-strong: rgba(255,255,255,0.15);

  /* ── Colour: text ─────────────────────────────────────────────────────── */
  --tq-text:          #edf0f8;   /* primary — warm off-white                  */
  --tq-text-2:        #a3adc4;   /* secondary — body on dark, AA at 15px      */
  --tq-text-muted:    #7d879e;   /* muted — labels, metadata. >=4.98:1 on every
                                    surface token above, so 12–14px muted copy
                                    clears WCAG AA. #6c7793 measured 4.25 on
                                    --tq-surface and failed axe on 6 nodes.    */
  --tq-text-on-accent:#04050a;   /* text on a cyan/magenta fill               */

  /* ── Colour: brand ────────────────────────────────────────────────────── */
  --tq-accent:        #00e5ff;   /* electric cyan — primary interaction       */
  --tq-accent-deep:   #0066ff;   /* cyan's deep partner, gradients only       */
  --tq-accent-soft:   rgba(0,229,255,0.10);
  --tq-accent-line:   rgba(0,229,255,0.30);
  --tq-brand-purple:  #a855f7;   /* secondary brand signal — restrained       */

  /* ── Colour: status. Never the only carrier of meaning. ───────────────── */
  --tq-success:       #2fe6a6;
  --tq-warning:       #f4c049;
  --tq-error:         #ff5c7a;
  --tq-info:          #7dd3fc;

  /* ── Colour: focus ────────────────────────────────────────────────────── */
  --tq-focus:         #7ce9ff;

  /* ── Typography: families ─────────────────────────────────────────────── */
  --tq-font-sans: 'IBM Plex Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --tq-font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* ── Typography: scale. Finite and responsive — no per-section sizes. ─── */
  --tq-type-display:   clamp(34px, 5.2vw, 58px);
  --tq-type-section:   clamp(24px, 3.2vw, 36px);
  --tq-type-card:      18px;
  --tq-type-body:      16px;
  --tq-type-support:   14px;
  --tq-type-label:     12px;
  --tq-type-button:    15px;
  --tq-type-technical: 13px;

  --tq-leading-tight: 1.12;
  --tq-leading-snug:  1.32;
  --tq-leading-body:  1.65;

  --tq-measure-display: 17ch;   /* controlled line length for the display head */
  --tq-measure-body:    66ch;

  /* ── Spacing: one scale, used everywhere ──────────────────────────────── */
  --tq-space-1: 4px;
  --tq-space-2: 8px;
  --tq-space-3: 12px;
  --tq-space-4: 16px;
  --tq-space-5: 24px;
  --tq-space-6: 32px;
  --tq-space-7: 48px;
  --tq-space-8: 64px;

  --tq-space-section: clamp(56px, 8vw, 88px);  /* vertical rhythm between sections */
  --tq-space-card:    24px;                    /* card interior padding            */
  --tq-space-control: 10px;                    /* gap inside a control group       */

  /* ── Shape ────────────────────────────────────────────────────────────── */
  --tq-radius-sm:  6px;
  --tq-radius-md:  10px;
  --tq-radius-lg:  14px;
  --tq-radius-pill: 999px;

  --tq-elev-1: 0 1px 2px rgba(0,0,0,0.40);
  --tq-elev-2: 0 8px 24px rgba(0,0,0,0.45);
  --tq-elev-3: 0 20px 56px rgba(0,0,0,0.55);

  /* ── Motion ───────────────────────────────────────────────────────────── */
  --tq-motion-fast: 120ms;
  --tq-motion-base: 180ms;
  --tq-motion-slow: 260ms;
  --tq-ease: cubic-bezier(0.22, 0.61, 0.36, 1);

  /* ── Layering ─────────────────────────────────────────────────────────── */
  --tq-z-nav:     100;
  --tq-z-overlay: 800;
  --tq-z-dialog:  900;
  --tq-z-toast:   950;
  --tq-z-tooltip: 1000;

  /* ── Icons ────────────────────────────────────────────────────────────── */
  --tq-icon-stroke: 2;
}

/* ══ Typography primitives ══════════════════════════════════════════════ */

.tq-display {
  font-family: var(--tq-font-sans);
  font-size: var(--tq-type-display);
  font-weight: 700;
  line-height: var(--tq-leading-tight);
  letter-spacing: -0.022em;
  max-width: var(--tq-measure-display);
  color: var(--tq-text);
  text-wrap: balance;
}
.tq-h2 {
  font-family: var(--tq-font-sans);
  font-size: var(--tq-type-section);
  font-weight: 700;
  line-height: var(--tq-leading-snug);
  letter-spacing: -0.014em;
  color: var(--tq-text);
  text-wrap: balance;
}
.tq-h3 {
  font-family: var(--tq-font-sans);
  font-size: var(--tq-type-card);
  font-weight: 600;
  line-height: var(--tq-leading-snug);
  letter-spacing: -0.006em;
  color: var(--tq-text);
}
.tq-body {
  font-family: var(--tq-font-sans);
  font-size: var(--tq-type-body);
  font-weight: 400;
  line-height: var(--tq-leading-body);
  color: var(--tq-text-2);
  max-width: var(--tq-measure-body);
  text-wrap: pretty;
}
.tq-support {
  font-family: var(--tq-font-sans);
  font-size: var(--tq-type-support);
  line-height: var(--tq-leading-body);
  color: var(--tq-text-2);
  text-wrap: pretty;
}
/* Monospace is reserved: code, filenames, measurements, circuit labels and
   short technical eyebrow text. It is never the marketing voice. */
.tq-eyebrow {
  font-family: var(--tq-font-mono);
  font-size: var(--tq-type-label);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--tq-accent);
}
.tq-label {
  font-family: var(--tq-font-sans);
  font-size: var(--tq-type-label);
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--tq-text-muted);
}
.tq-mono {
  font-family: var(--tq-font-mono);
  font-size: var(--tq-type-technical);
  color: var(--tq-text-2);
}

/* Visually hidden, still read by assistive technology and still present in
   textContent. Used by icon-only controls whose name should be real text rather
   than an aria-label — a rail button reads "Community" to a screen reader while
   showing only its glyph. Not `display:none`, which would remove it from the
   accessibility tree entirely. */
.tq-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ══ Focus ═════════════════════════════════════════════════════════════════
   One visible focus treatment for every interactive element in the system. ══ */

.tq-btn:focus-visible,
.tq-input:focus-visible,
.tq-card--interactive:focus-visible,
.tq-link:focus-visible {
  outline: 2px solid var(--tq-focus);
  outline-offset: 2px;
  border-radius: var(--tq-radius-sm);
}

/* Baseline focus ring for interactive elements that are NOT system components —
   a plain logo anchor, a nav link, a footer link. Chromium's default ring is
   `auto 1px` in near-black, which is invisible on this palette, so keyboard
   focus was undetectable on the first Tab stop.

   Deliberately opt-in via `.tq-surface-root` rather than a bare `a:focus-visible`
   so the layer still never restyles an existing app selector on its own: a
   surface adopts the ring by taking the class when it is migrated. landing.html
   opts in on <body>; index.html has not been migrated yet. */
.tq-surface-root :is(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--tq-focus);
  outline-offset: 2px;
}

/* ══ Buttons ═══════════════════════════════════════════════════════════════
   Finite variants: primary · secondary · quiet · destructive · icon · disabled
   · loading. Every variant shares one border, radius, spacing and type spec. ══ */

.tq-btn {
  --_tq-btn-bg: transparent;
  --_tq-btn-fg: var(--tq-text);
  --_tq-btn-bd: transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--tq-space-2);
  min-height: 44px;
  padding: 11px 20px;
  border: 1px solid var(--_tq-btn-bd);
  border-radius: var(--tq-radius-md);
  background: var(--_tq-btn-bg);
  color: var(--_tq-btn-fg);
  font-family: var(--tq-font-sans);
  font-size: var(--tq-type-button);
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--tq-motion-base) var(--tq-ease),
              border-color var(--tq-motion-base) var(--tq-ease),
              color var(--tq-motion-base) var(--tq-ease);
}
.tq-btn > svg { flex: none; }

.tq-btn--primary {
  --_tq-btn-bg: var(--tq-accent);
  --_tq-btn-fg: var(--tq-text-on-accent);
  --_tq-btn-bd: var(--tq-accent);
  font-weight: 700;
}
.tq-btn--primary:hover { --_tq-btn-bg: #4ff0ff; --_tq-btn-bd: #4ff0ff; }

/* Secondary is a real, obviously-active action — not a greyed-out primary. */
.tq-btn--secondary {
  --_tq-btn-bg: var(--tq-surface-2);
  --_tq-btn-fg: var(--tq-text);
  --_tq-btn-bd: var(--tq-border-strong);
}
.tq-btn--secondary:hover { --_tq-btn-bd: var(--tq-accent-line); --_tq-btn-bg: #182030; }

.tq-btn--quiet {
  --_tq-btn-fg: var(--tq-text-2);
  padding-left: var(--tq-space-3);
  padding-right: var(--tq-space-3);
}
.tq-btn--quiet:hover { --_tq-btn-fg: var(--tq-accent); }

.tq-btn--destructive {
  --_tq-btn-bg: transparent;
  --_tq-btn-fg: var(--tq-error);
  --_tq-btn-bd: var(--tq-error);
}
.tq-btn--destructive:hover { --_tq-btn-bg: rgba(255,92,122,0.12); }

/* Icon-only controls carry no visible label, so they always need an accessible
   name and a 44px touch target. */
.tq-btn--icon {
  min-width: 44px;
  padding: 0;
  --_tq-btn-fg: var(--tq-text-2);
}
.tq-btn--icon:hover { --_tq-btn-fg: var(--tq-text); }

.tq-btn[disabled],
.tq-btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
}

/* Loading: the control keeps its width so the layout never jumps. */
.tq-btn[data-tq-loading="true"] {
  cursor: progress;
  pointer-events: none;
  color: transparent;
  position: relative;
}
.tq-btn[data-tq-loading="true"]::after {
  content: '';
  position: absolute;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-top-color: var(--_tq-btn-fg);
  opacity: 0.85;
  animation: tq-spin 700ms linear infinite;
  color: var(--_tq-btn-fg);
}
@keyframes tq-spin { to { transform: rotate(360deg); } }

.tq-link {
  color: var(--tq-accent);
  text-decoration: none;
  font-weight: 600;
}
.tq-link:hover { text-decoration: underline; text-underline-offset: 3px; }

/* ══ Inputs ════════════════════════════════════════════════════════════════ */

.tq-input {
  min-height: 44px;
  padding: 11px 14px;
  background: var(--tq-surface);
  border: 1px solid var(--tq-border-strong);
  border-radius: var(--tq-radius-md);
  color: var(--tq-text);
  font-family: var(--tq-font-sans);
  font-size: var(--tq-type-body);
  line-height: 1.2;
  transition: border-color var(--tq-motion-base) var(--tq-ease);
}
.tq-input::placeholder { color: var(--tq-text-muted); }
.tq-input:hover { border-color: var(--tq-accent-line); }
.tq-input[aria-invalid="true"] { border-color: var(--tq-error); }
.tq-input[disabled] { opacity: 0.45; cursor: not-allowed; }
.tq-input[data-tq-loading="true"] { cursor: progress; }

/* ══ Cards and panels ══════════════════════════════════════════════════════
   Finite variants. Interactive/selected/status/pricing/demo differ in role, not
   only in colour, so no two variants look alike for different behaviour.    ══ */

.tq-card {
  background: var(--tq-surface);
  border: 1px solid var(--tq-border);
  border-radius: var(--tq-radius-lg);
  padding: var(--tq-space-card);
}
.tq-card--interactive {
  cursor: pointer;
  transition: border-color var(--tq-motion-base) var(--tq-ease),
              background var(--tq-motion-base) var(--tq-ease);
}
.tq-card--interactive:hover { border-color: var(--tq-accent-line); background: #101420; }
.tq-card--selected { border-color: var(--tq-accent); box-shadow: inset 0 0 0 1px var(--tq-accent-soft); }
.tq-card--status  { border-left: 3px solid var(--tq-border-strong); border-radius: var(--tq-radius-md); }
.tq-card--pricing { padding: var(--tq-space-6); }
.tq-card--demo    { padding: 0; overflow: hidden; box-shadow: var(--tq-elev-3); }

/* ══ Status ════════════════════════════════════════════════════════════════
   Colour is never the only cue — each state also carries an icon slot and a
   text label supplied by the caller.                                       ══ */

.tq-status {
  display: inline-flex;
  align-items: center;
  gap: var(--tq-space-2);
  padding: 6px 12px;
  border: 1px solid var(--tq-border-strong);
  border-radius: var(--tq-radius-pill);
  font-family: var(--tq-font-sans);
  font-size: var(--tq-type-label);
  font-weight: 600;
  color: var(--tq-text-2);
}
.tq-status--success { color: var(--tq-success); border-color: rgba(47,230,166,0.35); }
.tq-status--warning { color: var(--tq-warning); border-color: rgba(244,192,73,0.35); }
.tq-status--error   { color: var(--tq-error);   border-color: rgba(255,92,122,0.35); }
.tq-status--info    { color: var(--tq-info);    border-color: rgba(125,211,252,0.35); }
.tq-status--neutral { color: var(--tq-text-muted); }

/* ══ Icons ═════════════════════════════════════════════════════════════════
   Lucide (lucide-static 1.28.0, ISC) inlined as <svg>. One family, one stroke
   width, currentColor, sizes from a finite 16/18/20/24 scale.              ══ */

.tq-icon {
  flex: none;
  width: 20px;
  height: 20px;
  stroke: currentColor;
  stroke-width: var(--tq-icon-stroke);
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.tq-icon--16 { width: 16px; height: 16px; }
.tq-icon--18 { width: 18px; height: 18px; }
.tq-icon--24 { width: 24px; height: 24px; }

/* ══ Tooltip primitive ═════════════════════════════════════════════════════
   For unlabelled icon-only controls only. Behaviour lives in tq-ui.js:
   hover delay, keyboard focus, hoverable tooltip, Escape to close,
   aria-describedby, edge-aware placement. Never a substitute for an
   accessible name, and never used to hide essential instructions.         ══ */

.tq-tooltip {
  position: fixed;
  z-index: var(--tq-z-tooltip);
  max-width: 240px;
  padding: 7px 10px;
  background: var(--tq-surface-2);
  border: 1px solid var(--tq-border-strong);
  border-radius: var(--tq-radius-sm);
  box-shadow: var(--tq-elev-2);
  color: var(--tq-text);
  font-family: var(--tq-font-sans);
  font-size: var(--tq-type-label);
  font-weight: 500;
  line-height: 1.4;
  pointer-events: auto;
  opacity: 0;
  transform: translateY(2px);
  transition: opacity var(--tq-motion-fast) var(--tq-ease),
              transform var(--tq-motion-fast) var(--tq-ease);
}
.tq-tooltip[data-tq-open="true"] { opacity: 1; transform: translateY(0); }

/* ══ Loading-state primitive ═══════════════════════════════════════════════
   Skeletons stand in for values that are genuinely unknown until an async
   read resolves. They match final geometry, use a restrained pulse (not a
   bright shimmer), and are removed atomically by tq-ui.js.                ══ */

.tq-skeleton {
  display: block;
  background: linear-gradient(90deg, #161b26, #1d2434, #161b26);
  border-radius: var(--tq-radius-sm);
  animation: tq-pulse 1.6s var(--tq-ease) infinite;
}
@keyframes tq-pulse { 0%, 100% { opacity: 0.55; } 50% { opacity: 0.85; } }

.tq-skeleton--text   { height: 12px; width: 100%; margin: 5px 0; }
.tq-skeleton--title  { height: 20px; width: 60%;  margin: 6px 0; border-radius: var(--tq-radius-sm); }
.tq-skeleton--avatar { height: 30px; width: 30px; border-radius: 50%; }
.tq-skeleton--button { height: 44px; width: 120px; border-radius: var(--tq-radius-md); }
.tq-skeleton--card   { height: 140px; width: 100%; border-radius: var(--tq-radius-lg); }

/* A region whose real content is already in the DOM but not yet trustworthy:
   the geometry is the live element's own, so removing the mask shifts nothing. */
[data-tq-skeleton][aria-busy="true"] {
  position: relative;
  /* `> *` below hides element children only. A region whose markup mixes an
     element with a bare text node (the credits pill is `<span>5</span> chats
     left`) would keep rendering that text, and the mask pulses between 0.55 and
     0.85 opacity, so it shows through rather than being covered. Making the
     region's own text transparent hides it at every point of the cycle. */
  color: transparent;
}
[data-tq-skeleton][aria-busy="true"] > * { visibility: hidden; }
[data-tq-skeleton][aria-busy="true"]::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(90deg, #161b26, #1d2434, #161b26);
  animation: tq-pulse 1.6s var(--tq-ease) infinite;
}

/* ══ Reduced motion ════════════════════════════════════════════════════════
   Restrained by default; nothing decorative survives a reduced-motion pref. ══ */

@media (prefers-reduced-motion: reduce) {
  .tq-skeleton,
  [data-tq-skeleton][aria-busy="true"]::after,
  .tq-btn[data-tq-loading="true"]::after {
    animation: none;
  }
  .tq-tooltip { transition: none; transform: none; }
  .tq-btn, .tq-input, .tq-card--interactive { transition: none; }
}
