:root {
  --header-h: 4.5rem; /* JS refines this from the header's measured height */

  /* Palette: the brand pair (blue/teal, analogous hues ~215 and ~189) plus
     its own tints and shades: expanded monochromatically, no new hues.
     Semantics carried from the hero: teal = interactive, blue = chosen. */
  --blue: #004aad;
  --blue-deep: #003a87;   /* pressed/hover shade of blue */
  --teal: #0097b2;
  --ink: #10192b;
  --navy: #081b3c;
  --muted: #5a6b85;
  --ice: #eaf1fa;         /* solid tint of blue, for quiet surfaces */
  --foam: #e6f5f8;        /* solid tint of teal, for hovered surfaces */
  --frost: rgba(255, 255, 255, 0.62);
  --hairline: rgba(16, 25, 43, 0.14);

  /* Steel accents: the brand blue desaturated. Same hue neighborhood,
     chroma dropped, so Industry's metal reads as ours. */
  --steel-500: #46536a;
  --steel-700: #323d4d;
}

/* Cross-document view transitions: navigating between pages cross-fades in
   place. The header and footer are identical on every page, so they hold
   still while the content changes, and the site reads as one page. */
@view-transition {
  navigation: auto;
}

html {
  /* the gutter is reserved on every page, so the header never shifts
     sideways when scrollable and non-scrollable pages trade places */
  scrollbar-gutter: stable;

  /* iOS Safari inflates text per block, scaled by how wide that block is
     relative to the viewport. The code panes on nrv.html are exactly the
     worst case: each holds a different longest line, so each got its own
     inflation factor and the six panes rendered at six different sizes on a
     phone while being identical on a desktop. This turns the autosizer off;
     the type scale is already responsive on its own. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* --- Themed pages: nav sections wear their institution's design ----------- */

/* The veil wears the settled academia look; the page itself is plain paper
   and the dots render in dot by dot on the .page-dots canvas, exactly as
   they do in the Academia specialized section */
.veil-academia {
  background-color: #fcfbf6;
  background-image: radial-gradient(circle, rgba(0, 74, 173, 0.25) 1px, transparent 1.4px);
  background-size: 26px 26px;
}

body.page-academia {
  background: #fcfbf6;
  color: #17253d;
}

/* Per-theme animated background layers, injected by site.js */
.page-bg,
.page-dots {
  position: fixed;
  inset: 0;
  pointer-events: none;
}

.page-bg {
  z-index: -3;
}

.page-dots {
  z-index: -2; /* above .page-bg, below the veil (-1) and all content */
  width: 100%;
  height: 100%;
}

/* Industry: light brushed aluminum. Same value structure as the neutral
   pages; the theme is carried by texture (machined hairline grain along
   105°, one broad sheen band) and steel accents, not by a dark surface.
   The finish is machined in by .page-bg-industry with the same brush wipe
   the Industry specialized section uses. The veil wears the settled look
   for cross-theme fades. */
.veil-industry,
.page-bg-industry {
  background:
    linear-gradient(115deg,
      transparent 32%,
      rgba(255, 255, 255, 0.5) 44%,
      rgba(255, 255, 255, 0.75) 50%,
      rgba(255, 255, 255, 0.5) 56%,
      transparent 68%),
    repeating-linear-gradient(105deg,
      rgba(70, 83, 106, 0.055) 0 2px,
      rgba(255, 255, 255, 0.05) 2px 4px),
    linear-gradient(160deg, #f6f8fb 0%, #e7ebf1 55%, #f1f3f7 100%);
}

.page-bg-industry {
  mask-image: linear-gradient(105deg, #000 0 33%, transparent 66% 100%);
  mask-size: 300% 100%;
  mask-repeat: no-repeat;
  animation: brush-in 3000ms ease-out forwards;
}

body.page-industry {
  background: #eef1f5; /* flat steel base so text is readable from frame one */
}

/* Machined cards: milled faces, a specular top edge, and a showroom
   light-sweep on hover; the steel hue lives in the border and shadow */
body.page-industry .card {
  position: relative;
  overflow: hidden;
  background: linear-gradient(165deg, #ffffff, #edf0f5);
  border-color: rgba(70, 83, 106, 0.28);
  box-shadow:
    inset 0 1px 0 #ffffff,
    0 10px 24px rgba(16, 25, 43, 0.1);
}

body.page-industry .card::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg,
    transparent 35%,
    rgba(255, 255, 255, 0.7) 50%,
    transparent 65%);
  transform: translateX(-130%);
  transition: transform 700ms ease;
  pointer-events: none;
}

body.page-industry .card:hover {
  background: linear-gradient(165deg, #ffffff, #f4f6fa);
  box-shadow:
    inset 0 1px 0 #ffffff,
    0 14px 30px rgba(16, 25, 43, 0.16);
}

body.page-industry .card:hover::after {
  transform: translateX(130%);
}

body.page-industry .facts {
  background: linear-gradient(165deg, #f8fafc, #eceff4);
  border-color: rgba(70, 83, 106, 0.28);
  box-shadow: inset 0 1px 0 #ffffff;
}

/* Government: engraved bond paper. Light like everything else; the theme is
   a fine navy crosshatch (security-print paper) and a navy letterhead
   accent structure. */
body.page-government,
.veil-government {
  background-color: #f7f9fd;
  background-image:
    repeating-linear-gradient(45deg, rgba(8, 27, 60, 0.05) 0 1px, transparent 1px 9px),
    repeating-linear-gradient(-45deg, rgba(8, 27, 60, 0.05) 0 1px, transparent 1px 9px);
}

/* Persona copy variants: site.js stamps the inferred persona on the body and
   exactly one variant of each block shows. Without JS, the broad one shows. */
.pv {
  display: none;
}

body:not([data-persona]) .pv-neutral,
body[data-persona="neutral"] .pv-neutral,
body[data-persona="academia"] .pv-academia,
body[data-persona="industry"] .pv-industry,
body[data-persona="government"] .pv-government {
  display: block;
}

/* Letterhead rule: cards and the facts panel open with a navy keyline */
body.page-government .card,
body.page-government .facts {
  border-top: 3px solid var(--navy);
}

body.page-government .facts dt {
  color: var(--navy);
}

body {
  margin: 0;
  font-family: system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  color: #10192b;
}

/* Faint brand wash behind everything, so translucent panels have depth.
   Each theme's background is shared with a .veil-* class: when navigation
   crosses themes, a veil wearing the PREVIOUS background fades out over the
   new one, so the change reads as a progression, not a snap. */
body,
.veil-neutral {
  background: linear-gradient(160deg, #ffffff 0%, #f2f8fa 45%, #e7eef8 100%) fixed;
}

.theme-veil {
  position: fixed;
  inset: 0;
  z-index: -1; /* above the page background, below all content */
  pointer-events: none;
  transition: opacity 900ms ease;
}

/* Sticky over every section; frosted brand tint keeps it legible on any
   panel background */
.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
  /* natural height; bar spans the viewport and the padding keeps contents
     on the 1150px column */
  padding: 1.3rem max(2rem, calc((100vw - 1150px) / 2));
  box-sizing: border-box;
  /* opaque and flat, so the bar reads identically over every theme; one
     hairline is all the separation it needs */
  background:
    linear-gradient(90deg, rgba(0, 74, 173, 0.07), rgba(0, 151, 178, 0.07)),
    #ffffff;
  box-shadow: 0 1px 0 var(--hairline);
  /* the bar is always light, so its text is always ink, whatever the page */
  color: var(--ink);
}

.brand {
  text-decoration: none;
  color: inherit;
}

.brand-name {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

/* --- Navbar with hover dropdowns ------------------------------------------ */

.site-nav ul {
  display: flex;
  gap: 2.2rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.site-nav li {
  position: relative;
}

.site-nav ul > li > a {
  color: inherit;
  text-decoration: none;
  font-size: 0.95rem;
  font-weight: 500;
  padding-bottom: 0.15rem;
  border-bottom: 2px solid transparent;
  transition: color 120ms ease, border-color 120ms ease;
}

.site-nav ul > li > a:hover {
  color: var(--teal);
  border-bottom-color: var(--teal);
}

/* The page you are on: blue, like a chosen word in the hero */
.site-nav ul > li > a.active {
  color: var(--blue);
  border-bottom-color: var(--blue);
}

/* Dropdown: opens on hover (or keyboard focus), collapses when the pointer
   leaves. The padding-top is a hover bridge so the pointer can travel from
   the item into the panel without collapsing it. */
.nav-menu {
  position: absolute;
  top: 100%;
  right: -0.5rem;
  padding-top: 0.9rem;
  width: max-content;
  max-width: 21rem;
  opacity: 0;
  visibility: hidden;
  transition: opacity 160ms ease, visibility 0s linear 160ms;
}

.has-menu:hover .nav-menu,
.has-menu:focus-within .nav-menu {
  opacity: 1;
  visibility: visible;
  transition-delay: 0s;
}

.nav-menu-panel {
  display: grid;
  gap: 0.25rem;
  padding: 0.55rem;
  border-radius: 0.6rem;
  background:
    linear-gradient(90deg, rgba(0, 74, 173, 0.05), rgba(0, 151, 178, 0.05)),
    rgba(255, 255, 255, 0.88);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--hairline);
  box-shadow: 0 12px 32px rgba(16, 25, 43, 0.14);
}

.nav-menu a {
  display: block;
  padding: 0.55rem 0.7rem;
  border-radius: 0.4rem;
  text-decoration: none;
  transition: background-color 120ms ease;
}

.nav-menu a:hover,
.nav-menu a:focus-visible {
  background-color: var(--foam);
}

.nav-menu strong {
  display: block;
  font-size: 0.92rem;
  color: var(--teal);
}

.nav-menu a:hover strong {
  color: var(--blue-deep);
}

.nav-menu span {
  display: block;
  font-size: 0.8rem;
  line-height: 1.35;
  color: var(--muted);
}

/* Touch-first small screens have no hover: top-level links still reach the
   grid pages, which list everything the dropdowns do */
@media (max-width: 800px) {
  .nav-menu {
    display: none;
  }
}

.cube-logo {
  width: 100%;
  height: auto;
}

.type-headline {
  font-size: clamp(2rem, 4.5vw, 3.75rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
  white-space: pre-wrap; /* keep the space typed at the end of a segment */
}

.type-cursor {
  display: inline-block;
  width: 0.5ch;
  height: 1em;
  margin-left: 0.08em;
  background-color: #10192b; /* JS retints this to match the preceding character */
  vertical-align: text-bottom;
  animation: cursor-blink 1.1s steps(1) infinite;
}

@keyframes cursor-blink {
  50% { opacity: 0; }
}

/* --- Footer --------------------------------------------------------------- */

/* --- Content pages (Products, Services, R&D, Contact, and detail pages) -- */

.page-main {
  width: 100%;
  max-width: 1150px;
  margin: 0 auto;
  padding: 3.5rem 2rem 5rem;
  box-sizing: border-box;
  /* keeps the footer at the viewport bottom even on short pages */
  min-height: calc(100vh - var(--header-h) - 9rem);
}

.page-title {
  font-size: clamp(1.9rem, 3.4vw, 3rem);
}

.crumb {
  display: inline-block;
  margin-bottom: 1.5rem;
  font-size: 0.9rem;
  text-decoration: none;
  color: var(--teal);
}

.crumb:hover {
  color: var(--blue-deep);
}

.page-lead {
  max-width: 46rem;
  font-size: 1.08rem;
  line-height: 1.65;
}

/* The dropdown contents, laid out as cards: at most three columns, wrapping
   to a new row every three entries */
.card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
  margin-top: 2.5rem;
}

.card {
  display: block;
  padding: 1.6rem 1.7rem;
  border-radius: 0.8rem;
  background:
    linear-gradient(90deg, rgba(0, 74, 173, 0.04), rgba(0, 151, 178, 0.04)),
    rgba(255, 255, 255, 0.6);
  border: 1px solid var(--hairline);
  text-decoration: none;
  color: inherit;
  transition: background-color 140ms ease, transform 140ms ease, box-shadow 140ms ease;
}

.card:hover {
  background-color: var(--foam);
  transform: translateY(-3px);
  box-shadow: 0 14px 30px rgba(16, 25, 43, 0.12);
}

.card h3 {
  margin: 0 0 0.5rem;
  font-size: 1.2rem;
  letter-spacing: -0.01em;
  color: var(--teal);
}

.card:hover h3 {
  color: var(--blue-deep);
}

.card p {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--muted);
}

.card .card-meta {
  margin-top: 0.9rem;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--navy);
}

/* Detail pages: prose column + a key-facts panel */
.detail {
  max-width: 50rem;
  font-size: 1.02rem;
  line-height: 1.65;
}

.detail h3 {
  margin-top: 2.2rem;
  letter-spacing: -0.01em;
}

.facts {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.4rem 1.5rem;
  max-width: 50rem;
  margin: 2.2rem 0 0;
  padding: 1.4rem 1.7rem;
  box-sizing: border-box;
  background: var(--ice);
  border: 1px solid var(--hairline);
  border-radius: 0.8rem;
}

.facts dt {
  font-weight: 600;
  color: var(--blue);
}

.facts dd {
  margin: 0;
}

@media (max-width: 800px) {
  .card-grid {
    grid-template-columns: 1fr;
  }

  .facts {
    grid-template-columns: 1fr;
    gap: 0.1rem;
  }

  .facts dd {
    margin-bottom: 0.6rem;
  }
}

footer {
  /* opaque and flat like the header, so it reads the same everywhere */
  background:
    linear-gradient(90deg, rgba(0, 74, 173, 0.07), rgba(0, 151, 178, 0.07)),
    #ffffff;
  box-shadow: 0 -1px 0 var(--hairline);
}

footer p {
  max-width: 1150px;
  margin: 0 auto;
  padding: 1.5rem 2rem;
  box-sizing: border-box;
  font-size: 0.85rem;
  color: #5a6b85;
  text-align: center;
}

@media (max-width: 800px) {
  /* the navbar grows on small screens: comfortable type, real tap targets */
  .site-header {
    flex-wrap: wrap;
    gap: 0.5rem 1.5rem;
    padding: 0.9rem 1.25rem;
  }

  .brand-name {
    font-size: 1.2rem;
  }

  /* one full-width row that never wraps: a wrapped item ("Contact" under
     "Home") is a misclick waiting to happen. The font gives way instead. */
  .site-nav {
    width: 100%;
  }

  .site-nav ul {
    flex-wrap: nowrap;
    justify-content: space-between;
    gap: 0.75rem;
  }

  .site-nav ul > li > a {
    display: inline-block;
    font-size: clamp(0.85rem, 3.4vw, 1.05rem);
    white-space: nowrap;
    padding: 0.3rem 0 0.35rem;
  }

}

/* Portrait viewports of any width (phones, rotated monitors): tighten the
   type and the page column. The hero's own portrait rules live with the rest
   of the index layout further down, because a base rule declared after a
   media query of the same specificity wins whatever the viewport is. */
@media (orientation: portrait) {
  .type-headline {
    font-size: clamp(2rem, 7vw, 3.4rem);
  }

  .page-main {
    padding: 2rem 1.25rem 3.5rem;
  }
}

/* Large portrait screens (rotated monitors, tablets on end): scale the
   stage up so the tall viewport is filled, not framed in blank space */
@media (orientation: portrait) and (min-width: 900px) {
  .type-headline {
    font-size: clamp(3rem, 6.5vw, 4.5rem);
  }
}

/* --- Index: the scrollable page ------------------------------------------ */
/* One column of sections: a hero that fills the viewport exactly, a statement
   of what the company does, then one block per product, service and research
   area, each carrying its own spinning mark. Nothing is gated and nothing is
   hidden behind a click. The page is read by scrolling it, which is the whole
   point of the rewrite: the text tree it replaced asked visitors to click
   words that did not look clickable. */

/* Industry's hairline texture is "machined" in along its grain: a soft wipe
   sweeps across the finish */
@keyframes brush-in {
  from { mask-position: 100% 0, 0 0; }
  to { mask-position: 0 0, 0 0; }
}

.hero-screen,
.band,
.topic-set,
.close-cta {
  width: 100%;
  max-width: 1150px;
  margin: 0 auto;
  padding: 0 2rem;
  box-sizing: border-box;
}

/* With the sticky header, exactly one viewport */
.hero-screen {
  display: grid;
  align-items: center;
  min-height: calc(100vh - var(--header-h));
  min-height: calc(100dvh - var(--header-h));
}

/* Headline and cube side by side, cube filling its column */
.hero {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  align-items: center;
  gap: 3rem;
}

.hero-lead {
  max-width: 34rem;
  margin: 1.6rem 0 0;
  font-size: 1.06rem;
  line-height: 1.65;
  color: var(--muted);
}

/* The only instruction the page needs, and it fades in after the headline has
   had time to type itself, so it does not compete with it */
.hero-cue {
  display: inline-block;
  margin-top: 1.8rem;
  font-size: 0.95rem;
  font-weight: 600;
  text-decoration: none;
  color: var(--teal);
}

.hero-cue::after {
  content: '\00a0\2193';
  display: inline-block;
  animation: cue-nudge 2.4s ease-in-out infinite;
}

.hero-cue:hover {
  color: var(--blue-deep);
}

@keyframes cue-nudge {
  0%, 70%, 100% { transform: translateY(0); }
  82% { transform: translateY(0.28em); }
}

/* Arriving at a #hash directly: park the target below the sticky header, the
   same way the eased scroll in main.js does for a click it can intercept */
.band[id],
.set-title[id] {
  scroll-margin-top: calc(var(--header-h) + 0.75rem);
}

/* --- Bands: the statements between the offerings -------------------------- */

.band {
  margin-top: 7rem;
}

.band-title {
  margin: 0 0 1.6rem;
  font-size: clamp(1.5rem, 2.6vw, 2.1rem);
  letter-spacing: -0.02em;
}

.band-lead {
  max-width: 44rem;
  margin: -0.8rem 0 0;
  font-size: 1.04rem;
  line-height: 1.65;
  color: var(--muted);
}

.band-points {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2.2rem;
  margin-top: 2.2rem;
}

.band-points h4 {
  margin: 0 0 0.5rem;
  padding-top: 0.9rem;
  border-top: 2px solid var(--teal);
  font-size: 1.05rem;
  letter-spacing: -0.01em;
  color: var(--blue);
}

.band-points p {
  margin: 0;
  font-size: 0.98rem;
  line-height: 1.6;
  color: var(--muted);
}

/* --- Offerings ------------------------------------------------------------ */

.topic-set {
  margin-top: 7rem;
}

/* A quiet label with a rule running off to the right, so the three groups
   read as chapters rather than as more headings */
.set-title {
  display: flex;
  align-items: center;
  gap: 1.2rem;
  margin: 5.5rem 0 0;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--teal);
}

.set-title::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--hairline);
}

.topic {
  display: grid;
  grid-template-columns: 0.8fr 1.2fr;
  align-items: center;
  gap: 3.5rem;
  margin-top: 4rem;
}

/* The mark alternates sides down the page, so the column edge never becomes a
   railway line of identical rows. The widths swap with it: the copy always
   gets the wide column, whichever side it is on. */
.topic:nth-of-type(even) {
  grid-template-columns: 1.2fr 0.8fr;
}

.topic:nth-of-type(even) .topic-figure {
  order: 2;
}

.topic-figure a {
  display: block;
}

.mark {
  display: block;
  width: min(100%, 19rem);
  height: auto;
  margin: 0 auto;
  overflow: visible; /* vertex halos bloom past the viewBox as pulses land */
}

/* A vertex changes color when a pulse lands on it; easing the fill turns that
   from a hard snap into the color crossing over with the pulse */
.mark circle,
.nrv-logo circle {
  transition: fill 320ms ease;
}

/* The line that earns the rest of the block */
.topic-problem {
  margin: 0 0 0.9rem;
  font-size: clamp(1.18rem, 2vw, 1.5rem);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--ink);
}

.topic-name {
  margin: 0 0 0.7rem;
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--muted);
}

.topic-name a {
  color: var(--blue);
  text-decoration: none;
  border-bottom: 2px solid var(--teal);
}

.topic-name a:hover {
  color: var(--teal);
}

.topic-copy p {
  max-width: 38rem;
  font-size: 1.01rem;
  line-height: 1.65;
}

.topic-link {
  display: inline-block;
  margin-top: 0.3rem;
  font-size: 0.92rem;
  font-weight: 600;
  text-decoration: none;
  color: var(--teal);
}

.topic-link::after {
  content: '\00a0\2192';
}

.topic-link:hover {
  color: var(--blue-deep);
}

/* --- Closing ------------------------------------------------------------- */

.close-cta {
  margin: 7rem auto 5rem;
  padding-top: 3rem;
  border-top: 1px solid var(--hairline);
  text-align: center;
}

.close-cta h3 {
  margin: 0 0 0.6rem;
  font-size: clamp(1.5rem, 2.6vw, 2.1rem);
  letter-spacing: -0.02em;
}

.close-cta p {
  max-width: 34rem;
  margin: 0 auto 1.8rem;
  font-size: 1.02rem;
  line-height: 1.6;
  color: var(--muted);
}

/* --- Topic page heroes ---------------------------------------------------- */
/* Every product, service and research page opens the way nrv.html does: title
   and lead on the left, the topic's own mark spinning on the right. The mark
   is the same one the index shows for that topic, so arriving on the page is
   a continuation rather than a fresh start. */

.page-hero {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  align-items: center;
  gap: 3rem;
  margin-bottom: 1.5rem;
}

.page-hero .page-title {
  margin-top: 0;
}

.page-hero .page-lead {
  margin-bottom: 0;
}

.page-hero-figure .mark {
  width: min(100%, 22rem);
}

@media (max-width: 900px) {
  .page-hero {
    grid-template-columns: 1fr;
    gap: 1.75rem;
  }

  .page-hero-figure .mark {
    width: min(62vw, 34vh, 20rem);
  }
}

@media (orientation: portrait) {
  .page-hero {
    grid-template-columns: 1fr;
    gap: 1.75rem;
  }

  .page-hero-figure .mark {
    width: min(62vw, 34vh, 20rem);
  }
}

/* --- Scroll entrances ----------------------------------------------------- */
/* Applied by main.js through body.index-anim, never by the stylesheet alone,
   so with JavaScript off the page is a finished page and not a blank one. */

body.index-anim .reveal {
  opacity: 0;
  transform: translateY(1.3rem);
  transition: opacity 700ms ease, transform 700ms cubic-bezier(0.22, 0.8, 0.3, 1);
}

body.index-anim .reveal.shown {
  opacity: 1;
  transform: none;
}

@media (max-width: 900px) {
  .hero {
    grid-template-columns: 1fr;
    gap: 1.5rem;
    padding: 2rem 0;
  }

  .hero .cube-logo {
    width: min(58vw, 20rem);
    justify-self: center;
  }

  .topic,
  .topic:nth-of-type(even) {
    grid-template-columns: 1fr;
    gap: 1.5rem;
    margin-top: 3.5rem;
  }

  /* Stacked, the mark reads as the block's opening image, so it goes first
     whatever side it would have taken */
  .topic:nth-of-type(even) .topic-figure {
    order: 0;
  }

  .mark {
    width: min(58vw, 14rem);
  }

  .band-points {
    grid-template-columns: 1fr;
    gap: 1.6rem;
  }
}

@media (max-width: 800px) {
  .hero-screen,
  .band,
  .topic-set,
  .close-cta {
    padding: 0 1.25rem;
  }

  .band,
  .topic-set {
    margin-top: 4.5rem;
  }

  .set-title {
    margin-top: 4rem;
  }
}

@media (orientation: portrait) {
  .hero {
    grid-template-columns: 1fr;
    gap: 1.25rem;
    padding: 0.5rem 0 2rem;
  }

  .hero .cube-logo {
    width: min(72vw, 38vh, 500px);
    justify-self: center;
  }

  .topic,
  .topic:nth-of-type(even) {
    grid-template-columns: 1fr;
    gap: 1.5rem;
  }

  .topic:nth-of-type(even) .topic-figure {
    order: 0;
  }

  .mark {
    width: min(58vw, 14rem);
  }
}

/* Large portrait screens: the cube fills the tall viewport rather than
   being framed in blank space */
@media (orientation: portrait) and (min-width: 900px) {
  .hero {
    gap: 2.5rem;
  }

  .hero .cube-logo {
    width: min(62vw, 46vh, 760px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero-cue::after {
    animation: none;
  }

  .mark circle,
  .nrv-logo circle,
  .theme-veil {
    transition: none;
  }

  .page-bg-industry {
    animation: none; /* default mask-position is the settled state */
  }
}

.nrv-logo {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible; /* vertex halos bloom past the viewBox as pulses land */
}

/* --- Capability statement ------------------------------------------------- */
/* Government is the theme with no animated background of its own, so this
   page's motion is structural: each section settles up and has its navy rule
   struck across it, left to right, the way a keyline is printed onto bond
   paper. The hiding is gated on body.cap-anim, which the script adds, so with
   JavaScript off the page is just a finished document. */

.cap-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem 1.5rem;
}

.cap-section {
  margin-top: 2.9rem;
}

.cap-section h3 {
  position: relative;
  margin: 0 0 1.15rem;
  padding-bottom: 0.55rem;
  font-size: 1.18rem;
  letter-spacing: -0.01em;
  color: var(--navy);
}

.cap-section h3::after {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 2px;
  background: var(--navy);
}

body.cap-anim .cap-section {
  opacity: 0;
  transform: translateY(1.1rem);
  transition: opacity 650ms ease, transform 650ms cubic-bezier(0.22, 0.8, 0.3, 1);
}

body.cap-anim .cap-section h3::after {
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 750ms cubic-bezier(0.22, 0.8, 0.3, 1) 120ms;
}

body.cap-anim .cap-section.inked {
  opacity: 1;
  transform: none;
}

body.cap-anim .cap-section.inked h3::after {
  transform: scaleX(1);
}

/* Four capability cards read as a 2x2 block, not a 3 + 1 orphan */
.cap-grid {
  grid-template-columns: repeat(2, 1fr);
  margin-top: 0;
}

/* Cards that are statements, not links: no lift, no pointer */
.card-plain:hover {
  background-color: transparent;
  transform: none;
  box-shadow: none;
}

body.page-government .card-plain:hover {
  background: linear-gradient(90deg, rgba(0, 74, 173, 0.04), rgba(0, 151, 178, 0.04)),
    rgba(255, 255, 255, 0.6);
}

.card h4 {
  margin: 0 0 0.7rem;
  font-size: 1.02rem;
  letter-spacing: -0.01em;
  color: var(--navy);
}

.card h4 a {
  color: inherit;
  text-decoration: none;
  border-bottom: 2px solid var(--teal);
}

.card h4 a:hover {
  color: var(--blue);
}

.card ul,
.cap-list {
  margin: 0;
  padding-left: 1.1rem;
  list-style: none;
}

.card li,
.cap-list li {
  position: relative;
  margin-bottom: 0.45rem;
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--muted);
}

.card li::before,
.cap-list li::before {
  content: '';
  position: absolute;
  left: -1.1rem;
  top: 0.6em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--teal);
}

.cap-list {
  max-width: 50rem;
}

.cap-list li {
  margin-bottom: 0.7rem;
  font-size: 1rem;
  color: var(--ink);
}

.cap-list strong {
  color: var(--blue);
}

.card-note,
.cap-note {
  margin: 0.9rem 0 0;
  font-size: 0.87rem;
  line-height: 1.5;
  color: var(--muted);
}

.cap-note {
  margin: 0 0 0.9rem;
  max-width: 50rem;
}

.cap-tech {
  max-width: 50rem;
  margin: 0;
  font-size: 0.85rem;
  line-height: 1.6;
  color: var(--muted);
}

.cap-tech strong {
  color: var(--blue);
}

/* The positioning line, set between the page title and the overview: one
   sentence, blue, sized between the two so it reads as a subtitle */
.cap-position {
  max-width: 46rem;
  margin: 0.4rem 0 0.9rem;
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--blue);
}

.cap-body {
  max-width: 50rem;
  margin: 0;
  font-size: 1rem;
  line-height: 1.65;
}

/* A competency card: one plain-English line, then the dense keyword run that
   a contracting officer scans for a match. */
.cap-comp-lead {
  margin: 0 0 0.75rem;
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--muted);
}

.cap-keys {
  margin: 0;
  padding-top: 0.7rem;
  border-top: 1px solid var(--hairline);
  font-size: 0.82rem;
  line-height: 1.75;
  color: var(--navy);
}

/* Separators are generated, not typed, so the run stays one editable string
   of terms and the pipes pick up the interactive teal */
.cap-keys span::after {
  content: '|';
  margin: 0 0.4em;
  color: var(--teal);
}

.cap-keys span:last-child::after {
  content: none;
}

.cap-naics strong {
  font-variant-numeric: tabular-nums;
}

/* The section heading already sets the gap, so the facts panel does not */
.cap-section .facts {
  margin-top: 0;
}

.cap-cta {
  max-width: 50rem;
  margin: 2.6rem 0 0;
  padding: 1rem 1.3rem;
  box-sizing: border-box;
  border-top: 3px solid var(--navy);
  background: var(--ice);
  font-size: 0.98rem;
}

/* Shown only on paper: the navbar is not printed, so the sheet needs its own
   masthead. Everything that styles it lives in the print block below. */
.cap-letterhead {
  display: none;
}

@media (max-width: 800px) {
  .cap-grid {
    grid-template-columns: 1fr;
  }
}

/* --- Printing the capability statement ------------------------------------ */
/* Ctrl+P (or the button) yields a typeset one-sheet document, not a printed
   web page: a letterhead masthead with the codes set right, a two-column body,
   ruled small-caps section headings, and a contact band at the foot. The
   design language is the screen page's own, carried over: navy keylines, ice
   tint for quiet surfaces, teal for separators, the same type family.

   Three things to know before editing this block. First, a letter sheet is
   about 720 CSS px of content, so the max-width: 800px branch above is live
   here and every one-column rule in it has to be overridden explicitly (the
   orientation: portrait branch is live too, for the same reason). Second, the
   whole stylesheet is rem-based, so the root font-size is the one lever that
   scales the entire document at once: turn that dial before touching anything
   else. Third, the body is a multi-column container, so only direct children
   of .cap-sheet can carry column-span: all.

   Everything that is specific to this document is scoped to .cap-sheet, the
   class on capability-statement.html's <main>, so printing any other page is
   left alone. */
@media print {
  html {
    font-size: 11.5px; /* any page: 16px screen default, tightened for paper */
  }

  /* The dial for the capability sheet: turn this before touching anything
     else. If :has() is unsupported the sheet just prints larger.

     It is set by legibility, not by page count. At 7.9px the whole sheet fit
     on one page, but body copy landed at about 5.6pt, half the size of the
     federal statement Ashvin pointed at as the benchmark (that one runs about
     11pt, with a third of our word count). A contracting officer has to be
     able to read this. Two pages at a readable size beats one page nobody
     finishes, and a two page capability statement is entirely normal. */
  html:has(.cap-sheet) {
    font-size: 10.2px;
  }

  @page {
    size: letter;
    margin: 0.42in 0.45in;
  }

  .site-header,
  footer,
  .crumb,
  .cap-head,
  .theme-veil,
  .page-bg,
  .page-dots {
    display: none !important;
  }

  body,
  body.page-government {
    background: #ffffff !important;
    color: var(--ink);
  }

  /* Nothing may print mid-entrance */
  body.cap-anim .cap-section,
  .cap-section {
    opacity: 1 !important;
    transform: none !important;
  }

  body.cap-anim .cap-section h3::after,
  .cap-section h3::after {
    transform: scaleX(1) !important;
  }

  .page-main {
    max-width: none;
    min-height: 0;
    margin: 0;
    padding: 0 !important;
  }

  /* The document grid: the sheet is a two-column page, not one long web
     column. Everything flows through it except the four spanners below. */
  .cap-sheet {
    columns: 2;
    column-gap: 1.6rem;
    column-rule: 1px solid var(--hairline);
    orphans: 2;
    widows: 2;
  }

  /* Hand-placed column break, and the only hand-placed thing in this document.
     A multi-column container that spans pages fills each column to the full
     page before starting the next, so the last page filled column one and left
     column two blank: half a page of nothing, which reads as an accident. This
     splits the tail of the document down the middle instead. It is tuned to
     the current copy: if the sheet grows or shrinks by much, move the class to
     whichever section now sits nearest the middle of the last page, or drop it
     if the document stops running to two pages.

     One consequence, and the reason .cap-cta is not in the column-span list
     above: a forced break stops Chromium balancing that column set, so the
     columns claim the whole page height and a spanner after them is pushed to
     a page of its own. The contact band therefore closes the second column
     rather than running full width under both. */
  .cap-turn {
    break-before: column;
  }

  .cap-letterhead,
  .cap-position,
  .cap-sheet .page-lead {
    column-span: all;
  }

  /* --- Masthead: name and title left, the codes a contracting officer looks
     for set right, the whole thing closed by the navy letterhead keyline --- */
  .cap-letterhead {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: end;
    gap: 0 1.5rem;
    margin: 0 0 0.85rem;
    padding-bottom: 0.55rem;
    border-bottom: 3px solid var(--navy);
  }

  .cap-lh-name strong {
    display: block;
    font-size: 2.15rem;
    font-weight: 700;
    line-height: 1.02;
    letter-spacing: -0.028em;
    color: var(--navy);
  }

  .cap-lh-title {
    display: block;
    margin-top: 0.35rem;
    font-size: 1.02rem;
    font-weight: 600;
    letter-spacing: 0.3em;
    text-transform: uppercase;
    color: var(--blue);
  }

  .cap-lh-sub {
    display: block;
    margin-top: 0.4rem;
    font-size: 0.78rem;
    color: var(--muted);
  }

  .cap-lh-ids {
    display: grid;
    grid-template-columns: auto auto;
    gap: 0.12rem 0.75rem;
    margin: 0;
    padding: 0.5rem 0.75rem 0.45rem;
    border-top: 3px solid var(--navy);
    background: var(--ice);
    /* the tint is structure, not decoration, so it survives a browser print
       dialog with background graphics switched off */
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
    font-size: 0.72rem;
    line-height: 1.45;
  }

  .cap-lh-ids dt {
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--navy);
  }

  .cap-lh-ids dd {
    margin: 0;
    white-space: nowrap;
    color: var(--ink);
  }

  /* --- Opening block, above the columns --- */
  .cap-position {
    max-width: none;
    margin: 0 0 0.45rem;
    font-size: 1.22rem;
  }

  .cap-sheet .page-lead {
    max-width: none;
    margin: 0 0 1rem;
    padding-bottom: 0.85rem;
    border-bottom: 1px solid var(--hairline);
    font-size: 0.94rem;
    line-height: 1.55;
  }

  /* --- Section headings read as document headings: small, letterspaced,
     navy, ruled. The rule is the page's existing keyline, kept. --- */
  .cap-section {
    margin-top: 0;
    padding-top: 0.95rem;
  }

  .cap-section h3 {
    margin-bottom: 0.55rem;
    padding-bottom: 0.28rem;
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--navy);
    break-after: avoid;
  }

  .cap-section h3::after {
    height: 1.5px;
  }

  /* Beating the narrow-viewport branch: inside a print column the cards stack,
     but the facts panel must stay a two-column definition list */
  .cap-grid {
    grid-template-columns: 1fr !important;
    gap: 0.6rem;
    margin-top: 0;
  }

  .cap-sheet .facts {
    grid-template-columns: auto 1fr !important;
    gap: 0.16rem 0.9rem !important;
    max-width: none;
    margin: 0;
    padding: 0.6rem 0.8rem;
    background: var(--ice) !important;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
    border: 0;
    border-top: 3px solid var(--navy);
    border-radius: 0;
    box-shadow: none;
    font-size: 0.85rem;
  }

  .cap-sheet .facts dd {
    margin-bottom: 0 !important;
  }

  /* Blocks that must not be split across a column or a page. .cap-section is
     deliberately NOT here: core competencies is taller than one column and has
     to be allowed to flow. */
  .cap-sheet .card,
  .cap-sheet .facts,
  .cap-cta,
  .cap-list li,
  .cap-tech,
  .cap-body {
    break-inside: avoid;
  }

  .cap-sheet .card {
    background: #ffffff !important;
    border: 1px solid var(--hairline);
    border-top: 2px solid var(--navy);
    border-radius: 0;
    box-shadow: none;
    padding: 0.6rem 0.75rem;
  }

  .cap-sheet .card h4 {
    margin-bottom: 0.35rem;
    font-size: 0.95rem;
  }

  .cap-sheet .card h4 a {
    border-bottom: 0;
  }

  .cap-sheet .card li,
  .cap-list li {
    margin-bottom: 0.25rem;
    font-size: 0.86rem;
    line-height: 1.45;
  }

  .cap-comp-lead {
    margin-bottom: 0.5rem;
    font-size: 0.84rem;
    line-height: 1.45;
  }

  .cap-keys {
    padding-top: 0.45rem;
    font-size: 0.78rem;
    line-height: 1.6;
  }

  .card-note {
    margin-top: 0.45rem;
    font-size: 0.78rem;
    line-height: 1.4;
  }

  .cap-list,
  .cap-tech,
  .cap-note,
  .cap-body {
    max-width: none;
  }

  .cap-note {
    margin-bottom: 0.5rem;
    font-size: 0.8rem;
  }

  .cap-body,
  .cap-tech {
    font-size: 0.86rem;
    line-height: 1.5;
  }

  /* --- Contact band at the foot of the sheet --- */
  .cap-cta {
    max-width: none;
    margin: 1.1rem 0 0;
    padding: 0.55rem 0.85rem;
    border-top: 3px solid var(--navy);
    background: var(--ice) !important;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
    border-radius: 0;
    box-shadow: none;
    font-size: 0.86rem;
    text-align: center;
  }

  .cap-cta strong {
    color: var(--navy);
  }

  a {
    color: inherit;
    text-decoration: none;
  }
}

/* --- Forms ---------------------------------------------------------------- */
/* Same vocabulary as the rest of the site: light surfaces, hairline borders,
   teal for the interactive state, blue for the committed one. */

.compose {
  max-width: 40rem;
  margin: 2rem 0 0;
}

.field {
  display: grid;
  gap: 0.4rem;
  margin-bottom: 1.1rem;
}

.field label {
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--blue);
}

.field input,
.field textarea {
  width: 100%;
  padding: 0.6rem 0.75rem;
  box-sizing: border-box;
  font: inherit;
  font-size: 0.98rem;
  color: var(--ink);
  background: rgba(255, 255, 255, 0.75);
  border: 1px solid var(--hairline);
  border-radius: 0.45rem;
  transition: border-color 120ms ease, box-shadow 120ms ease, background-color 120ms ease;
}

.field textarea {
  resize: vertical;
  line-height: 1.55;
}

.field input::placeholder,
.field textarea::placeholder {
  color: var(--muted);
  opacity: 0.75;
}

.field input:hover,
.field textarea:hover {
  border-color: rgba(0, 151, 178, 0.5);
}

.field input:focus,
.field textarea:focus {
  outline: none;
  background: #ffffff;
  border-color: var(--teal);
  box-shadow: 0 0 0 3px rgba(0, 151, 178, 0.18);
}

.compose-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.9rem 1.1rem;
  margin-top: 0.4rem;
}

/* Flat, like the header and footer: no gloss, no gradient. Works as either a
   <button> or an <a>, so a link that acts like an action can wear it. */
.btn {
  display: inline-block;
  padding: 0.62rem 1.15rem;
  font: inherit;
  font-size: 0.95rem;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  color: #ffffff;
  background: var(--blue);
  border: 1px solid var(--blue);
  border-radius: 0.45rem;
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}

.btn:hover {
  background: var(--blue-deep);
  border-color: var(--blue-deep);
}

.btn:focus-visible {
  outline: 3px solid rgba(0, 151, 178, 0.45);
  outline-offset: 2px;
}

/* Outlined: a secondary action that does not shout over the letterhead.
   Must follow .btn, since it overrides it at the same specificity. */
.btn-quiet {
  padding: 0.45rem 0.9rem;
  font-size: 0.88rem;
  color: var(--navy);
  background: transparent;
  border-color: var(--navy);
}

.btn-quiet:hover {
  color: #ffffff;
  background: var(--navy);
  border-color: var(--navy);
}

.compose-to {
  font-size: 0.87rem;
  color: var(--muted);
}

.compose-status {
  margin: 1rem 0 0;
  font-size: 0.9rem;
  line-height: 1.55;
  color: var(--muted);
}

.compose-status:empty {
  margin: 0;
}

.compose-status.warn {
  color: var(--blue-deep);
  font-weight: 600;
}

/* --- NRV product page ----------------------------------------------------- */
/* Same two-column rhythm as the index: copy on the left, the animated mark on
   the right, then a run of steps that keep the prose left and put an editor
   where the mark was. */

.nrv-hero {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  align-items: center;
  gap: 3rem;
  margin-bottom: 1rem;
}

.nrv-hero .page-title {
  margin-top: 0;
}

/* The beta tag rides on the heading's baseline, and wraps under it rather than
   squeezing the wordmark on a narrow screen */
/* The status tag sits on its own line under the title rather than beside it.
   Beside it, the tag competed with the wordmark for the eye and it was the
   first thing to wrap on a narrow screen. */
.title-row {
  margin-bottom: 1.5rem;
}

.title-row .page-title {
  margin: 0 0 0.75rem;
}

.nrv-hero-figure .nrv-logo {
  width: min(100%, 26rem);
  margin: 0 auto;
}

/* Closed beta: stated once, plainly, next to the lead */
.beta-note {
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  max-width: 46rem;
  margin: 1.4rem 0 0;
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--muted);
}

/* The closing invitation, after the last step */
.beta-close {
  margin-top: 4rem;
}

.beta-tag {
  display: inline-block;
  flex: none; /* it also rides inside .beta-note, which is a flex row */
  padding: 0.2rem 0.55rem;
  border-radius: 0.3rem;
  background: var(--foam);
  border: 1px solid rgba(0, 151, 178, 0.35);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--teal);
}

/* The editor column is the wider one: the examples are kept under 70 columns,
   and that plus the gutter is what decides the split, not the prose. */
.nrv-step {
  display: grid;
  grid-template-columns: 1fr 1.15fr;
  align-items: start;
  gap: 3rem;
  margin-top: 7rem;
}

.nrv-prose {
  max-width: 34rem;
  font-size: 1.02rem;
  line-height: 1.65;
}

.nrv-prose h3 {
  margin: 0 0 0.8rem;
  letter-spacing: -0.01em;
}

/* Inline API names in prose: quiet, but unmistakably code */
.nrv-prose code,
.detail code {
  padding: 0.08em 0.3em;
  border-radius: 0.25em;
  background: var(--ice);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace;
  font-size: 0.88em;
  color: var(--blue-deep);
}

/* A compact glossary inside a step, wearing the facts panel's clothes */
.glossary {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.45rem 1.2rem;
  margin: 1.4rem 0 0;
  padding: 1.1rem 1.3rem;
  box-sizing: border-box;
  background: var(--ice);
  border: 1px solid var(--hairline);
  border-radius: 0.7rem;
  font-size: 0.92rem;
  line-height: 1.5;
}

.glossary dt {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace;
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--blue);
}

.glossary dd {
  margin: 0;
  color: var(--muted);
}

/* --- The editor ----------------------------------------------------------- */
/* A dark pane is the one place the site goes dark, and it earns it: this is a
   terminal, and a terminal that is not dark reads as a screenshot of prose.
   The surface is the brand navy rather than a generic black, and every token
   color is a tint of the brand pair, so the pane still belongs to the system. */

.editor {
  --ed-bg: #06162e;
  --ed-fg: #a8bfda;
  --ed-dim: #4a648a;
  position: relative;
  margin: 0;
  border-radius: 0.6rem;
  overflow: hidden;
  background: var(--ed-bg);
  border: 1px solid rgba(8, 27, 60, 0.5);
  box-shadow: 0 18px 40px rgba(8, 27, 60, 0.28);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace;
  font-size: 0.74rem;
  line-height: 1.6;
  opacity: 0;
  transform-origin: center center;
  /* Typing rewrites a row's text every few milliseconds. Containment keeps
     that work inside the pane instead of letting it invalidate layout and
     paint for the rest of the page on every character. */
  contain: layout paint;
}

/* Before the script takes over, the figure is just a readable code block */
.editor:not(.ed) {
  opacity: 1;
  padding: 1rem 1.2rem;
  color: var(--ed-fg);
}

.editor:not(.ed) pre {
  margin: 0;
  overflow-x: auto;
}

/* The set switching on: a bright horizontal line snaps to width, opens
   vertically, overshoots bright, then settles. */
@keyframes crt-on {
  0% { opacity: 0; transform: scaleY(0.004) scaleX(0.7); filter: brightness(7) saturate(0); }
  8% { opacity: 1; transform: scaleY(0.004) scaleX(1); filter: brightness(7) saturate(0); }
  30% { opacity: 1; transform: scaleY(0.012) scaleX(1); filter: brightness(5) saturate(0.25); }
  58% { transform: scaleY(1) scaleX(1); filter: brightness(2.2) saturate(0.7); }
  72% { filter: brightness(0.72); }
  84% { filter: brightness(1.3); }
  100% { opacity: 1; transform: scaleY(1) scaleX(1); filter: brightness(1); }
}

.editor.lit {
  animation: crt-on 900ms cubic-bezier(0.22, 0.8, 0.3, 1) forwards;
}

/* The wipe scales a pane full of text, with a gradient overlay on top. Without
   a layer of its own the browser re-rasterizes all of it every frame, which is
   what makes a phone stutter as a pane enters. Promote for the wipe only:
   .settled comes after the animation ends and hands the memory back, and it is
   ordered after these rules so it wins while .lit is still present. */
.editor.lit {
  will-change: transform, opacity, filter;
}

.editor.settled {
  will-change: auto;
}

/* Scanlines and a faint bloom, always on once the pane is up */
.editor.ed::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    repeating-linear-gradient(
      to bottom,
      rgba(8, 27, 60, 0.22) 0 1px,
      transparent 1px 3px),
    radial-gradient(120% 90% at 50% 50%,
      transparent 55%,
      rgba(6, 22, 46, 0.55) 100%);
  opacity: 0.55;
}

.ed-tab {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.9rem;
  background: #0b2044;
  box-shadow: inset 0 -1px 0 rgba(0, 151, 178, 0.22);
}

.ed-tab-name {
  padding: 0.1rem 0.55rem;
  border-radius: 0.25rem;
  background: var(--ed-bg);
  color: #9ec7f0;
  font-size: 0.72rem;
}

/* The examples fit; this is the safety valve for a narrow viewport, and it
   wears the pane's own colors rather than the OS scrollbar's. */
.ed-body {
  padding: 0.75rem 0 0.85rem;
  overflow-x: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(0, 151, 178, 0.4) transparent;
}

.ed-body::-webkit-scrollbar {
  height: 7px;
}

.ed-body::-webkit-scrollbar-thumb {
  border-radius: 4px;
  background: rgba(0, 151, 178, 0.4);
}

.ed-row {
  display: flex;
  white-space: pre;
}

.ed-row.is-cursor {
  background: rgba(0, 151, 178, 0.07);
}

.ed-num {
  flex: none;
  width: 3.2ch;
  padding: 0 1.1ch 0 0.9ch;
  text-align: right;
  color: var(--ed-dim);
  user-select: none;
}

.ed-row.is-cursor .ed-num {
  color: #9ec7f0;
  font-weight: 600;
}

.ed-text {
  color: var(--ed-fg);
}

/* Token colors: tints of the brand pair, separated by lightness */
.tk-com { color: #4c6890; font-style: italic; }
.tk-str { color: #cfe3f5; }
.tk-kw { color: #4fd0e6; }
.tk-api { color: #6fa8ff; font-weight: 600; }
.tk-num { color: #6fa8ff; }
.tk-call { color: #9ec7f0; }
.tk-pun { color: #7d95b4; }
.tk-id { color: var(--ed-fg); }

.ed-cursor {
  display: inline-block;
  width: 1ch;
  height: 1.15em;
  vertical-align: text-bottom;
  background: var(--teal);
  animation: cursor-blink 1.1s steps(1) infinite;
}

/* Insert mode gets the thin bar, normal mode the block, as in the editor */
.editor[data-mode="insert"] .ed-cursor {
  width: 0.16ch;
  animation: none;
}

.ed-status {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0.32rem 0.9rem;
  background: #0b2044;
  font-size: 0.72rem;
  color: var(--ed-dim);
  box-shadow: inset 0 1px 0 rgba(0, 151, 178, 0.22);
}

.ed-mode {
  padding: 0.1rem 0.5rem;
  border-radius: 0.2rem;
  background: var(--blue);
  color: #ffffff;
  font-weight: 700;
  letter-spacing: 0.05em;
}

.editor[data-mode="insert"] .ed-mode {
  background: var(--teal);
}

.ed-status-file {
  color: #9ec7f0;
}

.ed-status-gap {
  flex: 1;
}

@media (max-width: 900px) {
  .nrv-hero,
  .nrv-step {
    grid-template-columns: 1fr;
    gap: 1.75rem;
  }

  .nrv-step {
    margin-top: 4.5rem;
  }

  .nrv-hero-figure .nrv-logo {
    width: min(62vw, 34vh, 20rem);
  }
}

/* On a phone the code scrolls sideways whatever we do, so give the statusline
   only what fits on one line: a wrapped statusline reads as a broken pane. */
@media (max-width: 560px) {
  .editor {
    font-size: 0.68rem;
  }

  .ed-status-lang {
    display: none;
  }

  /* Scanlines only. The vignette is a large radial gradient that has to be
     re-rasterized as the pane scales, and on a phone it is most of the wipe's
     cost for something barely visible at this size. */
  .editor.ed::after {
    background: repeating-linear-gradient(
      to bottom,
      rgba(8, 27, 60, 0.22) 0 1px,
      transparent 1px 3px);
  }
}

@media (orientation: portrait) {
  .nrv-hero,
  .nrv-step {
    grid-template-columns: 1fr;
    gap: 1.75rem;
  }

  .nrv-hero-figure .nrv-logo {
    width: min(62vw, 34vh, 20rem);
  }
}

@media (prefers-reduced-motion: reduce) {
  .editor {
    opacity: 1;
    animation: none;
  }

  .ed-cursor {
    animation: none;
  }
}
