body {
  background-color: var(--almost-black);
  color: var(--white);
  font-family: var(--font-sans);
  min-height: 100vh;
  position: relative;
}

.bg-layer {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  /* Full-bleed by default. .bg-layer--rail below narrows it; the left/right:0
     plus auto margins is what centres the box once the width drops under
     100%. */
  width: var(--bg-width, 100%);
  margin-inline: auto;
  height: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  background-size: cover;
  background-position: center top;
  background-repeat: no-repeat;
  opacity: 0;
  transition: opacity 0.4s ease;
}
.bg-layer::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(10, 10, 10, 0.55);
  pointer-events: none;
  z-index: 1;
}
.bg-frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
  opacity: 0;
  transition: opacity 0.8s ease;
}
.bg-frame.active {
  opacity: 1;
}
.bg-layer.has-image {
  background-image: var(--bg-image);
}
.bg-layer video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ── Hero image held inside the tram lines ─────────────────────────────────
 * Opt-in via Shell.astro's bgWidth="rail". Used by the listing pages whose hero
 * is chrome rather than the pitch: /blog/, /case-studies/, /resources/. The
 * statement pages (home, product, the five industries, about) stay full-bleed
 * on purpose — there the photograph or video IS the message, and containing it
 * throws away most of its impact on a wide monitor.
 *
 * The width is exactly the tram-line box: --rail-width, clamped so it never
 * comes closer than --rail-min-margin to the viewport edge. That is the same
 * expression --rail-edge is built from, so the image lands ON the lines the
 * hero corner brackets and the nav/footer frame already sit on, rather than
 * near them.
 *
 * Above 1300px only. Below that css/mobile.css hides the hero corner brackets
 * and the tram lines stop being a visible idea. Worse, down there the rail
 * (100vw - 86px) is NARROWER than the page's text padding (100vw - 76px), so an
 * inset image would sit inside the headline it belongs to. Full bleed instead.
 */
@media (min-width: 1301px) {
  .bg-layer--rail {
    --bg-width: min(var(--rail-width), 100vw - 2 * var(--rail-min-margin));
  }
}

/* The layer starts at the top of the document so a full-bleed image can run
   behind the transparent nav. A contained one should not: the nav ends up half
   over photograph and half over flat background, and the image gains a top edge
   nothing else on the page shares. Clip the nav band away.
   clip-path rather than moving `top`, because the height of this box is set
   inline by each page's own sizing script against the hero's bottom edge —
   shifting the origin down would push that bottom edge down with it. Clipping
   leaves the box geometry (and therefore `cover`) exactly as the script
   intends and just hides the strip. Descendants are clipped too, so the
   ::after scrim goes with it.

   The cut is at the horizontal pinstripe, not at the bottom of the nav box: the
   nav's own rule (.nav::after in css/nav.css) hangs 30px BELOW the 64px bar, and
   that rule — with the hero's TL/TR corner brackets on it — is what reads as the
   bottom of the nav area. Clipping at --nav-height alone left a 30px band of
   image above it. Same expression as .nav::after so the two track together; if
   you change one, change all four (nav.css uses it three times). The image now
   starts exactly on the rule, so the top corner brackets frame it the way the
   bottom ones already do. */
.bg-layer--rail {
  clip-path: inset(calc(var(--nav-height) + 30px) 0 0 0);
}

.page-wrapper {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  /* background-color: #00000072; */
}


/* Main column — no side borders, corner brackets are on hero section */
.main-col {
  width: var(--col-width);
  max-width: 100%;
  margin: 0 auto;
}

/* ── Global heading styles ───────────────────────────────────────────────── */

h2 {
  font-family: var(--font-sans);
  font-size: 50px;
  font-weight: 500;
  color: inherit;
  line-height: 1.1;
  letter-spacing: -0.02em;
  margin-bottom: 32px;
  /* margin-left: 20px; */
}

/* ── Technical Features section ─────────────────────────────────────────── */

.tech-features__heading {
  padding: 0 38px;
}

/* Section dividers are now the reusable <bracket-rule> element (see
   css/brackets.css). These rules just carry the card-section spacing the old
   .tech-features__rule had. */
.tech-features-section bracket-rule {
  margin-bottom: -27px;
}

/* Thin vertical tram lines — driven off the SAME --rail-edge var the hero
   corner brackets use (css/variables.css), so the lines and brackets share one
   formula: identical position, identical --rail-min-margin clamp threshold, and
   identical scrollbar handling. The box stretches between left/right: rail-edge,
   so each border's outer edge lands exactly on a bracket leg at every width. */
.page-wrapper::after {
  content: '';
  position: fixed;
  top: 0;
  bottom: 0;
  left:  var(--rail-edge);
  right: var(--rail-edge);
  border-left: 1px solid rgba(255,255,255,0.3);
  border-right: 1px solid rgba(255,255,255,0.3);
  pointer-events: none;
  z-index: 101;
  box-sizing: border-box;
  /* Chameleon: the difference blend inverts the faint white line against
     whatever section scrolls behind it — it stays ~white over dark sections
     (unchanged from before), and flips to a faint dark rule over light sections
     (e.g. the case-study strip) so it never disappears. It's per-pixel, so the
     line splits correctly at a dark/light boundary. .page-wrapper isolates the
     blend from the hero bg-layer (a sibling at lower z-index), so the hero video
     doesn't shimmer through the line. */
  mix-blend-mode: difference;
}
