/* --- Hero --------------------------------------------------------------- */

.hero {
  display: grid; grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.25fr);
  gap: var(--ar-s-8); align-items: center;
  /* top-lit chassis, one flat value step. Not a gradient wash. */
  background-image: radial-gradient(90% 70% at 8% 0%, rgba(255,255,255,.024), transparent 68%);
}
@media (max-width: 1000px) { .hero { grid-template-columns: 1fr; gap: var(--ar-s-6); } }

/* Atmosphere behind the hero, in two layers on one pseudo element.
   Fading a near-black photo over a charcoal page is arithmetically a no-op: 13% of
   #000 over #1E1E1E is still #1E1E1E. Only the highlights carry information, so the
   plate is SCREEN blended - black contributes nothing, the rim light adds glow - and a
   soft warm radial is screened in above it to give that light a source.
   The scrim (::after) is horizontal and opaque down the copy column, so the plate can
   only ever brighten the half of the band that has no text. Measured against the flat
   band: right-hand side +7.1 luminance with a warm cast, the headline's own backdrop
   -1.1 and cast 0.0, i.e. untouched. That matters, because the first headline line is
   --ar-text-2 (#888) and sits at 4.91:1 on flat charcoal; lifting its backdrop by the
   ~6 levels a full-band wash produces drops it to 4.53:1, a hair off the 4.5 floor.
   Pseudo elements would otherwise become grid items - position:absolute takes them
   out of grid flow, which is why the two-column layout is unaffected. */
.hero { position: relative; overflow: hidden; }
.hero > div { position: relative; z-index: 1; }
.hero::before, .hero::after { content: ""; position: absolute; inset: 0; z-index: 0; }
.hero::before {
  background-image:
    radial-gradient(120% 95% at 90% 4%, rgba(255,172,98,.15), rgba(255,172,98,.05) 38%, transparent 62%),
    url("/img/atmos/hero-tex.webp");
  background-size: auto, cover;
  background-position: 0 0, 68% 50%;
  background-repeat: no-repeat;
  mix-blend-mode: screen; opacity: .62; filter: saturate(.85);
  /* Faded out by 300px from the TOP, in px rather than a percentage of the band.
     The light worth having is the top right, above the switcher; everything lower is
     where the text lives. A percentage stop tracks the band's height, and the band
     grows when the headline wraps - which silently slid the cutoff down past
     .switch-cap at 1024-1100px and leaked +15 levels into 11px grey text (3.87:1).
     The caption never sits closer than ~510px to the band top at any width above the
     single-column breakpoint, so 300px clears it with room to spare. */
  -webkit-mask-image: linear-gradient(180deg, #000 190px, rgba(0,0,0,0) 300px);
          mask-image: linear-gradient(180deg, #000 190px, rgba(0,0,0,0) 300px);
}
/* Fully opaque out to 48%, which clears the copy column's right edge at 41%. The
   original 24% stop only reached 81% opacity there, and the 19% that leaked was
   enough to put the lede's worst pixel at 4.31:1. The mask on ::before handles the
   vertical direction, so one gradient is enough here. */
.hero::after {
  background: linear-gradient(90deg, var(--ar-bg) 48%, rgba(30,30,30,.58) 64%, rgba(30,30,30,.30) 100%);
}
/* Single column. The copy now spans the full width, so the horizontal scrim protects
   nothing - worse, it would paint --ar-bg over the left 48% and leave the light stranded
   on one side. It goes, and the mask does the work on its own.
   Measured on a 390px hero (1132px tall) there is exactly one safe window for light:
     kicker  y  38-55   10.5px #888  -> floor 4.5:1, tolerates a backdrop of only 34/255
     line 1  y  79-118    38px #888  -> LARGE text, floor 3:1, tolerates 62/255
     line 2  y 118-197    38px #E0E0E0
     lede    y 221-465  17.5px #888  -> floor 4.5:1 again
   So the plate is banded into 76-194px: below the kicker, across the display type that
   has the headroom to carry it, and gone before the lede. The lamp moves to 78% 14% so
   its core lands behind the headline rather than up in the kicker. */
@media (max-width: 1000px) {
  .hero::after { display: none; }
  .hero::before {
    background-image:
      radial-gradient(150% 120% at 78% 14%, rgba(255,172,98,.17), rgba(255,172,98,.05) 40%, transparent 66%),
      url("/img/atmos/hero-tex.webp");
    /* NOT cover here. The mobile hero box is 388x1132 - portrait - and cover on a 21:9
       image scales it to 2638px wide, so a phone sees a 15% slice: what reads as fine
       texture on a desktop becomes coarse blobs sitting behind the letters. Pinning the
       image to 620px wide keeps it at roughly desktop scale, and the blur turns what is
       left into a form rather than a recognisable shape. */
    background-size: auto, 620px auto;
    background-position: 0 0, 46% 34%;
    opacity: .5;
    filter: saturate(.8) blur(7px);
    /* Longer fades at both ends. 24px was short enough for the bottom one to read as a
       hard edge under the headline. The stops are still bounded by the kicker ending at
       55px and the lede starting at 221px. */
    -webkit-mask-image: linear-gradient(180deg,
      rgba(0,0,0,0) 60px, #000 98px, #000 168px, rgba(0,0,0,0) 220px);
            mask-image: linear-gradient(180deg,
      rgba(0,0,0,0) 60px, #000 98px, #000 168px, rgba(0,0,0,0) 220px);
  }
  /* Both of these sit outside the lit band, so a flat --ar-bg fill is invisible. It is
     here to pin them: the mask gradient's alpha dithers by 1/255 across the whole
     pseudo-element, which is enough to read as 4.49:1 instead of the design's 4.54:1
     baseline. Same fix, same reason, as .switch-row and .switch-cap. It also means that
     if the headline ever reflows far enough to push the lede up into the band, the lede
     brings its own backdrop with it. */
  .hero-kicker, .hero p.lede { background: var(--ar-bg); }
}

.hero-kicker { display: inline-flex; align-items: center; gap: 8px; margin-bottom: var(--ar-s-5); }

h1 {
  font-size: clamp(38px, 4.9vw, 58px);
  letter-spacing: -0.028em;
  margin-bottom: var(--ar-s-5);
}
h1 .l1 { display: block; font-weight: 400; color: var(--ar-text-2); }
h1 .l2 { display: block; font-weight: 700; color: var(--ar-text); }

.hero p.lede { margin-bottom: var(--ar-s-5); }

.spec-strip {
  display: flex; flex-wrap: wrap;
  border: var(--ar-border); background: var(--ar-ink);
  margin-bottom: var(--ar-s-5);
}
.spec-strip div {
  flex: 1 1 auto; white-space: nowrap; padding: 9px 14px; border-right: var(--ar-border);
  font-family: var(--ar-font-mono); font-size: 10.5px; letter-spacing: .06em; color: var(--ar-text-2);
}
.spec-strip div:last-child { border-right: 0; }
.spec-strip b { color: var(--ar-text); font-weight: 400; }
/* Phones: four chips fit three-then-one, and because the cells are flex: 1 1 auto the
   orphan stretches the full width and reads as a second, separate bar rather than the
   tail of the first. A 2x2 grid is the same information deliberately arranged. */
@media (max-width: 560px) {
  .spec-strip { display: grid; grid-template-columns: 1fr 1fr; }
  .spec-strip div { border-right: var(--ar-border); border-bottom: var(--ar-border); }
  .spec-strip div:nth-child(2n) { border-right: 0; }
  .spec-strip div:nth-last-child(-n+2) { border-bottom: 0; }
}

.cta-row { display: flex; flex-wrap: wrap; gap: var(--ar-s-3); align-items: center; }
/* Phones: the two hero buttons are ~196px each against a 358px column, so they stacked.
   Equal halves of the row instead, with the label allowed to wrap onto a second line -
   keeping nowrap would make the text spill out of the button on a 320px screen, trading
   a stacked pair for a sideways scrollbar. The 44px touch minimum is untouched. */
@media (max-width: 560px) {
  .hero .cta-row { flex-wrap: nowrap; gap: var(--ar-s-2); }
  .hero .cta-row .btn {
    flex: 1 1 0; min-width: 0; padding: 6px 8px;
    font-size: 10.5px; letter-spacing: .04em;
    white-space: normal; line-height: 1.15; text-align: center;
  }
}
.cta-note { font-family: var(--ar-font-mono); font-size: 10.5px; color: var(--ar-text-2); letter-spacing: .06em; margin-top: var(--ar-s-3); }

/* --- Routing matrix (the signature visual) ------------------------------ */

.matrix {
  position: relative;
  border: var(--ar-border);
  background:
    radial-gradient(120% 90% at 50% 45%, rgba(255,255,255,.022), transparent 70%),
    var(--ar-ink);
  padding: var(--ar-s-4) var(--ar-s-3) 0;
}
.matrix svg { display: block; width: 100%; height: auto; }

/* HUD corner brackets — used once, here only */
.matrix::before, .matrix::after {
  content: ""; position: absolute; width: 12px; height: 12px; pointer-events: none;
  border-color: var(--ar-line-2); border-style: solid;
}
.matrix::before { top: -1px; left: -1px; border-width: 1px 0 0 1px; border-color: var(--ar-record); }
.matrix::after  { bottom: -1px; right: -1px; border-width: 0 1px 1px 0; border-color: var(--ar-record); }

.matrix-foot {
  display: flex; align-items: center; gap: var(--ar-s-4); flex-wrap: wrap;
  border-top: var(--ar-border); margin: 0 calc(var(--ar-s-4) * -1);
  padding: 10px var(--ar-s-4);
  font-family: var(--ar-font-mono); font-size: 10px; letter-spacing: .08em; color: var(--ar-text-2);
}

/* Small screens, third attempt, and worth recording why.
   First the diagram was hidden, which left an empty band under a heading. Then it
   scrolled sideways at 560px so the labels stayed readable - but a scrollbar with half a
   diagram behind it reads as a broken page, which is exactly how it was reported.
   So now it is hidden again AND replaced: .flow-mini plus .dest-list tell the same
   sources -> tap -> destinations story vertically, and the section is no longer empty.
   The lesson is that hiding a visual is only wrong when nothing takes its place. */
.dest-list, .flow-mini { display: none; }
@media (max-width: 620px) {
  .matrix { padding: 0; }
  .matrix > svg { display: none; }
  .flow-mini { display: block; padding: var(--ar-s-4) 14px var(--ar-s-3); text-align: center; }
  .flow-mini .lab {
    display: block; font-family: var(--ar-font-mono); font-size: 9.5px;
    letter-spacing: .12em; text-transform: uppercase; color: var(--ar-line-2);
  }
  .flow-mini p {
    margin: 6px 0 0; font-family: var(--ar-font-mono); font-size: 11px;
    line-height: 1.7; color: var(--ar-text-2);
  }
  .flow-mini .arw { display: block; margin: 8px 0; color: var(--ar-line-2); font-size: 13px; }
  .flow-mini .core {
    display: inline-block; padding: 7px 12px; border: 1px solid var(--ar-record-24);
    background: var(--ar-record-12); color: var(--ar-text);
    font-family: var(--ar-font-mono); font-size: 10.5px; letter-spacing: .06em;
  }
  .flow-mini .lab:last-child { margin-top: 2px; }
  .dest-list { display: block; list-style: none; margin: 0; padding: 0; }
  .dest-list li { padding: 12px 14px; border-bottom: var(--ar-border); display: flex; flex-direction: column; gap: 2px; }
  .dest-list b { font-family: var(--ar-font-mono); font-size: 11px; letter-spacing: .1em; color: var(--ar-text); font-weight: 400; }
  .dest-list span { font-family: var(--ar-font-mono); font-size: 10px; letter-spacing: .06em; color: var(--ar-text-2); }
  .matrix-foot { margin: 0; }
  .matrix::before, .matrix::after { display: none; }
}

/* SVG primitives */
.n-box { fill: var(--ar-ink); stroke: var(--ar-line); stroke-width: 1; }
.n-core { fill: var(--ar-panel); stroke: var(--ar-line-2); stroke-width: 1; }
.n-t  { font-family: var(--ar-font-mono); font-size: 10px; letter-spacing: .09em; fill: var(--ar-text-2); text-transform: uppercase; }
.n-s  { font-family: var(--ar-font-mono); font-size: 8.5px; letter-spacing: .07em; fill: var(--ar-text-2); }
.cord-base { fill: none; stroke: var(--ar-line); stroke-width: 1; }
.jacks circle { fill: var(--ar-ink); stroke: var(--ar-line-2); stroke-width: 1; }
.cord-live { fill: none; stroke-width: 1.8; stroke-dasharray: 5 58; stroke-linecap: round; animation: ar-flow 3s linear infinite; }
.cord-live.in  { stroke: var(--ar-blue); }
.cord-live.out { stroke: var(--ar-record); }
@keyframes ar-flow { from { stroke-dashoffset: 63 } to { stroke-dashoffset: 0 } }

.dest { cursor: pointer; }
.dest rect { transition: stroke 160ms ease-out, fill 160ms ease-out; }
.dest:hover rect { stroke: var(--ar-blue); fill: #171717; }
.dest:hover .n-t { fill: var(--ar-text); }

/* Core meters — level, not decoration */
.mfill { transform-box: fill-box; transform-origin: left center; transform: scaleX(.5); opacity: .92; }
.mpeak { fill: var(--ar-text); opacity: .8; }
.tab { font-variant-numeric: tabular-nums; }
.rec-led { animation: ar-pulse 2.6s ease-in-out infinite; }

/* --- Proof strip -------------------------------------------------------- */

.proof-strip { display: flex; align-items: center; gap: var(--ar-s-5); flex-wrap: wrap; padding: 13px var(--ar-s-6); }
/* 84px fitted "COVERED BY" and "WORKS WITH" (76px each) but not "DISCUSSED ON", which needs
   91px - so the third label alone wrapped onto two lines and sat visibly out of line with the
   other two. 96px plus nowrap keeps all three on one line and keeps the column aligned, which
   is the whole point of a fixed label width. */
.proof-strip .lab { flex: none; width: 96px; white-space: nowrap; }
.proof-strip.row-2 { border-top: 1px solid rgba(255,255,255,.055); }
.proof-strip.row-2 .hosts { margin-left: 0; }
.press-list { display: flex; align-items: center; gap: var(--ar-s-5); flex-wrap: wrap; }
.press-list a { font-family: var(--ar-font-mono); font-size: 11.5px; letter-spacing: .09em; text-transform: uppercase; color: var(--ar-text-2); }
.press-list a:hover { color: var(--ar-text); text-decoration: none; }
/* Phones: five press names wrap into a block under the label, and "All coverage" ends up
   buried at the bottom of it. display:contents dissolves the list wrapper so its links
   become flex items of the strip itself, which lets order put the all-coverage link
   right beside the label as a button, with the top three names wrapping below it. The
   fourth name is dropped rather than shown as a fragment - /press has the full list.
   No duplicated markup, and desktop is untouched. */
@media (max-width: 560px) {
  .proof-strip .press-list { display: contents; }
  .proof-strip .lab { order: -2; width: auto; }
  .press-list a.all {
    order: -1; border: 1px solid var(--ar-line-2); padding: 4px 8px;
    font-size: 10px; color: var(--ar-text);
  }
  /* Everything past the third name, except the all-coverage link, which order has
     already moved up beside the label. Written as n+4 rather than :nth-of-type(4) so
     adding an outlet cannot silently push a fourth name back onto the phone - which
     is exactly what happened when Sound on Sound was added at the front. */
  .press-list a:nth-of-type(n+4):not(.all) { display: none; }
  /* The three names need 351px at 11.5px/.09em in a 324px column, so Mixmag MENA
     orphaned onto a third line. A step down in size and tracking brings them to ~304px
     and all three sit on one line, which is the point of showing three. */
  /* Three names sat exactly on the right edge at 390px - zero slack, so any device whose
     font metrics differ by a hair would push the third onto its own line. A step down in
     size and gap buys ~20px of margin and keeps all three together down to 360px. */
  .press-list a { font-size: 10px; letter-spacing: .04em; }
  .proof-strip { column-gap: 11px; row-gap: 10px; }
  /* The names must start a new line, not fill whatever room is left beside the button.
     Relying on the natural wrap only looked right at 390px; at 466px two names fitted on
     the label's line and the third orphaned below. .brk sorts to the same order as the
     all-coverage link and follows it in the DOM, so it lands immediately after it and
     its 100% basis pushes every name to the next line at any width. */
  /* .proof-strip prefix, not a bare .brk: the global `.brk { display: none }` lives
     further down this file, and at equal specificity source order wins - so the bare
     selector lost at every width and this break never fired. */
  .proof-strip .brk { display: block; order: -1; flex: 0 0 100%; height: 0; }
}
.hosts { margin-left: auto; display: flex; gap: var(--ar-s-4); flex-wrap: wrap; font-family: var(--ar-font-mono); font-size: 11px; letter-spacing: .07em; color: var(--ar-text-2); }

/* --- Paths (interactive product demo) ----------------------------------- */

.paths { display: grid; grid-template-columns: repeat(3, 1fr); }
.paths > * { border-right: var(--ar-border); }
.paths > *:last-child { border-right: 0; }
@media (max-width: 940px) {
  .paths { grid-template-columns: 1fr; }
  .paths > * { border-right: 0; border-bottom: var(--ar-border); }
  .paths > *:last-child { border-bottom: 0; }
}

.path { padding: var(--ar-s-5); display: flex; flex-direction: column; gap: var(--ar-s-4); scroll-margin-top: 70px; }
.path-h { display: flex; align-items: baseline; gap: var(--ar-s-3); }
.path-h .n { font-family: var(--ar-font-mono); font-size: 10.5px; letter-spacing: .12em; color: var(--ar-record); }
.path p { font-size: 14.5px; color: var(--ar-text-2); margin: 0; }
.path p code { font-family: var(--ar-font-mono); font-size: 13px; color: var(--ar-text); background: var(--ar-ink); border: var(--ar-border); border-radius: var(--ar-r-1); padding: 1px 5px; }
.path ul { margin: 0; padding: 0; list-style: none; font-family: var(--ar-font-mono); font-size: 11px; color: var(--ar-text-2); letter-spacing: .04em; }
.path ul li { padding: 5px 0; border-top: 1px solid rgba(255,255,255,.05); display: flex; gap: 8px; }
.path ul li::before { content: "+"; color: var(--ar-line-2); }
.path .go { margin-top: auto; font-family: var(--ar-font-mono); font-size: 11px; letter-spacing: .07em; }
/* Both of these cards offered a single Mac link. Path 02's own bullet says the device
   ships on macOS and Windows, so linking only the Mac setup contradicted the card; Path
   01 led with Logic, which a Windows reader cannot run. Each now names two hosts, which
   is also the cheapest correction to the page reading as Mac-first. */
.path .go { color: var(--ar-text-2); }
.path .go .sep { color: var(--ar-line-2); margin: 0 7px; }

/* Screenshot chassis frame — real UI, framed like hardware. No drop shadow. */
.shot { border: var(--ar-border); background: var(--ar-ink); }
.shot .win { padding: var(--ar-s-3); display: flex; align-items: center; justify-content: center; height: 232px; }
.shot img { display: block; max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; border-radius: var(--ar-r-1); }
.shot video { display: block; width: 100%; height: auto; border-radius: var(--ar-r-1); background: var(--ar-ink); }
/* Path-card loops. Real product motion, so they earn autoplay; muted, short and
   silent-encoded (no audio track at all). Height is fixed so the three cards
   stay aligned whatever each clip's aspect is. */
.path .shot .win.film { height: auto; padding: 0; }
.path .shot video.loop { aspect-ratio: 16 / 9; object-fit: cover; }
/* Reduced motion is handled in script: autoplay is stripped and the video is
   paused, which leaves the poster frame visible. Hiding it would leave an empty
   card, which is worse than a still image. */
.shot .win.film { height: auto; padding: var(--ar-s-2); }
.shot figcaption {
  border-top: var(--ar-border); padding: 7px 10px;
  display: flex; align-items: center; gap: 7px;
  font-family: var(--ar-font-mono); font-size: 9.5px; letter-spacing: .08em; color: var(--ar-text-2);
}

/* --- Who uses which path ------------------------------------------------ */

.cases { border-top: var(--ar-border); padding: var(--ar-s-5) var(--ar-s-6) var(--ar-s-6); }
.case-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 0; margin-top: var(--ar-s-4); }
.case-grid > div {
  padding: 0 var(--ar-s-4) 0 0; border-left: var(--ar-border);
  padding-left: var(--ar-s-4); display: flex; flex-direction: column; gap: 7px;
}
.case-grid > div:first-child { border-left: 0; padding-left: 0; }
.case-grid b { font-size: 14.5px; font-weight: 500; color: var(--ar-text); }
.case-grid span { font-size: 13px; color: var(--ar-text-2); line-height: 1.5; }
.case-grid em {
  margin-top: auto; font-family: var(--ar-font-mono); font-style: normal;
  font-size: 9.5px; letter-spacing: .1em; color: var(--ar-record);
}
@media (max-width: 1000px) { .case-grid { grid-template-columns: repeat(2, 1fr); row-gap: var(--ar-s-5); } .case-grid > div:nth-child(odd) { border-left: 0; padding-left: 0; } }
@media (max-width: 560px)  { .case-grid { grid-template-columns: 1fr; } .case-grid > div { border-left: 0; padding-left: 0; } }

/* --- Comparison table --------------------------------------------------- */

.cmp-wrap { overflow-x: auto; border: var(--ar-border); }
table.cmp { width: 100%; min-width: 660px; border-collapse: collapse; font-size: 13.5px; }
table.cmp th, table.cmp td { padding: 11px 14px; text-align: left; border-bottom: 1px solid rgba(255,255,255,.055); }
table.cmp thead th {
  font-family: var(--ar-font-mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ar-text-2); font-weight: 400; background: var(--ar-ink); border-bottom: var(--ar-border);
}
table.cmp tbody th { font-weight: 400; color: var(--ar-text-2); }
table.cmp td { color: var(--ar-text-2); font-family: var(--ar-font-mono); font-size: 12px; }
table.cmp .ours { background: var(--ar-record-12); color: var(--ar-text); border-left: 1px solid var(--ar-record-24); border-right: 1px solid var(--ar-record-24); }
table.cmp thead .ours { background: var(--ar-record-12); color: var(--ar-record); }
table.cmp tbody tr:hover th, table.cmp tbody tr:hover td { color: var(--ar-text); }
table.cmp tbody tr:last-child th, table.cmp tbody tr:last-child td { border-bottom: 0; }
.yes { color: var(--ar-green); }
.no  { color: var(--ar-text-2); }

/* --- Demo band ---------------------------------------------------------- */

.demo-band { padding: var(--ar-s-6) var(--ar-s-6) var(--ar-s-7); }
.demo-band .shot { max-width: 940px; margin: 0 auto; }
.demo-band .sec-h { max-width: 940px; margin-left: auto; margin-right: auto; }

/* --- Product in the room: full bleed, its own caption strip ------------- */

.inroom { margin: 0; }
.inroom img { display: block; width: 100%; height: auto; }
.inroom figcaption {
  display: flex; gap: var(--ar-s-5); flex-wrap: wrap; align-items: center;
  border-top: var(--ar-border); padding: 11px var(--ar-s-6);
  font-family: var(--ar-font-mono); font-size: 10px; letter-spacing: .09em;
  text-transform: uppercase; color: var(--ar-text-2);
}
.inroom figcaption span { display: inline-flex; align-items: center; gap: 7px; }
.inroom figcaption .ml { margin-left: auto; color: var(--ar-line-2); text-transform: none; letter-spacing: .04em; }
@media (max-width: 620px) { .inroom figcaption .ml { display: none; } }

/* --- Breather band: atmosphere + one true statement -------------------- */

.breather { position: relative; overflow: hidden; }
.breather .atmos {
  position: absolute; inset: 0; z-index: 0;
  background-image: url("/img/atmos/studio-a.jpg");
  background-size: cover; background-position: 28% 62%;
  opacity: .34; filter: grayscale(1) contrast(1.02);
}
.breather .atmos::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, var(--ar-bg) 2%, rgba(30,30,30,.72) 55%, rgba(30,30,30,.35) 100%);
}
.breather .in { position: relative; z-index: 1; padding: var(--ar-s-7) var(--ar-s-6); }
.statement {
  font-family: var(--ar-font-display); font-weight: 700;
  font-size: clamp(22px, 2.6vw, 32px); letter-spacing: -0.02em;
  color: var(--ar-text); margin: 0 0 10px; max-width: 30ch;
}

/* --- Reviews ------------------------------------------------------------ */

.reviews { display: grid; grid-template-columns: repeat(3, 1fr); }
.reviews blockquote { margin: 0; padding: var(--ar-s-5); border-right: var(--ar-border); border-bottom: var(--ar-border); display: flex; flex-direction: column; gap: var(--ar-s-4); }
.reviews blockquote:nth-child(3n) { border-right: 0; }
.reviews blockquote:nth-last-child(-n+3) { border-bottom: 0; }
@media (max-width: 940px) {
  .reviews { grid-template-columns: 1fr; }
  .reviews blockquote { border-right: 0; border-bottom: var(--ar-border); }
  .reviews blockquote:last-child { border-bottom: 0; }
}
/* Six full-width quotes is roughly a screen and a half of scrolling on a phone for a
   point the first three already make. The rest stay one tap away on /testimonials,
   which the link directly above this block already offers. */
@media (max-width: 560px) {
  .reviews blockquote:nth-child(n+4) { display: none; }
  .reviews blockquote:nth-child(3) { border-bottom: 0; }
}
.reviews q { quotes: "\201C" "\201D"; font-size: 15px; color: var(--ar-text); }
.reviews footer { margin-top: auto; font-family: var(--ar-font-mono); font-size: 10px; letter-spacing: .08em; color: var(--ar-text-2); text-transform: uppercase; }
.reviews footer b { color: var(--ar-text); font-weight: 400; }
/* The credit line is where a quote stops being a claim and becomes checkable, so the
   venue links to the actual post. Styled as part of the credit rather than as a blue
   link: the mono uppercase run should not gain a bright colour mid-sentence. */
.reviews footer a { color: var(--ar-text-2); border-bottom: 1px solid var(--ar-line-2); }
.reviews footer a:hover { color: var(--ar-text); border-bottom-color: var(--ar-blue); text-decoration: none; }

/* --- Price -------------------------------------------------------------- */

.price { display: grid; grid-template-columns: 1.05fr .95fr; }
@media (max-width: 880px) { .price { grid-template-columns: 1fr; } }
.price > div { padding: var(--ar-s-7) var(--ar-s-6); }
.price > div:first-child { border-right: var(--ar-border); }
@media (max-width: 880px) { .price > div:first-child { border-right: 0; border-bottom: var(--ar-border); } }

.tag { display: flex; align-items: flex-start; gap: var(--ar-s-2); margin-bottom: var(--ar-s-3); }
.tag .cur { font-family: var(--ar-font-display); font-size: 26px; font-weight: 400; color: var(--ar-text-2); margin-top: 8px; }
.tag .amt { font-family: var(--ar-font-display); font-size: 78px; font-weight: 700; line-height: .9; letter-spacing: -0.03em; }
.tag .per { font-family: var(--ar-font-mono); font-size: 10.5px; letter-spacing: .09em; color: var(--ar-text-2); margin-top: 10px; max-width: 12ch; text-transform: uppercase; }

.incl { list-style: none; margin: var(--ar-s-5) 0 0; padding: 0; }
.incl li { display: flex; gap: var(--ar-s-3); padding: 8px 0; border-bottom: 1px solid rgba(255,255,255,.055); font-size: 14px; color: var(--ar-text-2); }
.incl li::before { content: "✓"; color: var(--ar-green); font-size: 12px; }

/* --- Final CTA + atmosphere -------------------------------------------- */

.closer { position: relative; overflow: hidden; }
.closer .atmos {
  position: absolute; inset: 0; z-index: 0;
  background-image: url("/img/atmos/patchbay-a.webp");
  background-size: cover; background-position: 72% 50%;
  opacity: .22; filter: grayscale(1) contrast(1.05);
}
.closer .atmos::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, var(--ar-bg) 0%, rgba(30,30,30,.7) 45%, rgba(30,30,30,.25) 100%);
}
.closer .in { position: relative; z-index: 1; }

/* --- Hero destination switcher ------------------------------------------- */
/* Three real captures behind three buttons. The hero has to carry the claim in
   the headline ("exactly where you need it"), and letting someone pick the
   destination proves it better than drawing it. */

/* Opaque, even though the band behind it is already --ar-bg and this looks like a
   no-op. The hero plate screens a warm light into the top right, which is exactly
   where this row sits, and the two unselected labels are --ar-text-2 (#888) on a
   transparent background: letting the light through lifts their backdrop from 29 to
   37, which takes them from 4.76:1 to 4.32:1 and under the 4.5 floor. A control
   surface should not be translucent over a photograph anyway. */
.switch-stage {
  position: relative; margin-top: -1px; border: 1px solid var(--ar-line);
  aspect-ratio: 16 / 9; overflow: hidden; background: var(--ar-ink);
}
.switch-stage video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; opacity: 0; transition: opacity 180ms ease-out;
}
.switch-stage video.on { opacity: 1; }
/* Opaque for the same reason as .switch-row: 11px --ar-text-2 is the most fragile text
   in the band, and this makes it independent of whatever the hero plate does. The plate
   is masked out well above this point, so the fill lands on flat --ar-bg and is
   invisible - it only removes the +/-1 dither the scrim's alpha compositing leaves
   behind, which was enough to read as 4.49:1 instead of 4.54:1. */
.switch-cap {
  margin: 12px 0 0; font-family: var(--ar-font-mono); font-size: 11px;
  line-height: 1.6; color: var(--ar-text-2); min-height: 2.6em;
  background: var(--ar-bg);
}

/* --- Signal-flow diagram: idle vs live ----------------------------------- */
/* A machine with every app making noise at once is a lie, so two sources sit
   idle. The contrast is what makes the live pair mean anything. */
.cord-base.on { stroke: var(--ar-line-2); }
.n-box.idle   { opacity: .5; }
.n-t.idle     { opacity: .45; }
.src-led.idle { opacity: .7; }

@media (prefers-reduced-motion: reduce) {
  .switch-stage video { transition: none; }
  .sw { transition: none; }
}

/* Breadth line under the hero switcher: the tabs lead with DAW TRACK, which is the
   differentiator the press picked up, so this says "and everything else" without
   demoting it. */
.switch-breadth {
  margin: 6px 0 0; font-size: 13px; color: var(--ar-text-2);
}
/* Specs keep their place in the chassis bar, one step quieter than the plain-language
   readout that now leads it. */
.readout .opt.spec { color: var(--ar-text-3); }

/* Works-with: a fixed 8-up grid. Free wrapping left one orphan on its own row,
   which reads as a bug rather than a list. */
.hosts.g8 { display: grid; grid-template-columns: repeat(8, 1fr); gap: 7px var(--ar-s-4); }
@media (max-width: 900px) { .hosts.g8 { grid-template-columns: repeat(4, 1fr); } }
.more-hosts { display: none; }
/* Phones: 16 host names in a 4-up mono grid is four rows of dense capitals that read as
   a wall rather than a list. Eight plus an honest "and more" makes the same point -
   it works with what you already use - in half the space. */
@media (max-width: 560px) {
  .hosts.g8 { grid-template-columns: repeat(2, 1fr); }
  .hosts.g8 > span:nth-child(n+7) { display: none; }
  .more-hosts { display: block; color: var(--ar-text-2); border-bottom: 1px solid var(--ar-line-2); justify-self: start; }
}
/* Forum threads: same size as the host names, but they are links, so they get the
   link affordance without becoming press logos. */
.hosts.talk { display: flex; gap: var(--ar-s-4); flex-wrap: wrap; }
.hosts.talk a { color: var(--ar-text-2); text-decoration: none; border-bottom: 1px solid var(--ar-line-2); }
.hosts.talk a:hover { color: var(--ar-text); border-bottom-color: var(--ar-blue); }
.press-list a.all { color: var(--ar-text-2); }
.brk { display: none; }
/* Case cards: the path tag is the way down to the matching path. */
.case-grid .pathlink {
  margin-top: auto; font-family: var(--ar-font-mono); font-size: 9.5px;
  letter-spacing: .1em; color: var(--ar-record); text-decoration: none;
}
.case-grid .pathlink:hover { text-decoration: underline; }
.case-grid .pathlink + .pathlink { margin-top: 2px; }

/* --- Narrow-window repairs ------------------------------------------------ */
/* These sections were only ever checked wide. Three separate faults showed up
   between roughly 560 and 900px, which is a real desktop window, not just phones. */

/* 1. Section headers. `.sub` is pushed right with margin-left:auto, so once the
      heading fills the row the label wrapped onto its own line and sat alone against
      the right edge, reading like a stray fragment. Below 820px it becomes a kicker
      above the heading instead, which is where a label like that belongs anyway. */
@media (max-width: 820px) {
  .sec-h { flex-direction: column; align-items: flex-start; gap: 6px; }
  .sec-h .sub { margin-left: 0; order: -1; }
  .sec-h .n { order: -2; }
}

/* 2. Headings. clamp()'s 3.4vw middle term collapses fast in a narrow window, but the
      floor of 26px still set two long sentences nearly edge to edge. */
@media (max-width: 720px) { h2 { font-size: clamp(22px, 5.2vw, 30px); } }

/* 3. Comparison table. 660px of min-width in a 700px window meant a scrollbar and a
      table bleeding into both edges. Tighter cells and a lower floor keep it inside
      its border, and it still scrolls rather than squashing the columns. */
/* Phones: the table stops being a table. Four columns cannot fit 390px, and the
   sideways-scrolling compromise reads as a broken layout - you see a scrollbar and half
   a column, not a comparison. Each row becomes a card: feature as the title, then one
   labelled line per tool, the label coming from data-col so the header row can go away
   without the values losing their meaning. */
@media (max-width: 560px) {
  .cmp-wrap { overflow-x: visible; border: 0; }
  table.cmp { min-width: 0; display: block; font-size: 13px; }
  table.cmp thead { display: none; }
  table.cmp tbody, table.cmp tr, table.cmp th, table.cmp td { display: block; }
  table.cmp tbody tr { border: var(--ar-border); margin-bottom: 8px; }
  table.cmp tbody tr:last-child { margin-bottom: 0; }
  table.cmp tbody th {
    padding: 10px 12px 7px; border-bottom: 1px solid rgba(255,255,255,.055);
    color: var(--ar-text); font-size: 13px;
  }
  table.cmp tbody td {
    display: grid; grid-template-columns: 104px 1fr; gap: 10px; align-items: baseline;
    padding: 6px 12px; border-bottom: 0; font-size: 11.5px;
  }
  table.cmp tbody td:last-child { padding-bottom: 10px; }
  table.cmp tbody td::before {
    content: attr(data-col);
    font-family: var(--ar-font-mono); font-size: 9.5px; letter-spacing: .09em;
    text-transform: uppercase; color: var(--ar-line-2);
  }
  /* the highlight is a full-width band on a card, so the side borders would float */
  table.cmp tbody td.ours { border-left: 0; border-right: 0; }
  table.cmp tbody td.ours::before { color: var(--ar-record); }
}
@media (max-width: 760px) and (min-width: 561px) {
  table.cmp { min-width: 520px; font-size: 12.5px; }
  table.cmp th, table.cmp td { padding: 9px 10px; }
  table.cmp td { font-size: 11px; }
}

/* 4. Anchor targets. The chassis bar is sticky, so #comparison and #proof scrolled their own
      headings underneath it. */
[id] { scroll-margin-top: 64px; }

/* --- Atmosphere band under the hero -------------------------------------- */
/* The top of the page is dense: headline, lede, chips, two CTAs, then two rows of
   press and host names. This gives the eye somewhere to rest before the three paths,
   and says the one thing the whole product rests on. Same recipe as .breather: a
   grayscale plate at low opacity under a directional scrim, so it reads as texture
   rather than as a photo competing with the copy. */
.atmos-band { position: relative; overflow: hidden; border-bottom: var(--ar-border); }
.atmos-band .atmos {
  position: absolute; inset: 0; z-index: 0;
  background-image: url("/img/atmos/patchbay-a.webp");
  background-size: cover; background-position: 50% 45%;
  opacity: .30; filter: grayscale(1) contrast(1.04);
}
.atmos-band .atmos::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, var(--ar-bg) 4%, rgba(30,30,30,.74) 52%, rgba(30,30,30,.30) 100%);
}
.atmos-band .in { position: relative; z-index: 1; padding: var(--ar-s-7) var(--ar-s-6); }
.atmos-band .line {
  font-family: var(--ar-font-display); font-weight: 700;
  font-size: clamp(20px, 2.3vw, 29px); letter-spacing: -0.02em;
  color: var(--ar-text); margin: 0 0 8px; max-width: 26ch;
}
.atmos-band .sub { max-width: 46ch; color: var(--ar-text-2); font-size: 14.5px; margin: 0; }
@media (max-width: 620px) { .atmos-band .in { padding: var(--ar-s-6) var(--ar-s-4); } }

/* --- Spec plate ---------------------------------------------------------- */
/* The specs used to live in the sticky bar, where they fought the nav for room and
   truncated. Here they are a plate under the lid: same instrument language, hairline
   separated, and they scroll away instead of taxing every screenful. Values are one
   step brighter than their labels so the row scans as data, not decoration. */
.spec-rail {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 0 var(--ar-s-5);
  padding: 9px var(--ar-s-6);
  border-bottom: var(--ar-border);
  font-family: var(--ar-font-mono); font-size: 10px;
  letter-spacing: var(--ar-tracking-label); text-transform: uppercase;
  color: var(--ar-text-3);
}
.spec-rail b { font-weight: 400; color: var(--ar-text-2); text-transform: none; letter-spacing: .04em; }
.spec-rail span { white-space: nowrap; padding: 2px 0; }
/* Drop the softest items first as the row narrows, so it never wraps to three lines. */
@media (max-width: 900px) { .spec-rail span.last { display: none; } }
@media (max-width: 620px) { .spec-rail { gap: 0 var(--ar-s-4); padding: 8px var(--ar-s-4); } }
/* It did wrap to three lines, despite the note above: 390px gives rows of 1, 2 and 1,
   which reads as a mistake. Two even columns instead, matching .spec-strip below the
   hero. The nowrap has to go with it - "DEPTH 16 / 24 / 32-bit float" is 185px against a
   179px half-column, so keeping it would trade a ragged row for a sideways scrollbar. */
@media (max-width: 560px) {
  .spec-rail { display: grid; grid-template-columns: 1fr 1fr; gap: 2px var(--ar-s-4); }
  .spec-rail span { white-space: normal; }
}

/* ── Ratings strip ──────────────────────────────────────────────────────
   ONE score, not four chips.
   The first version printed a five-star row per platform, and three of the
   four read "1 review". Repeating a small number three times draws the eye
   to how few there are, and four identical star rows in a line looks like a
   badge farm rather than evidence. Aggregated it is a single confident
   claim - 5.0 from 8 reviews - and 8 is a better number than 1, four times.
   The platform names stay as links, because the names are what carry the
   credibility; the stars are decoration and are hidden from screen readers. */
.ratings { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
.ratings .stars { color: #f5b544; font-size: 12.5px; letter-spacing: .5px; }
.ratings .score {
  color: var(--ar-fg, #f2f2f7); font-weight: 700; font-size: 13.5px;
  font-variant-numeric: tabular-nums;
}
.ratings .src { color: var(--ar-dim, #8a8f98); font-size: 12.5px; line-height: 1.5; }
.ratings .src a { color: var(--ar-dim, #8a8f98); text-decoration: none; border-bottom: 1px solid rgba(255,255,255,.16); }
.ratings .src a:hover { color: var(--ar-fg, #f2f2f7); border-bottom-color: rgba(255,255,255,.4); }
/* The link sits INSIDE .src so it inherits that size and colour. Left to the
   page's default anchor style it rendered in a different family and in blue,
   which made one short phrase the loudest thing in the whole proof band. */
.ratings .src a.read { border-bottom-color: rgba(255,255,255,.28); white-space: nowrap; }

/* The repeat beside the buy button. Quieter: one line, detail on /testimonials. */
.cta-rating { margin-top: 10px; font-size: 13px; display: flex; align-items: center; gap: 8px; }
.cta-rating .stars { color: #f5b544; font-size: 12.5px; letter-spacing: .5px; }
.cta-rating a { color: var(--ar-dim, #8a8f98); text-decoration: none; border-bottom: 1px solid rgba(255,255,255,.18); }
.cta-rating a:hover { color: var(--ar-fg, #f2f2f7); }
