/* Prisma Suite product page — deishmedia.com/audio
   Also serves the /trading/ and /apparel/ hubs. Everything under "shared
   chrome" and "hub pages" is load-bearing for those two — they use
   .wrap .eyebrow .lede .hub .stack .card .chip .btn .caveat .crumb .crumbsep
   .navname plus the body[data-line] accent switch. Change those with both
   hubs open.

   Direction: the page is an instrument, not a brochure. One chromatic source —
   the spectral ramp the plug-in actually draws — and everything else is black,
   graphite and light. Glow is treated as emission (something is on) rather
   than decoration. */

:root{
  /* Ground sits DEEPER than the plug-in's own #0e0f13. The window screenshot is
     that value, so a darker page makes the product read as a lit object resting
     on the page instead of a panel flush with it. This is the single change that
     does the most for "the product is the subject". */
  --bg:#07080b; --bg-lift:#0b0d13;
  --panel:#0f1218; --panel2:#141821; --edge:#1e2230; --edge-hi:#2b3143; --grid:#171b24;
  --text:#a7aebd; --dim:#6a7183; --bright:#eef1f7;

  --teal:#2ad0c4; --violet:#8a7cff; --green:#4ad07a; --red:#e4595b; --amber:#e4c65b;

  /* The spectral ramp, lifted from the shipping plug-in's Modern RGB theme and
     kept identical to SPECTRAL[] in prisma-viz.js. Low frequency is warm, high
     is violet. The five analyzer sections index into it, so the page is
     coloured by the same rule the product is. */
  --sp-0:#c63e30; --sp-1:#e8c440; --sp-2:#4acc78; --sp-3:#3a9de8; --sp-4:#9c4acc;

  /* The plug-in's own "neon" theme (marketing/brand/brand.json). Reserved for
     the buy path — the one place the page is allowed to raise its voice. */
  --neon-pink:#ff2bd0; --neon-cyan:#29e0ff;

  --accent:var(--teal); --accent-ink:#04211f;

  --display:"Space Grotesk",system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --sans:"IBM Plex Sans",system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --mono:"JetBrains Mono",ui-monospace,"Cascadia Mono",Consolas,monospace;

  --measure:64ch;
  --ease:cubic-bezier(.22,.61,.36,1);
}

*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
body{background:var(--bg);color:var(--text);font-family:var(--sans);font-size:16px;line-height:1.65;
     -webkit-font-smoothing:antialiased;overflow-x:hidden;position:relative}

/* Grain. Flat dark gradients are the thing that reads as machine-made; a few
   percent of noise is what film grain does for the same reason. The umbrella
   page has carried this since launch and the product page never did, which is
   most of why the two did not look like the same company. Inline data URI —
   no request, no CSP surface. */
body::after{content:"";position:fixed;inset:0;z-index:60;pointer-events:none;opacity:.055;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E")}

a{color:var(--accent);text-decoration:none}
a:hover{text-decoration:underline}
a:focus-visible,button:focus-visible,summary:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:2px}
img{max-width:100%}
::selection{background:var(--teal);color:#04211f}

.wrap{max-width:1180px;margin:0 auto;padding:0 24px}
.wrap.tight{max-width:920px}

.eyebrow{font-family:var(--mono);font-size:.7rem;letter-spacing:.24em;text-transform:uppercase;color:var(--accent)}
h2{font-family:var(--display);color:var(--bright);font-size:clamp(1.75rem,3.6vw,2.5rem);font-weight:700;
   letter-spacing:-.035em;line-height:1.1;text-wrap:balance;margin:.5rem 0 1.1rem}
.lede{max-width:var(--measure);margin-bottom:2.4rem;font-size:1.03rem}
section{padding:96px 0;position:relative}

/* Section seams. A hairline that fades out at both ends reads as a join in a
   machined panel; a full-width 1px rule reads as a table border. */
section + section::before{content:"";position:absolute;left:0;right:0;top:0;height:1px;
  background:linear-gradient(90deg,transparent,var(--edge) 18%,var(--edge) 82%,transparent)}

/* ───────────────────────── shared chrome ───────────────────────── */

nav{position:sticky;top:0;z-index:40;background:color-mix(in srgb,var(--bg) 82%,transparent);
    backdrop-filter:blur(14px) saturate(1.3);border-bottom:1px solid var(--edge)}
nav .wrap{display:flex;align-items:center;gap:12px;height:62px}
nav img{width:28px;height:28px;border-radius:7px}
.navname{font-family:var(--display);color:var(--bright);font-weight:700;letter-spacing:.02em;font-size:.98rem}
.navbeta{font-family:var(--mono);font-size:.66rem;color:var(--dim);border:1px solid var(--edge);
         padding:2px 9px;border-radius:99px}
.navlinks{margin-left:auto;display:flex;gap:22px;font-family:var(--mono);font-size:.7rem;
          letter-spacing:.12em;text-transform:uppercase}
.navlinks a{color:var(--dim);position:relative;padding-bottom:2px}
.navlinks a::after{content:"";position:absolute;left:0;right:100%;bottom:0;height:1px;
  background:var(--accent);transition:right .28s var(--ease)}
.navlinks a:hover{color:var(--bright);text-decoration:none}
.navlinks a:hover::after{right:0}
.crumb{font-family:var(--mono);font-size:.7rem;letter-spacing:.1em;color:var(--dim)}
.crumb:hover{color:var(--text);text-decoration:none}
.crumbsep{color:var(--dim);opacity:.45}
.navbuy{margin-left:18px}

.btn{font-family:var(--display);display:inline-block;background:var(--accent);color:var(--accent-ink);
     font-weight:700;letter-spacing:-.01em;padding:13px 24px;border-radius:7px;
     transition:transform .18s var(--ease),box-shadow .18s var(--ease),filter .18s;
     white-space:nowrap;box-shadow:0 0 0 0 rgba(42,208,196,0);
     position:relative;overflow:hidden;isolation:isolate}
/* Glare sweep — a band of light crosses the face once on hover. Ported from
   21st.dev "Glow Button" (@waleedkibhen/glow-button) as plain CSS; the original
   is React + Tailwind and this site has no build step. Runs once per hover
   rather than looping, so it reads as a reflection and not as a loading bar. */
.btn::after{content:"";position:absolute;top:0;left:-60%;width:38%;height:100%;z-index:-1;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.30),transparent);
  transform:skewX(-18deg);opacity:0}
.btn:hover::after{animation:glare .72s var(--ease) 1}
@keyframes glare{from{left:-60%;opacity:1}to{left:125%;opacity:1}}
.btn.ghost::after{background:linear-gradient(100deg,transparent,rgba(42,208,196,.18),transparent)}
.btn:hover{filter:brightness(1.08);text-decoration:none;transform:translateY(-1px);
           box-shadow:0 8px 26px -8px rgba(42,208,196,.55)}
.btn:active{transform:translateY(0)}
.btn.small{padding:8px 15px;font-size:.85rem}
.btn.ghost{background:transparent;color:var(--bright);border:1px solid var(--edge-hi);box-shadow:none}
.btn.ghost:hover{border-color:var(--accent);color:var(--accent);box-shadow:none;filter:none}
/* The buy button is the only element on the page wearing the neon theme. */
.btn.buy{background:linear-gradient(100deg,var(--neon-pink),#a637e8 55%,var(--violet));color:#fff}
.btn.buy:hover{box-shadow:0 10px 30px -8px rgba(255,43,208,.5)}

/* ───────────────────────────── hero ───────────────────────────── */

header{position:relative;overflow:hidden;padding-bottom:0}
#spec{position:absolute;left:0;right:0;top:0;height:min(62vh,540px);width:100%;opacity:.85;
      mask-image:linear-gradient(180deg,#000 0%,#000 42%,transparent 100%);
      -webkit-mask-image:linear-gradient(180deg,#000 0%,#000 42%,transparent 100%)}

/* Centred hero: the copy is a statement, the product is the evidence directly
   under it. Left-aligned copy with the icon opposite made the icon the hero's
   subject, which it is not. */
.hero{position:relative;z-index:2;padding:88px 0 0;text-align:center;
      display:flex;flex-direction:column;align-items:center}
/* align-items:center sizes each child to its own content width rather than the
   column's, so any child wider than the phone viewport overflows instead of
   wrapping — .heroline is a single ~600px tracked-out line and did exactly
   that. Cap every hero child at the container. */
.hero > *{max-width:100%}
/* --dim on the near-black ground is about 4.0:1 — under the 4.5:1 floor for
   text this size, and it sits over the moving hero bars on top of that. */
.hero .eyebrow{color:#8f96a8}
.hero h1{font-family:var(--display);color:var(--bright);font-size:clamp(2.6rem,7.4vw,5.1rem);
         font-weight:700;letter-spacing:-.045em;line-height:.98;text-wrap:balance;
         margin:1.1rem 0 0;max-width:15ch}
.hero h1 em{font-style:normal;background:linear-gradient(96deg,var(--teal) 10%,var(--violet) 90%);
            -webkit-background-clip:text;background-clip:text;color:transparent}
.hero-sub{max-width:52ch;margin:1.5rem 0 0;font-size:1.1rem;color:var(--text)}

/* The offer, stated once, in the first screenful. It used to appear for the
   first time in section 11 of 14 — roughly 4,000px down — on a $10 product
   whose entire pitch is that it is $10. */
.hero-offer{margin:1.9rem 0 0;display:flex;align-items:center;gap:14px;flex-wrap:wrap;
            justify-content:center;font-family:var(--mono);font-size:.78rem;letter-spacing:.04em}
.hero-offer .price{font-family:var(--display);font-size:1.5rem;font-weight:700;letter-spacing:-.03em;
                   color:var(--bright);line-height:1}
.hero-offer .sep{width:1px;height:22px;background:var(--edge-hi)}
.hero-offer .t{color:var(--dim)}
.hero-offer .t b{color:var(--text);font-weight:500}

.hero .ctas{display:flex;gap:13px;flex-wrap:wrap;align-items:center;justify-content:center;margin-top:1.7rem}
.heroline{margin-top:2.2rem;font-family:var(--mono);font-size:.72rem;color:var(--dim);
          letter-spacing:.16em;text-transform:uppercase}
.heroline b{color:var(--teal);font-weight:400;opacity:.7}
.heromark{width:56px;height:56px;border-radius:14px;filter:drop-shadow(0 10px 30px rgba(0,0,0,.6))}

/* The window, full-bleed and larger than the text column. It is 1200px wide
   natively and the old 1080px grid showed it below native size — the one
   asset with real detail in it was the one being shrunk. */
.hero-shot{position:relative;z-index:1;margin:64px auto 0;width:min(1500px,94vw);padding:0 0 34px}
.hero-shot::before{content:"";position:absolute;left:50%;top:-6%;transform:translateX(-50%);
  width:82%;height:80%;pointer-events:none;z-index:0;
  background:radial-gradient(ellipse at center,
    rgba(42,208,196,.20),rgba(138,124,255,.14) 42%,rgba(255,43,208,.05) 62%,transparent 74%);
  filter:blur(70px)}
.hero-shot .realshot,.hero-shot .win{
  position:relative;z-index:1;border-radius:12px;
  box-shadow:0 50px 120px -30px rgba(0,0,0,.9),0 0 0 1px rgba(255,255,255,.055),
             0 1px 0 0 rgba(255,255,255,.07) inset}
.hero-shot .realshot{display:block;width:100%;border:0}

/* Window chrome for the illustration that stands in until a capture lands.
   Still load-bearing: it renders on first paint, before the data-shot probe
   resolves, and it is what a visitor sees if the PNG ever 404s. */
.win{position:relative;z-index:1;border:1px solid var(--edge);overflow:hidden;background:var(--panel)}
.winbar{display:flex;align-items:center;gap:8px;height:46px;padding:0 12px;
        background:linear-gradient(180deg,#1a1e28,#101319);
        border-bottom:1px solid var(--edge);font-family:var(--mono);font-size:.66rem;
        letter-spacing:.08em;color:var(--dim);overflow:hidden;white-space:nowrap}
/* Never shrink a control: on a narrow screen the bar should clip at the frame
   edge like a real window, not squeeze labels until they overlap each other. */
.winbar > *{flex:0 0 auto}
.winbar .wm{display:flex;align-items:center;gap:7px;color:var(--bright);letter-spacing:.1em;font-weight:700}
.winbar .wm img{width:18px;height:18px;border-radius:5px}
.ctl{border:1px solid var(--edge);border-radius:4px;padding:3px 9px;color:var(--text);background:rgba(255,255,255,.02)}
.ctl.knob{width:22px;height:22px;border-radius:50%;padding:0;position:relative;flex:0 0 auto}
.ctl.knob::after{content:"";position:absolute;left:50%;top:3px;width:1px;height:7px;background:var(--teal);
                 transform-origin:50% 8px;transform:translateX(-50%) rotate(38deg)}
.ctl.gear{width:24px;height:24px;padding:0;display:grid;place-items:center;color:var(--teal)}
.pill{display:flex;border:1px solid var(--edge);border-radius:4px;overflow:hidden}
.pill span{padding:3px 8px}
.pill span.on{background:var(--teal);color:#04211f}
.winbar .right{margin-left:auto;display:flex;align-items:center;gap:8px}
.wingrid{display:grid;grid-template-columns:1fr 104px;grid-template-rows:1.15fr 1fr;gap:6px;padding:8px;
         height:min(52vw,560px)}
.wpanel{position:relative;background:#08090c;border:1px solid var(--edge);border-radius:6px;overflow:hidden}
.wpanel canvas{display:block;width:100%;height:100%}
.wpanel::after{content:attr(data-label);position:absolute;left:8px;top:6px;font-family:var(--mono);
               font-size:.6rem;letter-spacing:.16em;color:var(--dim);pointer-events:none}
.w-spec{grid-column:1;grid-row:1}
.w-scope{grid-column:1;grid-row:2}
.w-gonio{display:none}
.w-meter{grid-column:2;grid-row:1/3}
@media (min-width:900px){
  .wingrid{grid-template-columns:1.55fr 1fr 104px}
  .w-spec{grid-column:1/3;grid-row:1}
  .w-scope{grid-column:1;grid-row:2}
  .w-gonio{display:block;grid-column:2;grid-row:2}
  .w-meter{grid-column:3;grid-row:1/3}
}

/* ─────────────────────── spec ribbon ─────────────────────── */

.ribbon{border-top:1px solid var(--edge);border-bottom:1px solid var(--edge);
        background:linear-gradient(180deg,rgba(255,255,255,.022),transparent)}
.ribbon .wrap{display:flex;flex-wrap:wrap;gap:14px 0;padding-top:22px;padding-bottom:22px;
              font-family:var(--mono);font-size:.72rem;letter-spacing:.06em;color:var(--dim)}
.ribbon span{flex:1 1 auto;text-align:center;padding:0 14px;border-left:1px solid var(--edge)}
.ribbon span:first-child{border-left:0}
.ribbon b{display:block;color:var(--bright);font-family:var(--display);font-size:1.15rem;
          font-weight:700;letter-spacing:-.02em;margin-bottom:2px}

/* ──────────────────── the five analyzers ──────────────────── */
/* Formerly two sections saying the same thing: an 8-card #features grid and a
   5-row #panels deep dive, both enumerating the same analyzers. The grid is
   gone; what it had that the rows did not (system audio, MINI, focus) moved to
   the standalone section where it belongs. */

.panelrow{display:grid;grid-template-columns:1.2fr .8fr;gap:44px;align-items:center;padding:52px 0;
          position:relative}
.panelrow + .panelrow::before{content:"";position:absolute;left:0;right:0;top:0;height:1px;
  background:linear-gradient(90deg,transparent,var(--grid) 20%,var(--grid) 80%,transparent)}
.panelrow.flip .pview{order:2}

.pview{border:1px solid var(--edge);border-radius:10px;overflow:hidden;background:#08090c;
       aspect-ratio:var(--pv,16/9);position:relative;
       box-shadow:0 28px 60px -24px rgba(0,0,0,.85)}
/* The levels capture is 232x876 — a portrait strip. In a 16:9 frame `contain`
   pillarboxes it into a sliver with dead space either side, so that row gets a
   frame shaped like its subject instead. */
.panelrow.tall{--pv:5/6}
.pview canvas{display:block;width:100%;height:100%}
/* Each analyzer takes its colour from the spectral ramp — panel 01 is the warm
   low end, 05 the violet top. The numbering is the plug-in's own colour rule. */
.pview::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(120% 80% at 50% 0%,var(--tint,transparent),transparent 62%);opacity:.13}
.pnum{font-family:var(--mono);font-size:.72rem;letter-spacing:.22em;color:var(--tint,var(--violet));
      display:flex;align-items:center;gap:10px}
.pnum::before{content:"";width:22px;height:2px;background:var(--tint,var(--violet));border-radius:2px}
.panelrow:nth-of-type(1){--tint:var(--sp-0)}
.panelrow:nth-of-type(2){--tint:var(--sp-1)}
.panelrow:nth-of-type(3){--tint:var(--sp-2)}
.panelrow:nth-of-type(4){--tint:var(--sp-3)}
.panelrow:nth-of-type(5){--tint:var(--sp-4)}

.panelrow h3{font-family:var(--display);color:var(--bright);font-size:1.5rem;font-weight:700;
             letter-spacing:-.03em;line-height:1.14;margin:.55rem 0 .7rem;text-wrap:balance}
.panelrow p{font-size:.95rem}
.speclist{list-style:none;margin-top:1.1rem;font-family:var(--mono);font-size:.75rem;color:var(--dim);
          border-top:1px solid var(--grid);padding-top:.9rem}
.speclist li{padding-left:15px;position:relative;margin-bottom:.42rem;letter-spacing:.02em;line-height:1.55}
.speclist li::before{content:"";position:absolute;left:0;top:.62em;width:5px;height:5px;border-radius:1px;
                     background:var(--tint,var(--accent))}
.speclist b{color:var(--text);font-weight:500}

/* ─────── illustration framing + the real-screenshot swap ─────── */
/* Unchanged mechanism: prisma-viz.js probes data-shot and replaces the live
   drawing with the photograph when the file exists. Two slots are still
   drawings and stay stamped as such. */
.slot{position:relative}
.slot:has(> .stamp){padding-bottom:26px}
.slot .stamp{position:absolute;right:2px;bottom:0;font-family:var(--mono);font-size:.58rem;
             letter-spacing:.16em;text-transform:uppercase;color:var(--dim);pointer-events:none}
.slot.is-real .stamp{display:none}
.slot .realshot{display:block;width:100%;border:1px solid var(--edge);border-radius:11px}
/* contain, not cover: these are UI panels, and the levels strip is 232x876 —
   cover would crop it to a horizontal sliver and throw away the readouts that
   are the whole point of the shot. */
.pview .realshot{height:100%;object-fit:contain;background:#08090c;border:0;border-radius:0}
.caveat{margin-top:16px;font-size:.85rem;color:var(--dim);max-width:var(--measure)}

/* ───────────────── standalone + the extras ───────────────── */

.split{display:grid;grid-template-columns:1fr 1fr;gap:52px;align-items:center}
.ticks{list-style:none;margin-top:1.2rem}
.ticks li{padding-left:26px;position:relative;margin-bottom:.6rem;font-size:.95rem}
.ticks li::before{content:"";position:absolute;left:2px;top:.62em;width:9px;height:9px;
                  border:1px solid var(--accent);border-right:0;border-top:0;
                  transform:rotate(-45deg) translateY(-2px)}

.mini{border:1px solid var(--edge);border-radius:9px;overflow:hidden;
      display:grid;grid-template-columns:2fr 2fr 1.6fr 1fr 88px;gap:1px;height:104px;
      background-color:var(--edge);box-shadow:0 24px 56px -22px rgba(0,0,0,.85)}
.mini > div{background:#08090c;position:relative}
.mini canvas{display:block;width:100%;height:100%}

/* Extras: not cards. A rule-separated technical list, so the page stops
   rendering six different ideas as the same rounded rectangle. */
.extras{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:0;margin-top:40px;
        border-top:1px solid var(--edge)}
.extras > div{padding:22px 24px 20px;border-left:1px solid var(--edge)}
.extras > div:first-child{border-left:0}
.extras h3{font-family:var(--display);color:var(--bright);font-size:.98rem;font-weight:700;
           letter-spacing:-.015em;margin-bottom:.4rem}
.extras p{font-size:.87rem}

/* ─────────────────── who it is for ─────────────────── */
/* Editorial, not boxed: an oversized index numeral and a rule, so this section
   reads as a magazine spread against the instrument panels around it. */
.who{display:grid;grid-template-columns:repeat(auto-fit,minmax(262px,1fr));gap:34px;counter-reset:w}
.who > div{position:relative;padding-top:30px;border-top:1px solid var(--edge-hi)}
.who > div::before{counter-increment:w;content:"0" counter(w);position:absolute;right:0;top:20px;
  font-family:var(--display);font-size:3.4rem;font-weight:700;letter-spacing:-.05em;line-height:1;
  color:var(--bright);opacity:.06;pointer-events:none}
.who .role{display:block;font-family:var(--mono);font-size:.66rem;letter-spacing:.2em;
           text-transform:uppercase;color:var(--accent);margin-bottom:12px}
.who h3{font-family:var(--display);color:var(--bright);font-size:1.18rem;font-weight:700;
        letter-spacing:-.025em;margin-bottom:.55rem;text-wrap:balance}
.who p{font-size:.92rem}

/* ─────────────────── under the hood ─────────────────── */
/* Technical credibility. Mono headings and a left keyline — this is the
   engineering appendix and it should look like one. */
.hood{display:grid;grid-template-columns:repeat(auto-fit,minmax(268px,1fr));gap:14px 34px}
.hood div{padding:2px 0 2px 20px;border-left:2px solid var(--edge-hi);transition:border-color .2s}
.hood div:hover{border-left-color:var(--accent)}
.hood h3{font-family:var(--mono);color:var(--bright);font-size:.82rem;font-weight:500;
         letter-spacing:.06em;text-transform:uppercase;margin-bottom:.5rem}
.hood p{font-size:.89rem}
code{font-family:var(--mono);font-size:.86em;color:var(--teal)}

/* ─────────────────── trial & licence ─────────────────── */
/* A flow, not three parallel boxes: the connecting rule says these happen in
   order, which is the entire content of the section. */
.steps{display:grid;grid-template-columns:repeat(auto-fit,minmax(232px,1fr));gap:0;counter-reset:s;
       margin-top:8px}
.step{position:relative;padding:52px 26px 4px 0}
.step::after{content:"";position:absolute;left:0;right:0;top:17px;height:1px;background:var(--edge)}
.step::before{counter-increment:s;content:counter(s);position:absolute;left:0;top:4px;
  display:grid;place-items:center;width:28px;height:28px;border-radius:50%;
  background:var(--bg);border:1px solid var(--accent);color:var(--accent);
  font-family:var(--mono);font-size:.74rem;z-index:1}
.step:last-child::after{right:26px}
.step h3{font-family:var(--display);color:var(--bright);font-size:1.05rem;font-weight:700;
         letter-spacing:-.02em;margin-bottom:.45rem}
.step p{font-size:.89rem}
kbd{font-family:var(--mono);font-size:.82em;background:rgba(255,255,255,.055);border:1px solid var(--edge-hi);
    border-radius:4px;padding:1px 6px;color:var(--bright)}

.note{margin-top:1.6rem;padding:14px 18px;border:1px solid var(--edge);border-left:3px solid var(--amber);
      border-radius:6px;font-size:.86rem;color:var(--text);background:rgba(228,198,91,.028);
      max-width:var(--measure)}

/* ─────────────────── download & specs ─────────────────── */

.specs{display:grid;grid-template-columns:1fr 1fr;gap:44px;align-items:start}
.specs table{width:100%;border-collapse:collapse;font-family:var(--mono);font-size:.8rem}
.specs td{padding:9px 0;border-bottom:1px solid var(--grid);vertical-align:top}
.specs tr:last-child td{border-bottom:0}
.specs td:first-child{color:var(--dim);width:36%;letter-spacing:.08em;text-transform:uppercase;
                      font-size:.68rem;padding-top:12px}
.specs td:last-child{color:var(--text)}
.specs p + p{margin-top:1rem}

.offer{border:1px solid var(--edge);border-radius:10px;padding:24px;background:var(--panel)}
.offer + .offer{margin-top:14px}
.offer h3{font-family:var(--display);color:var(--bright);font-size:1.16rem;font-weight:700;
          letter-spacing:-.025em;margin:.3rem 0 .55rem}
.offer p{font-size:.91rem}
.offer .go{margin-top:1.15rem}
/* The paid offer is the page's loudest object — a neon hairline and a bloom, so
   the eye lands on it before anything else in the section. */
.offer.paid{position:relative;border-color:transparent;background:
    linear-gradient(var(--panel),var(--panel)) padding-box,
    linear-gradient(125deg,var(--neon-pink),var(--violet) 52%,var(--neon-cyan)) border-box;
  border:1px solid transparent}
.offer.paid::before{content:"";position:absolute;inset:-1px;border-radius:10px;pointer-events:none;
  background:radial-gradient(90% 130% at 12% 0%,rgba(255,43,208,.11),transparent 58%)}
.offer.paid > *{position:relative}
.offer.paid .eyebrow{color:var(--neon-pink)}

/* ─────────────────── releases + faq ─────────────────── */

.relnotes{display:grid;grid-template-columns:repeat(auto-fit,minmax(290px,1fr));gap:34px}
.rel{border-left:2px solid var(--edge-hi);padding-left:22px}
.rel:first-child{border-left-color:var(--violet)}
.rel h3{font-family:var(--display);color:var(--bright);font-size:1.06rem;font-weight:700;
        letter-spacing:-.02em;margin-bottom:.2rem}
.rel .when{font-family:var(--mono);font-size:.66rem;letter-spacing:.16em;color:var(--dim);text-transform:uppercase}
.rel ul{list-style:none;margin-top:.9rem;font-size:.88rem}
.rel li{padding-left:16px;position:relative;margin-bottom:.5rem}
.rel li::before{content:"";position:absolute;left:0;top:.62em;width:5px;height:5px;border-radius:50%;
                background:var(--violet);opacity:.65}

/* Constrain the questions, not the section. Setting max-width on .wrap.faq
   centred the whole block and left its edge out of line with every section
   above it, which read as a mistake rather than as a narrow measure. */
.faq details{max-width:820px;border-bottom:1px solid var(--edge);padding:16px 0}
.faq summary{font-family:var(--display);cursor:pointer;color:var(--bright);font-weight:700;font-size:1.02rem;
             letter-spacing:-.02em;list-style:none;display:flex;gap:14px;align-items:flex-start;
             transition:color .18s}
.faq summary:hover{color:var(--teal)}
.faq summary::-webkit-details-marker{display:none}
.faq summary::before{content:"+";color:var(--accent);font-family:var(--mono);font-weight:400;line-height:1.5;
                     transition:transform .22s var(--ease)}
.faq details[open] summary::before{content:"–"}
.faq p{font-size:.93rem;margin:.7rem 0 0 28px;max-width:var(--measure)}

footer{border-top:1px solid var(--edge);padding:44px 0 56px;font-size:.84rem;color:var(--dim)}
footer .wrap{display:flex;flex-wrap:wrap;gap:10px 30px;align-items:center}

/* ──────────────── pointer-tracked border glow ──────────────── */
/* Ported from 21st.dev "Glowing Effect" (@manuarora700/glowing-effect, the
   Cursor-website treatment) as plain CSS — the original is React + Tailwind and
   this site has no build step. The trick is the two-layer mask: paint a radial
   gradient over the whole box, then punch the content area out of it with
   mask-composite, leaving light only on the 1px border ring.
   prisma-viz.js feeds --mx/--my from pointermove; with no JS the vars fall back
   to top-centre and the effect still reads as a static bloom on hover. */
.glow{position:relative}
.glow::before{
  content:"";position:absolute;inset:-1px;border-radius:inherit;padding:1px;pointer-events:none;
  background:radial-gradient(230px circle at var(--mx,50%) var(--my,0%),
    rgba(42,208,196,.75),rgba(138,124,255,.42) 38%,transparent 72%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;
  mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  mask-composite:exclude;
  opacity:0;transition:opacity .35s var(--ease);z-index:2}
.glow:hover::before{opacity:1}
/* The buy panel already carries a neon border, so its glow leans pink to match
   rather than fighting it with the teal used everywhere else. */
.offer.paid.glow::before{background:radial-gradient(230px circle at var(--mx,50%) var(--my,0%),
  rgba(255,43,208,.7),rgba(138,124,255,.4) 40%,transparent 72%)}

/* ─────────────────────── motion ─────────────────────── */
/* One orchestrated page-load, then scroll reveals. Everything here is opt-in
   via .reveal, and prefers-reduced-motion disables the lot at the bottom. */
@keyframes rise{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}
.hero > *{animation:rise .8s var(--ease) both}
.hero > *:nth-child(1){animation-delay:.02s}
.hero > *:nth-child(2){animation-delay:.09s}
.hero > *:nth-child(3){animation-delay:.16s}
.hero > *:nth-child(4){animation-delay:.23s}
.hero > *:nth-child(5){animation-delay:.30s}
.hero > *:nth-child(6){animation-delay:.37s}
.hero-shot{animation:rise 1s var(--ease) .34s both}

/* Scoped to .js — set by an inline script in <head>. Without it the rule never
   applies, so a visitor whose JS failed to load gets the whole page at full
   opacity instead of a blank one. Never hide content behind a script that
   might not run. */
.js .reveal{opacity:0;transform:translateY(20px);transition:opacity .7s var(--ease),transform .7s var(--ease)}
.js .reveal.in{opacity:1;transform:none}

/* ─────────────────────── responsive ─────────────────────── */

@media (max-width:1000px){
  .navlinks{display:none}
  .specs,.split{grid-template-columns:1fr;gap:34px}
  .panelrow{grid-template-columns:1fr;gap:26px}
  .panelrow.flip .pview{order:0}
  .hero-shot{width:96vw;margin-top:48px}
}
/* Product pages now carry three crumbs (Deish Media / Deish.Audio / product)
   instead of two, and nav .wrap never wraps — it clips like a real window bar.
   Once the nav links have gone there is no longer room for the status pill as
   well as the button, so it leaves first. It comes back above this width. */
@media (max-width:880px){ .navbeta{display:none} }
@media (max-width:760px){
  section{padding:66px 0}
  .hero{padding-top:62px}
  .hero-offer{gap:10px}
  .hero-offer .sep{display:none}
  .ribbon span{flex:1 0 46%;border-left:0;text-align:left;padding:0 8px}
  .mini{grid-template-columns:1.6fr 1.6fr 1fr;height:84px}
  .mini > div:nth-child(n+4){display:none}
  .extras{grid-template-columns:1fr}
  .extras > div{border-left:0;border-top:1px solid var(--edge)}
  .extras > div:first-child{border-top:0}
  .steps{grid-template-columns:1fr;gap:26px}
  .step{padding:44px 0 0}
  .step::after{right:auto;width:1px;height:100%;top:34px;left:13px;background:var(--edge)}
  .step:last-child::after{display:none}
  .hood{gap:20px}
}
@media (max-width:560px){
  .navbeta,.crumb,.crumbsep{display:none}
  .navname{font-size:.88rem}
  .btn{padding:12px 20px}
  .hero .ctas{width:100%;flex-direction:column;align-items:stretch}
  .hero .ctas .btn{text-align:center}
}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation:none!important;transition:none!important}
  .reveal{opacity:1;transform:none}
  .hero > *,.hero-shot{opacity:1;transform:none}
}

/* ───────────── per-line accents + hub pages ───────────── */
/* The three hubs share this stylesheet; only the accent and its ink colour
   change, so a hub never drifts visually from the others again. */
/* audio is the sheet's default accent already; stated anyway so all three lines
   are switched by the same visible mechanism rather than one being implicit. */
body[data-line="audio"]{--accent:var(--teal);   --accent-ink:#04211f}
body[data-line="trading"]{--accent:var(--green); --accent-ink:#04220f}
body[data-line="apparel"]{--accent:var(--amber); --accent-ink:#2a2103}

/* Simple hub pages: a lede + stacked cards, no analyzers. .card is used ONLY
   here now that the product page's feature grid is gone — keep it self-contained. */
.hub{padding:104px 0 84px;position:relative}
.hub::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;
  background:linear-gradient(90deg,transparent,var(--edge) 18%,var(--edge) 82%,transparent)}
.hub h1{font-family:var(--display);color:var(--bright);font-size:clamp(2.2rem,6vw,3.6rem);font-weight:700;
        letter-spacing:-.04em;line-height:1.04;text-wrap:balance;margin:1.1rem 0 0}
/* Same gradient em as the product hero, but keyed to --accent so a hub tints it
   to its own line instead of hard-coding teal. */
.hub h1 em{font-style:normal;background:linear-gradient(96deg,var(--accent) 10%,var(--violet) 90%);
           -webkit-background-clip:text;background-clip:text;color:transparent}
.hub .lede{max-width:36em;margin:1.5rem 0 0;font-size:1.08rem}
.hub .ctas{display:flex;gap:13px;flex-wrap:wrap;align-items:center;margin-top:1.9rem}
.chip.soon{color:var(--dim)}

.card{background:var(--panel);border:1px solid var(--edge);border-radius:9px;padding:24px;
      transition:border-color .2s,transform .2s var(--ease)}
.card:hover{border-color:var(--accent);transform:translateY(-2px)}
.card h3{font-family:var(--display);color:var(--bright);font-size:1.06rem;font-weight:700;
         letter-spacing:-.02em;margin-bottom:.45rem}
.card p{font-size:.92rem;color:var(--text)}
.stack .card + .card{margin-top:14px}
.chip{font-family:var(--mono);font-size:.64rem;letter-spacing:.12em;text-transform:uppercase;
      color:var(--accent);border:1px solid var(--edge-hi);padding:3px 10px;border-radius:99px;
      margin-left:8px;white-space:nowrap;vertical-align:2px}

/* ───────────── long-form content pages (about, privacy, terms, ai
   policy, accessibility) ───────────── */
/* These read like a document, not a brochure — plain headings, paragraphs and
   lists rather than cards. Scoped to .legal so the global reset's zeroed
   ul/ol padding doesn't leak into the rest of the site. */
.legal{max-width:var(--measure);margin:0 auto}
.legal .updated{font-family:var(--mono);font-size:.78rem;color:var(--dim);margin-bottom:2.4rem}
.legal h2{margin-top:2.8rem}
.legal section:first-of-type h2,.legal h2:first-child{margin-top:0}
.legal h3{font-family:var(--display);color:var(--bright);font-size:1.14rem;font-weight:700;
          letter-spacing:-.02em;margin:1.9rem 0 .7rem}
.legal p{margin-bottom:1rem}
.legal ul,.legal ol{margin:0 0 1.2rem 1.25em}
.legal li{margin-bottom:.5rem}
.legal a{text-decoration:underline;text-underline-offset:3px}
.legal strong{color:var(--bright);font-weight:600}

/* ───────────── the Deish.Audio line-up (/audio/) ─────────────
   A brand hub lists products; it does not re-describe them. Each .prod is a
   picture, a paragraph, a spec line and a way in — the deep dive lives on the
   product's own page and is written there ONCE (see website/README.md #3).
   .card stays reserved for /trading/ and /apparel/, which have no visuals. */

.lineup{display:flex;flex-direction:column;gap:0}
.prod{display:grid;grid-template-columns:1.15fr .85fr;gap:44px;align-items:center;padding:46px 0;
      position:relative}
.prod + .prod::before{content:"";position:absolute;left:0;right:0;top:0;height:1px;
  background:linear-gradient(90deg,transparent,var(--grid) 20%,var(--grid) 80%,transparent)}
.prod .shot{border:1px solid var(--edge);border-radius:10px;overflow:hidden;background:#08090c;
            position:relative;box-shadow:0 28px 60px -24px rgba(0,0,0,.85)}
.prod .shot img{display:block;width:100%;height:auto}
.prod h3{font-family:var(--display);color:var(--bright);font-size:1.65rem;font-weight:700;
         letter-spacing:-.035em;line-height:1.1;margin:.5rem 0 .7rem;text-wrap:balance}
.prod p{font-size:.95rem}
/* The one-line contents list, in the plug-in's own mono voice. */
.prod .parts{font-family:var(--mono);font-size:.72rem;letter-spacing:.1em;text-transform:uppercase;
             color:var(--dim);margin-top:1.1rem;border-top:1px solid var(--grid);padding-top:.9rem}
.prod .parts b{color:var(--text);font-weight:400}
/* Status is stated as a fact next to the name, not implied by whether a button
   exists. A product with no purchase path has to SAY it has no purchase path. */
.prod .state{font-family:var(--mono);font-size:.7rem;letter-spacing:.18em;text-transform:uppercase;
             color:var(--accent);display:flex;align-items:center;gap:10px}
.prod .state::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--accent);
                     box-shadow:0 0 12px 1px currentColor}
.prod.wip .state{color:var(--dim)}
.prod.wip .state::before{background:transparent;border:1px solid var(--dim);box-shadow:none}
/* Full text colour, not --dim: on the in-development card this line is the
   "you cannot buy this yet" disclosure, and a disclosure set in the page's
   quietest grey is a disclosure that did not happen. */
.prod .terms{margin-top:1rem;font-size:.88rem;color:var(--text)}
.prod .terms b{color:var(--bright);font-weight:600}
.prod .ctas{display:flex;gap:12px;flex-wrap:wrap;align-items:center;margin-top:1.5rem}

/* ───────────── Base6 window illustration (/audio/base6/) ─────────────
   Pure CSS, no canvas: there is no capture of Base6 yet, and an empty grey box
   is how /audio/ sat broken for weeks. Six equal tiles in one row = the routing
   order, framed by the in/out meters, exactly as the plug-in draws it. Each
   tile wears its module's stop of the ramp (audio/Base6/docs/DESIGN.md §2).
   Stamped Illustration; drop a real PNG at the data-shot path and prisma-viz.js
   swaps it in with no markup change. */

/* The six module hues, defined ONCE and taken from --sp-*, the same spectral
   ramp the plug-in draws. Base6's ColorMap::moduleColour() uses these exact
   stops (audio/Base6/docs/DESIGN.md §2) and the two must not drift apart, which
   is the whole reason they are derived here rather than typed as hexes into the
   markup. Delay sits between the last two stops, so it is mixed rather than
   picked. Apply to a route chip, a tile, or a .chain entry — anything that
   should be identifiable as one module by hue alone. */
.m-utl{--m:var(--sp-0)}
.m-eq {--m:var(--sp-1)}
.m-flt{--m:var(--sp-2)}
.m-dyn{--m:var(--sp-3)}
.m-dly{--m:color-mix(in srgb,var(--sp-3),var(--sp-4))}
.m-rvb{--m:var(--sp-4)}

.b6win{position:relative;z-index:1;border:1px solid var(--edge);border-radius:12px;overflow:hidden;
       background:var(--panel);
       box-shadow:0 50px 120px -30px rgba(0,0,0,.9),0 0 0 1px rgba(255,255,255,.055),
                  0 1px 0 0 rgba(255,255,255,.07) inset}
.b6bar{display:flex;align-items:center;gap:8px;height:46px;padding:0 12px;
       background:linear-gradient(180deg,#1a1e28,#101319);border-bottom:1px solid var(--edge);
       font-family:var(--mono);font-size:.66rem;letter-spacing:.08em;color:var(--dim);
       overflow:hidden;white-space:nowrap}
.b6bar > *{flex:0 0 auto}
.b6bar .wm{color:var(--bright);letter-spacing:.1em;font-weight:700}
/* The route chips double as the legend: chip order is signal order, chip colour
   is module identity. */
.b6route{display:flex;gap:5px;margin-left:6px}
.b6route span{border:1px solid var(--edge);border-radius:4px;padding:3px 8px;
              color:var(--m,var(--text));background:rgba(255,255,255,.02)}
.b6bar .right{margin-left:auto;display:flex;align-items:center;gap:8px}

/* Kept near the real window's proportions (its minimum is 1000x680). Taller
   than this and each tile becomes a mostly-empty column, which reads as an
   unfinished drawing rather than a plug-in. */
.b6body{display:grid;grid-template-columns:12px 1fr 12px;gap:8px;padding:10px;
        height:min(30vw,330px)}
/* Level bars never wear a module hue — calm/amber/red is the universal reading
   and Base6's own design doc calls that non-negotiable. */
.b6meter{border:1px solid var(--edge);border-radius:4px;background:#08090c;position:relative;overflow:hidden}
.b6meter::after{content:"";position:absolute;left:0;right:0;bottom:0;height:var(--fill,58%);
  background:linear-gradient(180deg,var(--amber),var(--green) 34%,var(--green))}
.b6meter.in{--fill:54%}
.b6meter.out{--fill:62%}
.b6row{display:grid;grid-template-columns:repeat(6,1fr);gap:6px;min-width:0}
.b6tile{background:#08090c;border:1px solid var(--edge);border-radius:6px;position:relative;
        overflow:hidden;display:flex;flex-direction:column;min-width:0}
.b6tile::before{content:"";height:2px;background:var(--m,var(--accent));opacity:.85}
.b6tile b{font-family:var(--mono);font-size:.58rem;letter-spacing:.13em;text-transform:uppercase;
          color:var(--m,var(--text));font-weight:400;padding:8px 7px 0;
          overflow:hidden;text-overflow:ellipsis}
/* Two knob arcs per tile — enough to read as controls-on-the-face without
   pretending to be a screenshot of specific settings. */
.b6knobs{display:flex;gap:7px;padding:10px 7px;flex-wrap:wrap}
.b6knobs i{width:22px;height:22px;border-radius:50%;border:1px solid var(--edge-hi);position:relative;
           display:block;flex:0 0 auto}
.b6knobs i::after{content:"";position:absolute;left:50%;top:2px;width:1px;height:7px;
  background:var(--m,var(--accent));transform-origin:50% 9px;
  transform:translateX(-50%) rotate(var(--a,30deg))}
/* Spread the indicator angles so the row does not read as one control stamped
   six times. Positional, not per-element, so the markup carries no styling. */
.b6knobs i:nth-child(1){--a:-34deg}
.b6knobs i:nth-child(2){--a:22deg}
.b6knobs i:nth-child(3){--a:-6deg}
.b6tile:nth-child(2) .b6knobs i:nth-child(1),
.b6tile:nth-child(5) .b6knobs i:nth-child(2){--a:54deg}
.b6tile:nth-child(3) .b6knobs i:nth-child(2),
.b6tile:nth-child(6) .b6knobs i:nth-child(1){--a:-58deg}
.b6tile:nth-child(4) .b6knobs i:nth-child(1){--a:8deg}
.b6tile em{margin-top:auto;height:52%;display:block;
  background:linear-gradient(180deg,transparent,color-mix(in srgb,var(--m,var(--accent)) 26%,transparent))}

/* The six modules as prose. Same keyline grammar as .hood, but each entry keeps
   its module hue so the list and the window agree about which one is which —
   that is the whole point of colouring by chain position. */
.chain{display:grid;grid-template-columns:repeat(auto-fit,minmax(268px,1fr));gap:20px 34px}
.chain > div{padding:2px 0 2px 20px;border-left:2px solid var(--m,var(--edge-hi))}
.chain h3{font-family:var(--mono);color:var(--m,var(--bright));font-size:.82rem;font-weight:500;
          letter-spacing:.08em;text-transform:uppercase;margin-bottom:.5rem}
.chain h3 span{color:var(--dim);letter-spacing:.14em;font-size:.68rem;margin-left:8px}
.chain p{font-size:.89rem}

/* Inside a product card the frame is only ~half the page wide, so the same
   height would stand the tiles up as narrow columns again. */
.prod .b6body{height:min(20vw,230px)}

@media (max-width:1000px){
  .prod{grid-template-columns:1fr;gap:26px}
  .b6body,.prod .b6body{height:min(46vw,300px)}
}
@media (max-width:760px){
  /* Six tiles at phone width is four pixels each. Show the first three of the
     chain and let the frame clip, the way the .winbar already does. */
  .b6row{grid-template-columns:repeat(3,1fr)}
  .b6tile:nth-child(n+4){display:none}
  .b6knobs i:nth-child(n+3){display:none}
}
