/* ============================================================================
   RSAMAXXED — design system
   ----------------------------------------------------------------------------
   Principles, in priority order:
     1. The page is a product surface. The hero runs the actual arbitrage.
     2. Motion is compositor-only (transform/opacity) and scroll-driven where
        the browser supports it. No scroll event listeners.
     3. backdrop-filter is expensive (15-30% FPS on mid-tier Android). It is
        used on the nav and nowhere else. Cards fake glass with layered
        gradients, which costs nothing.
     4. Everything is same-origin. No CDN, no webfont, no chart library.
   ========================================================================= */

@layer tokens, base, motion, layout, components, marketing, explain, pricing, app;

/* ------------------------------------------------------------------ tokens */
@layer tokens {
  :root{
    /* Near-black with a cool cast, carried over from the desktop terminal. */
    --bg:        #05060a;
    --bg-1:      #080a10;
    --bg-2:      #0c0e15;
    --surface:   #0f1219;
    --surface-2: #151925;
    --elevated:  #1b2030;

    --line:      #1c2130;
    --line-2:    #2a3145;
    --line-glow: rgba(124,120,255,.28);

    --text:      #f4f5f9;
    --text-2:    #949aab;
    --text-3:    #5b6172;

    --accent:    #7c78ff;
    --accent-2:  #a78bfa;
    --accent-3:  #22d3ee;   /* cyan, used only in the simulation */
    --accent-hi: #9d9aff;

    --green:     #34d39e;
    --red:       #fb6f84;
    --amber:     #f2c14e;

    /* Chart fills. NOT the text tokens above: those are tuned to be read as
       type on the surface, and are too light to sit as large fills on it.
       These are the same hues stepped down until all six palette checks pass
       against the card surface (#0c0e15) in dark mode — lightness band, chroma
       floor, CVD separation, normal-vision floor and contrast. Re-run the
       validator if you change one. */
    --c-series:  #7c78ff;   /* the single series: profit */
    --c-good:    #1f9e77;   /* rounded up */
    --c-warn:    #b8892b;   /* fractional / cash in lieu */
    --c-null:    #3a4152;   /* nothing happened, or nothing to sell */

    --glow:      0 0 0 1px rgba(124,120,255,.16), 0 8px 40px -12px rgba(124,120,255,.42);
    --lift:      0 1px 0 0 rgba(255,255,255,.04) inset, 0 20px 50px -24px rgba(0,0,0,.9);

    --r-sm: 8px;  --r: 14px;  --r-lg: 20px;  --r-xl: 28px;

    --ease: cubic-bezier(.22,1,.36,1);        /* out-expo-ish */
    --ease-io: cubic-bezier(.65,0,.35,1);

    --maxw: 1140px;
    --nav-h: 62px;

    --sans: "Segoe UI Variable Display","Segoe UI",Inter,system-ui,-apple-system,
            "Helvetica Neue",sans-serif;
    --mono: "Cascadia Code",ui-monospace,SFMono-Regular,"SF Mono",Menlo,monospace;
  }
}

/* -------------------------------------------------------------------- base */
@layer base {
  *,*::before,*::after{box-sizing:border-box}
  /* overflow-x:clip on the root kills any sideways overflow (so a phone can't be
     pinched/panned out to reveal a wider layout) WITHOUT creating a scroll
     container — which `hidden` would, breaking the sticky nav. */
  html{scroll-behavior:smooth;overflow-x:clip;max-width:100%}
  body{
    margin:0; background:var(--bg); color:var(--text);
    font:400 15.5px/1.6 var(--sans);
    -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
    display:flex; flex-direction:column; min-height:100svh;
    overflow-x:clip; max-width:100%; width:100%;
  }
  a{color:inherit;text-decoration:none}
  button{font:inherit}
  h1,h2,h3,h4{margin:0;font-weight:600;letter-spacing:-.032em;line-height:1.06}
  p{margin:0}
  ::selection{background:rgba(124,120,255,.32)}

  /* Tabular figures everywhere a number can change, so digits don't jitter. */
  .num,.mono,table td.num,.stat-v,.tick{
    font-family:var(--mono); font-variant-numeric:tabular-nums;
    font-feature-settings:"tnum" 1,"zero" 1;
  }
  .muted{color:var(--text-3)} .dim{color:var(--text-2)}
  .pos{color:var(--green)} .neg{color:var(--red)}

  :focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:4px}

  .sr-only{
    position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
    clip-path:inset(50%);white-space:nowrap;border:0;
  }
}

/* ------------------------------------------------------------------ motion */
@layer motion {
  /* Reveal-on-scroll. Native scroll-driven timeline where supported; the
     JS fallback adds .in-view. Both animate only transform + opacity. */
  .reveal{opacity:0;transform:translateY(22px)}
  .reveal.in-view{opacity:1;transform:none;transition:opacity .7s var(--ease),transform .7s var(--ease)}

  @supports (animation-timeline: view()){
    .reveal{
      opacity:1;transform:none;
      animation:reveal-in linear both;
      animation-timeline:view();
      animation-range:entry 8% cover 26%;
    }
    .reveal.in-view{transition:none}
  }
  @keyframes reveal-in{
    from{opacity:0;transform:translateY(26px)}
    to  {opacity:1;transform:none}
  }

  .stagger > *{animation-delay:calc(var(--i,0) * 70ms)}

  @keyframes float-slow{
    0%,100%{transform:translate3d(0,0,0)}
    50%    {transform:translate3d(0,-14px,0)}
  }
  @keyframes drift{
    0%  {transform:translate3d(-4%,-2%,0) scale(1)}
    50% {transform:translate3d(4%,3%,0) scale(1.08)}
    100%{transform:translate3d(-4%,-2%,0) scale(1)}
  }
  @keyframes pulse-ring{
    0%  {opacity:.7;transform:scale(.82)}
    70% {opacity:0;transform:scale(1.5)}
    100%{opacity:0;transform:scale(1.5)}
  }
  @keyframes sweep{ to{background-position:200% 0} }

  /* Anyone who asks for less motion gets a static, fully legible page. */
  @media (prefers-reduced-motion: reduce){
    html{scroll-behavior:auto}
    *,*::before,*::after{
      animation-duration:.001ms !important; animation-iteration-count:1 !important;
      transition-duration:.001ms !important; scroll-behavior:auto !important;
    }
    .reveal{opacity:1 !important;transform:none !important}
  }
}

/* ------------------------------------------------------------------ layout */
@layer layout {
  .wrap{width:100%;max-width:var(--maxw);margin-inline:auto;padding-inline:clamp(16px,4vw,28px)}
  main{flex:1}

  /* Blueprint grid + aurora. Fixed, behind everything, pointer-transparent.
     The grid signals engineering seriousness; the mask keeps it from becoming
     wallpaper. */
  .backdrop{position:fixed;inset:0;z-index:-1;pointer-events:none;overflow:hidden}
  .backdrop .grid{
    position:absolute;inset:-2px;
    background-image:
      linear-gradient(to right, rgba(255,255,255,.038) 1px, transparent 1px),
      linear-gradient(to bottom, rgba(255,255,255,.038) 1px, transparent 1px);
    background-size:64px 64px;
    mask-image:radial-gradient(120% 78% at 50% 0%, #000 12%, transparent 72%);
  }
  /* Two nested elements so the slow drift and the pointer parallax can each
     own a transform without fighting over the same property. */
  .backdrop .aurora-wrap{
    position:absolute;inset:0;
    transform:translate3d(var(--px,0px), var(--py,0px), 0);
    transition:transform .5s cubic-bezier(.16,1,.3,1);
    will-change:transform;
  }
  .backdrop .aurora{
    position:absolute;top:-30vh;left:50%;width:130vw;height:110vh;
    margin-left:-65vw;
    background:
      radial-gradient(38% 44% at 26% 32%, rgba(124,120,255,.30), transparent 62%),
      radial-gradient(34% 40% at 74% 24%, rgba(34,211,238,.16),  transparent 60%),
      radial-gradient(46% 38% at 52% 62%, rgba(167,139,250,.16), transparent 66%);
    filter:blur(28px);
    animation:drift 26s var(--ease-io) infinite;
  }

  /* The blueprint grid, brightened only where the cursor is. Same 64px cell and
     same origin as .grid, so the lit lines register exactly with the dim ones.
     Masked rather than translated: a transform would create a containing block
     and knock the pattern out of alignment. */
  .backdrop .grid-spot{
    position:absolute;inset:-2px;opacity:0;
    background-image:
      linear-gradient(to right, rgba(124,120,255,.32) 1px, transparent 1px),
      linear-gradient(to bottom, rgba(124,120,255,.32) 1px, transparent 1px);
    background-size:64px 64px;
    -webkit-mask-image:radial-gradient(220px circle at var(--mx,50%) var(--my,50%), #000 0%, transparent 72%);
            mask-image:radial-gradient(220px circle at var(--mx,50%) var(--my,50%), #000 0%, transparent 72%);
    transition:opacity .45s var(--ease);
  }
  body.pointer-fine .backdrop .grid-spot{opacity:1}

  .backdrop .vig{
    position:absolute;inset:0;
    background:radial-gradient(100% 70% at 50% 0%, transparent 40%, var(--bg) 92%);
  }

  /* Cursor spotlight — pointer coords are written to --mx/--my by site.js,
     rAF-throttled. Fine pointers only; it's meaningless on touch. */
  @media (pointer:fine){
    .spotlight{
      position:fixed;inset:0;z-index:-1;pointer-events:none;
      background:radial-gradient(420px circle at var(--mx,50%) var(--my,0%),
                 rgba(124,120,255,.09), transparent 62%);
      transition:opacity .4s var(--ease);
    }
  }
  .spotlight{display:none}
  @media (pointer:fine){ .spotlight{display:block} }
}

/* -------------------------------------------------------------- components */
@layer components {
  /* ---- nav: the one place backdrop-filter earns its cost ---- */
  .nav{
    position:sticky;top:0;z-index:60;height:var(--nav-h);
    display:flex;align-items:center;
    border-bottom:1px solid transparent;
    transition:border-color .3s var(--ease),background .3s var(--ease);
  }
  .nav.stuck{
    background:color-mix(in oklab, var(--bg) 72%, transparent);
    backdrop-filter:blur(14px) saturate(1.4);
    -webkit-backdrop-filter:blur(14px) saturate(1.4);
    border-bottom-color:var(--line);
  }
  .nav .wrap{display:flex;align-items:center;justify-content:space-between;gap:18px}

  .brand{display:flex;align-items:center;gap:10px;font-size:16.5px;letter-spacing:-.02em;font-weight:600}
  .brand b{
    background:linear-gradient(96deg,var(--accent) 8%,var(--accent-2) 92%);
    -webkit-background-clip:text;background-clip:text;color:transparent;
  }
  .brand .mark{
    width:24px;height:24px;border-radius:7px;flex:none;position:relative;
    background:linear-gradient(150deg,var(--accent),#4d49d6);
    box-shadow:0 0 18px -2px rgba(124,120,255,.7);
  }
  .brand .mark::after{
    content:"";position:absolute;inset:0;border-radius:inherit;
    border:1px solid rgba(255,255,255,.18);
  }

  .navlinks{display:flex;align-items:center;gap:2px}
  .navlinks a,.linkish{
    padding:8px 13px;border-radius:9px;color:var(--text-2);font-size:14px;
    background:none;border:0;cursor:pointer;white-space:nowrap;
    transition:color .18s var(--ease),background .18s var(--ease);
  }
  .navlinks a:hover,.linkish:hover{color:var(--text);background:rgba(255,255,255,.045)}
  .navlinks a.on{color:var(--text);background:rgba(124,120,255,.13)}
  .inline{display:inline}

  /* On phones the bar tightens and sheds its optional links (opt-md, then opt-sm)
     so it stays a single row inside the fixed nav height instead of wrapping and
     getting clipped. white-space:nowrap (above) stops the labels wrapping. */
  @media(max-width:640px){
    .navlinks{gap:1px}
    .navlinks a,.linkish{padding:7px 9px;font-size:13px}
    .navlinks .opt-md{display:none}
    .brand{font-size:15px;gap:8px}
    .brand .mark{width:21px;height:21px}
    .btn.btn-sm{padding:8px 12px}
  }
  @media(max-width:430px){ .navlinks .opt-sm{display:none} }

  /* ---- buttons ---- */
  .btn{
    --bg-btn:var(--accent);
    position:relative;display:inline-flex;align-items:center;justify-content:center;gap:9px;
    padding:12px 20px;border-radius:11px;border:1px solid transparent;
    background:var(--bg-btn);color:#fff;font-weight:550;font-size:14.5px;letter-spacing:-.005em;
    cursor:pointer;overflow:hidden;isolation:isolate;
    box-shadow:0 1px 0 rgba(255,255,255,.16) inset, 0 10px 30px -12px rgba(124,120,255,.8);
    transition:transform .14s var(--ease),box-shadow .22s var(--ease),background .18s var(--ease);
  }
  .btn:hover{background:var(--accent-hi);transform:translateY(-1px);
             box-shadow:0 1px 0 rgba(255,255,255,.2) inset, 0 16px 40px -14px rgba(124,120,255,.95)}
  .btn:active{transform:translateY(0)}
  /* Specular sweep on hover — pure transform, no repaint of the button. */
  .btn::after{
    content:"";position:absolute;inset:0;z-index:-1;
    background:linear-gradient(105deg,transparent 38%,rgba(255,255,255,.22) 50%,transparent 62%);
    background-size:200% 100%;background-position:-100% 0;
  }
  .btn:hover::after{animation:sweep .8s var(--ease) 1}

  .btn-ghost{
    background:rgba(255,255,255,.03);color:var(--text);
    border-color:var(--line-2);box-shadow:none;
  }
  .btn-ghost:hover{background:rgba(255,255,255,.07);box-shadow:none}
  .btn-sm{padding:8px 14px;font-size:13.5px;border-radius:9px}
  .btn-danger{background:transparent;border-color:var(--line-2);color:var(--red);box-shadow:none}
  .btn-danger:hover{background:rgba(251,111,132,.1);box-shadow:none}
  .btn-block{width:100%}

  /* ---- cards: gradient-faked glass, zero blur cost ---- */
  .card{
    position:relative;border-radius:var(--r-lg);padding:22px;
    background:
      linear-gradient(180deg, rgba(255,255,255,.045), rgba(255,255,255,.012) 42%, transparent),
      var(--surface);
    border:1px solid var(--line);
    box-shadow:var(--lift);
  }
  /* Hairline highlight along the top edge — the tell of a good dark UI. */
  .card::before{
    content:"";position:absolute;inset:0 0 auto;height:1px;border-radius:inherit;
    background:linear-gradient(90deg,transparent,rgba(255,255,255,.16) 32%,rgba(124,120,255,.4) 50%,rgba(255,255,255,.16) 68%,transparent);
    opacity:.55;
  }
  .card + .card{margin-top:14px}

  /* Cards that light up toward the cursor. --cx/--cy set per-card in JS. */
  .card.interactive::after{
    content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
    background:radial-gradient(240px circle at var(--cx,50%) var(--cy,50%), rgba(124,120,255,.10), transparent 60%);
    opacity:0;transition:opacity .3s var(--ease);
  }
  .card.interactive:hover::after{opacity:1}

  .card-h{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:16px}
  .card-h h3{
    font-size:11.5px;letter-spacing:.14em;text-transform:uppercase;
    color:var(--text-2);font-weight:600;
  }

  .eyebrow{
    display:inline-flex;align-items:center;gap:9px;
    padding:6px 8px 6px 6px;border-radius:99px;
    background:rgba(255,255,255,.035);border:1px solid var(--line-2);
    font-size:12.5px;color:var(--text-2);
  }
  .eyebrow .pip{
    width:6px;height:6px;border-radius:50%;background:var(--green);position:relative;
    box-shadow:0 0 8px var(--green);
  }
  .eyebrow .pip::after{
    content:"";position:absolute;inset:-3px;border-radius:50%;border:1px solid var(--green);
    animation:pulse-ring 2.4s var(--ease-io) infinite;
  }
  .eyebrow b{color:var(--text);font-weight:550}

  .tag{
    display:inline-block;padding:2px 8px;border-radius:99px;font-size:11px;
    background:var(--elevated);color:var(--text-2);letter-spacing:.03em;
  }
  .tag.buy{color:var(--green);background:rgba(52,211,158,.12)}
  .tag.sell{color:var(--red);background:rgba(251,111,132,.12)}

  .notice{padding:12px 15px;border-radius:12px;font-size:13.5px;margin-bottom:14px}
  .notice.err {background:rgba(251,111,132,.09);color:var(--red);border:1px solid rgba(251,111,132,.22)}
  .notice.ok  {background:rgba(52,211,158,.08); color:var(--green);border:1px solid rgba(52,211,158,.2)}
  .notice.warn{background:rgba(242,193,78,.07); color:var(--amber);border:1px solid rgba(242,193,78,.2)}

  /* ---- forms ---- */
  label{display:block;font-size:12.5px;color:var(--text-2);margin:16px 0 7px}
  input[type=text],input[type=email],input[type=password]{
    width:100%;padding:13px 14px;border-radius:12px;color:var(--text);font:inherit;
    background:rgba(255,255,255,.025);border:1px solid var(--line);
    transition:border-color .18s var(--ease),box-shadow .18s var(--ease),background .18s var(--ease);
  }
  input::placeholder{color:var(--text-3)}
  input:focus{
    outline:none;border-color:var(--accent);background:rgba(124,120,255,.05);
    box-shadow:0 0 0 4px rgba(124,120,255,.12);
  }

  /* ---- tables ---- */
  .table{width:100%;border-collapse:collapse;font-size:14px}
  .table th{
    text-align:left;font-size:10.5px;letter-spacing:.13em;text-transform:uppercase;
    color:var(--text-3);font-weight:600;padding:0 10px 11px;border-bottom:1px solid var(--line);
  }
  .table td{padding:12px 10px;border-bottom:1px solid var(--line)}
  .table tbody tr{transition:background .15s var(--ease)}
  .table tbody tr:hover{background:rgba(255,255,255,.022)}
  .table tr:last-child td{border-bottom:0}
  .table td.num,.table th.num{text-align:right;font-size:13px}
  .scroll-x{overflow-x:auto;-webkit-overflow-scrolling:touch}

  .foot{
    border-top:1px solid var(--line);margin-top:80px;padding:26px 0;
    color:var(--text-3);font-size:12.5px;
  }
  .foot .wrap{display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap}
}

/* --------------------------------------------------------------- marketing */
@layer marketing {
  .hero{padding:clamp(56px,9vw,104px) 0 40px;text-align:center}
  .hero h1{
    font-size:clamp(38px,6.6vw,72px);
    max-width:15ch;margin:22px auto 20px;
  }
  .hero h1 .grad{
    background:linear-gradient(102deg,var(--accent) 4%,var(--accent-2) 48%,var(--accent-3) 96%);
    -webkit-background-clip:text;background-clip:text;color:transparent;
  }
  .hero .lede{color:var(--text-2);font-size:clamp(15.5px,1.9vw,19px);max-width:56ch;margin:0 auto 32px}
  .cta{display:flex;gap:12px;justify-content:center;flex-wrap:wrap}

  /* ---- the round-up engine: the hero IS the product ---- */
  .engine{
    margin-top:clamp(40px,6vw,72px);
    border-radius:var(--r-xl);
    background:linear-gradient(180deg, rgba(255,255,255,.05), transparent 30%), var(--bg-1);
    border:1px solid var(--line);
    box-shadow:0 40px 120px -50px rgba(124,120,255,.55), var(--lift);
    overflow:hidden;
  }
  .engine-bar{
    display:flex;align-items:center;gap:10px;padding:12px 16px;
    border-bottom:1px solid var(--line);background:rgba(255,255,255,.015);
  }
  .engine-bar .dots{display:flex;gap:6px}
  .engine-bar .dots i{width:10px;height:10px;border-radius:50%;background:var(--line-2)}
  .engine-bar .title{
    font-family:var(--mono);font-size:11.5px;color:var(--text-3);letter-spacing:.08em;
    text-transform:uppercase;margin-inline:auto;
  }
  .engine-body{display:grid;grid-template-columns:1fr 300px}
  @media(max-width:880px){ .engine-body{grid-template-columns:1fr} }

  #roundup{display:block;width:100%;height:360px}
  @media(max-width:880px){ #roundup{height:290px} }

  .engine-side{
    border-left:1px solid var(--line);padding:20px;display:flex;flex-direction:column;gap:18px;
    background:rgba(0,0,0,.18);
  }
  @media(max-width:880px){ .engine-side{border-left:0;border-top:1px solid var(--line)} }

  .ctrl label{margin:0 0 9px;display:flex;justify-content:space-between;align-items:baseline}
  .ctrl label b{color:var(--text);font-family:var(--mono);font-weight:500;font-size:14px}

  input[type=range]{
    -webkit-appearance:none;appearance:none;width:100%;height:4px;border-radius:99px;
    background:linear-gradient(90deg,var(--accent) var(--pct,50%), var(--line-2) var(--pct,50%));
    cursor:pointer;
  }
  input[type=range]::-webkit-slider-thumb{
    -webkit-appearance:none;width:16px;height:16px;border-radius:50%;background:#fff;
    box-shadow:0 0 0 4px rgba(124,120,255,.28);transition:box-shadow .18s var(--ease);
  }
  input[type=range]:hover::-webkit-slider-thumb{box-shadow:0 0 0 7px rgba(124,120,255,.28)}
  input[type=range]::-moz-range-thumb{
    width:16px;height:16px;border:0;border-radius:50%;background:#fff;
    box-shadow:0 0 0 4px rgba(124,120,255,.28);
  }

  .readout{margin-top:auto;padding-top:18px;border-top:1px solid var(--line)}
  .readout .k{font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--text-3)}
  .readout .v{
    font-size:clamp(28px,3.1vw,36px);font-weight:650;letter-spacing:-.035em;margin-top:6px;
    transform-origin:left center;
  }
  .readout .sub{color:var(--text-3);font-size:12.5px;margin-top:6px;line-height:1.5}
  .readout .post{
    display:flex;justify-content:space-between;align-items:baseline;gap:10px;
    margin-top:12px;padding-top:10px;border-top:1px dashed var(--line);
    font-size:12px;color:var(--text-3);
  }
  .readout .post b{color:var(--text-2);font-family:var(--mono);font-weight:500}

  /* Fires the instant the shares round up. The money never leaves the screen —
     it just gets louder. */
  .readout .v.pop{animation:money-pop .62s var(--ease)}
  @keyframes money-pop{
    0%  {transform:scale(1);   text-shadow:none}
    28% {transform:scale(1.09);text-shadow:0 0 26px rgba(52,211,158,.75)}
    100%{transform:scale(1);   text-shadow:none}
  }

  /* The caption names the beat you are watching. Each beat is held for seconds,
     not milliseconds, and the text cross-fades in rather than snapping — four
     hard cuts in four seconds read as a flicker, not as a sentence. */
  .engine-note{
    padding:11px 16px;border-top:1px solid var(--line);
    font-size:12px;color:var(--text-3);text-align:center;background:rgba(0,0,0,.25);
    min-height:40px;display:flex;align-items:center;justify-content:center;
  }
  .engine-note.swap{animation:note-swap .55s var(--ease) both}
  @keyframes note-swap{
    from{opacity:0;transform:translateY(5px)}
    to  {opacity:1;transform:none}
  }

  /* ---- section furniture ---- */
  .sect{margin-top:clamp(88px,12vw,150px)}
  .sect-h{text-align:center;max-width:60ch;margin-inline:auto}
  .sect-h .kicker{
    font-family:var(--mono);font-size:11.5px;letter-spacing:.18em;text-transform:uppercase;
    color:var(--accent);margin-bottom:14px;
  }
  .sect-h h2{font-size:clamp(27px,4.1vw,44px)}
  .sect-h p{color:var(--text-2);margin-top:16px;font-size:16.5px}

  .feat{display:grid;grid-template-columns:repeat(auto-fit,minmax(258px,1fr));gap:16px;margin-top:44px}
  .feat h3{font-size:17px;letter-spacing:-.014em;margin-bottom:9px}
  .feat p{color:var(--text-2);font-size:14.2px}
  .feat .ico{
    width:38px;height:38px;border-radius:11px;display:grid;place-items:center;margin-bottom:16px;
    background:linear-gradient(160deg,rgba(124,120,255,.22),rgba(124,120,255,.06));
    border:1px solid rgba(124,120,255,.26);
  }
  .feat .ico svg{width:18px;height:18px;stroke:var(--accent);fill:none;stroke-width:1.8;
                 stroke-linecap:round;stroke-linejoin:round}

  /* ---- mirror fan-out ------------------------------------------------------
     Two layouts, one animation. Wide: ten chips in a row, ten wires dropping
     onto their top edges. Narrow (<=860px, matching STACKED in site.js): the
     chips become a list and the wires braid down a left-hand gutter, each
     peeling off into its own row. The SVG overlays the stage in both cases —
     it used to be display:none on phones, which quietly deleted the entire
     point of the section. */
  .mirror{margin-top:44px;padding:0;overflow:hidden}
  .mirror-stage{position:relative;padding:30px 22px 22px}
  .mirror-fire{display:flex;justify-content:center}

  .fan-wrap{position:relative;padding-top:150px}
  .fanout{
    position:absolute;inset:0;width:100%;height:100%;z-index:0;
    pointer-events:none;overflow:visible;
  }
  /* Stacked, the wires sweep across the column on their way to the gutter.
     The chips have to sit on top of them, or the text is unreadable. */
  .brokers{position:relative;z-index:1}
  .fanout .wire{
    stroke:var(--line-2);stroke-width:1.5;fill:none;stroke-linejoin:round;
    stroke-dasharray:var(--len,300);stroke-dashoffset:var(--len,300);
  }
  .fanout .wire.live{
    stroke:url(#wireGrad);
    animation:wire-fill .55s var(--ease) forwards;
    animation-delay:var(--d,0ms);
  }
  @keyframes wire-fill{to{stroke-dashoffset:0}}

  /* the packet that rides down each wire */
  .fanout .packet{fill:#fff;filter:drop-shadow(0 0 6px rgba(124,120,255,.95))}

  .fan-total{
    display:flex;align-items:baseline;justify-content:center;gap:12px;margin:22px 0 4px;
  }
  .fan-total .k{font-size:10.5px;letter-spacing:.15em;text-transform:uppercase;color:var(--text-3)}
  /* Reserve the width of the final figure, or the label shuffles sideways on
     every tick of the odometer. */
  .fan-total .v{
    font-size:clamp(24px,3vw,32px);font-weight:650;letter-spacing:-.03em;
    min-width:8.5ch;text-align:left;
  }

  /* The button label has to survive a 320px screen. */
  #fire .sm{display:none}
  #fire.firing .lg,#fire.firing .sm{visibility:hidden}
  #fire.firing::before{content:"Executing…";position:absolute;inset:0;display:grid;place-items:center}
  #fire.again .lg::after{content:" — again"}

  .brokers{display:grid;grid-template-columns:repeat(10,1fr);gap:8px}

  .bnode{
    position:relative;padding:11px 5px;border-radius:11px;text-align:center;
    background:rgba(255,255,255,.028);border:1px solid var(--line);
    font-size:11.4px;line-height:1.25;color:var(--text-2);
    transition:border-color .3s var(--ease),color .3s var(--ease),background .3s var(--ease),transform .3s var(--ease);
  }
  .bnode .st{display:block;font-family:var(--mono);font-size:9.6px;color:var(--text-3);margin-top:4px}
  .bnode.filled{
    border-color:rgba(52,211,158,.42);color:var(--text);
    background:rgba(52,211,158,.07);transform:translateY(-2px);
  }
  .bnode.filled .st{color:var(--green)}

  /* impact ring on fill */
  .bnode.filled::before{
    content:"";position:absolute;inset:-1px;border-radius:inherit;
    border:1px solid var(--green);animation:pulse-ring .85s var(--ease) 1 forwards;
  }
  /* the money, flung upward out of the node */
  .bnode .money{
    position:absolute;left:50%;top:-4px;translate:-50% 0;
    font-family:var(--mono);font-size:12.5px;font-weight:600;color:var(--green);
    opacity:0;pointer-events:none;white-space:nowrap;
  }
  .bnode.filled .money{animation:money-fly 1.15s var(--ease) forwards}
  @keyframes money-fly{
    0%  {opacity:0;transform:translateY(4px)   scale(.86)}
    22% {opacity:1;transform:translateY(-9px)  scale(1.06)}
    72% {opacity:1;transform:translateY(-19px) scale(1)}
    100%{opacity:0;transform:translateY(-30px) scale(1)}
  }

  /* ---- fan-out, stacked (phones + small tablets) ---- */
  @media(max-width:860px){
    .mirror-stage{padding:24px 16px 18px}
    #fire{width:100%}
    #fire .lg{display:none}
    #fire .sm{display:inline}

    /* 44px gutter: the ten strands run down it at x = 8..34. The top padding
       is headroom for them to fan out before the first chip. */
    .fan-wrap{padding-top:82px;padding-left:44px}
    .brokers{grid-template-columns:1fr;gap:7px}

    .bnode{
      display:flex;align-items:center;justify-content:space-between;gap:10px;
      text-align:left;padding:13px 14px;font-size:13.5px;
    }
    .bnode .st{margin-top:0;font-size:10.5px}
    /* The wire lands on the left edge; lifting the chip would detach it. */
    .bnode.filled{transform:none}
    .bnode.filled::before{animation-name:pulse-row}

    /* Stacked, the figure must stay inside its own row. Flying it upward (the
       desktop behaviour) parks it over the broker above for a full second, and
       it reads as that broker's fill. So it slides in beside the status text
       instead — clear of it, and unambiguously on its own line. */
    .bnode .money{left:auto;right:76px;top:50%;translate:0 -50%;font-size:13px}
    .bnode.filled .money{animation-name:money-slide}
  }

  /* A row is wide and short: a scaling ring reads as a glitch, a fading edge
     reads as an arrival. */
  @keyframes pulse-row{
    0%  {opacity:.9}
    100%{opacity:0}
  }
  @keyframes money-slide{
    0%  {opacity:0;transform:translateX(10px) scale(.9)}
    24% {opacity:1;transform:translateX(0)    scale(1.05)}
    72% {opacity:1;transform:translateX(-2px) scale(1)}
    100%{opacity:0;transform:translateX(-9px) scale(1)}
  }

  /* ---- pairing steps ---- */
  .steps-lp{display:grid;grid-template-columns:repeat(auto-fit,minmax(232px,1fr));gap:16px;margin-top:44px}
  .steps-lp .n{
    font-family:var(--mono);font-size:11.5px;color:var(--accent);letter-spacing:.12em;margin-bottom:12px;
  }
  .steps-lp h3{font-size:16px;margin-bottom:8px}
  .steps-lp p{color:var(--text-2);font-size:14px}

  /* ---- proof strip ---- */
  .proof{
    display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:1px;
    margin-top:44px;border:1px solid var(--line);border-radius:var(--r-lg);
    overflow:hidden;background:var(--line);
  }
  .proof .cell{background:var(--bg-1);padding:24px 20px;text-align:center}
  .proof .v{font-size:30px;font-weight:650;letter-spacing:-.03em}
  .proof .k{font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--text-3);margin-top:8px}

  .broker-chips{display:flex;flex-wrap:wrap;gap:9px;justify-content:center;margin-top:36px}
  .broker-chips span{
    padding:9px 16px;border-radius:10px;font-size:13.5px;color:var(--text-2);
    background:rgba(255,255,255,.026);border:1px solid var(--line);
    transition:color .2s var(--ease),border-color .2s var(--ease),transform .2s var(--ease);
  }
  .broker-chips span:hover{color:var(--text);border-color:var(--line-2);transform:translateY(-2px)}

  .final{margin-top:clamp(88px,12vw,150px);text-align:center;padding:clamp(44px,6vw,72px) 24px;
         border-radius:var(--r-xl);position:relative;overflow:hidden;
         background:radial-gradient(90% 130% at 50% 0%, rgba(124,120,255,.16), transparent 62%), var(--surface);
         border:1px solid var(--line)}
  .final h2{font-size:clamp(25px,3.6vw,38px)}
  .final p{color:var(--text-2);margin:14px auto 26px;max-width:46ch}
}

/* ----------------------------------------------------------------- explain */
/* The teaching page. Every scene is a claim on the left and a diagram on the
   right that demonstrates it. Diagrams are inline SVG animated with CSS and
   armed by .lit (set by the scene observer in site.js), so a phone renders
   exactly the same thing a desktop does — just stacked. */
@layer explain {
  .ex-hero{padding:clamp(48px,7vw,86px) 0 8px;text-align:center}
  .ex-hero h1{font-size:clamp(32px,5.4vw,58px);max-width:19ch;margin:20px auto 18px}
  .ex-hero .lede{color:var(--text-2);font-size:clamp(15.5px,1.8vw,18.5px);max-width:60ch;margin:0 auto}

  .ex-jump{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;margin-top:30px}
  .ex-jump a{
    padding:8px 14px;border-radius:99px;font-size:13px;color:var(--text-2);
    background:rgba(255,255,255,.026);border:1px solid var(--line);
    transition:color .2s var(--ease),border-color .2s var(--ease);
  }
  .ex-jump a:hover{color:var(--text);border-color:var(--accent)}

  .scenes{list-style:none;padding:0;margin:clamp(56px,8vw,96px) 0 0;counter-reset:sc}
  .scene{
    display:grid;grid-template-columns:1fr 1fr;gap:clamp(28px,5vw,72px);align-items:center;
    padding:clamp(40px,5vw,64px) 0;border-top:1px solid var(--line);
  }
  .scene:first-child{border-top:0}
  /* Zig-zag: even scenes put the figure on the left. */
  .scene:nth-child(even) .scene-fig{order:-1}
  @media(max-width:900px){
    .scene{grid-template-columns:1fr;gap:26px}
    .scene:nth-child(even) .scene-fig{order:0}
  }

  .scene-n{
    font-family:var(--mono);font-size:11.5px;letter-spacing:.16em;text-transform:uppercase;
    color:var(--accent);margin-bottom:14px;
  }
  .scene-copy h2{font-size:clamp(23px,2.9vw,34px);margin-bottom:14px}
  .scene-copy p{color:var(--text-2);font-size:15.5px}
  .scene-copy p + p{margin-top:13px}
  .scene-copy .aside{
    margin-top:18px;padding:13px 15px;border-radius:12px;font-size:13.4px;color:var(--text-2);
    background:rgba(255,255,255,.022);border:1px solid var(--line);border-left:2px solid var(--accent);
  }
  .scene-copy .aside b{color:var(--text);font-weight:550}

  .scene-fig{
    position:relative;border-radius:var(--r-lg);padding:22px;min-height:280px;
    display:grid;place-items:center;
    background:radial-gradient(120% 100% at 50% 0%, rgba(124,120,255,.09), transparent 60%), var(--bg-1);
    border:1px solid var(--line);box-shadow:var(--lift);
  }
  .scene-fig svg{width:100%;height:auto;max-width:420px;overflow:visible}
  .fig-cap{
    position:absolute;left:0;right:0;bottom:12px;text-align:center;
    font-family:var(--mono);font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--text-3);
  }

  /* shared SVG vocabulary */
  .scene-fig .stroke{fill:none;stroke:var(--line-2);stroke-width:1.5}
  .scene-fig .dash{fill:none;stroke:var(--text-3);stroke-width:1;stroke-dasharray:4 4}
  .scene-fig text{font-family:var(--mono);font-size:11px;fill:var(--text-2)}
  .scene-fig text.big{font-size:15px;fill:var(--text);font-weight:600}
  .scene-fig .g{fill:var(--green)} .scene-fig .r{fill:var(--red)} .scene-fig .a{fill:var(--amber)}

  /* 01 — the price line that must climb back over $1.00 */
  .fig-price .line{
    fill:none;stroke:var(--accent);stroke-width:2;stroke-linecap:round;
    stroke-dasharray:var(--len,520);stroke-dashoffset:var(--len,520);
  }
  .lit .fig-price .line{animation:draw 1.6s var(--ease) .2s forwards}
  .fig-price .jump{opacity:0}
  .lit .fig-price .jump{animation:fade-up .7s var(--ease) 1.5s forwards}
  @keyframes draw{to{stroke-dashoffset:0}}
  @keyframes fade-up{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}

  /* 02 — twenty tiles (the "before"), beside the one tile they become */
  .fig-tiles .t{
    fill:var(--accent);opacity:.85;
    transform-box:fill-box;transform-origin:center;
  }
  /* Stagger the twenty tiles IN and LEAVE them: like every other scene, this
     figure animates in and persists. The old 'collapse' faded all twenty to
     opacity:0, so the resting state was an empty grid under the "20 shares"
     label — which read as a broken chart. */
  .lit .fig-tiles .t{animation:tile-in .5s var(--ease) both;animation-delay:calc(.25s + var(--i) * 30ms)}
  @keyframes tile-in{from{opacity:0;transform:scale(.4)}to{opacity:.85;transform:none}}
  .fig-tiles .one{opacity:0;transform-box:fill-box;transform-origin:center}
  .lit .fig-tiles .one{animation:pop-in .8s var(--ease) 1.9s both}
  @keyframes pop-in{0%{opacity:0;transform:scale(.4)}70%{opacity:1;transform:scale(1.06)}100%{opacity:1;transform:scale(1)}}
  .fig-tiles .after{opacity:0}
  .lit .fig-tiles .after{animation:fade-up .6s var(--ease) 2.3s forwards}

  /* 03 — the 1/20 wedge */
  .fig-wedge .ring{fill:none;stroke:var(--line-2);stroke-width:1.5;stroke-dasharray:3 4}
  .fig-wedge .slice{fill:var(--accent);opacity:0;transform-box:fill-box;transform-origin:50% 50%}
  .lit .fig-wedge .slice{animation:pop-in .7s var(--ease) .5s both}
  .fig-wedge .lbl{opacity:0}
  .lit .fig-wedge .lbl{animation:fade-up .6s var(--ease) 1s forwards}

  /* 04 — the three-way fork */
  .fig-fork .branch{
    fill:none;stroke-width:1.6;
    stroke-dasharray:var(--len,180);stroke-dashoffset:var(--len,180);
  }
  .lit .fig-fork .branch{animation:draw .9s var(--ease) both}
  .fig-fork .b1{stroke:var(--green)}  .lit .fig-fork .b1{animation-delay:.3s}
  .fig-fork .b2{stroke:var(--amber)}  .lit .fig-fork .b2{animation-delay:.5s}
  .fig-fork .b3{stroke:var(--red)}    .lit .fig-fork .b3{animation-delay:.7s}
  .fig-fork .out{opacity:0}
  .lit .fig-fork .out{animation:fade-up .6s var(--ease) both}
  .lit .fig-fork .o1{animation-delay:1.1s}
  .lit .fig-fork .o2{animation-delay:1.3s}
  .lit .fig-fork .o3{animation-delay:1.5s}

  /* 05 — the receipt */
  .fig-book .row{opacity:0}
  .lit .fig-book .row{animation:fade-up .55s var(--ease) both}
  .lit .fig-book .row:nth-child(1){animation-delay:.3s}
  .lit .fig-book .row:nth-child(2){animation-delay:.65s}
  .lit .fig-book .row:nth-child(3){animation-delay:1s}
  .lit .fig-book .row:nth-child(4){animation-delay:1.45s}
  .fig-book .rule{stroke:var(--line-2);stroke-width:1}

  /* 06 — the account multiplier (interactive) */
  .mult{width:100%;max-width:420px}
  .mult .ctrl label{margin:0 0 9px;display:flex;justify-content:space-between;align-items:baseline}
  .mult .ctrl label b{color:var(--text);font-family:var(--mono);font-weight:500;font-size:14px}
  .m-grid{
    display:flex;flex-wrap:wrap;gap:6px;justify-content:center;
    margin:22px 0;min-height:104px;align-content:center;
  }
  .m-grid i{
    width:20px;height:20px;border-radius:6px;flex:none;
    background:linear-gradient(150deg,#4ade9f,#22b98a);
    box-shadow:0 0 10px -2px rgba(52,211,158,.7);
    animation:pop-in .35s var(--ease) both;
  }
  .m-out{text-align:center;padding-top:16px;border-top:1px solid var(--line)}
  .m-out .k{font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--text-3)}
  .m-out .v{font-size:clamp(28px,3.4vw,38px);font-weight:650;letter-spacing:-.035em;margin-top:6px}

  /* the worked-example ledger */
  .ledger{margin-top:18px}
  .ledger td:first-child{color:var(--text-2)}
  .ledger tr.total td{font-weight:650;color:var(--text);border-top:1px solid var(--line-2)}

  /* risks: the section that earns the rest of the page */
  .risks{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:14px;margin-top:40px}
  .risk{
    padding:20px;border-radius:var(--r);background:var(--surface);
    border:1px solid var(--line);border-top:2px solid var(--red);
  }
  .risk h3{font-size:15.5px;margin-bottom:8px}
  .risk p{color:var(--text-2);font-size:14px}

  /* FAQ — shared by the explainer and the pricing page */
  .faq{max-width:74ch;margin:44px auto 0}
  .faq details{border-bottom:1px solid var(--line)}
  .faq summary{
    padding:18px 34px 18px 0;cursor:pointer;list-style:none;position:relative;
    font-weight:550;font-size:15.5px;
  }
  .faq summary::-webkit-details-marker{display:none}
  .faq summary::after{
    content:"";position:absolute;right:6px;top:50%;width:9px;height:9px;
    border-right:1.6px solid var(--text-3);border-bottom:1.6px solid var(--text-3);
    translate:0 -70%;rotate:45deg;transition:rotate .25s var(--ease),border-color .25s var(--ease);
  }
  .faq details[open] summary::after{rotate:225deg;border-color:var(--accent)}
  .faq summary:hover::after{border-color:var(--text)}
  .faq p{color:var(--text-2);font-size:14.6px;padding:0 0 20px;max-width:66ch}
  .faq p + p{padding-top:0;margin-top:-8px}
}

/* ----------------------------------------------------------------- pricing */
@layer pricing {
  .pr-hero{padding:clamp(48px,7vw,84px) 0 0;text-align:center}
  .pr-hero h1{font-size:clamp(32px,5.2vw,56px);max-width:16ch;margin:20px auto 18px}
  .pr-hero .lede{color:var(--text-2);font-size:clamp(15.5px,1.8vw,18.5px);max-width:56ch;margin:0 auto}

  /* billing switch */
  .bill{display:flex;align-items:center;justify-content:center;gap:14px;margin-top:34px;font-size:14px}
  .bill .opt{color:var(--text-3);transition:color .2s var(--ease)}
  body:not(.annual) .bill .opt.m,
  body.annual      .bill .opt.y{color:var(--text)}
  .bill .sw{display:inline-flex;align-items:center;position:relative}
  .bill input{position:absolute;opacity:0;width:0;height:0}
  .bill .track{
    width:50px;height:28px;border-radius:99px;background:var(--surface-2);
    border:1px solid var(--line-2);position:relative;cursor:pointer;flex:none;
    transition:background .22s var(--ease),border-color .22s var(--ease);
  }
  .bill .track::after{
    content:"";position:absolute;top:3px;left:3px;width:20px;height:20px;border-radius:50%;
    background:var(--text-2);transition:translate .24s var(--ease),background .24s var(--ease);
  }
  body.annual .bill .track{background:rgba(124,120,255,.22);border-color:var(--accent)}
  body.annual .bill .track::after{translate:22px 0;background:#fff}
  .bill input:focus-visible + .track{outline:2px solid var(--accent);outline-offset:2px}
  .bill .save{
    padding:4px 9px;border-radius:99px;font-size:11.5px;font-weight:550;
    color:var(--green);background:rgba(52,211,158,.12);border:1px solid rgba(52,211,158,.24);
  }

  .tiers{
    display:grid;grid-template-columns:repeat(3,1fr);gap:16px;
    margin-top:44px;align-items:start;
  }
  @media(max-width:940px){ .tiers{grid-template-columns:1fr;max-width:460px;margin-inline:auto} }

  .tier{
    position:relative;border-radius:var(--r-lg);padding:26px 24px;
    background:linear-gradient(180deg, rgba(255,255,255,.04), transparent 40%), var(--surface);
    border:1px solid var(--line);box-shadow:var(--lift);
    display:flex;flex-direction:column;
  }
  /* The tier we actually want to sell: lifted, outlined, badged. */
  .tier.star{
    border-color:rgba(124,120,255,.44);
    box-shadow:var(--glow), var(--lift);
    background:radial-gradient(110% 80% at 50% 0%, rgba(124,120,255,.14), transparent 62%), var(--surface);
  }
  @media(min-width:941px){ .tier.star{transform:translateY(-12px)} }

  .tier .badge{
    position:absolute;top:-11px;left:50%;translate:-50% 0;white-space:nowrap;
    padding:4px 12px;border-radius:99px;font-size:11px;font-weight:600;letter-spacing:.06em;
    text-transform:uppercase;color:#fff;background:var(--accent);
    box-shadow:0 8px 22px -8px rgba(124,120,255,.9);
  }

  .tier .nm{font-size:12px;letter-spacing:.15em;text-transform:uppercase;color:var(--text-2);font-weight:600}
  .tier .pitch{color:var(--text-3);font-size:13.6px;margin-top:9px;min-height:2.8em}

  .tier .price{display:flex;align-items:baseline;gap:6px;margin:20px 0 4px}
  .tier .price .amt{
    font-family:var(--mono);font-size:42px;font-weight:650;letter-spacing:-.04em;
    font-variant-numeric:tabular-nums;
  }
  .tier .price .per{color:var(--text-3);font-size:13.5px}
  .tier .bill-note{color:var(--text-3);font-size:12.4px;min-height:1.5em}

  .tier .btn{margin:22px 0 6px}
  .tier .reassure{text-align:center;color:var(--text-3);font-size:12px}

  .tier .feats{list-style:none;padding:0;margin:22px 0 0;display:flex;flex-direction:column;gap:11px}
  .tier .feats .head{
    font-size:11px;letter-spacing:.13em;text-transform:uppercase;color:var(--text-3);
    padding-bottom:2px;
  }
  .tier .feats li:not(.head){position:relative;padding-left:26px;font-size:14.2px;color:var(--text-2)}
  .tier .feats li:not(.head)::before{
    content:"";position:absolute;left:0;top:6px;width:15px;height:15px;border-radius:50%;
    background:rgba(52,211,158,.14);border:1px solid rgba(52,211,158,.3);
  }
  .tier .feats li:not(.head)::after{
    content:"";position:absolute;left:5px;top:9.5px;width:4px;height:7px;
    border-right:1.6px solid var(--green);border-bottom:1.6px solid var(--green);
    rotate:45deg;
  }
  .tier .feats li b{color:var(--text);font-weight:550}
  /* Not-included lines read grey with a dash, never a green tick. */
  .tier .feats li.no{color:var(--text-3)}
  .tier .feats li.no::before{background:rgba(255,255,255,.03);border-color:var(--line-2)}
  .tier .feats li.no::after{
    left:4px;top:12px;width:7px;height:0;border-right:0;border-bottom:1.6px solid var(--text-3);rotate:0deg;
  }

  .pr-note{
    max-width:70ch;margin:44px auto 0;text-align:center;color:var(--text-3);
    font-size:13px;line-height:1.7;
  }
}

/* --------------------------------------------------------------------- app */
@layer app {
  .page{padding:32px 0 60px}

  .hero-pl{
    position:relative;overflow:hidden;border-radius:var(--r-xl);padding:30px 28px;
    background:radial-gradient(110% 150% at 8% 0%, rgba(124,120,255,.20), transparent 58%), var(--surface);
    border:1px solid var(--line);box-shadow:var(--lift);
  }
  .hero-pl .k{font-size:11px;letter-spacing:.17em;text-transform:uppercase;color:var(--text-2)}
  .hero-pl .v{font-size:clamp(40px,8.4vw,62px);font-weight:650;letter-spacing:-.038em;line-height:1.02;margin:10px 0 6px}
  .hero-pl .s{color:var(--text-3);font-size:13.5px}

  .tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(148px,1fr));gap:12px;margin-top:14px}
  .tile{
    border-radius:var(--r);padding:16px;background:var(--surface);border:1px solid var(--line);
    transition:border-color .2s var(--ease),transform .2s var(--ease);
  }
  .tile:hover{border-color:var(--line-2);transform:translateY(-2px)}
  .tile .k{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--text-3)}
  .tile .v{font-size:24px;font-weight:600;letter-spacing:-.022em;margin-top:7px}

  .grid-2{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:14px}
  @media(max-width:860px){.grid-2{grid-template-columns:1fr}}

  /* charts.py emits these class names directly */
  .chart-eq,.chart-bars,.chart-hbars,.chart-donut{display:block;width:100%;height:auto}
  .chart-eq{height:210px}
  .chart-donut{max-width:236px;margin-inline:auto}

  .legend{margin-top:16px;display:flex;flex-direction:column;gap:8px}
  .legend-row{display:flex;align-items:center;gap:10px;font-size:13.5px}
  .swatch{width:10px;height:10px;border-radius:3px;flex:none}
  .legend-row .sym{flex:1;font-weight:500}

  /* pairing */
  .code-input{
    font-family:var(--mono);font-size:27px;letter-spacing:.4em;text-align:center;
    text-transform:uppercase;padding:17px 13px;
  }
  .steps{counter-reset:s;list-style:none;padding:0;margin:0 0 20px}
  .steps li{counter-increment:s;position:relative;padding:0 0 17px 40px;color:var(--text-2);font-size:14px}
  .steps li:before{
    content:counter(s);position:absolute;left:0;top:-1px;width:26px;height:26px;border-radius:50%;
    background:rgba(124,120,255,.13);color:var(--accent);border:1px solid rgba(124,120,255,.28);
    font-size:12px;font-weight:600;display:grid;place-items:center;font-family:var(--mono);
  }
  .steps li b{color:var(--text);font-weight:550}

  .device-row{display:flex;align-items:center;gap:13px;padding:15px 0;border-bottom:1px solid var(--line)}
  .device-row:last-child{border-bottom:0}
  .device-row .grow{flex:1;min-width:0}
  .device-row .nm{font-weight:550}
  .dot{width:8px;height:8px;border-radius:50%;flex:none;position:relative}
  .dot.live{background:var(--green);box-shadow:0 0 10px var(--green)}
  .dot.live::after{content:"";position:absolute;inset:-4px;border-radius:50%;
                   border:1px solid var(--green);animation:pulse-ring 2.4s var(--ease-io) infinite}
  .dot.dead{background:var(--text-3)}

  .empty{text-align:center;padding:64px 22px}
  .empty h2{font-size:21px;margin-bottom:10px}
  .empty p{color:var(--text-2);max-width:44ch;margin:0 auto 24px}

  /* auth: split screen, marketing on the left */
  .auth{display:grid;grid-template-columns:1.05fr .95fr;min-height:calc(100svh - var(--nav-h))}
  @media(max-width:900px){ .auth{grid-template-columns:1fr} .auth .aside{display:none} }
  .auth .aside{
    border-right:1px solid var(--line);padding:clamp(32px,5vw,64px);
    display:flex;flex-direction:column;justify-content:center;gap:26px;
  }
  .auth .aside h2{font-size:clamp(24px,2.9vw,36px);max-width:16ch}
  .auth .aside .quote{color:var(--text-2);font-size:15px;max-width:44ch}
  .auth .pane{display:flex;align-items:center;justify-content:center;padding:clamp(28px,5vw,56px)}
  .auth form{width:100%;max-width:392px}
  .auth h1{font-size:27px;margin-bottom:8px}
  .auth .sub{color:var(--text-3);font-size:13.5px;margin-bottom:22px}
  .auth .btn{margin-top:24px}
  .alt{margin-top:20px;text-align:center;color:var(--text-3);font-size:13.5px}
  .alt a{color:var(--accent)}

  .mini-stat{display:flex;gap:26px;flex-wrap:wrap}
  .mini-stat .s .v{font-size:24px;font-weight:620;letter-spacing:-.025em}
  .mini-stat .s .k{font-size:10.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--text-3);margin-top:4px}

  /* ======================================================== THE PLAYS BOARD
     Two columns that mean two different things: the left one is a to-do list
     ordered by urgency, the right one is a record ordered by time. They are
     given equal width on purpose — neither is the sidebar of the other. */

  .board{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:14px;align-items:start}
  @media(max-width:1000px){ .board{grid-template-columns:1fr} }

  .side{margin:0}
  .side .card-h h3{display:flex;align-items:center;gap:9px}

  /* The side dot: the only colour that separates the two columns at a glance. */
  .sd{width:7px;height:7px;border-radius:50%;flex:none}
  .sd.buy{background:var(--accent);box-shadow:0 0 9px rgba(124,120,255,.65)}
  .sd.sell{background:var(--green);box-shadow:0 0 9px rgba(52,211,158,.5)}

  .plist{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:9px}
  .plist.tight{gap:6px;margin-top:10px}

  .prow{
    border:1px solid var(--line);border-radius:var(--r);padding:13px 14px;
    background:linear-gradient(180deg,rgba(255,255,255,.016),transparent);
    transition:border-color .18s var(--ease),transform .18s var(--ease);
  }
  .prow:hover{border-color:var(--line-2);transform:translateX(2px)}
  /* A play whose window shuts today earns a left edge you can't scroll past. */
  .prow.open{border-left:2px solid rgba(124,120,255,.55)}
  .prow.exit{border-left:2px solid rgba(52,211,158,.45)}
  .prow.past,.prow.expired{opacity:.62}
  .prow.watch{border-left-color:rgba(242,193,78,.5)}

  .prow-top{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
  .prow-top .spacer{flex:1;min-width:8px}
  .prow .sym{font-size:16px;font-weight:640;letter-spacing:-.012em}
  .prow .proceeds{font-family:var(--mono);font-size:14.5px;font-weight:600;white-space:nowrap}

  .ptag{
    font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;font-weight:650;
    padding:3px 7px;border-radius:5px;white-space:nowrap;
  }
  .ptag.std {color:var(--text-2);background:rgba(255,255,255,.05)}
  .ptag.otc {color:var(--accent-2);background:rgba(167,139,250,.14)}
  .ptag.cond{color:var(--amber);background:rgba(242,193,78,.13)}
  .ptag.ru  {color:var(--green);background:rgba(52,211,158,.13)}

  /* Countdown. Colour is the message; the words repeat it for anyone who
     can't see the colour. */
  .cd{font-size:11.5px;font-weight:600;white-space:nowrap;font-family:var(--mono)}
  .cd.now {color:var(--red)}
  .cd.soon{color:var(--amber)}
  .cd.ok  {color:var(--text-2)}
  .cd.gone,.cd.none{color:var(--text-3);font-weight:500}

  .prow-facts{display:flex;flex-wrap:wrap;gap:6px 20px;margin-top:9px}
  .prow-facts .f{display:flex;flex-direction:column;gap:2px;min-width:62px}
  .prow-facts .f i{
    font-style:normal;font-size:9.5px;letter-spacing:.11em;text-transform:uppercase;
    color:var(--text-3);
  }
  .prow-facts .f b{font-family:var(--mono);font-size:13px;font-weight:600}

  .prow-foot{margin-top:9px;font-size:11.5px;display:flex;flex-wrap:wrap;gap:5px}
  .prow-foot .warn-note{color:var(--amber);width:100%;margin-top:3px}

  .legs{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}
  .leg{
    font-size:11.5px;padding:4px 9px;border-radius:99px;
    border:1px solid var(--line-2);color:var(--text-2);white-space:nowrap;
  }
  .leg b{font-family:var(--mono);color:var(--text);font-weight:600;margin-left:3px}

  /* A broker the reader holds nothing at. The count beside it belongs to the
     ALERTER, so it is shown (it is what the alert said) but struck through and
     dimmed, because it paid this reader nothing. */
  .unheld{opacity:.4;text-decoration:line-through;text-decoration-thickness:1px}
  .leg.unheld{border-style:dashed}
  .leg.unheld b{color:var(--text-3)}

  .exit-note{
    margin:10px 0 0;padding:9px 11px;border-radius:9px;font-size:12px;line-height:1.55;
    background:rgba(242,193,78,.06);border:1px solid rgba(242,193,78,.16);color:var(--amber);
  }

  .daygroup + .daygroup{margin-top:18px}
  .dayhead{display:flex;align-items:center;gap:11px;margin:0 0 9px}
  .dayhead span{
    font-family:var(--mono);font-size:11px;letter-spacing:.09em;color:var(--text-3);
    white-space:nowrap;
  }
  .dayhead i{flex:1;height:1px;background:var(--line)}

  .closed-fold{margin-top:16px;border-top:1px solid var(--line);padding-top:13px}
  .closed-fold summary{
    cursor:pointer;font-size:12.5px;color:var(--text-3);list-style:none;
    transition:color .15s var(--ease);
  }
  .closed-fold summary::-webkit-details-marker{display:none}
  .closed-fold summary::before{content:"▸ ";font-size:10px}
  .closed-fold[open] summary::before{content:"▾ "}
  .closed-fold summary:hover{color:var(--text-2)}

  .tile.hot{border-color:rgba(242,193,78,.32);background:rgba(242,193,78,.045)}
  .tile.hot .v{color:var(--amber)}

  /* ================================================== "I BOUGHT THIS" MARKS
     The reader's own note on a play, and the only state on this board that
     isn't the feed's. It lives in localStorage because it has nowhere else to
     live — the board is behind one shared password and there is no account to
     hang it on.

     Which is why the whole affordance is gated on html.js, set at the top of
     site.js: a checkbox that silently forgets itself on reload is worse than
     not offering one, and every other control on this page works with scripts
     blocked. */
  .own,.markbar{display:none}
  html.js .own{display:inline-flex}
  html.js .markbar{display:flex}

  .own{
    align-items:center;gap:6px;flex:none;cursor:pointer;margin:0;
    font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;font-weight:650;
    color:var(--text-3);user-select:none;
    transition:color .15s var(--ease);
  }
  .own:hover{color:var(--text-2)}
  /* Off-screen rather than display:none — a hidden input takes no focus, and
     the box is only reachable by keyboard through the real checkbox. */
  .own input{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
  .own i{
    width:15px;height:15px;border-radius:5px;flex:none;display:grid;place-items:center;
    border:1px solid var(--line-2);background:rgba(255,255,255,.02);
    transition:border-color .15s var(--ease),background .15s var(--ease);
  }
  .own i::after{
    content:"";width:7px;height:4px;margin-top:-2px;
    border-left:2px solid var(--bg);border-bottom:2px solid var(--bg);
    transform:rotate(-45deg) scale(.4);opacity:0;
    transition:transform .16s var(--ease),opacity .16s var(--ease);
  }
  .own:hover i{border-color:var(--accent)}
  .own input:checked + i{background:var(--green);border-color:var(--green)}
  .own input:checked + i::after{opacity:1;transform:rotate(-45deg) scale(1)}
  .own input:focus-visible + i{outline:2px solid var(--accent);outline-offset:2px}
  .own input:checked ~ span{color:var(--green)}

  /* A ticked row steps back; it does not disappear. The job is telling it
     apart from the ones still to do, not losing it — hiding is the separate,
     deliberate act of the toggle below. */
  .prow.bought{opacity:.5;border-left:2px solid rgba(52,211,158,.55)}
  .prow.bought:hover{opacity:.85}
  html.hide-bought .prow.bought{display:none}

  .markbar{align-items:center;gap:10px;flex-wrap:wrap;margin:-4px 0 14px}
  .markbar .mstat{font-size:12px;color:var(--text-2)}
  .markbar .mstat b{font-family:var(--mono);color:var(--text);font-weight:650}
  .markbar .chip.sm{padding:4px 11px;font-size:11.5px}
  .markbar .linkish{font-size:11.5px;padding:4px 9px;color:var(--text-3)}
  .markbar .linkish.armed{color:var(--red)}

  /* The payoff, on the Sells tab: a solid pill, so it can't be mistaken for
     the translucent "rounded up" tag sitting beside it. */
  .ptag.you{color:var(--bg);background:var(--green)}
  .prow.exit.held{border-left-color:var(--green)}

  /* ==================================================== THE NEW-ALERT CHIME
     A <button> wearing the gear's pill, so the two controls in the header read
     as one row. Buttons bring their own background, font and border. */
  .gear.snd{background:transparent;font:inherit;font-size:12.5px}
  .gear.snd .sndico{font-size:13px;line-height:1;opacity:.75}
  .gear.snd.on{
    color:var(--text);border-color:var(--green);background:rgba(52,211,158,.09);
  }
  .gear.snd.on .sndico{opacity:1;color:var(--green)}
  /* Hidden with scripts blocked, for the same reason as the checkboxes: it
     cannot do anything without site.js, and a dead control is worse than none. */
  .gear.snd{display:none}
  html.js .gear.snd{display:inline-flex}

  /* The toast. Bottom-right, above everything, and it never redraws the board
     under someone who is reading it — it says what landed and offers the
     reload. */
  #toast-host{
    position:fixed;right:18px;bottom:18px;z-index:60;
    display:flex;flex-direction:column;gap:8px;max-width:min(92vw,340px);
  }
  .toast{
    display:flex;align-items:center;gap:12px;flex-wrap:wrap;
    padding:13px 15px;border-radius:var(--r);
    background:var(--surface);border:1px solid var(--line-2);box-shadow:var(--lift);
    animation:toast-in .32s var(--ease) both;
  }
  .toast b{font-size:13px;font-weight:640;white-space:nowrap}
  .toast .syms{
    font-family:var(--mono);font-size:12px;color:var(--text-2);
    flex:1;min-width:80px;overflow:hidden;text-overflow:ellipsis;
  }
  .toast .tnote{
    font-style:normal;font-size:11px;color:var(--text-3);
    width:100%;order:3;margin-top:-4px;
  }
  .toast .btn{flex:none}
  .toast .tclose{
    background:none;border:0;cursor:pointer;color:var(--text-3);
    font-size:13px;padding:2px 4px;line-height:1;
  }
  .toast .tclose:hover{color:var(--text)}
  @keyframes toast-in{from{opacity:0;transform:translateY(10px) scale(.97)}}
  @media(prefers-reduced-motion:reduce){ .toast{animation:none} }

  /* ============================================================ PLAYS TABS
     Radio inputs and sibling selectors, not JavaScript. The board is the thing
     people paid for; it must not depend on a script to be readable, and the CSP
     forbids the inline handler that would be the lazy way to do it. */

  .tabs{margin-top:14px}
  .tabs > input{
    position:absolute;width:1px;height:1px;opacity:0;pointer-events:none;
  }
  .tabbar{
    display:flex;gap:6px;flex-wrap:wrap;margin-bottom:12px;
    border-bottom:1px solid var(--line);padding-bottom:10px;
  }
  .tabbar label{
    display:inline-flex;align-items:center;gap:8px;cursor:pointer;
    padding:8px 14px;border-radius:99px;font-size:13.5px;font-weight:550;
    color:var(--text-3);border:1px solid transparent;
    transition:color .15s var(--ease),background .15s var(--ease),border-color .15s var(--ease);
  }
  .tabbar label:hover{color:var(--text-2);background:rgba(255,255,255,.04)}
  .tabbar label b{
    font-family:var(--mono);font-size:11px;font-weight:600;
    padding:2px 6px;border-radius:5px;background:rgba(255,255,255,.06);color:var(--text-3);
  }
  .sd.gold{background:var(--amber);box-shadow:0 0 9px rgba(242,193,78,.5)}

  .tabs > .pane{display:none;margin:0}
  #tab-dash:checked  ~ .p-dash,
  #tab-cal:checked   ~ .p-cal,
  #tab-buys:checked  ~ .p-buys,
  #tab-sells:checked ~ .p-sells,
  #tab-track:checked ~ .p-track{display:block}

  #tab-dash:checked  ~ .tabbar label[for="tab-dash"],
  #tab-cal:checked   ~ .tabbar label[for="tab-cal"],
  #tab-buys:checked  ~ .tabbar label[for="tab-buys"],
  #tab-sells:checked ~ .tabbar label[for="tab-sells"],
  #tab-track:checked ~ .tabbar label[for="tab-track"]{
    color:var(--text);background:rgba(255,255,255,.06);border-color:var(--line-2);
  }
  #tab-dash:checked  ~ .tabbar label[for="tab-dash"] b,
  #tab-cal:checked   ~ .tabbar label[for="tab-cal"] b,
  #tab-buys:checked  ~ .tabbar label[for="tab-buys"] b,
  #tab-sells:checked ~ .tabbar label[for="tab-sells"] b,
  #tab-track:checked ~ .tabbar label[for="tab-track"] b{color:var(--text-2)}

  /* Keyboard users get a visible target on the tab they are actually on;
     mouse users never see it. */
  #tab-dash:focus-visible  ~ .tabbar label[for="tab-dash"],
  #tab-cal:focus-visible   ~ .tabbar label[for="tab-cal"],
  #tab-buys:focus-visible  ~ .tabbar label[for="tab-buys"],
  #tab-sells:focus-visible ~ .tabbar label[for="tab-sells"],
  #tab-track:focus-visible ~ .tabbar label[for="tab-track"]{
    outline:2px solid var(--accent);outline-offset:2px;
  }

  /* Inside a tab there is one full-width card, so the rows pair up on desktop
     instead of stretching to the width of the page. */
  .plist.grid2{display:grid;grid-template-columns:1fr 1fr;gap:9px}
  @media(max-width:900px){ .plist.grid2{grid-template-columns:1fr} }

  /* ------------------------------------------------------- the calculator */
  .calc-in{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-bottom:18px}
  .calc-in label{font-size:13.5px;color:var(--text-2)}
  .calc-in input{
    width:110px;padding:9px 12px;border-radius:10px;font-family:var(--mono);
    font-size:15px;font-weight:600;color:var(--text);
    background:rgba(255,255,255,.04);border:1px solid var(--line-2);
  }
  .calc-in input:focus{outline:2px solid var(--accent);outline-offset:1px}
  .calc-in .hint{font-size:11.5px;color:var(--text-3)}
  .calc-in + .calc-in{margin-top:-8px}

  .calc-out{display:flex;gap:34px;flex-wrap:wrap;margin-bottom:16px}
  .calc-out .k{
    font-size:9.5px;letter-spacing:.11em;text-transform:uppercase;color:var(--text-3);
    margin-bottom:5px;
  }
  .calc-out .v{font-family:var(--mono);font-size:24px;font-weight:640;letter-spacing:-.02em}
  .calc-out .big .v{font-size:38px}

  .calc-note{font-size:12.5px;color:var(--text-3);line-height:1.6;max-width:70ch;margin:0 0 10px}
  .calc-note b{color:var(--text-2);font-family:var(--mono)}
  .calc-warn{
    font-size:12.5px;line-height:1.6;max-width:70ch;margin:0 0 18px;
    padding:11px 13px;border-radius:10px;
    background:rgba(242,193,78,.06);border:1px solid rgba(242,193,78,.16);color:var(--amber);
  }

  /* ================================================= PLAYS PAGE FURNITURE */

  .page-h{
    display:flex;align-items:flex-start;justify-content:space-between;
    gap:20px;flex-wrap:wrap;margin-bottom:16px;
  }
  .page-h h1{font-size:26px;letter-spacing:-.02em;margin:0}
  .page-h .sub{font-size:13px;margin:5px 0 0;max-width:64ch}
  .disclaim{max-width:78ch;margin:26px auto 0;text-align:center;font-size:12.4px;line-height:1.65}

  /* The settings gear. Reachable from every tab, because the account counts
     scope every number on the page and not just one card. */
  .gear{
    display:inline-flex;align-items:center;gap:7px;cursor:pointer;
    padding:7px 12px;border-radius:99px;border:1px solid var(--line-2);
    font-size:12.5px;color:var(--text-2);white-space:nowrap;
    transition:color .15s var(--ease),border-color .15s var(--ease),background .15s var(--ease);
  }
  .gear:hover{color:var(--text);border-color:var(--accent);background:rgba(124,120,255,.08)}

  /* A popover anchored under the gear, not a slab across the page: editing ten
     numbers is a two-second errand and shouldn't displace the board. The dim
     behind it is a label, so clicking anywhere outside closes it. */
  .drawer-toggle{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
  .drawer-scrim{display:none}
  .drawer-toggle:checked ~ .drawer-scrim{
    display:block;position:fixed;inset:0;z-index:40;
    background:rgba(3,4,8,.55);backdrop-filter:blur(2px);cursor:default;
  }
  .drawer{
    display:none;position:absolute;z-index:41;right:0;top:100%;margin-top:10px;
    width:min(560px,calc(100vw - 32px));
    box-shadow:0 24px 60px rgba(0,0,0,.6);
  }
  .drawer-toggle:checked ~ .pop-anchor .drawer{display:block}
  .pop-anchor{position:relative}
  @media(max-width:640px){
    /* No room to anchor on a phone: centre it instead of hanging it off-screen. */
    .drawer{position:fixed;right:16px;left:16px;top:auto;bottom:16px;width:auto;margin:0}
  }

  .bgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:9px}
  @media(max-width:560px){ .bgrid{grid-template-columns:repeat(2,1fr)} }
  .bslot{display:flex;flex-direction:column;gap:6px}
  .bslot .bn{font-size:11.5px;color:var(--text-3);display:flex;align-items:center;gap:4px}
  .bslot .bn i{color:var(--accent-2);font-style:normal;font-size:9px}
  .bslot input{
    width:100%;padding:8px 10px;border-radius:9px;font-family:var(--mono);
    font-size:14px;font-weight:600;color:var(--text);
    background:rgba(255,255,255,.04);border:1px solid var(--line-2);
  }
  .bslot input:focus{outline:2px solid var(--accent);outline-offset:1px}
  .bfoot{
    display:flex;align-items:center;justify-content:space-between;gap:16px;
    flex-wrap:wrap;margin-top:16px;padding-top:14px;border-top:1px solid var(--line);
    font-size:12.5px;color:var(--text-3);
  }
  .bfoot b{font-family:var(--mono);color:var(--text);font-weight:650}
  .bfoot i{color:var(--accent-2);font-style:normal;font-size:9px}
  .xclose{cursor:pointer;color:var(--text-3);font-size:13px;padding:2px 6px;border-radius:6px}
  .xclose:hover{color:var(--text);background:rgba(255,255,255,.06)}

  /* ---- one filter row above everything it scopes */
  .filters{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:16px}
  .flabel{font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--text-3)}
  .chips{display:flex;gap:6px;flex-wrap:wrap}
  .chip{
    padding:6px 13px;border-radius:99px;font-size:12.5px;cursor:pointer;
    background:transparent;border:1px solid var(--line-2);color:var(--text-3);
    transition:color .15s var(--ease),border-color .15s var(--ease),background .15s var(--ease);
  }
  .chip:hover{color:var(--text-2)}
  .chip.on{color:var(--text);border-color:var(--accent);background:rgba(124,120,255,.1)}
  /* nowrap: the basis is one sentence with its own control at the end, and
     breaking "change" onto its own line reads as a stray link. */
  .basis{margin-left:auto;flex:none;font-size:12px;color:var(--text-3);white-space:nowrap}
  /* display+margin, because the base label{} rule is a block with 16px of top
     margin — which is what was breaking "change" onto a line of its own. */
  .basis label{
    display:inline;margin:0;font-size:inherit;
    color:var(--accent);cursor:pointer;text-decoration:underline;
  }

  /* Day/month toggle above the profit chart. Its own row under the card
     header, so the header stays a title and a caption. */
  .chips.grain{margin:-6px 0 12px;padding:0 2px}
  .chips.grain .chip.sm{padding:4px 11px;font-size:11.5px}
  .chips.grain .chipgap{width:14px;flex:none}

  /* "Since you were last here". A line, not a card: it is news about the
     board rather than part of it, and it is gone the moment it is read. */
  .since{
    display:flex;align-items:center;gap:12px;flex-wrap:wrap;
    margin:0 0 14px;padding:11px 14px;border-radius:var(--r);
    background:rgba(124,120,255,.07);border:1px solid rgba(124,120,255,.28);
    font-size:13px;
  }
  .since b{font-weight:640;white-space:nowrap}
  .since span{font-family:var(--mono);font-size:12px;color:var(--text-2);flex:1;min-width:80px}

  /* A broker's own sells, opened by clicking its bar. */
  .bdetail{margin-top:14px;border-top:1px solid var(--line);padding-top:12px}
  .bdetail .bd-h{
    display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:8px;
  }
  .bdetail .bd-h b{font-size:13px}
  .bdetail .bd-h .clear{
    margin-left:auto;background:none;border:0;cursor:pointer;
    color:var(--text-3);font-size:11.5px;padding:2px 6px;border-radius:6px;
  }
  .bdetail .bd-h .clear:hover{color:var(--text);background:rgba(255,255,255,.06)}
  .bdetail table{width:100%;border-collapse:collapse}
  .bdetail th{
    text-align:left;font-size:9.5px;letter-spacing:.11em;text-transform:uppercase;
    color:var(--text-3);font-weight:600;padding:0 8px 6px 0;
  }
  .bdetail td{
    padding:5px 8px 5px 0;font-size:12px;border-top:1px solid var(--line);
    white-space:nowrap;
  }
  .bdetail td.mono{font-family:var(--mono)}
  .bdetail tfoot td{border-top:1px solid var(--line-2);font-weight:650}
  .bdetail .empty-note{margin:6px 0 0}

  /* ---- the hero figure: exactly one per view */
  .hero-row{display:grid;grid-template-columns:minmax(240px,.9fr) 2.1fr;gap:12px;align-items:stretch}
  @media(max-width:900px){ .hero-row{grid-template-columns:1fr} }
  .hero-card{
    position:relative;overflow:hidden;
    margin:0;display:flex;flex-direction:column;justify-content:center;
    /* tighter than a normal card: it holds one number. The extra bottom is the
       lane the sparkline runs in, so text never sits on top of the line. */
    padding:20px 22px 36px;
    background:
      radial-gradient(120% 100% at 0% 0%, rgba(124,120,255,.12), transparent 70%),
      var(--bg-2);
  }
  .hero-card > *{position:relative;z-index:1}
  .hero-card .k{font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--text-3)}
  /* Proportional figures, not tabular: equal-width digits read loose this big. */
  .hero-fig{font-size:clamp(36px,4.4vw,52px);font-weight:660;letter-spacing:-.03em;margin:8px 0 6px;line-height:1}
  .hero-sub{font-size:12.5px}
  /* The spark is a band across the foot of the card, not a block in the flow:
     as a flow item it stood 70px tall and pushed every KPI tile beside it into
     a field of nothing. Bled to the card's edges it costs no height at all. */
  .spark{position:absolute;inset:auto 0 0 0;margin:0;line-height:0;z-index:0;opacity:.75}
  .spark svg{display:block;width:100%;height:auto}
  .spark-line{fill:none;stroke:var(--c-series);stroke-width:1.6;stroke-linejoin:round;stroke-linecap:round}
  /* Three across, so the six KPIs fill two rows exactly and leave no hole.
     They were five on one row; a sixth cannot join them — at this page width
     six columns give each tile about 83px of usable space, and "$1,269.42" at
     the tile's own type size needs more than that. Two rows of three is also
     what makes the tiles come out the height of the hero beside them. */
  .tiles.compact{grid-template-columns:repeat(3,1fr);margin:0}
  @media(max-width:900px){ .tiles.compact{grid-template-columns:repeat(2,1fr)} }
  /* The tiles stretch to the hero's height whatever it is, so centre what is in
     them: content pinned to the top of a tall box reads as a rendering fault. */
  .tiles.compact .tile{display:flex;flex-direction:column;justify-content:center}
  .tile .k2{font-size:11px;color:var(--text-3);margin-top:3px;font-family:var(--mono)}

  /* ---- the lifecycle rail
     Four stages on one line. Each one owns a track of the SAME width, and the
     fill inside it is the stage's share of every alert — so the eye compares
     fills against a constant, which is the only honest way to draw a funnel
     out of four separate bars. */
  .funnel{
    margin-top:12px;padding:16px 20px;display:grid;gap:10px 26px;
    grid-template-columns:repeat(4,1fr);
  }
  @media(max-width:900px){ .funnel{grid-template-columns:repeat(2,1fr);gap:16px 22px} }
  @media(max-width:520px){ .funnel{grid-template-columns:1fr} }
  /* Two columns puts stages 3 and 4 on a second row, where the chevron on the
     first of them points at the left margin. Odd children start a row here. */
  @media(max-width:900px){ .fstep:nth-child(odd)::before{display:none} }
  .fstep{position:relative;min-width:0}
  /* The chevron between stages. Drawn on the gap, hidden on the last one and
     whenever the grid wraps — an arrow pointing off the end of a row is worse
     than no arrow. */
  .fstep + .fstep::before{
    content:"";position:absolute;left:-16px;top:9px;width:5px;height:5px;
    border-top:1.5px solid var(--line-2);border-right:1.5px solid var(--line-2);
    transform:rotate(45deg);
  }
  @media(max-width:520px){ .fstep + .fstep::before{display:none} }
  .fhead{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
  .fk{font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--text-3);white-space:nowrap}
  .fv{font-size:20px;font-weight:640;letter-spacing:-.02em;line-height:1;font-family:var(--mono)}
  .ftrack{
    display:block;height:4px;border-radius:99px;margin:9px 0 7px;overflow:hidden;
    background:rgba(255,255,255,.05);
  }
  .ftrack i{
    display:block;height:100%;border-radius:99px;min-width:2px;
    background:linear-gradient(90deg,var(--accent-2),var(--c-series));
    transition:width .5s var(--ease);
  }
  .fn{font-size:11px;color:var(--text-3);line-height:1.35;display:block}
  /* The stage that is actually money, and the only one the account profile moves. */
  .fstep.paid .fv{color:var(--green)}
  .fstep.paid .ftrack i{background:linear-gradient(90deg,var(--c-series),var(--green))}

  /* ---- charts */
  /* align-items:start, so a card with a table under its chart doesn't stretch
     the one beside it into a field of empty space. The wide column carries the
     month chart and its two audit tables; the narrow one stacks the two
     supporting figures. */
  .chart-grid{display:grid;grid-template-columns:1.5fr 1fr;gap:12px;margin-top:12px;align-items:start}
  @media(max-width:1020px){ .chart-grid{grid-template-columns:1fr} }
  .chart-card{margin:0;min-width:0}
  .chart-card.outcomes{margin-top:12px;padding-bottom:18px}
  .chart{margin:0;width:100%;min-height:0}
  .chart svg{display:block;width:100%;height:auto;overflow:visible}
  .chart .empty-note{font-size:13px;color:var(--text-3);padding:22px 0}

  /* The outcome key. HTML rather than SVG text so it wraps on its own, and its
     own class rather than .legend, which is a column list somewhere else. */
  .chartkey{display:flex;flex-flow:row wrap;gap:9px 22px;margin-top:14px}
  .chartkey .ck{display:inline-flex;align-items:center;gap:7px;font-size:12.5px;color:var(--text-2)}
  .chartkey .ck i{width:9px;height:9px;border-radius:3px;flex:none}
  .chartkey .ck b{font-family:var(--mono);color:var(--text-3);font-weight:650}

  .ax-line{stroke:var(--line);stroke-width:1}
  /* The average, stated as a line where the KPI tile only states it as a word. */
  .ax-avg{stroke:var(--line-2);stroke-width:1;stroke-dasharray:3 4}
  .ax-text{fill:var(--text-3);font-size:10px;font-family:var(--mono)}
  .ax-text.name{font-family:inherit;font-size:11px;fill:var(--text-2)}
  .ax-text.run{fill:var(--accent-2);opacity:.75}
  .ax-text.avg{fill:var(--text-3);font-size:9px;letter-spacing:.04em}
  .val-text{fill:var(--text-2);font-size:10.5px;font-family:var(--mono)}

  .mark-bar{fill:var(--c-series);transition:filter .16s var(--ease)}
  .mark-bar.hot{filter:brightness(1.35) saturate(1.1)}
  .mark-line{fill:none;stroke:var(--c-series);stroke-width:2;stroke-linejoin:round;stroke-linecap:round}
  /* A fat translucent copy of the line under the crisp one. Reads as a glow at
     a fraction of the cost of an SVG blur filter, which would re-rasterise on
     every repaint — and there is a repaint per keystroke in the accounts panel. */
  .mark-line.halo{stroke:var(--accent-2);stroke-width:7;opacity:.14}
  .mark-area{opacity:1}
  .mark-dot{fill:var(--c-series);stroke:var(--bg-2);stroke-width:2}
  .mark-dot.live{opacity:0;fill:var(--accent-2);transition:opacity .12s var(--ease)}
  .mark-dot.live.on{opacity:1}
  .hoverband{fill:#fff;opacity:0;transition:opacity .14s var(--ease)}
  .hoverband.on{opacity:.035}
  .track{fill:rgba(255,255,255,.05)}
  .mark-hbar{transition:filter .16s var(--ease)}
  .mark-hbar.hot{filter:brightness(1.3)}
  .seg{transition:filter .16s var(--ease)}
  .seg.hot{filter:brightness(1.25)}
  .seg-text{fill:#080a10;font-size:10px;font-weight:700;font-family:var(--mono);pointer-events:none}
  .hit{fill:transparent;cursor:pointer}

  /* Marks arrive from their own baseline: bars grow up out of the axis, ranked
     bars grow out of the left. transform-box:fill-box is what makes a percentage
     origin mean the shape's own box rather than the whole SVG's. */
  @keyframes markGrowY{from{transform:scaleY(0)}to{transform:scaleY(1)}}
  @keyframes markGrowX{from{transform:scaleX(0)}to{transform:scaleX(1)}}
  .grow{transform-box:fill-box;transform-origin:50% 100%;animation:markGrowY .5s var(--ease) both}
  .growx{transform-box:fill-box;transform-origin:0 50%;animation:markGrowX .55s var(--ease) both}
  @media(prefers-reduced-motion:reduce){
    .grow,.growx{animation:none}
    .ftrack i{transition:none}
  }

  .charttip{
    position:fixed;z-index:60;pointer-events:none;opacity:0;transform:translate(-50%,-115%);
    background:var(--bg-1);border:1px solid var(--line-2);border-radius:10px;
    padding:8px 11px;font-size:12px;white-space:nowrap;
    box-shadow:0 10px 30px rgba(0,0,0,.5);transition:opacity .12s var(--ease);
  }
  .charttip.on{opacity:1}
  .charttip b{font-family:var(--mono);display:block;font-size:13.5px;margin-top:2px}
  /* The second figure. Present but subordinate: on the month chart it is the
     running total, which is context for the number above it, not a rival. */
  .charttip i{
    font-style:normal;display:block;font-size:11px;margin-top:3px;
    color:var(--text-3);font-family:var(--mono);
  }

  .tableview{margin-top:14px;border-top:1px solid var(--line);padding-top:12px}
  .tableview summary{cursor:pointer;font-size:12.5px;color:var(--text-3);list-style:none}
  .tableview summary::-webkit-details-marker{display:none}
  .tableview summary::before{content:"▸ ";font-size:10px}
  .tableview[open] summary::before{content:"▾ "}
  .tableview .htable{min-width:0;margin-top:10px}

  /* ---- calendar */
  .calwrap{display:grid;grid-template-columns:minmax(300px,420px) 1fr;gap:12px;align-items:start}
  @media(max-width:900px){ .calwrap{grid-template-columns:1fr} }
  .cals{display:flex;flex-direction:column;gap:22px}
  .calhead{font-size:13px;font-weight:600;margin-bottom:10px}
  .caldow,.calgrid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px}
  .caldow span{
    text-align:center;font-size:9.5px;letter-spacing:.08em;color:var(--text-3);
    padding-bottom:6px;
  }
  .cday{
    display:flex;flex-direction:column;align-items:center;justify-content:center;
    aspect-ratio:1;border-radius:9px;font-size:12px;font-family:var(--mono);
    color:var(--text-3);border:1px solid transparent;background:transparent;
  }
  .cday.out{opacity:.28}
  .cday.gone{opacity:.4}
  .cday.today{border-color:var(--line-2);color:var(--text)}
  button.cday{
    cursor:pointer;color:var(--text);background:rgba(124,120,255,.1);
    border-color:rgba(124,120,255,.38);
    transition:background .15s var(--ease),border-color .15s var(--ease);
  }
  button.cday:hover{background:rgba(124,120,255,.2);border-color:var(--accent)}
  button.cday.sel{background:var(--accent);border-color:var(--accent);color:#0b0b16}
  button.cday i{font-style:normal;font-size:9px;opacity:.85;margin-top:1px}
  .dayblock.hide{display:none}

  /* ---- pager */
  .pgnav{
    display:flex;align-items:center;gap:14px;justify-content:flex-end;
    margin-bottom:14px;padding-bottom:12px;border-bottom:1px solid var(--line);
  }
  .pgstat{font-size:12px;color:var(--text-3);font-family:var(--mono);order:-1;margin-right:auto}
  .pgbtn{
    padding:6px 13px;border-radius:99px;font-size:12.5px;cursor:pointer;
    background:transparent;border:1px solid var(--line-2);color:var(--text-2);
    transition:color .15s var(--ease),border-color .15s var(--ease),background .15s var(--ease);
  }
  .pgbtn:hover:not(:disabled){color:var(--text);border-color:var(--accent);background:rgba(124,120,255,.1)}
  .pgbtn:disabled{opacity:.35;cursor:default}

  /* ---- page header side: freshness stamp + the lock-this-browser control */
  .head-side{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
  .eyebrow.stale{color:var(--amber);border-color:rgba(242,193,78,.3)}
  .eyebrow.stale .pip{background:var(--amber)}

  /* ---- what the split did. Colour groups the outcomes; the label states it. */
  .ptag.st{font-size:9.5px}
  .ptag.st.ok  {color:var(--green);background:rgba(52,211,158,.13)}
  .ptag.st.warn{color:var(--amber);background:rgba(242,193,78,.13)}
  .ptag.st.wait{color:var(--text-2);background:rgba(124,120,255,.13)}
  .ptag.st.off {color:var(--text-3);background:rgba(255,255,255,.05)}
  .ptag.st.dim {color:var(--text-3);background:rgba(255,255,255,.035)}

  /* The post-split rename. Loud on purpose: an order in the old ticker fails. */
  .rename{
    color:var(--accent-2);font-size:11.5px;
  }
  .rename b{font-family:var(--mono);font-weight:650}

  /* ======================================================== THE RECORD
     Every alert ever published, with its outcome. A table, not cards: the
     question this section answers is "how often does this actually work",
     which is a question about columns you can run your eye down. */

  .hist{margin-top:14px}
  .sd.hist{background:var(--text-3);box-shadow:none}

  .statbar{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:14px}
  .sb{
    font-size:11.5px;padding:5px 10px;border-radius:99px;
    border:1px solid var(--line-2);color:var(--text-3);white-space:nowrap;
  }
  .sb b{font-family:var(--mono);color:var(--text-2);font-weight:650;margin-right:3px}
  .sb-rounded_up{border-color:rgba(52,211,158,.32);color:var(--green)}
  .sb-rounded_up b{color:var(--green)}
  .sb-fractional,.sb-cash_in_lieu{border-color:rgba(242,193,78,.26);color:var(--amber)}
  .sb-fractional b,.sb-cash_in_lieu b{color:var(--amber)}

  /* The table scrolls inside its own box; the page never scrolls sideways. */
  .htable-wrap{overflow-x:auto;margin:0 -4px;padding:0 4px}
  .htable{width:100%;border-collapse:collapse;font-size:12.5px;min-width:920px}
  .htable th{
    text-align:left;font-size:9.5px;letter-spacing:.11em;text-transform:uppercase;
    color:var(--text-3);font-weight:600;padding:0 12px 9px 0;white-space:nowrap;
    border-bottom:1px solid var(--line);
  }
  .htable td{
    padding:9px 12px 9px 0;border-bottom:1px solid var(--line);vertical-align:middle;
    white-space:nowrap;
  }
  .htable tbody tr:hover{background:rgba(255,255,255,.018)}
  .htable tbody tr:last-child td{border-bottom:0}
  .htable .mono{font-family:var(--mono)}
  .htable .dim{color:var(--text-3)}
  .htable .small{font-size:11.5px;white-space:normal;max-width:22ch}
  .htable .arrow{color:var(--accent-2);font-family:var(--mono);font-size:11.5px;margin-left:4px}
  @media(max-width:700px){ .htable{font-size:12px} }
}
