/* ==========================================================================
   nanocosmos Product Theme
   ==========================================================================

   A dark, technical UI theme extracted from player-diagnostics.html
   (nanoStudio Player Diagnostics). Reusable for future diagnostics /
   dev-tool style pages: dark neutral panels, orange for primary/committing
   actions, blue for secondary actions and status, flat (no drop-shadow)
   surfaces, pill-shaped buttons and badges.

   USAGE
   --------------------------------------------------------------------------
   1. Load fonts in <head> before this stylesheet:

      <link rel="preconnect" href="https://fonts.googleapis.com">
      <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
      <link href="https://fonts.googleapis.com/css2?family=Lexend+Deca:wght@400;700&family=Source+Sans+Pro:wght@400&family=Roboto+Mono:wght@400&display=swap" rel="stylesheet">
      <link rel="stylesheet" href="product-theme.css">

   2. Fonts:
      - Lexend Deca (700 Bold) — page/panel titles, buttons.
      - Lexend Deca (400 Regular) — header eyebrow labels only.
      - Source Sans Pro (400 Regular) — all other body text (labels,
        helper text, values, status text). This is the default body font.
      - Roboto Mono (400 Regular) — monospace content only (event log,
        raw JSON payload dumps).

   3. Components documented section by section below. Each section can be
      lifted independently — they only depend on the :root tokens.

   3a. Permission / consent gate (.engage-*, near the bottom, before the
      footer section): optional — only include it if the page gates a
      sensitive browser permission request (camera, mic, location, etc.)
      behind an explicit user action. Skip it entirely otherwise.

   3b. Header product identity: use the product line's canonical logo image
      (.logo-lockup) — never spell the product name out as plain eyebrow
      text (e.g. don't type "nanoStream"). See the comment above
      .logo-lockup for the canonical asset URL per product line.

   4. This copy is synced from the canonical nanocosmos-brand-guidelines
      skill's product-theme.css. Linked directly by instanttest.html in
      this repo — page-specific extensions (badges, journey cards, chart
      panels, error overlay, etc.) live in a page-scoped <style> block in
      instanttest.html, loaded after this stylesheet. Do not fork the
      shared rules below into that block; only add what's genuinely
      unique to this page. (This file's own Moodboard/documentation
      section from the skill's canonical copy is intentionally omitted
      here — it's only used by the skill's diagnostics-theme-moodboard.html
      reference page, not by any page in this repo.)

   ========================================================================== */

:root {
  /* Surfaces */
  --bg: #0d171e;              /* page background */
  --panel: #252a2f;            /* card / panel background */
  --panel-inset: #1c2228;      /* recessed surfaces: inputs, log body, code blocks */
  --border: #2e343d;           /* 1px borders on panels, inputs, dividers */

  /* Accents */
  --accent-orange: #e5883c;        /* primary / committing actions, footer */
  --accent-orange-hover: #f0954a;  /* hover/active state for orange elements */
  --accent-blue: #408bc3;          /* secondary actions, checked checkboxes */
  --accent-blue-hover: #5398cf;    /* hover/active state for blue elements */

  /* Text */
  --text-primary: #eef1f3;     /* headings, values, primary labels */
  --text-secondary: #97a1ad;   /* de-emphasized labels (reserve for content INSIDE recessed/inset surfaces) */
  --text-muted: #6b7480;       /* placeholders, least-important text (inset surfaces only) */
  --text-on-accent: #ffffff;   /* text sitting on orange/blue fills */

  /* Fonts */
  --font-heading: 'Lexend Deca', sans-serif;   /* titles + buttons, weight 700 (400 for header eyebrow) */
  --font-body: 'Source Sans Pro', sans-serif;  /* everything else, weight 400 */
  --font-mono: 'Roboto Mono', monospace;       /* event log, raw payload dumps */
}

/* Note on --text-secondary / --text-muted (updated per instant-test.html
   design feedback, 2026-08): standalone text — labels, headings, status
   text, paragraphs, anything NOT living inside a field-shaped box — is
   #ffffff. Text INSIDE a field-shaped box (text/password inputs, <select>,
   wrapped copyable value boxes) is --text-secondary, so the box itself
   reads as "a field you interact with" versus the surrounding white body
   copy; --text-muted stays reserved for placeholders and disabled state.
   (An earlier revision of this file had it the other way for player-
   diagnostics.html — pure white even inside input boxes — per different
   feedback on that specific tool. player-diagnostics.html keeps its own
   inline copy, so it is unaffected by this file's current convention; if
   you're reusing this theme for a new page, this — box content grey,
   everything else white — is the current default.) */

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
}

body {
  background: var(--bg);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-weight: 400;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

main { flex: 1; }

a { color: inherit; }

button, input {
  font-family: inherit;
}

/* Focus states — keep visible, this is a tool meant for keyboard use */
input:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent-blue);
  outline-offset: 2px;
}
.btn-primary:focus-visible {
  outline-color: var(--accent-orange-hover);
}

/* ==========================================================================
   Header — brand-blue gradient bar, full width, content column-aligned
   ========================================================================== */

.header {
  /* Dark-to-light blue gradient, weighted toward the darker stop so the
     lighter tone only takes over in the bottom quarter. Adjust the two
     hex values and the 25% stop to retune the balance/smoothness. */
  background: linear-gradient(180deg, #00486c 0%, #00486c 25%, #0f8dc8 100%);
  padding: 9px 0;
  border-bottom: 1px solid #0f8dc8;
}

/* Shares max-width + horizontal padding with .container / .footer-inner so
   header/body/footer content edges all line up regardless of viewport. */
.header-inner {
  max-width: 1040px;
  margin: 0 auto;
  padding: 0 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
}

.header-left {
  display: flex;
  align-items: center;
  gap: 18px;
}

/* Logo lockup image (brand mark + product name combined asset).
   Standard: identify the product line with its canonical logo image here,
   not with plain eyebrow text (e.g. don't type "nanoStream" as a label —
   use the logo asset below). Canonical URLs by product line:
     nanoStream — https://www.nanocosmos.net/wp-content/uploads/2026/06/nanoStream-logo-V1.webp
     nanoStudio — https://www.nanocosmos.net/wp-content/uploads/2026/06/nanoStudio-logo-V2.webp
   Pair it with .header-divider + .nav-label (below) for the page-specific
   name (e.g. "Instant Test", "Player Diagnostics") — see product-sample.html. */
.logo-lockup {
  display: block;
  height: 30px;
  width: auto;
}

.header-divider {
  width: 1px;
  height: 34px;
  background: rgba(255, 255, 255, 0.22);
}

.nav-label {
  display: flex;
  flex-direction: column;
  line-height: 1.3;
}

.nav-label .eyebrow {
  font-family: var(--font-heading);
  font-size: 11px;
  font-weight: 400; /* Lexend Deca Regular, not Bold — small caps eyebrow */
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #ffffff;
}

.nav-label .title {
  font-family: var(--font-heading);
  font-size: 16px;
  font-weight: 700; /* Lexend Deca Bold */
  color: #ffffff;
}

.header-right {
  display: flex;
  align-items: center;
  gap: 18px;
}

.theme-pill {
  border: 1px solid rgba(255, 255, 255, 0.35);
  background: transparent;
  color: #ffffff;
  border-radius: 999px;
  padding: 5px 14px;
  font-size: 13px;
  font-weight: 500;
  text-decoration: none; /* often used on <a> nav links — don't show the default link underline */
}

/* Secondary brand mark image (company logo, right side of header) */
.brand-mark {
  display: block;
  height: 26px;
  width: auto;
}

/* ==========================================================================
   Page layout
   ========================================================================== */

.container {
  max-width: 1040px;
  margin: 0 auto;
  padding: 24px 16px 40px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

/* Base panel: the flat #252a2f card used everywhere (form, player, stats,
   log). No drop shadows — border + fill only. */
.panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 4px; /* deliberately modest — squared-off, not pill-like */
}

/* ==========================================================================
   Form panel — label-beside-input layout
   ========================================================================== */

.form-panel {
  padding: 20px;
}

.field {
  display: flex;
  align-items: flex-start;
  gap: 20px;
  margin-bottom: 16px;
}
.field:last-of-type { margin-bottom: 0; }

.field label {
  flex: 0 0 200px; /* fixed label column so inputs align vertically */
  padding-top: 10px; /* optically aligns label baseline with input text */
  font-size: 16px;
  font-weight: 500;
  color: #ffffff;
}

.field-control {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.field input[type="text"],
.field input[type="password"],
.field select {
  background: var(--panel-inset);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text-secondary); /* field content reads as "a box", not body copy — see note above :root */
  padding: 10px 12px;
  font-size: 16px;
  width: 100%;
}

.field select:hover { border-color: var(--accent-blue); }
.field select:disabled { color: var(--text-muted); cursor: not-allowed; }

.field input::placeholder {
  color: var(--text-muted);
}

/* Stack label above input below 640px so the fixed label column doesn't
   crowd the field on narrow viewports. */
@media (max-width: 640px) {
  .field {
    flex-direction: column;
    gap: 6px;
  }
  .field label {
    flex-basis: auto;
    padding-top: 0;
  }
}

.field .helper {
  font-size: 11.5px;
  line-height: 1.5;
  color: #ffffff;
}

.checkbox-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin: 20px 0;
  padding: 16px 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}

.checkbox-item {
  display: flex;
  align-items: center;
  gap: 8px;
}

.checkbox-item input[type="checkbox"] {
  width: 17px;
  height: 17px;
  accent-color: var(--accent-blue);
}

.checkbox-item label {
  font-size: 13px;
  color: var(--text-primary);
}

/* ==========================================================================
   Buttons
   ========================================================================== */

.button-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.btn {
  font-family: var(--font-heading); /* Lexend Deca */
  border: none;
  border-radius: 999px; /* pill */
  padding: 10px 22px;
  font-size: 14px;
  font-weight: 700; /* Bold */
  cursor: pointer;
  transition: background-color 0.15s ease, transform 0.05s ease;
}
.btn:active { transform: translateY(1px); }
.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
}

/* Use for the single primary/committing action per view (load, save, copy) */
.btn-primary {
  background: var(--accent-orange);
  color: var(--text-on-accent);
}
.btn-primary:hover:not(:disabled) { background: var(--accent-orange-hover); }

/* Use for secondary/utility actions (resume, stop, clear, mute) */
.btn-secondary {
  background: var(--accent-blue);
  color: var(--text-on-accent);
}
.btn-secondary:hover:not(:disabled) { background: var(--accent-blue-hover); }

@media (prefers-reduced-motion: reduce) {
  .btn { transition: none; }
}

/* ==========================================================================
   Monitor / player surface
   ========================================================================== */

.player-panel {
  overflow: hidden; /* clips the video element to the panel's border-radius */
  padding: 0;
}

.video-surface {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 10.5;
  background: #000000;
  display: flex;
  align-items: center;
  justify-content: center;
}

.video-el {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #000000;
}

.status-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  padding: 14px 20px;
}

.status-left {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* ==========================================================================
   Badges — status pills
   ========================================================================== */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 13px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
}

.badge.paused { background: var(--accent-orange); color: var(--text-on-accent); }
.badge.playing { background: var(--accent-blue); color: var(--text-on-accent); }
.badge.loading { background: var(--accent-blue); color: var(--text-on-accent); }

.badge .dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}
.badge.loading .dot {
  animation: pulse 0.9s ease-in-out infinite;
}
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.25; }
}
@media (prefers-reduced-motion: reduce) {
  .badge.loading .dot { animation: none; }
}

.status-left .status-text,
.status-right {
  font-size: 12px;
  color: #ffffff;
}

/* ==========================================================================
   Stats / info panels — label/value row list
   ========================================================================== */

.stats-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
}
@media (max-width: 640px) {
  .stats-row { grid-template-columns: 1fr; }
}

.stats-panel {
  padding: 20px;
}

.stats-panel h2 {
  font-family: var(--font-heading);
  margin: 0 0 12px;
  font-size: 15px;
  font-weight: 700;
  color: var(--text-primary);
}

.info-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding: 7px 0;
  border-bottom: 1px solid var(--border);
  font-size: 14px;
}
.info-row:last-child { border-bottom: none; }

/* Use for long values (URLs, IDs) that need to wrap onto their own line
   instead of squeezing next to the label */
.info-row.wrap {
  flex-direction: column;
  gap: 6px;
  align-items: stretch;
  padding: 10px 0;
}

.info-row .label {
  color: #ffffff;
  flex-shrink: 0;
}

.info-row .value {
  color: var(--text-primary);
  font-weight: 500;
  text-align: right;
}

/* Renders as a field-shaped box (background/border), not plain wrapped
   text — so its --text-secondary color reads as "a box", matching
   selects/inputs above, not as de-emphasized body copy. */
.info-row.wrap .value {
  text-align: left;
  word-break: break-all;
  font-weight: 400;
  font-family: var(--font-mono);
  font-size: 13.5px;
  color: var(--text-secondary);
  background: var(--panel-inset);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
}

/* Expandable "raw payload" disclosure row */
.raw-toggle {
  width: 100%;
  background: none;
  border: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 7px 0 0;
  font-size: 13px;
  color: #ffffff;
  cursor: pointer;
  font-family: inherit;
}
.raw-toggle:hover { color: var(--accent-blue-hover); }

.raw-toggle .chevron {
  transition: transform 0.15s ease;
  display: inline-block;
}
.raw-toggle[aria-expanded="true"] .chevron {
  transform: rotate(90deg);
}
@media (prefers-reduced-motion: reduce) {
  .raw-toggle .chevron { transition: none; }
}

.raw-payload {
  display: none;
  margin-top: 10px;
  background: var(--panel-inset);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: #ffffff;
  overflow-x: auto;
  white-space: pre;
}
.raw-payload.open { display: block; }

/* ==========================================================================
   Event log
   ========================================================================== */

.log-panel {
  padding: 20px;
}

.log-panel h2 {
  font-family: var(--font-heading);
  margin: 0 0 12px;
  font-size: 15px;
  font-weight: 700;
  color: var(--text-primary);
}

.log-box {
  background: var(--panel-inset);
  border: 1px solid var(--border);
  border-radius: 8px;
  height: 210px;
  overflow-y: auto;
  padding: 12px 14px;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.7;
}

.log-line {
  white-space: pre-wrap;
  word-break: break-word;
}
.log-line .ts { color: #ffffff; margin-right: 10px; }
.log-line .evt { color: var(--text-primary); }

.log-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 16px;
}

.copy-confirm {
  font-size: 12px;
  color: var(--accent-blue-hover);
  opacity: 0;
  transition: opacity 0.15s ease;
}
.copy-confirm.show { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .copy-confirm { transition: none; }
}

/* ==========================================================================
   Permission / consent gate — full-screen overlay with a single primary
   action, shown before the page requests a sensitive browser permission
   (camera, mic, location, notifications, etc.) so the browser's own
   prompt doesn't come out of nowhere. Extracted from instanttest.html's
   camera/mic gate (2026-08) — optional section, only needed by pages that
   gate a permission request behind an explicit user action.

   Usage: swap .engage-title / .engage-hint copy for the page's own —
   title states the payoff, hint states what's about to be asked for and
   why (plus a privacy reassurance, e.g. "nothing is recorded or stored").

   Deliberately no pulsing/blinking animation on .engage-btn: a blinking
   CTA reads as attention-grabbing at first glance but becomes visually
   noisy on a static page and can be uncomfortable for some users. A
   static shadow still stands out against the dimmed backdrop without
   relying on motion — see .btn-primary/#startButton-style CTAs elsewhere
   on the page for the same rule if they need extra emphasis.
   ========================================================================== */

.engage-overlay {
  position: fixed;
  inset: 0;
  background: rgba(13, 23, 30, 0.88);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 15vh;
  z-index: 10002;
  transition: opacity 0.6s ease;
}
.engage-overlay.fadeout { opacity: 0; pointer-events: none; }

.engage-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.engage-title {
  font-family: var(--font-heading);
  font-size: 1.3em;
  font-weight: 700;
  color: #ffffff;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin-bottom: -4px;
}

.engage-hint {
  color: #ffffff;
  font-size: 14px;
  text-align: center;
  max-width: 380px;
  line-height: 1.5;
  opacity: 0.85;
}

.engage-btn {
  padding: 18px 42px;
  background: var(--accent-orange);
  color: var(--text-on-accent);
  border: none;
  border-radius: 999px;
  font-family: var(--font-heading);
  font-size: 1.15em;
  font-weight: 700;
  cursor: pointer;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  box-shadow: 0 15px 35px rgba(0, 0, 0, 0.5);
  transition: background-color 0.15s ease, transform 0.15s ease;
  opacity: 1;
}
.engage-btn.fadeout { opacity: 0; }
.engage-btn:hover { background: var(--accent-orange-hover); transform: translateY(-2px); }

@media (max-width: 640px) {
  .engage-btn { padding: 16px 28px; font-size: 1em; max-width: 90%; text-align: center; }
}

/* ==========================================================================
   Footer — full-width orange bar, column-aligned content
   ========================================================================== */

.footer {
  background: var(--accent-orange);
  color: #ffffff;
  padding: 16px 0;
  font-size: 13px;
}

.footer-inner {
  max-width: 1040px;
  margin: 0 auto;
  padding: 0 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
}

.footer a {
  text-decoration: underline;
}
