/* ==========================================================================
   SIGMA SCANNER — hero-demo.css
   §2b Product Demo — "The Ranking"

   This is the original hero__stage component (score, then rank, then backtest,
   performed once via a FLIP-sorted list and a drawn equity curve),
   relocated to its own section below the redesigned hero and renamed to
   the .demo__ namespace so nothing here collides with the new image-based
   .hero__stage in hero.css. Markup, styling and choreography are otherwise
   unchanged from the original — see js/hero-demo.js for the entrance.

   Independent entrance state machine, mirroring hero.css's:
   <html data-demo="...">
     (absent)   default, everything visible (no-JS contract)
     pending    set by the <head> script before first paint
     playing    the master timeline is running
     done       timeline finished
     static     failsafe — 6s after pending with nothing watching
   ========================================================================== */

@layer layout {

  .demo {
    position: relative;
    isolation: isolate;
    overflow: clip;
  }

  .demo__inner {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    inline-size: 100%;
  }
}

/* ==========================================================================
   STAGE — the browser, the floats, the reflection
   ========================================================================== */
@layer components {

  .demo__stage {
    position: relative;
    inline-size: 100%;
    margin-block-start: var(--sp-9);
    /* 3D context for the pointer tilt. 2200px is deliberately long: a short
       perspective exaggerates rotation into the "tilted mockup" look this
       design explicitly rejects. */
    perspective: 2200px;
  }

  /* ---------- BROWSER MOCKUP ------------------------------------------
     Two layers of chrome, which is what a real user actually sees: a
     browser window containing the application's own header. The doubling
     is what makes it read as depth rather than as a sticker. */
  .demo__browser {
    position: relative;
    z-index: 2;
    border-radius: var(--r-lg);
    background: var(--paper);
    border: 1px solid var(--ink-200);
    box-shadow: var(--shadow-hero);
    overflow: hidden;
    transform-style: preserve-3d;
    will-change: transform;
  }

  .demo__chrome {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    block-size: 40px;
    padding-inline: var(--sp-4);
    background: var(--ink-050);
    border-block-end: 1px solid var(--ink-200);
  }

  .demo__dots { display: flex; gap: 6px; flex: none; }
  .demo__dots i {
    inline-size: 9px; block-size: 9px; border-radius: var(--r-full);
    background: var(--ink-200);
  }
  /* Ink-toned, not macOS red/amber/green. Traffic-light colours here would
     put three saturated hues into a hero whose whole discipline is that
     colour means something. */

  .demo__url {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    max-inline-size: 320px;
    margin-inline: auto;
    block-size: 24px;
    padding-inline: var(--sp-3);
    border-radius: var(--r-full);
    background: var(--paper);
    border: 1px solid var(--ink-200);
    font-size: 11px;
    color: var(--ink-400);
    font-family: var(--font-body);
  }
  .demo__url svg { inline-size: 11px; block-size: 11px; color: var(--signal-600); }

  /* ---------- APPLICATION HEADER --------------------------------------
     The product's own chrome. Deep green, exactly as it appears once the
     visitor signs in — so their first sight of the real thing is
     continuous rather than a jump cut. */
  .demo__appbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-4);
    block-size: 38px;
    padding-inline: var(--sp-4);
    background: var(--deep-900);
    color: var(--deep-fg);
  }
  .demo__wordmark {
    display: inline-flex; align-items: center; gap: var(--sp-2);
    font-size: 12px; font-weight: var(--fw-semibold); letter-spacing: -0.01em;
  }
  .demo__wordmark i {
    inline-size: 14px; block-size: 14px; border-radius: 3px;
    background: var(--signal-400); flex: none;
  }
  .demo__context {
    font-size: 9.5px;
    letter-spacing: .12em;
    text-transform: uppercase;
    font-weight: var(--fw-semibold);
    color: var(--deep-fg-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .demo__panels { display: grid; grid-template-columns: 1fr; }

  /* ---------- RANK PANEL ------------------------------------------------ */
  .demo__rank {
    position: relative;
    padding: var(--sp-4) var(--sp-4) var(--sp-5);
    border-block-end: 1px solid var(--ink-200);
    /* Fixed row height keeps the FLIP sort clean and lets the portfolio-cut
       divider be positioned arithmetically instead of measured. */
    --row-h: 30px;
    --head-h: 26px;
  }

  .demo__rankhead,
  .demo__rank-row {
    display: grid;
    grid-template-columns: 22px 1fr 54px 46px;
    align-items: center;
    gap: var(--sp-2);
  }
  .demo__rankhead {
    block-size: var(--head-h);
    font-size: 9px;
    letter-spacing: .1em;
    text-transform: uppercase;
    font-weight: var(--fw-semibold);
    color: var(--ink-300);
    border-block-end: 1px solid var(--ink-150);
  }

  /* min-block-size is load-bearing, not decorative.

     hero-demo.js's FLIP sort runs with `absolute: true` (Flip.from), which
     takes every .demo__rank-row out of document flow for the duration of
     that tween so they can move freely without shoving their siblings
     around mid-flight. With no other content, a `position: relative`
     parent whose only children just went absolute has nothing left to
     size itself against and collapses to zero height — then snaps back
     the instant Flip hands the rows back to static layout. That collapse-
     and-return is exactly the "shrinks, then jumps back" this rule fixes:
     always exactly 9 rows (hard-coded in the markup, never fewer), so
     reserving 9 row-heights up front keeps the panel's height constant
     through the entire sort regardless of how the rows are positioned. */
  .demo__rank-list { position: relative; min-block-size: calc(var(--row-h) * 9); }

  .demo__rank-row {
    block-size: var(--row-h);
    font-size: 12px;
    color: var(--ink-400);
    border-radius: var(--r-xs);
    transition: color var(--dur-base) var(--ease-out-quad),
                opacity var(--dur-base) var(--ease-out-quad);
  }
  .demo__rank-row[data-in="true"]  { color: var(--ink-800); }
  .demo__rank-row[data-in="false"] { opacity: .42; }

  .demo__rk {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 10px;
    color: var(--ink-300);
    text-align: end;
  }
  .demo__rank-row[data-in="true"] .demo__rk { color: var(--signal-600); }

  .demo__tk {
    display: flex; align-items: center; gap: var(--sp-2);
    font-weight: var(--fw-medium);
    letter-spacing: -0.005em;
    text-align: start;
    min-inline-size: 0;
  }
  .demo__tk em {
    font-style: normal; font-weight: inherit;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }

  /* Score bar. scaleX is the animated property — width would trigger
     layout on every frame for nine rows simultaneously. */
  .demo__bar {
    flex: 1 1 auto;
    block-size: 3px;
    min-inline-size: 20px;
    max-inline-size: 88px;
    border-radius: var(--r-full);
    background: var(--ink-150);
    overflow: hidden;
  }
  .demo__bar i {
    display: block; block-size: 100%;
    border-radius: inherit;
    background: var(--ink-300);
    transform-origin: left center;
    transform: scaleX(var(--v, 0));
    transition: transform 600ms var(--ease-out-cubic),
                background-color var(--dur-base) var(--ease-out-quad);
  }
  .demo__rank-row[data-in="true"] .demo__bar i { background: var(--signal-500); }

  .demo__sc {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 11.5px;
    font-weight: var(--fw-semibold);
    color: var(--ink-500);
    text-align: end;
  }
  .demo__rank-row[data-in="true"] .demo__sc { color: var(--signal-700); }

  .demo__dt {
    display: inline-flex; align-items: center; justify-content: flex-end; gap: 2px;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 10px;
    color: var(--ink-300);
  }
  /* Glyph + sign, never colour alone — roughly 1 in 12 men has a red/green
     deficiency and this audience skews heavily male. */
  .demo__dt[data-dir="up"]   { color: var(--data-gain-text); }
  .demo__dt[data-dir="down"] { color: var(--data-loss-text); }

  /* Portfolio cut. Absolutely positioned by arithmetic so it never
     participates in the FLIP sort or shifts the rows below it. */
  .demo__cut {
    position: absolute;
    inset-inline: 0;
    inset-block-start: calc(var(--row-h) * var(--cut, 6));
    display: flex; align-items: center; gap: var(--sp-2);
    translate: 0 -50%;
    font-size: 8.5px;
    letter-spacing: .12em;
    text-transform: uppercase;
    font-weight: var(--fw-semibold);
    color: var(--ink-300);
    pointer-events: none;
  }
  .demo__cut::before, .demo__cut::after {
    content: ""; flex: 1 1 auto; block-size: 1px;
    background: repeating-linear-gradient(90deg, var(--ink-200) 0 3px, transparent 3px 6px);
  }

  /* Scoring sweep. One translating element rather than a per-row class
     cascade — one layer, one paint. */
  .demo__scan {
    position: absolute;
    inset-inline: 0;
    block-size: 76px;
    opacity: 0;
    pointer-events: none;
    background: linear-gradient(180deg,
      rgb(16 160 80 / 0) 0%,
      rgb(16 160 80 / .09) 46%,
      rgb(16 160 80 / .015) 72%,
      rgb(16 160 80 / 0) 100%);
    border-block-end: 1px solid rgb(16 160 80 / .28);
  }

  /* ---------- CHART PANEL ---------------------------------------------- */
  .demo__chart { padding: var(--sp-4) var(--sp-4) var(--sp-5); }

  .demo__charthead {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--sp-3);
    block-size: var(--head-h, 26px);
    font-size: 9px;
    letter-spacing: .1em;
    text-transform: uppercase;
    font-weight: var(--fw-semibold);
    color: var(--ink-300);
    border-block-end: 1px solid var(--ink-150);
    margin-block-end: var(--sp-3);
  }
  .demo__legend { display: inline-flex; align-items: center; gap: var(--sp-3); }
  .demo__legend b { display: inline-flex; align-items: center; gap: 5px; font-weight: inherit; }
  .demo__legend i { inline-size: 10px; block-size: 2px; border-radius: 2px; flex: none; }
  .demo__legend i[data-s="strategy"] { background: var(--data-gain); }
  .demo__legend i[data-s="bench"] {
    background: repeating-linear-gradient(90deg, var(--data-benchmark) 0 3px, transparent 3px 5px);
  }

  /* preserveAspectRatio="none" lets the plot be shortened on narrow
     viewports without letterboxing. vector-effect keeps every stroke at
     its authored weight under that non-uniform scale — without it the
     curve thins horizontally and thickens vertically, which is exactly
     the kind of detail a quant audience notices. */
  .demo__plot {
    display: block;
    inline-size: 100%;
    block-size: clamp(150px, 34vw, 200px);
  }
  .demo__plot * { vector-effect: non-scaling-stroke; }
  .demo__plot .grid  { stroke: var(--ink-150); stroke-width: 1; }
  .demo__plot .bench { stroke: var(--data-benchmark); stroke-width: 1.6; fill: none;
                       stroke-dasharray: 4 3; stroke-linecap: round; }
  .demo__plot .strat { stroke: var(--data-gain); stroke-width: 2.2; fill: none;
                       stroke-linecap: round; stroke-linejoin: round; }
  .demo__plot .area  { fill: url(#demoArea); }
  .demo__plot .ddmark circle { fill: var(--paper); stroke: var(--data-loss); stroke-width: 1.6; }
  .demo__plot .ddmark text { font-family: var(--font-mono); font-size: 8px;
                             fill: var(--data-loss); font-weight: 600; }

  .demo__axis {
    display: flex; justify-content: space-between;
    margin-block-start: var(--sp-2);
    font-family: var(--font-mono);
    font-size: 9px;
    color: var(--ink-300);
  }

  .demo__stats {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sp-3);
    margin-block-start: var(--sp-4);
    padding-block-start: var(--sp-4);
    border-block-start: 1px solid var(--ink-150);
  }
  .demo__stat { display: flex; flex-direction: column; gap: 3px; text-align: start; }
  .demo__stat b {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: clamp(1.0625rem, .9rem + .5vw, 1.375rem);
    font-weight: var(--fw-semibold);
    letter-spacing: -0.01em;
    line-height: 1.05;
  }
  .demo__stat[data-tone="gain"] b { color: var(--data-gain-text); }
  .demo__stat[data-tone="loss"] b { color: var(--data-loss-text); }
  .demo__stat span {
    font-size: 8.5px; letter-spacing: .12em; text-transform: uppercase;
    font-weight: var(--fw-semibold); color: var(--ink-400);
  }

  /* ---------- REFLECTION ------------------------------------------------
     Grounding, not a mirror. If it reads AS a reflection it is too strong. */
  .demo__reflection {
    position: absolute;
    inset-block-start: 100%;
    inset-inline: 6%;
    block-size: 76px;
    z-index: 1;
    border-radius: 0 0 var(--r-2xl) var(--r-2xl);
    background: linear-gradient(180deg, rgb(7 26 18 / .085) 0%, rgb(7 26 18 / 0) 100%);
    filter: blur(12px);
    pointer-events: none;
  }
}


/* ==========================================================================
   FLOATING LAYER
   The brief's "floating stock symbols", made meaningful: every floating
   object is a real data object, because scoring things is what the product
   does. Decorative tickers would be confetti.

   Glass budget: the two CARDS are glass; the three CHIPS are not.
   backdrop-blur on a 96px chip is imperceptible and still costs a
   compositor layer and a per-frame repaint. Two glass surfaces, inside the
   design system's limit of three per viewport.
   ========================================================================== */
@layer components {

  .demo__floats {
    position: absolute;
    inset: -6% 0;
    z-index: 3;
    pointer-events: none;
  }

  .demo__float {
    position: absolute;
    will-change: transform;
  }

  /* --- chip --- */
  .demo__chip {
    display: flex; align-items: center; gap: var(--sp-2);
    padding: 7px 10px;
    border-radius: var(--r-md);
    background: var(--paper);
    border: 1px solid var(--ink-200);
    box-shadow: var(--shadow-md);
    font-size: 10.5px;
    white-space: nowrap;
  }
  .demo__chip b { font-weight: var(--fw-semibold); color: var(--ink-800); letter-spacing: -0.01em; }
  .demo__chip span {
    font-family: var(--font-mono); font-variant-numeric: tabular-nums;
    font-weight: var(--fw-semibold); color: var(--signal-700);
  }
  .demo__chip i {
    inline-size: 5px; block-size: 5px; border-radius: var(--r-full);
    background: var(--signal-500); flex: none;
  }
  /* The rank label is what stops this being a decorative ticker. It names
     the chip's relationship to the list below it. */
  .demo__chip em {
    font-style: normal;
    font-size: 9px;
    letter-spacing: .1em;
    text-transform: uppercase;
    font-weight: var(--fw-semibold);
    color: var(--ink-400);
    padding-inline-start: var(--sp-2);
    border-inline-start: 1px solid var(--ink-200);
  }

  /* --- glass card --- */
  .demo__card {
    padding: var(--sp-3) var(--sp-4) var(--sp-4);
    border-radius: var(--r-lg);
    background: var(--glass-bg);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border: 1px solid rgb(255 255 255 / .7);
    box-shadow: var(--inset-top), var(--shadow-lg);
  }
  @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .demo__card { background: rgb(255 255 255 / .97); }
  }
  @media (prefers-reduced-transparency: reduce) {
    .demo__card { background: var(--paper); -webkit-backdrop-filter: none; backdrop-filter: none; }
  }

  .demo__cardhead {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: var(--sp-3); margin-block-end: var(--sp-2);
    font-size: 8.5px; letter-spacing: .12em; text-transform: uppercase;
    font-weight: var(--fw-semibold); color: var(--ink-400);
  }
  .demo__cardhead b {
    font-family: var(--font-mono); font-size: 10px; letter-spacing: 0;
    text-transform: none; color: var(--data-gain-text);
  }

  /* --- candlesticks --- */
  .demo__candles { display: block; inline-size: 152px; block-size: 60px; }
  .demo__candles .wick { stroke-width: 1; stroke-linecap: round; }
  .demo__candles [data-d="up"]   { fill: var(--data-gain); stroke: var(--data-gain); }
  .demo__candles [data-d="down"] { fill: var(--data-loss); stroke: var(--data-loss); }
  .demo__candles .body { transform-origin: center; }

  /* --- metric card --- */
  .demo__cardmetric {
    font-family: var(--font-mono); font-variant-numeric: tabular-nums;
    font-size: 1.5rem; font-weight: var(--fw-semibold);
    letter-spacing: -0.02em; line-height: 1;
    color: var(--data-gain-text);
  }
  .demo__cardsub {
    margin-block-start: 5px;
    font-size: 9.5px; color: var(--ink-400);
    display: flex; align-items: center; gap: 5px;
  }
  .demo__cardsub b {
    font-family: var(--font-mono); font-weight: var(--fw-semibold);
    color: var(--data-loss-text);
  }

  /* --- transfer pills: emitted by the top three rows, dissolve into the
         curve. This is the causal beat — ranking produced that line. --- */
  .demo__pill {
    position: absolute;
    z-index: 4;
    padding: 3px 7px;
    border-radius: var(--r-full);
    background: var(--signal-600);
    color: #fff;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 9.5px;
    font-weight: var(--fw-semibold);
    box-shadow: 0 2px 10px rgb(11 122 62 / .38);
    pointer-events: none;
    opacity: 0;
    will-change: transform, opacity;
  }
}



/* ==========================================================================
   ENTRANCE FROM-STATES
   Same discipline as hero.css: only [data-demo="pending"] hides anything,
   and every property here has exactly one owner — this stylesheet until
   js/hero-demo.js takes over via gsap.set(), then GSAP alone.
   ========================================================================== */

:root[data-demo="pending"] .demo__rank-row,
:root[data-demo="pending"] .demo__stat,
:root[data-demo="pending"] .demo__dt,
:root[data-demo="pending"] .demo__cut,
:root[data-demo="pending"] .demo__float,
:root[data-demo="pending"] .demo__reflection,
:root[data-demo="pending"] .demo__plot .area,
:root[data-demo="pending"] .demo__plot .ddmark { opacity: 0; }

:root[data-demo="pending"] .demo__browser {
  opacity: 0;
  transform: translateY(56px) scale(.965);
}

/* Scores read as em dashes until the row is actually scored — the number
   arriving IS the information. */
:root[data-demo="pending"] .demo__sc { color: var(--ink-300); }

:root[data-demo="pending"] .demo__candles .body { transform: scaleY(0); }
:root[data-demo="pending"] .demo__candles .wick { opacity: 0; }

/* Bars: --v is authored inline per row, so they are filled by default and
   only zeroed by JS. No CSS override needed. */


/* ==========================================================================
   RESPONSIVE
   Same breakpoints as hero.css, trimmed to only what this section has:
   no copy column, no badge/title/pillars/actions here.
   ========================================================================== */
@layer components {

  /* ---------- ≥ 640 ------------------------------------------------------ */
  @media (min-width: 640px) {
    .demo__rankhead, .demo__rank-row { grid-template-columns: 24px 1fr 60px 52px; }
    .demo__rank { --row-h: 32px; }
  }

  /* ---------- ≥ 768 · floats appear --------------------------------------- */
  @media (min-width: 768px) {
    .demo__browser { border-radius: var(--r-xl); }
    .demo__chrome { block-size: 44px; }
    .demo__appbar { block-size: 42px; }
    .demo__rank, .demo__chart { padding: var(--sp-5) var(--sp-6) var(--sp-6); }
    .demo__rank { --row-h: 34px; --head-h: 28px; }
    .demo__rank-row { font-size: 13px; }
    .demo__sc { font-size: 12.5px; }
    .demo__candles { inline-size: 168px; block-size: 66px; }

    .demo__floats { display: block; }

    /* Three floats, DOCKED to the panel rather than scattered around it.
       data-depth drives the parallax multiplier in hero-demo.js — closer
       objects travel further, which is what makes them read as a z-stack. */
    .demo__float--candles { inset-block-start: -4%;  inset-inline-start: 0; }
    .demo__float--metric  { inset-block-start: 58%;  inset-inline-end: 0; }
    .demo__float--chip    { inset-block-start: -5%;  inset-inline-end: 6%; }
  }

  /* ---------- ≥ 900 · the split -------------------------------------------
     Ranking beside curve rather than above it. 62/38 — the ranking is the
     subject, the curve is the consequence. */
  @media (min-width: 900px) {
    .demo__panels { grid-template-columns: 62fr 38fr; }
    .demo__rank {
      border-block-end: 0;
      border-inline-end: 1px solid var(--ink-200);
    }
    .demo__chart { display: flex; flex-direction: column; }
    .demo__stats { margin-block-start: auto; }
  }

  @media (min-width: 1024px) {
    /* Overhang is capped at -3%, which is ~37px against the 1240px stage.
       The narrowest viewport that reaches this breakpoint still leaves a
       48px gutter, so the cards overlap the panel edge without ever
       reaching the viewport edge. */
    .demo__float--candles { inset-block-start: -7%;  inset-inline-start: -3%; }
    .demo__float--metric  { inset-block-start: 54%;  inset-inline-end: -3%; }
    .demo__float--chip    { inset-block-start: -8%;  inset-inline-end: 9%; }

    .demo__reflection { block-size: 92px; inset-inline: 10%; }
  }

  @media (min-width: 1280px) {
    .demo__rank { --row-h: 36px; }
  }

  /* ---------- COARSE POINTER ----------------------------------------------
     No tilt, no parallax — none of them have an input device. The entrance
     timeline still runs. */
  @media (pointer: coarse) {
    /* Nothing demo-specific needs hiding here — the stage has no spotlight
       of its own; it shares the hero's ambient layer only conceptually. */
  }

  /* ---------- REDUCED MOTION -----------------------------------------------
     T1: the end state IS the design. These rules finish the job: bars
     filled, candles up, chips placed, no idle loops. */
  @media (prefers-reduced-motion: reduce) {
    .demo__float { opacity: 1 !important; transform: none !important; }
    .demo__cut { opacity: 1; }
    .demo__plot .area { opacity: 1; }
    .demo__plot .ddmark { opacity: 1; }
    .demo__candles .body { transform: scaleY(1) !important; }
    .demo__candles .wick { opacity: 1 !important; }
    .demo__browser { opacity: 1 !important; transform: none !important; }
    .demo__bar i { transition: none; }
  }
}


/* ==========================================================================
   FAILSAFE / STATIC / DONE
   No rules needed — same reasoning as hero.css. `pending` is the only state
   that hides anything, so every other state is already the finished
   composition.
   ========================================================================== */
