/*
 * public-market-demo.css — Hero mockup + tab-switching demo area styles for
 * views/market.ejs ONLY. Phase A of
 * docs/plans/2026-09-03-public-site-visual-unification.md.
 *
 * Deliberately NOT folded into public-base.css / public-marketing.css: those two files
 * are the shared dependency closure of views/partials/public-nav.ejs +
 * views/partials/public-footer.ejs, loaded by all 13 marketing pages. Everything in
 * this file is specific to /market's hero + demo sections and must not leak to the
 * other 12 pages. Loaded via its own <link> in views/market.ejs, right after
 * views/partials/public-head.ejs's two shared <link> tags.
 *
 * Consumes --bg/--surface/--surface-2/--text/--muted/--line/--primary/--accent from
 * market.ejs's own inline <style> :root block (loaded before this file has any need
 * to reference them — these are read at paint time, not at parse time, so load order
 * between this file and that inline block does not matter for var() resolution).
 *
 * New animation tokens (--ease-spring/--dur-base/--dur-slow) are scoped to
 * .demo-stage, NOT :root — see docs/plans/2026-04-25-privora-seo-aeo-ui-design.md's
 * 2026-09-03 amendments to §1.1 ("No new tokens") and §5.5 ("No animated elements"),
 * which permit exactly this class of token and this class of component, explicitly
 * scoped to a container and to /market's #demo section, not global/all-pages.
 *
 * Animation whitelist actually used below: transform + opacity everywhere, plus two
 * named exceptions — SVG stroke-dashoffset (.backtest-path, exactly one element) and
 * box-shadow on a single small ring (.alert-kpi-ring). No width/height/top/left is
 * ever animated.
 */

/* ===================== Hero product mockup (static — no motion) ===================== */

/* ===================== Demo stage (tab switching) ===================== */

.demo-stage {
  --ease-spring: cubic-bezier(.34, 1.56, .64, 1);
  --dur-base: .3s;
  --dur-slow: .5s;
  margin-top: 8px;
}
.demo-sample-note {
  margin: 0 0 14px;
  font-size: .8rem;
  color: var(--muted);
  padding: 8px 12px;
  border: 1px dashed var(--line);
  border-radius: 8px;
  background: rgba(255, 255, 255, .02);
}
.demo-tablist {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 18px;
  border-bottom: 1px solid var(--line);
  padding-bottom: 12px;
}
.demo-tab {
  appearance: none;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, .02);
  color: var(--muted);
  padding: 9px 16px;
  border-radius: 999px;
  font-size: .88rem;
  font-weight: 600;
  cursor: pointer;
  transition: .15s;
}
.demo-tab:hover { color: var(--text); }
.demo-tab[aria-selected="true"] {
  color: #fff;
  background: linear-gradient(135deg, var(--primary), var(--accent));
  border-color: transparent;
}
.demo-tab:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

.demo-panel {
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--surface);
  padding: 26px 24px;
  margin-bottom: 14px;
}
/* Progressive enhancement: WITHOUT the .js-tabs-ready class (i.e. no JS, or the
   setup script threw before reaching this point), every .demo-panel stays visible
   and stacked — this is the no-JS fallback, not a bug. Only once JS successfully
   wires up tab switching does it hide the inactive panels. */
.demo-stage.js-tabs-ready .demo-panel { display: none; margin-bottom: 0; }
.demo-stage.js-tabs-ready .demo-panel.is-active { display: block; }

.demo-panel-visual { min-height: 200px; display: flex; flex-direction: column; justify-content: center; }
.demo-panel-caption { margin: 16px 0 0; color: var(--muted); font-size: .92rem; line-height: 1.6; }

/* ---- Dashboard widgets ---- */
.demo-widgets { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.demo-widget {
  background: rgba(255, 255, 255, .03);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 14px;
  opacity: 1;
  transform: none;
}
.demo-widget-label { display: block; font-size: .74rem; color: var(--muted); margin-bottom: 6px; }
.demo-widget-value { display: block; font-size: 1.1rem; font-weight: 700; color: var(--text); }
/* Marks a figure as a real SGE quote rather than the sample beside it.
   Green, not the brand colour: it reports liveness, and using --primary
   would make it move with the palette as if it were decoration. */
.demo-widget-live { display: block; font-size: .66rem; color: #4ade80; margin-top: 3px; letter-spacing: .02em; }
.demo-widgets.is-animating .demo-widget {
  animation: widgetIn var(--dur-slow) var(--ease-spring) both;
  animation-delay: calc(var(--i, 0) * 90ms);
}
@keyframes widgetIn {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ---- Subscription flow ---- */
.flow-demo { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.flow-card { flex: 1; min-width: 200px; background: rgba(255, 255, 255, .03); border: 1px solid var(--line); border-radius: 12px; padding: 14px 16px; }
.flow-card-title { font-weight: 700; font-size: .9rem; color: var(--text); margin-bottom: 4px; }
.flow-card-meta { font-size: .78rem; color: var(--muted); }
.flow-track { position: relative; width: 64px; height: 40px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.flow-arrow { color: var(--muted); font-size: 1.3rem; }
.flow-ghost {
  position: absolute;
  top: 50%;
  left: 0;
  width: 140px;
  padding: 8px 10px;
  border-radius: 10px;
  background: rgba(var(--primary-rgb), .18);
  border: 1px solid rgba(var(--primary-rgb), .4);
  color: #f0dba0;
  font-size: .72rem;
  font-weight: 600;
  opacity: 0;
  transform: translate(0, -50%);
  pointer-events: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.flow-badge {
  display: inline-block;
  margin-top: 8px;
  font-size: .76rem;
  font-weight: 700;
  color: #4ade80;
  background: rgba(34, 197, 94, .14);
  border: 1px solid rgba(34, 197, 94, .35);
  padding: 3px 10px;
  border-radius: 999px;
  opacity: 1;
  transition: opacity var(--dur-base) var(--ease-spring);
}
.flow-badge.is-hidden { opacity: 0; }

/* ---- Alert ---- */
.alert-demo { display: flex; align-items: center; gap: 24px; flex-wrap: wrap; }
.alert-kpi { display: flex; align-items: center; gap: 12px; background: rgba(255, 255, 255, .03); border: 1px solid var(--line); border-radius: 12px; padding: 14px 18px; }
.alert-kpi-ring { width: 14px; height: 14px; border-radius: 50%; background: var(--primary); box-shadow: 0 0 0 4px rgba(var(--primary-rgb), .25); flex-shrink: 0; }
.alert-kpi-ring.is-live { animation: pulseRing 2s infinite; }
@keyframes pulseRing {
  0% { box-shadow: 0 0 0 0 rgba(var(--primary-rgb), .45); }
  70% { box-shadow: 0 0 0 14px rgba(var(--primary-rgb), 0); }
  100% { box-shadow: 0 0 0 0 rgba(var(--primary-rgb), 0); }
}
.alert-kpi-label { display: block; font-size: .74rem; color: var(--muted); }
.alert-kpi-value { display: block; font-size: 1.05rem; font-weight: 700; color: #f87171; }
.alert-toast {
  display: flex;
  align-items: center;
  gap: 10px;
  background: rgba(255, 255, 255, .04);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 12px 16px;
  max-width: 360px;
  opacity: 1;
  transform: translateX(0);
  transition: transform .4s var(--ease-spring), opacity .3s;
}
.alert-toast.is-out { opacity: 0; transform: translateX(120%); }
.alert-toast.no-transition { transition: none; }
.alert-toast-icon { font-size: 1.1rem; }
.alert-toast-text { font-size: .85rem; color: var(--text); line-height: 1.5; }

/* ---- Backtest curve ---- */
.backtest-demo { display: flex; flex-direction: column; gap: 12px; }
.backtest-legend { display: flex; gap: 16px; font-size: .8rem; color: var(--muted); }
.backtest-legend span { display: inline-flex; align-items: center; gap: 6px; }
.backtest-legend i { width: 14px; height: 3px; border-radius: 2px; display: inline-block; }
.backtest-legend .lg-strategy i { background: var(--primary); }
.backtest-legend .lg-benchmark i { background: var(--muted); }
.backtest-stats { display: flex; gap: 24px; }
/* Nine real metrics need a grid; two sample ones did not. Kept as a
   separate class so the sample layout is untouched when the backend has
   nothing to show. auto-fit rather than a fixed column count: the same
   grid then holds at 960px and at 390px without another breakpoint. */
.backtest-stats.is-real {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: 10px 18px;
}
.backtest-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 10px; font-size: .78rem; }
/* Green, like .demo-widget-live and for the same reason: it reports that
   the figures are real, which is not a decorative property. */
.backtest-run-tag { color: #4ade80; font-weight: 700; letter-spacing: .02em; }
.backtest-run-name { color: var(--text); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.backtest-run-period { color: var(--muted); }
.backtest-stat-label { display: block; font-size: .74rem; color: var(--muted); }
.backtest-stat-value { display: block; font-size: 1.02rem; font-weight: 700; color: var(--text); }
.backtest-svg-wrap { width: 100%; overflow: hidden; }
.backtest-svg-wrap svg { width: 100%; height: auto; display: block; }
.backtest-path { fill: none; stroke: var(--primary); stroke-width: 2.5; stroke-linecap: round; stroke-dashoffset: 0; }
.backtest-bench-path { fill: none; stroke: var(--muted); stroke-width: 1.5; stroke-dasharray: 4 4; opacity: .6; }

/* ===================== Responsive ===================== */
@media (max-width: 960px) {
  .demo-widgets { grid-template-columns: 1fr 1fr; }
  .flow-demo { flex-direction: column; }
  .flow-track { transform: rotate(90deg); }
}
@media (max-width: 560px) {
  .demo-widgets { grid-template-columns: 1fr; }
  .backtest-stats { flex-direction: column; gap: 8px; }
  /* auto-fit already handles narrow widths; without this the
     rule above would turn nine metrics into a nine-row column. */
  .backtest-stats.is-real { display: grid; }
}

/* ===================== Reduced-motion safety net =====================
 * Defense in depth: market.ejs's script already checks
 * prefers-reduced-motion and never starts any sequencer when it matches, so
 * none of the .is-* toggle classes below are ever added by JS in that case
 * — the server-rendered baseline (already the terminal state for every
 * component) is what renders. This block additionally forces the terminal
 * state at the CSS layer in case those classes ever get added anyway
 * (e.g. a future bug, or someone toggling them via devtools). */
@media (prefers-reduced-motion: reduce) {
  .demo-widget, .flow-badge, .alert-toast, .flow-ghost {
    transition: none !important;
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  .flow-ghost { opacity: 0 !important; } /* decorative-only clone, never a real content state */
  .alert-kpi-ring.is-live { animation: none !important; box-shadow: 0 0 0 4px rgba(var(--primary-rgb), .25) !important; }
  .backtest-path { transition: none !important; stroke-dashoffset: 0 !important; }
}
