/* ==========================================================================
   BIMR.ai landing / os.css
   The operating system for Swedish real estate: hero, continuous background,
   register rail, and the new sections.

   Loaded AFTER the inline <style> block in index.html, so it wins on equal
   specificity. Every colour here comes from the :root tokens declared there
   (--bg, --bg-raise, --ink, --muted, --accent, --line, --line-soft,
   --line-strong, --mono, --display, --ease). No token hex is re-declared.

   OWNERSHIP / PARTITION
     1  contract values and defaults
     2  the fixed layers (canvas + two veils)
     3  no section paints a rectangle
     4  header
     ---------------- boundary: the hero and the sections start here --------
     5  hero
     6  register rail
     7  one roof
     8  what it does
     9  the model (showcase, incl. the relocated scripted chat)
     10 surviving sections on the new ground (api, contact, footer)
     11 responsive: 1060 / 940 / 800 / 480
     12 reduced motion and html.noanim

   ONE RULE ABOVE ALL: --os-depth and --os-stage are published for reading,
   but NOTHING on this page may take them in a property that affects paint.
   The only paint-affecting reader is #osVeilDeep reading --os-veil, which is
   written on that one childless element. A full-bleed element taking
   opacity: var(--os-depth) repaints the viewport on every scroll frame and
   undoes the whole performance argument.
   ========================================================================== */

/* ---------- 1. contract values and defaults ------------------------------ */

@property --os-depth { syntax: "<number>"; inherits: true; initial-value: 0; }
@property --os-stage { syntax: "<number>"; inherits: true; initial-value: 0; }
@property --os-veil  { syntax: "<number>"; inherits: false; initial-value: 0; }

/* Declared plainly as well: sections may read these before os-hero.js runs,
   or when it never runs at all (no JS, no WebGL, reduced motion before the
   first scroll). */
:root { --os-depth: 0; --os-stage: 0; }

/* ---------- 2. the fixed layers ------------------------------------------ */

/* One canvas and two veils, all pointer-transparent, all aria-hidden in the
   markup, all at z-index 0 so they stack by document order. Content sits
   above them because main and footer are positioned at z-index 1. */
#osField,
#osVeil,
#osVeilDeep {
  position: fixed; inset: 0; z-index: 0;
  pointer-events: none;
}
#osField {
  display: block; width: 100%; height: 100%;
  opacity: 0; transition: opacity .35s ease-out;
  transform: scaleX(-1); /* Put the surveyed foreground on the right of the copy. */
}
#osField.on { opacity: 1; }

/* The veils are black over black until the field fades in, so they cost
   nothing when there is no canvas: they are the legibility ground, not a
   look. #osVeil never changes after load. */
#osVeil {
  background: linear-gradient(180deg,
    rgba(0, 0, 0, .55) 0%,
    rgba(0, 0, 0, .16) 16%,
    rgba(0, 0, 0, .06) 42%,
    rgba(0, 0, 0, .30) 74%,
    rgba(0, 0, 0, .78) 92%,
    rgba(0, 0, 0, .92) 100%);
  opacity: 1;
  transition: opacity .9s var(--ease);
  contain: layout style paint;
}

/* Only this one moves, and only its opacity, so a scroll is a composite and
   never a repaint. Lighter at mid screen than at the edges: the field
   survives as a texture where the eye rests and dies at the seams. */
#osVeilDeep {
  background: linear-gradient(180deg,
    rgba(0, 0, 0, .96) 0%,
    rgba(0, 0, 0, .90) 22%,
    rgba(0, 0, 0, .86) 50%,
    rgba(0, 0, 0, .90) 78%,
    rgba(0, 0, 0, .97) 100%);
  opacity: var(--os-veil, 0);
  will-change: opacity;
  contain: layout style paint;
}

/* The markup ships one layer, the canvas. So the static veil is carried by
   body::after, which is generated AFTER every child of body and therefore
   paints above #osField at the same z-index while staying below main and
   footer at z-index 1. Same gradient, same job, no extra element. If the two
   veil divs are ever added to the markup, this one stands down rather than
   darkening the page twice. */
body.os::after {
  content: "";
  position: fixed; inset: 0; z-index: 0;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(0, 0, 0, .55) 0%,
    rgba(0, 0, 0, .16) 16%,
    rgba(0, 0, 0, .06) 42%,
    rgba(0, 0, 0, .30) 74%,
    rgba(0, 0, 0, .78) 92%,
    rgba(0, 0, 0, .92) 100%);
}
body.os:has(#osVeil)::after { content: none; }

/* No WebGL: the veils are pointless over an empty canvas, and the page falls
   back to black ground with content on it, which is the design it shipped
   with. */
.os-nofield #osVeil,
.os-nofield #osVeilDeep { display: none; }
html.os-nofield body.os::after { content: none; }
.os-nofield #osField { opacity: 0; }

/* Everything that is not a layer sits above the layers. The header keeps its
   own position: fixed and z-index 100 from the inline style: do not give it
   position: relative here. */
body.os main,
body.os footer { position: relative; z-index: 1; overflow-x: clip; }
/* Feathered copy backplates may extend past the viewport. Clip their paint
   without creating a scroll container or clipping content inside the page. */

/* ---------- 3. no section paints a rectangle ----------------------------- */

/* A section-sized opaque rectangle IS the seam. Once nothing paints one, a
   seam becomes unrepresentable rather than merely avoided. Opaque panels
   INSIDE a section (the API cards, the four output cards) are instruments on
   a table and keep their own ground. */
body.os section { background: transparent; }
body.os footer { background: transparent; border-top: 0; z-index: 1; }

/* Feathered hairline: fades out before the viewport edge, so it reads as a
   survey line drawn on the field rather than the top of a box. */
.os-rule { position: relative; }
.os-rule::before,
body.os footer::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px;
  pointer-events: none;
  background: linear-gradient(90deg,
    transparent, var(--line-soft) 14%, var(--line-soft) 86%, transparent);
}

/* Local ground for copy that sits over an unveiled field. Feathered across
   28% of its own width, so no edge is findable and no plate is visible. */
.os-plate,
.os-hero-copy,
.os-roof-lede, .os-roof-row p, .os-does-lede, .os-showcase-lede,
.os-more-grid p, body.os .cta-final p,
body.os footer .foot-grid { position: relative; }
.os-plate::before,
.os-hero-copy::before,
.os-roof-lede::before, .os-roof-row p::before, .os-does-lede::before,
.os-showcase-lede::before, .os-more-grid p::before, body.os .cta-final p::before,
body.os footer .foot-grid::before {
  content: ""; position: absolute; inset: -10% -14%; z-index: -1;
  pointer-events: none;
  background: radial-gradient(72% 58% at 50% 50%,
    rgba(0, 0, 0, .86), rgba(0, 0, 0, .62) 48%, rgba(0, 0, 0, 0) 100%);
}

/* Blue on a blue-lit scan is the one case the existing accent ring can lose.
   White reads against the field and against black, and needs no halo. */
body.os :focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

/* The first body child is a canvas, so a skip link earns its place. */
.skip-link:not(:focus) {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.skip-link:focus {
  position: fixed; left: 16px; top: 16px; z-index: 200;
  background: #fff; color: #000; padding: 12px;
}

/* Anchors clear the fixed header. */
body.os #what,
body.os #showcase,
body.os #contact,
body.os .os-rail { scroll-margin-top: 82px; }

/* ---------- 4. header ---------------------------------------------------- */

/* Glass rather than a bar: the field smears under the nav instead of being
   cut off by it, which is the one-surface read at the most visible seam. */
body.os header.scrolled {
  background: rgba(0, 0, 0, .62);
  backdrop-filter: blur(14px) saturate(120%);
  -webkit-backdrop-filter: blur(14px) saturate(120%);
  border-bottom-color: var(--line-soft);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  body.os header.scrolled { background: rgba(0, 0, 0, .85); }
}

/* ======================= boundary: hero and sections ====================== */

/* ---------- 5. hero ------------------------------------------------------ */

.os-hero {
  position: relative; min-height: 800px; min-height: max(800px, 100svh);
  display: flex; align-items: center; padding: 130px 0 120px;
  isolation: isolate;
}
.os-hero::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: linear-gradient(90deg, #000 0%, rgba(0,0,0,.92) 24%, rgba(0,0,0,.48) 45%, transparent 65%),
    radial-gradient(ellipse at 80% 45%, rgba(59,130,246,.09), transparent 52%);
}
.os-hero-grid {
  position: relative; z-index: 1; display: grid;
  grid-template-columns: 1.08fr 1fr; gap: clamp(24px, 4vw, 64px);
  align-items: center; width: 100%; max-width: 1440px; margin: 0 auto;
  padding: 0 clamp(20px, 5vw, 80px);
}
.os-hero-copy { min-width: 0; max-width: 680px; position: relative; z-index: 1; }
.os-hero-copy::before { content: none; }
.os-hero-kicker { display: flex; align-items: center; gap: 10px; font-size: .72rem; color: #b7bec9; }
.os-hero-kicker > span { width: 6px; height: 6px; background: var(--accent); box-shadow: 0 0 14px var(--accent); }
.os-hero-copy h1 {
  font-size: clamp(3.3rem, 5.55vw, 5rem); font-weight: 510;
  letter-spacing: -.065em; line-height: 1.04; margin: 30px 0 0;
}
.os-hero-word { color: #85b3ff; }
@supports (background-clip: text) {
  .os-hero-word { background: linear-gradient(105deg, #f5f5f5, #8cb7ff 48%, #3b82f6);
    background-clip: text; -webkit-text-fill-color: transparent; }
}
.os-hero-lede { color: #a7adb7; font-size: 1.06rem; line-height: 1.75; max-width: 27em; margin-top: 28px; text-wrap: pretty; }
.os-hero-ctas { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 32px; }
.os-hero-ctas .btn { padding: 14px 22px; display: inline-flex; align-items: center; justify-content: center; gap: 26px; }
.os-hero-ctas .btn-ghost { background: rgba(0,0,0,.35); }
.os-hero-visual { min-width: 0; height: 510px; position: relative; pointer-events: none; }
.os-city-fallback { position: absolute; width: 140%; height: 115%; max-width: none;
  left: -25%; top: -16%; z-index: -1; pointer-events: none; visibility: hidden; }
/* A fallback is only for unavailable WebGL, never a second city during loading. */
html.os-nofield .os-city-fallback { visibility: visible; }
.os-hero-bottom { position: absolute; bottom: 30px; left: max(5vw, calc((100vw - 1280px) / 2));
  font: .63rem var(--mono); color: var(--muted); }

/* No canvas: close the hero with a hairline instead of a hole. */
.os-nofield .os-hero { border-bottom: 1px solid var(--line-soft); }

/* ---------- 6. register rail --------------------------------------------- */

/* Glass laid on the field, not a black strip cut out of it. Masked ends mean
   items fade instead of clipping, so the band has no vertical edge and its
   hairlines feather out before the viewport edge. */
.os-rail {
  position: relative;
  padding: 0;
  overflow: hidden;
  border-block: 1px solid var(--line);
  background: rgba(0, 0, 0, .5);
  backdrop-filter: blur(8px) saturate(115%);
  -webkit-backdrop-filter: blur(8px) saturate(115%);
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 3%, #000 97%, transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 3%, #000 97%, transparent 100%);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .os-rail { background: rgba(0, 0, 0, .78); }
}
.os-rail .wrap { padding-block: 14px; }
.os-rail-label {
  font-family: var(--mono); font-size: .72rem; letter-spacing: .04em;
  color: var(--muted);
}
.os-rail-track {
  display: flex; width: max-content;
  animation: os-rail-scroll 52s linear infinite;
  will-change: transform;
}
/* Read it by stopping it: hover or tab into the band and the track holds. */
.os-rail:hover .os-rail-track,
.os-rail:focus-within .os-rail-track { animation-play-state: paused; }
.os-rail-item {
  flex: 0 0 auto;
  display: flex; flex-direction: column; gap: 3px;
  padding: 18px clamp(22px, 3vw, 44px);
  border-right: 1px solid var(--line-soft);
}
.os-rail-name {
  font-size: .9rem; font-weight: 510; letter-spacing: -.01em; color: var(--ink);
}
.os-rail-what {
  font-family: var(--mono); font-size: .7rem; letter-spacing: .02em;
  color: var(--muted);
}
.os-rail-note {
  font-family: var(--mono); font-size: .7rem; line-height: 1.7;
  color: var(--muted); max-width: 64em;
}
@keyframes os-rail-scroll {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

/* ---------- 7. one roof -------------------------------------------------- */

.os-roof .mega,
.os-roof h2 { font-size: clamp(1.9rem, 3.6vw, 3rem); }
.os-roof .eyebrow + .mega,
.os-roof .eyebrow + h2 { margin-top: 14px; }
.os-roof .mega + .mega { margin-top: .1em; }
.os-roof-lede {
  color: var(--muted); font-size: 1.08rem; max-width: 46em; margin-top: 28px;
}
.os-roof-rows { margin-top: 48px; display: grid; grid-template-columns: repeat(3, 1fr); gap: 30px; }
.os-roof-row { display: flex; flex-direction: column; gap: 20px;
  padding: 28px 0; border-top: 1px solid var(--line-strong); align-items: flex-start; }
.os-roof-num {
  font-family: var(--mono); font-size: .8rem; line-height: 2;
  color: var(--muted); letter-spacing: .04em;
}
.os-roof-row h3 {
  font-size: clamp(1.2rem, 1.9vw, 1.6rem);
  font-weight: 510; letter-spacing: -.01em; line-height: 1.2;
}
.os-roof-row p { color: var(--muted); font-size: 1.04rem; }

/* ---------- 8. what it does ---------------------------------------------- */

.os-does h2 { font-size: clamp(1.9rem, 3.6vw, 3rem); margin: 14px 0 20px; }
.os-does-lede { color: var(--muted); font-size: 1.08rem; max-width: 46em; }

/* One intake on the left, four things out on the right. */
.os-mech {
  display: grid; grid-template-columns: minmax(260px, 340px) 1fr;
  gap: clamp(28px, 4vw, 64px); align-items: start;
  margin-top: clamp(48px, 7vh, 90px);
}
.os-mech-label,
.os-mech-cap,
.os-mech-caption {
  font-family: var(--mono); font-size: .72rem; letter-spacing: .04em;
  color: var(--muted);
}
.os-mech-file {
  font-family: var(--mono); font-size: .8rem; color: var(--ink);
  padding: 10px 0; border-bottom: 1px solid var(--line-soft);
  overflow-wrap: anywhere;
}
.os-mech-file:first-child,
.os-mech-label + .os-mech-file { border-top: 1px solid var(--line-soft); }
.os-mech-cap,
.os-mech-caption { display: block; margin-top: 14px; }

/* Open columns leave the city visible between the four outcomes. */
.os-mech-grid {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: 32px;
  margin-top: 18px;
}
.os-mech-grid > * {
  border-top: 1px solid var(--line);
  padding-top: 20px;
}
.os-mech-grid h3 {
  font-size: 1.12rem; font-weight: 510; letter-spacing: -.01em;
  margin-bottom: 10px; color: var(--ink);
}
.os-mech-grid p { color: var(--muted); font-size: .98rem; line-height: 1.6; }

/* Reading limits stay beside the intake, in the same open layout. */
.os-refusal {
  margin-top: 48px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
  background: transparent;
}
.os-refusal h3 {
  font-size: 1.12rem; font-weight: 510; letter-spacing: -.01em;
  margin-bottom: 10px; color: var(--ink);
}
.os-refusal p { color: var(--muted); font-size: .98rem; line-height: 1.65; max-width: 62em; }

/* Also under the roof: eight capabilities, one line each. Cards with borders
   at this count would read as a feature wall. */
.os-more { margin-top: clamp(60px, 8vh, 100px); }
.os-more-label {
  font-family: var(--mono); font-size: .72rem; letter-spacing: .04em;
  color: var(--muted);
}
.os-more summary { cursor: pointer; padding-block: 16px; min-height: 48px; }
.os-more summary:hover { color: var(--ink); }
.os-more-grid {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: clamp(24px, 3vw, 40px);
  margin-top: 28px;
}
.os-more-grid h3 {
  font-size: .98rem; font-weight: 510; letter-spacing: -.01em;
  margin-bottom: 8px; color: var(--ink);
}
.os-more-grid p { color: var(--muted); font-size: .9rem; line-height: 1.6; }

/* ---------- 9. the model (showcase) -------------------------------------- */

.os-showcase h2 { font-size: clamp(1.9rem, 3.6vw, 3rem); margin: 14px 0 20px; }
.os-showcase-lede { color: var(--muted); font-size: 1.08rem; max-width: 46em; }
.os-showcase-lede + .os-showcase-lede { margin-top: 18px; }
.os-showcase-grid {
  display: grid; grid-template-columns: 1fr 390px;
  gap: clamp(28px, 4vw, 56px); align-items: center;
  margin-top: clamp(40px, 6vh, 72px);
}

/* hero3d.js sizes itself from stage.clientWidth/clientHeight, so this height
   must be definite before its first frame or the scene renders at zero.
   No border: the stage is a window on the same world, not a framed picture.
   The radial ground plus the mask on the composited canvas dissolve the
   opaque black rectangle hero3d's renderer paints. */
#showcaseStage {
  position: relative;
  min-height: clamp(420px, 58vh, 680px);
  background: radial-gradient(120% 90% at 50% 45%,
    rgba(0, 0, 0, .55), rgba(0, 0, 0, .88) 62%, rgba(0, 0, 0, .94) 100%);
}
#showcaseStage canvas {
  display: block; width: 100%; height: 100%;
  -webkit-mask-image: radial-gradient(132% 106% at 50% 50%, #000 56%, transparent 100%);
  mask-image: radial-gradient(132% 106% at 50% 50%, #000 56%, transparent 100%);
}
.os-showcase-cap,
.os-showcase-caption {
  margin-top: 16px;
  font-family: var(--mono); font-size: .72rem; letter-spacing: .04em;
  color: var(--muted);
}

/* The scripted chat, relocated out of the hero. In the hero it was absolutely
   positioned over the scene; in a bounded section it is an ordinary column. */
.os-showcase .hero-phase,
.os-showcase .os-showcase-chat {
  position: static; width: auto; transform: none;
  display: flex; flex-direction: column; align-items: flex-start; gap: 16px;
}
.os-showcase .hero-chat {
  display: flex; flex-direction: column; gap: 12px; width: 100%;
}
.os-showcase .hb {
  max-width: 94%; padding: 13px 18px;
  font-size: .95rem; line-height: 1.55;
  border-radius: 8px;
  display: none;
}
.os-showcase .hb.show { display: block; animation: os-bub-in .45s var(--ease) both; }
@keyframes os-bub-in {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}
.os-showcase .hb.user {
  align-self: flex-end;
  background: rgba(13, 27, 51, .9);
  border: 1px solid rgba(59, 130, 246, .35);
  color: var(--ink);
}
.os-showcase .hb.ai {
  align-self: flex-start;
  background: rgba(17, 17, 17, .92);
  border: 1px solid var(--line);
  color: #d4d4d4;
}
.os-showcase .hb.typing-b { padding: 10px 18px 6px; }
.os-showcase .hero-dashes { display: flex; gap: 8px; }
.os-showcase .hero-dashes button {
  width: 28px; height: 3px; border: 0; padding: 0; cursor: pointer;
  background: rgba(255, 255, 255, .18);
  transition: background .3s;
}
.os-showcase .hero-dashes button:hover { background: rgba(255, 255, 255, .5); }
.os-showcase .hero-dashes button.on { background: var(--accent); }

/* ---------- 10. surviving sections on the new ground --------------------- */

/* The API section's own panels are opaque and stay that way: they are
   instruments on a table, not sections. Only the section ground changes, and
   its border-block is one of the two full-bleed hairlines the page keeps. */
body.os #api { background: transparent; scroll-margin-top: 82px; }

/* The closing CTA keeps its structure from the inline style; it only stops
   sitting on a painted rectangle. Its copy is --ink and #d4d4d4, which reads
   over the field at every veil value. */
body.os #contact .row { display: flex; flex-wrap: wrap; gap: 14px; }

/* ---------- 11. responsive ----------------------------------------------- */

@media (max-width: 1060px) {
  .os-hero-grid { gap: 24px; }
  .os-more-grid { grid-template-columns: repeat(2, 1fr); }
  .os-showcase-grid { grid-template-columns: 1fr 330px; }
}

@media (max-width: 940px) {
  .os-hero { padding: 110px 0 95px; align-items: flex-start; min-height: 100svh; }
  .os-hero-grid { grid-template-columns: 1fr; gap: 12px; }
  .os-hero-copy { max-width: 620px; }
  .os-hero-copy h1 { font-size: clamp(3.2rem, 8vw, 4.7rem); }
  .os-hero-visual { height: 260px; }
  .os-hero::after { background: linear-gradient(180deg, #000, rgba(0,0,0,.85) 35%, transparent 70%); }
  .os-hero-bottom { bottom: 22px; }
  .os-roof-rows { grid-template-columns: 1fr; gap: 4px; }

  /* On a phone the grid is stacked, so the copy sits over the field rather
     than beside it and the radial plate is the wrong shape. Same legibility
     device the page already used at .hero-stage::after. */
  .os-hero::before {
    content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
    background: linear-gradient(180deg,
      rgba(0, 0, 0, .94) 0%, rgba(0, 0, 0, .72) 40%, rgba(0, 0, 0, 0) 78%);
  }
  .os-hero-copy::before { content: none; }

  .os-roof-row { grid-template-columns: 1fr; gap: 12px; }
  .os-mech { grid-template-columns: 1fr; }
  .os-showcase-grid { grid-template-columns: 1fr; }
  #showcaseStage { min-height: 420px; aspect-ratio: 4 / 5; }
  .os-showcase .hb { max-width: 100%; }
  .os-rail-item { padding: 16px clamp(18px, 4vw, 30px); }
}

@media (max-width: 800px) {

  .os-mech-grid { grid-template-columns: 1fr; }
  .os-refusal { margin-top: 32px; }
  .os-showcase-grid { gap: 26px; }
}

@media (max-width: 480px) {
  .os-hero { padding: 104px 0 90px; }
  .os-hero-copy h1 { font-size: clamp(2.65rem, 10vw, 4rem); }
  .os-hero-kicker { font-size: .58rem; }
  .os-hero-visual { height: 230px; }
  .os-hero-ctas { gap: 10px; }
  .os-hero-ctas .btn { flex: 1 1 auto; padding: 13px 14px; gap: 12px; font-size: .8rem; }
  .os-hero-lede,
  .os-hero-copy .lede { font-size: 1rem; }
  .os-more-grid { grid-template-columns: 1fr; gap: 22px; }
  .os-rail-item { padding: 14px 18px; }
  .os-rail-name { font-size: .86rem; }
  .os-showcase .hero-dashes button { width: 34px; height: 4px; }
}

/* ---------- 12. reduced motion and html.noanim --------------------------- */

/* One composed still, never a loop. The canvas is shown immediately because
   os-hero.js renders exactly one frame and never adds .on through a
   transition it will not wait for. The rail wraps instead of scrolling: a
   paused marquee would hide six of the nine registers, which is exactly the
   proof the band exists to deliver. */
@media (prefers-reduced-motion: reduce) {
  #osField { opacity: 1; transition: none; }
  #osVeil,
  #osVeilDeep { transition: none; }

  .os-rail {
    -webkit-mask-image: none;
    mask-image: none;
  }
  .os-rail-track {
    animation: none;
    width: auto;
    flex-wrap: wrap;
    justify-content: flex-start;
  }
  .os-rail-track [aria-hidden="true"] { display: none; }
  .os-rail-item { border-right: 0; border-top: 1px solid var(--line-soft); }

  .os-showcase .hb.show { animation: none; }
  body.os header.scrolled { transition: none; }
}

html.noanim #osField { opacity: 1; transition: none; }
html.noanim #osVeil,
html.noanim #osVeilDeep { transition: none; }
html.noanim .os-rail {
  -webkit-mask-image: none;
  mask-image: none;
}
html.noanim .os-rail-track {
  animation: none;
  width: auto;
  flex-wrap: wrap;
  justify-content: flex-start;
}
html.noanim .os-rail-track [aria-hidden="true"] { display: none; }
html.noanim .os-rail-item { border-right: 0; border-top: 1px solid var(--line-soft); }
html.noanim .os-showcase .hb.show { animation: none; }
html.noanim .os-showcase .hb { transition: none; }

/* ---------------------------------------------------------------- 10b · api
   The API section predates this page and carries its own system: nine rounded
   corners, two decorative gradients, six untokenised blues and eight different
   off-black panel hexes where the token is --bg-raise. It also paints opaque
   full-width slabs for roughly 1500 px of scroll, three sections after this
   file declares that no section paints a rectangle, which cuts the field dead
   exactly where it should still be crossing a seam.

   Normalised from here rather than in api-showcase.css: that file is shared
   with landing/developers/ and is regenerated, so a change there would be
   reverted by the next render. os.css loads last, so this wins on equal
   specificity without !important. Panels stay semi-transparent so they keep
   the instruments-on-a-table read and the field survives underneath them. */
body.os #api :is(
  .api-order-feature, .api-flow, .api-detail, .api-catalogue-link,
  .api-output-card, .api-nodes li, .api-choice, .api-response, .api-bar-track
) { border-radius: 0; }

body.os #api :is(.api-order-feature, .api-flow) { background: rgba(17, 17, 17, .62); }
body.os #api :is(.api-detail, .api-output-card, .api-nodes li, .api-response pre, .api-endpoint)
  { background: rgba(17, 17, 17, .72); }
body.os #api .api-order-feature { border-color: var(--line); }
body.os #api :is(.api-choice, .api-bar-track) { background: rgba(17, 17, 17, .55); }

/* One blue on the page, and it is the token. */
body.os #api :is(.api-choice[aria-selected="true"], .api-choice.on) { border-color: var(--accent); color: var(--ink); }
body.os #api :is(.api-endpoint, .api-nodes li b, .api-flow b) { color: var(--accent); }
body.os #api .api-response pre code { color: var(--ink); }
body.os #api :is(.api-preview-note, .api-order-path li, .api-principles p) { color: var(--muted); }
body.os #api svg [stroke="#60a5fa"] { stroke: var(--accent); }
body.os #api svg [fill="#60a5fa"] { fill: var(--accent); }
