/* Rala public site — lifted verbatim from the auth server's inline <style> block when the
   landing page moved into its own app. The sign-in page (still served by auth) inlines its
   own copy of these tokens; they are two documents on one brand, and a colour change has to
   land in both. Note the sign-in page has no theme toggle — see the note on --accent below. */

/* ── Theme tokens ────────────────────────────────────────────
   Light is the default and the no-JS fallback. Dark is the palette the site shipped with,
   restored value-for-value. Three states, in the order the cascade needs them:
     1. :root                       — light
     2. :root:not([data-theme])     — dark, only when the OS asks and JS never ran
     3. :root[data-theme="dark"]    — dark, chosen explicitly by the footer toggle
   The inline script in App.razor resolves 1-vs-2 before first paint and always stamps an
   explicit data-theme, so in practice only 1 and 3 are live; 2 exists for JS-off visitors.

   The accent INVERTS between the two: on white it is the charcoal (dark pills, dark icon
   tiles); on the dark ground it is white. That is why it is two tokens, not one colour. */
:root {
  color-scheme: light;
  --html-bg: #ffffff;
  --page-bg:
    radial-gradient(58% 44% at 2% 0%,     #eef2f9 0%, rgba(238,242,249,0) 100%),
    radial-gradient(52% 40% at 100% 2%,   #eef3fa 0%, rgba(238,243,250,0) 100%),
    radial-gradient(55% 42% at 100% 100%, #edf2f9 0%, rgba(237,242,249,0) 100%),
    radial-gradient(58% 44% at 0% 100%,   #f1f3f8 0%, rgba(241,243,248,0) 100%),
    #ffffff;
  --grain: .025;

  --text: #1d1d1f;
  --text-2: #6e6e73;
  --text-3: #86868b;
  --mark: #5f6875;
  /* The one raster brand mark on the site ships light-on-transparent; on the white ground
     it is knocked down to black rather than given a box to sit on. */
  --mark-filter: brightness(0) opacity(.78);

  --bar-bg: rgba(255,255,255,.82);
  --hairline: rgba(18,22,31,.08);

  --surface: #f6f7fa;
  --surface-hover: #f2f4f8;
  --surface-border: rgba(18,22,31,.07);
  --surface-blur: none;
  --surface-shadow: none;
  --surface-shadow-hover: 0 14px 36px rgba(18,22,31,.08);

  --accent-bg: linear-gradient(160deg, #2a2d34, #131419);
  --accent-fg: #ffffff;
  --accent-shadow: 0 12px 30px rgba(15,16,20,.24);
  --accent-shadow-sm: 0 6px 16px rgba(15,16,20,.18);
  --accent-hover: brightness(1.12);
  --tile-bg: linear-gradient(160deg, #2a2d34, #131419);
  --tile-fg: #9ba2b0;
  --tile-shadow: 0 8px 20px rgba(15,16,20,.22);

  --ghost-bg: #ffffff;
  --ghost-fg: #1d1d1f;
  --ghost-border: rgba(18,22,31,.14);
  --ghost-hover: #f5f5f7;

  /* The drawings used to sit on a panel, which is what made their own near-white boxes read
     as boxes. Standing on the page itself they need the opposite treatment on the light
     theme — a grey shape on white rather than a white one — so the artwork carries its own
     fills instead of borrowing the buttons'. On the dark ground the old values still hold. */
  --art-fill: #edeff4;
  --art-edge: rgba(18,22,31,.12);
  --art-fill-lit: #dfe3ea;
  --art-edge-lit: rgba(18,22,31,.18);
  --art-line: rgba(18,22,31,.22);
  --art-grid: rgba(18,22,31,.12);

  --chip-bg: rgba(18,22,31,.045);
  --chip-border: rgba(18,22,31,.12);

  --control-bg: rgba(18,22,31,.04);
  --control-hover: rgba(18,22,31,.08);
  --control-border: rgba(18,22,31,.12);
  --caret: rgba(18,22,31,.5);

  --menu-bg: #ffffff;
  --menu-border: rgba(18,22,31,.09);
  --menu-shadow: 0 16px 42px rgba(18,22,31,.14);
  --menu-fg: #1d1d1f;
  --menu-hover: #f5f5f7;
  --menu-logout: #c02626;

  /* The bezels around the screenshots. Near-black on white, a shade lighter on the dark
     ground: at #1b1d22 the frame disappears into the page there and the screens float. */
  --bezel: #1b1d22;
  --bezel-edge: rgba(255,255,255,.08);
  --deck: linear-gradient(180deg, #43474f 0%, #2a2d33 55%, #1c1e23 100%);
  --device-shadow: 0 30px 60px rgba(15,16,20,.26), 0 2px 6px rgba(15,16,20,.14);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    color-scheme: dark;
    --html-bg: #0a0a0d;
    --page-bg:
      radial-gradient(120% 120% at 12% 8%,   #2a2e38 0%, rgba(42,46,56,0) 55%),
      radial-gradient(115% 115% at 100% 0%,  #313743 0%, rgba(49,55,67,0) 50%),
      radial-gradient(120% 120% at 100% 100%, #1b2431 0%, rgba(27,36,49,0) 48%),
      radial-gradient(130% 130% at 0% 100%,  #191a1f 0%, rgba(25,26,31,0) 55%),
      linear-gradient(155deg, #0c0c10 0%, #131419 52%, #0a0a0d 100%);
    --grain: .05;
    --text: #ffffff;
    --text-2: rgba(255,255,255,.78);
    --text-3: rgba(255,255,255,.45);
    --mark: #9ba2b0;
    --mark-filter: none;
    --bar-bg: rgba(10,10,13,.42);
    --hairline: rgba(255,255,255,.08);
    --surface: rgba(255,255,255,.06);
    --surface-hover: rgba(255,255,255,.10);
    --surface-border: rgba(255,255,255,.12);
    --surface-blur: blur(14px);
    --surface-shadow: 0 18px 44px rgba(0,0,0,.32);
    --surface-shadow-hover: 0 18px 44px rgba(0,0,0,.32);
    --accent-bg: #ffffff;
    --accent-fg: #0c0c10;
    --accent-shadow: 0 12px 30px rgba(0,0,0,.4);
    --accent-shadow-sm: 0 6px 16px rgba(0,0,0,.3);
    --accent-hover: brightness(.94);
    --tile-bg: #0c0c0f;
    --tile-fg: #9ba2b0;
    --tile-shadow: 0 8px 20px rgba(0,0,0,.4);
    --ghost-bg: rgba(255,255,255,.08);
    --ghost-fg: #ffffff;
    --ghost-border: rgba(255,255,255,.2);
    --ghost-hover: rgba(255,255,255,.14);
    --art-fill: rgba(255,255,255,.08);
    --art-edge: rgba(255,255,255,.2);
    --art-fill-lit: rgba(255,255,255,.09);
    --art-edge-lit: rgba(255,255,255,.16);
    --art-line: rgba(255,255,255,.16);
    --art-grid: rgba(255,255,255,.08);
    --chip-bg: rgba(255,255,255,.09);
    --chip-border: rgba(255,255,255,.16);
    --control-bg: rgba(255,255,255,.08);
    --control-hover: rgba(255,255,255,.14);
    --control-border: rgba(255,255,255,.16);
    --caret: rgba(255,255,255,.6);
    --menu-bg: #16171c;
    --menu-border: rgba(255,255,255,.12);
    --menu-shadow: 0 16px 42px rgba(0,0,0,.45);
    --menu-fg: #ffffff;
    --menu-hover: rgba(255,255,255,.09);
    --menu-logout: #ff7b72;
    --bezel: #2b2e35;
    --bezel-edge: rgba(255,255,255,.18);
    --deck: linear-gradient(180deg, #585d67 0%, #3b3f47 55%, #2b2e35 100%);
    --device-shadow: 0 30px 70px rgba(0,0,0,.55), 0 2px 8px rgba(0,0,0,.4);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --html-bg: #0a0a0d;
  --page-bg:
    radial-gradient(120% 120% at 12% 8%,   #2a2e38 0%, rgba(42,46,56,0) 55%),
    radial-gradient(115% 115% at 100% 0%,  #313743 0%, rgba(49,55,67,0) 50%),
    radial-gradient(120% 120% at 100% 100%, #1b2431 0%, rgba(27,36,49,0) 48%),
    radial-gradient(130% 130% at 0% 100%,  #191a1f 0%, rgba(25,26,31,0) 55%),
    linear-gradient(155deg, #0c0c10 0%, #131419 52%, #0a0a0d 100%);
  --grain: .05;
  --text: #ffffff;
  --text-2: rgba(255,255,255,.78);
  --text-3: rgba(255,255,255,.45);
  --mark: #9ba2b0;
  --mark-filter: none;
  --bar-bg: rgba(10,10,13,.42);
  --hairline: rgba(255,255,255,.08);
  --surface: rgba(255,255,255,.06);
  --surface-hover: rgba(255,255,255,.10);
  --surface-border: rgba(255,255,255,.12);
  --surface-blur: blur(14px);
  --surface-shadow: 0 18px 44px rgba(0,0,0,.32);
  --surface-shadow-hover: 0 18px 44px rgba(0,0,0,.32);
  --accent-bg: #ffffff;
  --accent-fg: #0c0c10;
  --accent-shadow: 0 12px 30px rgba(0,0,0,.4);
  --accent-shadow-sm: 0 6px 16px rgba(0,0,0,.3);
  --accent-hover: brightness(.94);
  --tile-bg: #0c0c0f;
  --tile-fg: #9ba2b0;
  --tile-shadow: 0 8px 20px rgba(0,0,0,.4);
  --ghost-bg: rgba(255,255,255,.08);
  --ghost-fg: #ffffff;
  --ghost-border: rgba(255,255,255,.2);
  --ghost-hover: rgba(255,255,255,.14);
  --art-fill: rgba(255,255,255,.08);
  --art-edge: rgba(255,255,255,.2);
  --art-fill-lit: rgba(255,255,255,.09);
  --art-edge-lit: rgba(255,255,255,.16);
  --art-line: rgba(255,255,255,.16);
  --art-grid: rgba(255,255,255,.08);
  --chip-bg: rgba(255,255,255,.09);
  --chip-border: rgba(255,255,255,.16);
  --control-bg: rgba(255,255,255,.08);
  --control-hover: rgba(255,255,255,.14);
  --control-border: rgba(255,255,255,.16);
  --caret: rgba(255,255,255,.6);
  --menu-bg: #16171c;
  --menu-border: rgba(255,255,255,.12);
  --menu-shadow: 0 16px 42px rgba(0,0,0,.45);
  --menu-fg: #ffffff;
  --menu-hover: rgba(255,255,255,.09);
  --menu-logout: #ff7b72;
  --bezel: #2b2e35;
  --bezel-edge: rgba(255,255,255,.18);
  --deck: linear-gradient(180deg, #585d67 0%, #3b3f47 55%, #2b2e35 100%);
  --device-shadow: 0 30px 70px rgba(0,0,0,.55), 0 2px 8px rgba(0,0,0,.4);
}

/* html's own background is what paints the overscroll gutter and the scrollbar: body's
   gradient can't cover it, because `background-attachment: fixed` confines that paint to
   the viewport and the rubber-band area is outside it. */
html { background-color: var(--html-bg); scroll-behavior: smooth; }
* { box-sizing: border-box; }
body {
  margin: 0; min-height: 100vh; color: var(--text); position: relative; overflow-x: hidden;
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  background: var(--page-bg);
  background-attachment: fixed;
}
/* Fine film grain for depth. Carried lighter on white, where the same noise reads as dirt. */
body::after {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none; opacity: var(--grain);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* The whole page is one column at least as tall as the viewport. That gives a short page
   (see .soon) slack to distribute, and costs the long ones nothing — they already overflow. */
.shell { position: relative; z-index: 1; display: flex; flex-direction: column; min-height: 100vh; }

/* ── Top bar ─────────────────────────────────────────────── */
.nav {
  position: sticky; top: 0; z-index: 10;
  padding: 18px 28px; backdrop-filter: blur(12px);
  background: var(--bar-bg); border-bottom: 1px solid var(--hairline);
}
/* Same column as .foot-top and .features, on the same 28px gutter, so the wordmark in the
   bar sits directly above the one in the footer. The bar itself stays full-bleed — the
   hairline and the blur are meant to run edge to edge. */
.nav-inner {
  max-width: 1040px; margin: 0 auto; gap: 24px;
  display: flex; align-items: center; justify-content: space-between;
}
.logo { display: inline-flex; align-items: center; gap: 12px; text-decoration: none; }
.logo .mark { display: grid; place-items: center; color: var(--mark); }
.logo .mark svg { width: 26px; height: 26px; display: block; }
.logo .word {
  font-size: 15px; font-weight: 300; text-transform: uppercase; letter-spacing: .34em;
  color: var(--mark); padding-left: .06em;
}
/* Everything but the lockup sits together on the right, so the product links read as part
   of the same group as the account control rather than floating mid-bar. Mirrors .foot-right. */
.nav-right { display: flex; align-items: center; gap: 28px; }
/* Same weight and hover as the footer's nav so the two rows of links read as one system. */
.nav-links { display: flex; align-items: center; gap: 28px; }
.nav-links a {
  color: var(--text-2); text-decoration: none; font-size: 14.5px; font-weight: 500;
  transition: color .15s ease;
}
.nav-links a:hover { color: var(--text); }

/* The About menu wears the nav link's own type and colour — it is one of the three items in
   the bar, not a control bolted onto it. Opens on hover, on click (nav.js) and on keyboard
   focus, so every way in works. */
.navmenu { position: relative; display: inline-flex; }
.navmenu-btn {
  display: inline-flex; align-items: center; gap: 5px; padding: 0; cursor: pointer;
  font-family: inherit; font-size: 14.5px; font-weight: 500; color: var(--text-2);
  background: none; border: 0; transition: color .15s ease;
}
.navmenu-btn:hover, .navmenu:hover .navmenu-btn, .navmenu.open .navmenu-btn { color: var(--text); }
.navmenu-caret { color: var(--caret); transition: transform .18s ease; }
.navmenu:hover .navmenu-caret,
.navmenu:focus-within .navmenu-caret,
.navmenu.open .navmenu-caret { transform: rotate(180deg); }
/* Hangs from the left edge of the word, unlike the account menu on the far right. */
.navmenu .menu { left: 0; right: auto; min-width: 176px; }
/* The 10px between button and sheet would drop :hover on the way down; this bridges it.
   It lives inside .menu, so hovering it still counts as hovering .navmenu. */
.navmenu .menu::before { content: ""; position: absolute; left: 0; right: 0; top: -10px; height: 10px; }
.navmenu:hover .menu,
.navmenu:focus-within .menu,
.navmenu.open .menu { opacity: 1; visibility: visible; transform: translateY(0); }

.signin {
  display: inline-block; padding: 10px 22px; font-size: 14.5px; font-weight: 600; text-decoration: none;
  color: var(--accent-fg); background: var(--accent-bg); border-radius: 980px;
  box-shadow: var(--accent-shadow-sm); transition: filter .2s ease, transform .12s ease;
}
.signin:hover { filter: var(--accent-hover); transform: translateY(-1px); }

/* Logged-in account menu */
.account { position: relative; }
.acct-btn {
  display: inline-flex; align-items: center; gap: 9px; cursor: pointer; font: inherit; color: var(--text);
  padding: 5px 12px 5px 5px; border-radius: 999px;
  background: var(--control-bg); border: 1px solid var(--control-border);
  transition: background .18s ease;
}
.acct-btn:hover { background: var(--control-hover); }
.acct-avatar {
  width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; flex: 0 0 auto;
  font-size: 12px; font-weight: 600; color: #fff; background: linear-gradient(135deg, #3a3d45, #1c1e22);
}
.acct-name { font-size: 14px; font-weight: 550; max-width: 168px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acct-caret { color: var(--caret); transition: transform .18s ease; }
.account.open .acct-caret { transform: rotate(180deg); }
/* The dropdown is a surface in its own right, so it carries its own set of tokens —
   a white sheet on the light ground, a near-black one on the dark. */
.menu {
  position: absolute; top: calc(100% + 10px); right: 0; min-width: 210px; padding: 6px; z-index: 20;
  background: var(--menu-bg); border-radius: 14px; border: 1px solid var(--menu-border); box-shadow: var(--menu-shadow);
  opacity: 0; visibility: hidden; transform: translateY(-6px); transition: opacity .16s ease, transform .16s ease;
}
.account.open .menu { opacity: 1; visibility: visible; transform: translateY(0); }
.menu form { margin: 0; }
.menu-item {
  display: block; width: 100%; text-align: left; padding: 10px 12px; border-radius: 9px;
  font-family: inherit; font-size: 14.5px; font-weight: 500; color: var(--menu-fg); text-decoration: none;
  background: none; border: 0; cursor: pointer; transition: background .14s ease;
}
.menu-item:hover { background: var(--menu-hover); }
.menu-item.logout { color: var(--menu-logout); }

/* ── Hero ────────────────────────────────────────────────── */
.hero { max-width: 920px; margin: 0 auto; padding: 96px 28px 72px; text-align: center; }
.eyebrow {
  display: inline-block; margin-bottom: 22px; padding: 6px 14px; font-size: 12px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .09em; color: var(--text-2);
  background: var(--chip-bg); border: 1px solid var(--chip-border); border-radius: 999px;
}
.hero h1 {
  margin: 0; font-size: 60px; line-height: 1.04; letter-spacing: -.035em; font-weight: 680;
  max-width: 16ch; margin-inline: auto;
}
.hero .lede {
  margin: 24px auto 0; max-width: 46ch; font-size: 19px; line-height: 1.55; color: var(--text-2);
}
.cta { margin-top: 38px; display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; }
.btn-primary {
  display: inline-block; padding: 15px 30px; font-size: 16px; font-weight: 600; text-decoration: none;
  color: var(--accent-fg); background: var(--accent-bg); border-radius: 980px;
  box-shadow: var(--accent-shadow); transition: transform .12s ease, filter .2s ease;
}
.btn-primary:hover { transform: translateY(-2px); filter: var(--accent-hover); }
.btn-ghost {
  display: inline-block; padding: 15px 30px; font-size: 16px; font-weight: 600; text-decoration: none;
  color: var(--ghost-fg); background: var(--ghost-bg); border: 1px solid var(--ghost-border); border-radius: 980px;
  transition: background .2s ease, transform .12s ease;
}
.btn-ghost:hover { background: var(--ghost-hover); transform: translateY(-2px); }

/* ── Home ────────────────────────────────────────────────── */
/* The hero carries a headline again, so it needs less bottom room than the bare one it
   replaced: the signal row below it is the next thing to read. */
.home-hero { padding-bottom: 40px; }
.home-hero h1 { max-width: 15ch; }
.hero-note { margin: 28px auto 0; max-width: 54ch; font-size: 13.5px; line-height: 1.55; color: var(--text-3); }

/* The app itself, in frames drawn in CSS: a lid, the deck below it with the thumb notch in
   its front edge, and a bare phone. Both bezels stay the same near-black in either theme,
   the way the hardware does. */
/* Wider than the 1040px text column on purpose: the shots are the first thing on the page
   and carry it, so they run past the measure the copy is set to. */
.devices {
  width: 100%; max-width: 1200px; margin: 0 auto; padding: 4px 28px 60px;
  display: flex; align-items: flex-end; justify-content: center; gap: 48px;
}
/* The deck runs past the lid on both sides, so the lid is inset by exactly that overhang and
   the deck fills the box edge to edge. That keeps the flex gap honest: it is measured from
   the widest part of the machine, not from the lid, which is what put the deck's corners
   into the phone before. */
.mac { --overhang: 34px; flex: 0 1 894px; min-width: 0; padding-inline: var(--overhang); }
/* No camera dot: it sits on the centre line of the machine while the app's own title is
   centred in its content pane, right of the sidebar, so the two can never line up, and the
   dot was the only thing making the mismatch visible. */
.mac-lid {
  position: relative; padding: 12px 12px 14px; border-radius: 19px;
  background: var(--bezel); border: 1px solid var(--bezel-edge); box-shadow: var(--device-shadow);
}
.mac-screen { display: block; width: 100%; height: auto; border-radius: 7px; }
/* Rounded off rather than clipped to a trapezoid: the polygon that gave it its taper also
   gave it two sharp angled corners no machine has. */
.mac-base {
  position: relative; height: 15px;
  width: calc(100% + var(--overhang) * 2); margin-inline: calc(var(--overhang) * -1);
  background: var(--deck); border-radius: 0 0 16px 16px;
  box-shadow: 0 18px 30px rgba(15,16,20,.2);
}
/* The thumb notch in the front edge. */
.mac-base::after {
  content: ""; position: absolute; top: 0; left: 0; right: 0; margin: 0 auto;
  width: 13%; height: 5px; border-radius: 0 0 7px 7px; background: rgba(0,0,0,.3);
}
.phone { flex: 0 0 200px; }
.phone-body {
  position: relative; padding: 7px; border-radius: 31px;
  background: var(--bezel); border: 1px solid var(--bezel-edge); box-shadow: var(--device-shadow);
}
.phone-screen { display: block; width: 100%; height: auto; border-radius: 25px; }

/* The system in one row: source, Rala, output. Panels rather than a screenshot, which would
   date the moment the app's own chrome changes. */
.signal {
  width: 100%; max-width: 1040px; margin: 0 auto; padding: 12px 28px 44px;
  display: flex; align-items: stretch; justify-content: center;
}
.sig-card {
  flex: 1 1 0; min-width: 0; padding: 26px 22px; border-radius: 18px; text-align: center;
  background: var(--surface); border: 1px solid var(--surface-border);
  backdrop-filter: var(--surface-blur); box-shadow: var(--surface-shadow);
}
/* The middle panel is the product: a lit surface and a firmer border. Same tile size as its
   neighbours, so all three headings sit on one line. */
.sig-card.core {
  background: var(--surface-hover); border-color: var(--chip-border); box-shadow: var(--surface-shadow-hover);
}
.sig-ic {
  width: 46px; height: 46px; margin: 0 auto 16px; border-radius: 13px; display: grid; place-items: center;
  color: var(--tile-fg); background: var(--tile-bg); box-shadow: var(--tile-shadow);
}
.sig-ic svg { width: 24px; height: 24px; display: block; }
/* The services, side by side. A white chip in both themes: these are brand marks in brand
   colours, and the Qobuz Q is black — it would disappear into the dark tile the page's own
   icons sit on. */
.sig-logos { display: flex; justify-content: center; gap: 10px; margin-bottom: 16px; }
.logo-chip {
  width: 52px; height: 52px; border-radius: 15px; display: grid; place-items: center;
  background: #fff; border: 1px solid rgba(18,22,31,.10); box-shadow: var(--tile-shadow);
}
.logo-chip img { width: 30px; height: 30px; display: block; }
/* The platform marks dealt over each other. The border is the card's own background, so the
   overlap reads as a stack rather than as one run-together shape. */
.sig-stack { display: flex; justify-content: center; margin-bottom: 16px; }
.sig-stack .plat {
  width: 52px; height: 52px; border-radius: 15px; display: grid; place-items: center;
  color: #c2c8d2; background: var(--tile-bg); box-shadow: var(--tile-shadow);
}
/* Each card casts a shadow onto the one it covers, which is what separates them. A border in
   the card's own colour would do it too, but between two near-black tiles it doubles into a
   bright 4px seam that reads as an outline drawn around every icon.
   10px of overlap, not more: the mark is centred, so deeper starts cutting into the logo
   rather than into empty bezel. */
.sig-stack .plat + .plat {
  margin-left: -10px; box-shadow: var(--tile-shadow), -5px 0 9px rgba(0,0,0,.45);
}
/* 26px, not 20: Tux carries fine detail that turns to mush below about this size, and a
   lighter grey than --tile-fg keeps all four crisp against the near-black tile. */
.sig-stack .plat svg { width: 26px; height: 26px; display: block; }
/* The one raster in the row: sized on width, since the HQPlayer icon is wider than it is
   tall and would come out tiny if it were fitted to the same square as the marks. */
.sig-stack .plat img { width: 32px; height: auto; display: block; }
.sig-card h3 { margin: 0 0 7px; font-size: 16.5px; font-weight: 640; letter-spacing: -.01em; }
.sig-card p { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--text-2); }
/* The joiner is a hairline with a chevron sitting on it, centred against the panels. */
.sig-join {
  flex: 0 0 64px; align-self: center; display: grid; place-items: center; color: var(--text-3);
  background:
    linear-gradient(90deg, transparent, var(--chip-border) 25%, var(--chip-border) 75%, transparent)
    center / 100% 1px no-repeat;
}
.sig-join svg { width: 18px; height: 18px; display: block; }

/* The grid on the landing page follows the hero rather than a page heading, so it needs the
   heading rhythm without the standalone page's extra top room. */
.features .more { margin-top: 30px; text-align: center; }

/* Closing panel: the same offer as the top bar, at the point someone has read enough. */
/* width:100% is load-bearing: .shell is a column flex container, so the auto side margins
   below would otherwise shrink this to fit its text instead of filling the column. */
.closer { width: 100%; max-width: 1040px; margin: 0 auto; padding: 0 28px 96px; }
.closer-inner {
  padding: 48px 32px; border-radius: 24px; text-align: center;
  background: var(--surface); border: 1px solid var(--surface-border);
  backdrop-filter: var(--surface-blur); box-shadow: var(--surface-shadow);
}
.closer-inner h2 { margin: 0 0 10px; font-size: 28px; font-weight: 660; letter-spacing: -.02em; }
.closer-inner p { margin: 0 auto; max-width: 46ch; color: var(--text-2); font-size: 16px; line-height: 1.55; }
.closer-inner .cta { margin-top: 30px; }

/* ── Coming soon ─────────────────────────────────────────── */
/* One centred column on the hero's own rhythm — the page carries no content of its own,
   so the mark does the work the feature grid does on the landing page.

   Too short to fill the viewport, so `margin-block: auto` hands the section every pixel of
   the column's leftover space, split evenly above and below: the content sits centred
   between the top bar and the footer, and the footer lands on the bottom edge rather than
   halfway up. Padding is symmetric here (the hero's is top-heavy) so the centring holds. */
.soon { margin-block: auto; padding-block: 56px; }
.soon .soon-mark {
  width: 74px; height: 74px; margin: 0 auto 26px; border-radius: 22px;
  display: grid; place-items: center; color: var(--tile-fg);
  background: var(--tile-bg); box-shadow: var(--tile-shadow);
}
.soon .soon-mark svg { width: 38px; height: 38px; display: block; }
.soon .soon-note { margin: 36px auto 0; max-width: 44ch; font-size: 13.5px; color: var(--text-3); }

/* ── Feature grid ────────────────────────────────────────── */
.features { max-width: 1040px; margin: 0 auto; padding: 24px 28px 96px; }
/* The grid as a page in its own right rather than a section under the hero: it has to supply
   the top breathing room the hero above it used to give it. */
.features.standalone { padding-top: 84px; }
.features h1,
.features h2 {
  text-align: center; margin: 0 0 8px; font-size: 32px; font-weight: 660; letter-spacing: -.02em;
}
.features .sub {
  text-align: center; margin: 0 auto 44px; max-width: 44ch; color: var(--text-2); font-size: 16px; line-height: 1.55;
}
.grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
/* On white the panel is the tinted surface and the page is white; on the dark ground the
   relationship flips and the panel is the lighter one. Same token, opposite side. */
.feature {
  padding: 28px 26px; border-radius: 18px; text-align: left;
  background: var(--surface); border: 1px solid var(--surface-border);
  backdrop-filter: var(--surface-blur); box-shadow: var(--surface-shadow);
  transition: transform .18s ease, background .18s ease, border-color .18s ease, box-shadow .18s ease;
}
.feature:hover {
  transform: translateY(-3px); background: var(--surface-hover);
  border-color: var(--chip-border); box-shadow: var(--surface-shadow-hover);
}
.feature .ic {
  width: 46px; height: 46px; margin-bottom: 18px; border-radius: 13px; display: grid; place-items: center;
  color: var(--tile-fg); background: var(--tile-bg); box-shadow: var(--tile-shadow);
}
.feature .ic svg { width: 24px; height: 24px; }
.feature h3 { margin: 0 0 8px; font-size: 18px; font-weight: 640; letter-spacing: -.01em; }
.feature p { margin: 0; font-size: 14.5px; line-height: 1.55; color: var(--text-2); }

/* ── Download ────────────────────────────────────────────── */
/* Three product blocks on the feature grid's column and heading rhythm. Everything is
   centred — headings, copy, and the boxes themselves, which are capped at 300px and centred
   as a group, so every block lines up on the same axis whatever it holds. */
.download { width: 100%; max-width: 1040px; margin: 0 auto; padding: 84px 28px 96px; text-align: center; }
.dl-block + .dl-block { margin-top: 68px; }
.download h1,
.download h2 {
  text-align: center; margin: 0 0 8px; font-size: 32px; font-weight: 660; letter-spacing: -.02em;
}
.download .sub {
  text-align: center; margin: 0 auto 36px; max-width: 46ch; color: var(--text-2); font-size: 16px; line-height: 1.55;
}
/* minmax(0, 300px), not a fixed 300px: the tracks give way on a narrow viewport instead of
   pushing the row wider than the column. */
.dl-grid {
  display: grid; grid-template-columns: repeat(3, minmax(0, 300px)); justify-content: center; gap: 18px;
}
/* A .feature panel that happens to be a link: same surface, same lift on hover, so the two
   pages read as one system. Centred, because a platform logo has no reading direction. */
.dl-card {
  display: flex; flex-direction: column; align-items: center; text-align: center; text-decoration: none;
  padding: 34px 26px 30px; border-radius: 18px; color: inherit;
  background: var(--surface); border: 1px solid var(--surface-border);
  backdrop-filter: var(--surface-blur); box-shadow: var(--surface-shadow);
  transition: transform .18s ease, background .18s ease, border-color .18s ease, box-shadow .18s ease;
}
.dl-card:hover {
  transform: translateY(-3px); background: var(--surface-hover);
  border-color: var(--chip-border); box-shadow: var(--surface-shadow-hover);
}
/* The icon tile from the feature grid, one size up: the logo IS the content here. */
.dl-logo {
  width: 62px; height: 62px; margin-bottom: 20px; border-radius: 18px; display: grid; place-items: center;
  color: var(--tile-fg); background: var(--tile-bg); box-shadow: var(--tile-shadow);
}
.dl-logo svg { width: 32px; height: 32px; display: block; }
.dl-card h3 { margin: 0 0 8px; font-size: 17.5px; font-weight: 640; letter-spacing: -.01em; }
.dl-card p { margin: 0 0 22px; font-size: 14.5px; line-height: 1.55; color: var(--text-2); }
/* Pushed to the bottom edge so every pill in a row lines up, however many lines the name or
   the requirements above it ran to. */
.dl-file {
  margin-top: auto; display: inline-block; padding: 11px 24px; border-radius: 980px;
  font-size: 15px; font-weight: 600; color: var(--accent-fg); background: var(--accent-bg);
  box-shadow: var(--accent-shadow-sm); transition: filter .2s ease;
}
.dl-card:hover .dl-file { filter: var(--accent-hover); }

/* Signed out: the same box, minus the affordances. No lift, no pointer, and the pill goes
   flat and grey so the row still reads as "these exist" rather than "this is broken". The
   markup drops the anchor entirely (DownloadCard.razor), so there is nothing to click,
   tab to, or copy the address of — this only has to look the part. */
.dl-locked { cursor: default; }
.dl-locked:hover {
  transform: none; background: var(--surface);
  border-color: var(--surface-border); box-shadow: var(--surface-shadow);
}
.dl-locked .dl-logo { opacity: .55; }
.dl-locked h3 { color: var(--text-2); }
/* Outline drawn inset rather than as a border, so the pill keeps the exact size it has on
   the live cards and the row does not shift by a pixel when someone logs in. */
.dl-locked .dl-file {
  color: var(--text-2); background: var(--chip-bg);
  box-shadow: inset 0 0 0 1px var(--chip-border);
}
.dl-locked:hover .dl-file { filter: none; }
/* The one line that explains the row above being inert. Sits on the page's own column and
   reads as a note, not an error — nothing has gone wrong. */
.dl-notice {
  margin: 0 auto 40px; max-width: 52ch; padding: 14px 22px; border-radius: 14px;
  font-size: 15px; line-height: 1.6; color: var(--text-2);
  background: var(--surface); border: 1px solid var(--surface-border);
  backdrop-filter: var(--surface-blur);
}
.dl-notice a { color: var(--text); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.dl-notice a:hover { opacity: .8; }

/* ── Features, long form ─────────────────────────────────── */
/* One row per feature instead of a grid of boxes: copy on one side, a drawing on the other,
   the sides swapping each row so the eye zig-zags down the page. */
.feat-head { width: 100%; max-width: 1040px; margin: 0 auto; padding: 84px 28px 4px; text-align: center; }
.feat-head h1 { margin: 0 0 10px; font-size: 40px; font-weight: 680; letter-spacing: -.025em; }
.feat-head .sub { margin: 0 auto; max-width: 46ch; color: var(--text-2); font-size: 17px; line-height: 1.55; }
.feats { width: 100%; max-width: 1040px; margin: 0 auto; padding: 0 28px; }
.feat { display: grid; grid-template-columns: 1fr 1fr; gap: 56px; align-items: center; padding: 64px 0; }
.feat + .feat { border-top: 1px solid var(--hairline); }
/* Only the columns swap — the text keeps its source order, so it is still read first. */
.feat:nth-child(even) .feat-text { order: 2; }
.feat-num { display: block; margin-bottom: 12px; font-size: 12px; font-weight: 600; letter-spacing: .14em; color: var(--text-3); }
.feat-text h2 { margin: 0 0 14px; font-size: 30px; font-weight: 660; letter-spacing: -.02em; }
.feat-text p { margin: 0; font-size: 16px; line-height: 1.62; color: var(--text-2); }
.feat-points { margin: 22px 0 0; padding: 0; list-style: none; display: grid; gap: 10px; }
.feat-points li { position: relative; padding-left: 22px; font-size: 14.5px; color: var(--text-2); }
.feat-points li::before {
  content: ""; position: absolute; left: 2px; top: .5em; width: 7px; height: 7px;
  border-radius: 50%; background: var(--text-3);
}
/* No panel behind the artwork. Most of these drawings draw their own panels, so a surface
   under them was a box inside a box, and the one row that is a single brand mark had a box
   around nothing. A hairline between the two columns does the dividing instead — the same
   one the rows themselves are separated by. */
.feat-art {
  padding: 8px 0 8px 56px; border-left: 1px solid var(--hairline);
}
.feat:nth-child(even) .feat-art { padding: 8px 56px 8px 0; border-left: 0; border-right: 1px solid var(--hairline); }
/* Two sources converging on one library. Vertical, so nothing has to line up with anything
   horizontally, and the chips are the landing page's. */
.art-merge { display: grid; justify-items: center; gap: 14px; padding: 16px 0; }
.merge-row { display: flex; gap: 30px; }
.merge-item {
  display: grid; justify-items: center; gap: 10px;
  font-size: 13px; font-weight: 550; color: var(--text-2);
}
.merge-arrow { width: 22px; height: 22px; color: var(--text-3); }
/* What the two converge on is the brand lockup itself — the same mark and wordmark the bar
   and the footer carry, borrowed wholesale from .logo and set a size up, since here it is
   the artwork rather than a fixture at the edge of the page. */
.merge-out { margin-top: 4px; }
.merge-out .mark svg { width: 32px; height: 32px; }
.merge-out .word { font-size: 18px; }
/* Where the relay runs, as the platform marks rather than drawings of the machines. Same
   near-black tile the landing page deals them on, but laid out flat and named, since here
   each one is a place a DAC can be rather than a badge. */
.art-fan { display: grid; justify-items: center; gap: 14px; padding: 16px 0; }
.fan-row { display: flex; gap: 22px; flex-wrap: wrap; justify-content: center; }
.os-tile {
  width: 52px; height: 52px; border-radius: 15px; display: grid; place-items: center;
  color: #c2c8d2; background: var(--tile-bg); box-shadow: var(--tile-shadow);
}
.os-tile svg { width: 26px; height: 26px; display: block; }
.fan-note { font-size: 11.5px; color: var(--text-3); }
/* The one row that is a brand mark rather than a drawing. The mark is a flat light grey on
   a transparent ground, right on the dark theme and invisible on the light one, so on white
   it is knocked down to black. Kept to the file's own 96px so it stays crisp on a 2x screen. */
.art-logo { display: grid; place-items: center; padding: 36px 0; }
.art-logo img { width: 96px; height: auto; display: block; filter: var(--mark-filter); }

/* The drawings. Every part is a token the rest of the page already defines, so they inherit
   the theme instead of carrying colours of their own. */
.art { display: block; width: 100%; height: auto; }
.art text { font-family: inherit; }
.a-panel { fill: var(--art-fill); stroke: var(--art-edge); stroke-width: 1.4; }
.a-lit { fill: var(--art-fill-lit); stroke: var(--art-edge-lit); }
.a-cap { fill: var(--text-2); font-size: 12px; font-weight: 550; }
.a-mid { fill: var(--text); font-weight: 640; }
.a-tag { fill: var(--text-3); font-size: 10.5px; }
.a-wave { fill: none; stroke: var(--text); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.a-link { fill: none; stroke: var(--art-line); stroke-width: 1.5; }
/* The solid shapes take --text and cut their detail out with --html-bg, so they flip with
   the theme: a dark object on white, a light one on the dark ground. Fixed near-blacks read
   as smudges against the dark panels. */
.a-dac rect { fill: var(--text-2); }
.a-art { fill: var(--text); }
.a-vinyl { fill: none; stroke: var(--html-bg); stroke-width: 2; }
.a-hole { fill: var(--html-bg); }
.a-bar { fill: var(--art-line); }
.a-bar.a-dim { fill: var(--art-edge); }
.a-vu rect { fill: var(--text-3); }
.a-grid path { fill: none; stroke: var(--art-grid); stroke-width: 1; }
.a-zero { fill: none; stroke: var(--art-line); stroke-width: 1.2; stroke-dasharray: 4 5; }
.a-curve { fill: none; stroke: var(--text); stroke-width: 2.4; stroke-linecap: round; }
.a-node circle { fill: var(--text); }

/* ── Footer ──────────────────────────────────────────────── */
.foot { border-top: 1px solid var(--hairline); padding: 42px 28px 46px; }
.foot-top {
  max-width: 1040px; margin: 0 auto; display: flex; align-items: center; justify-content: space-between;
  gap: 24px; flex-wrap: wrap;
}
.foot-brand { display: inline-flex; align-items: center; gap: 11px; text-decoration: none; }
.foot-brand .mark { display: grid; place-items: center; color: var(--mark); }
.foot-brand .mark svg { width: 22px; height: 22px; display: block; }
.foot-brand .word {
  font-size: 13px; font-weight: 300; text-transform: uppercase; letter-spacing: .34em; color: var(--mark);
}
.foot-right { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; }
.foot-nav { display: flex; gap: 26px; flex-wrap: wrap; }
.foot-nav a {
  color: var(--text-2); text-decoration: none; font-size: 14.5px; font-weight: 500;
  transition: color .15s ease;
}
.foot-nav a:hover { color: var(--text); }
.foot-copy { max-width: 1040px; margin: 30px auto 0; font-size: 13px; color: var(--text-3); }

/* ── Theme toggle ────────────────────────────────────────── */
/* Shows the theme you would switch TO, which is the convention users expect: a moon while
   you are on light, a sun while you are on dark. */
.theme-toggle {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: 34px; height: 34px; padding: 0; cursor: pointer; color: var(--text-2);
  background: var(--control-bg); border: 1px solid var(--control-border); border-radius: 999px;
  transition: background .18s ease, color .18s ease;
}
.theme-toggle:hover { background: var(--control-hover); color: var(--text); }
.theme-toggle svg { width: 16px; height: 16px; display: block; }
.theme-toggle .sun { display: none; }
.theme-toggle .moon { display: block; }
/* JS-off on a dark-preferring OS: the page is dark, so offer the sun. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .theme-toggle .sun { display: block; }
  :root:not([data-theme]) .theme-toggle .moon { display: none; }
}
:root[data-theme="dark"] .theme-toggle .sun { display: block; }
:root[data-theme="dark"] .theme-toggle .moon { display: none; }

@media (max-width: 900px) {
  /* Stacked: text first, then its drawing, whichever side the row was on. */
  .feat { grid-template-columns: 1fr; gap: 26px; padding: 44px 0; }
  .feat:nth-child(even) .feat-text { order: 0; }
  .feat-art, .feat:nth-child(even) .feat-art {
    padding: 26px 0 8px; border-left: 0; border-right: 0; border-top: 1px solid var(--hairline);
  }
  .art-logo { padding: 14px 0; }
  .feat-head { padding-top: 60px; }
  .feat-head h1 { font-size: 32px; }
  .feat-text h2 { font-size: 25px; }
}
@media (max-width: 860px) {
  .grid { grid-template-columns: 1fr 1fr; }
  .hero h1 { font-size: 46px; }
  .devices { gap: 26px; }
  .phone { flex: 0 0 152px; }
  /* Stacked, with the joiners turned on their side. Width is pinned: stretched to the full
     column, the rotated hairline would run straight through the panels above and below. */
  .signal { flex-direction: column; align-items: stretch; }
  .sig-join { flex: 0 0 36px; width: 36px; height: 36px; align-self: center; transform: rotate(90deg); }
}
@media (max-width: 700px) {
  .nav-inner { gap: 14px; }
  .nav-right { gap: 18px; }
  .nav-links { gap: 18px; font-size: 14px; }
  .navmenu-btn { font-size: 14px; }
  .dl-grid { grid-template-columns: repeat(2, minmax(0, 300px)); }
  .dl-block + .dl-block { margin-top: 52px; }
}
@media (max-width: 560px) {
  .features.standalone { padding-top: 52px; }
  .nav { padding: 14px 20px; }
  .nav-right { gap: 14px; }
  .nav-links { gap: 16px; }
  .nav-links a, .navmenu-btn { font-size: 13.5px; }
  /* The wordmark is the first thing to go: the mark alone still identifies the page, and
     the two product links are worth more than the lettering at this width. */
  .logo .word { display: none; }
  .hero { padding: 64px 22px 52px; }
  /* Side by side there is no room left for either: the pair stacks instead, laptop first. */
  .devices { flex-direction: column; align-items: center; gap: 22px; padding: 0 22px 40px; }
  .mac { --overhang: 18px; flex: 1 1 auto; width: 100%; }
  .phone { flex: 0 0 auto; width: 148px; }
  .signal { padding: 8px 22px 32px; }
  .closer { padding: 0 22px 64px; }
  .closer-inner { padding: 36px 22px; }
  .closer-inner h2 { font-size: 24px; }
  .soon { padding-block: 40px; }
  .hero h1 { font-size: 36px; }
  .hero .lede { font-size: 17px; }
  .grid { grid-template-columns: 1fr; }
  .dl-grid { grid-template-columns: minmax(0, 340px); }
  .download { padding: 56px 22px 64px; }
  .download h1, .download h2 { font-size: 27px; }
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } * { transition: none !important; } }
