@import url("../../css/case-chrome.css?v=4");
@import url("../../css/device-morph.css?v=3");

/* =====================================================================
   NIVORA HEALTH — case study

   Built from two Pencil exports: the 1440px "Expanded" frame is the
   desktop layout, the 390px "Mobile" frame the phone layout. Between
   them the page steps through a tablet layout at <=1099px, so neither
   design is ever scaled to a width it was not drawn for. Type, colour,
   radii and spacing are the exports' own values.
   ===================================================================== */

/* Everything is scoped to .nv-root — the <body> on the standalone page,
   and the overlay container when the homepage opens this case study in
   place (js/selected-work.js) — so none of it can leak into the homepage. */
.nv-root {

  /* ---- Type scale ----------------------------------------------------
     Every px font-size on this page, named. There were 23 distinct values
     with 12 packed between 11px and 20px, which is drift rather than a
     scale. Five one-off neighbours were retired (10, 12.5, 13.5, 21, 25px).
     The rest keep their values: each is in real use at a distinct role or
     breakpoint, and the mobile scale in particular was set deliberately.
     Fluid sizes stay as clamp() where they are; a clamp is its own scale.
     Rule: no px font-size literal in this file. Add a step here instead. */
  --nv-fs-1: 11px;
  --nv-fs-2: 12px;
  --nv-fs-3: 13px;
  --nv-fs-4: 14px;
  --nv-fs-5: 15px;
  --nv-fs-6: 16px;
  --nv-fs-7: 17px;
  --nv-fs-8: 18px;
  --nv-fs-9: 19px;
  --nv-fs-10:20px;
  --nv-fs-11:22px;
  --nv-fs-12:24px;
  --nv-fs-13:28px;
  --nv-fs-14:30px;
  --nv-fs-15:44px;
  --nv-fs-16:46px;
  --nv-fs-17:54px;
  --nv-fs-18:56px;
  --ink: #0E100F;
  --muted: #6B726F;
  --faint: #9AA19E;
  --granite: #213532;
  --signal: #C9F59A;
  --signal-soft: #DDF3BE;
  --plate: #F4F5F2;
  --line: #E6E8E3;
  --link: #3F46E0;
  --paper: #FFFFFF;
  /* The design-system section already names Data blue; these give it and the
     neutral pill fill actual tokens, since the IA diagram below uses the whole
     family rather than the one swatch. */
  --data: #7DAEE8;
  --data-mid: #A2C7F5;
  --data-soft: #C4DAF3;
  --pill: #E6EBE5;

  /* Corner radius, four steps and three named exceptions. The page had grown
     eight ad-hoc values (999, 100, 24, 20, 18, 12, 10, 9, 8, 7, 4, 3, 2px),
     several of them redundant with each other — 100px and 999px are both
     "pill", 7/8/9/10/12 were all "inner". Anything that is not one of these
     four is a deliberate exception and says so where it is used. */
  --r-pill: 999px;   /* chips, buttons, anything capsule */
  --r-card: 20px;    /* panels, plates, large containers */
  --r-inner: 10px;   /* tiles, icon wells, controls inside a card */
  --r-hair: 3px;     /* bars and cells in the token specimens */
  --r-frame: 8px;    /* screen captures — set deliberately tighter than
                        --r-inner so the frame does not compete with the
                        rounded cards inside the captures themselves */

  /* Same pairing as Freight Intelligence and the homepage: Zalando Sans
     Expanded for display titles, Geist for everything the reader reads.
     The case study speaks in the portfolio's voice; the product it
     documents keeps its own, below. */
  --font-display: "Zalando Sans Expanded", "Geist", system-ui, sans-serif;
  --font-body: "Geist", system-ui, -apple-system, sans-serif;
  /* Nivora Health's own typeface. Used only where the design-system
     section SHOWS the product's type, so the specimen keeps matching the
     "Inter" labels beside it. The embedded portal is Inter throughout for
     the same reason. */
  --font-product: Inter, system-ui, sans-serif;
  /* --ease-out-quart now comes from tokens.css, which this page loads. It used
     to be declared here, which is why the site had three names for two curves:
     this one, freight's --fi-ease-out-quart, and the global --ease-out. */
  /* Freight's hero scale and page gutter. */
  --f-hero: clamp(40px, 5.4vw, 68px);

  --gutter: clamp(24px, 6.95vw, 100px);
  --content: 1240px;
  --section-gap: clamp(84px, 10.4vw, 150px);
}

.nv-root, .nv-root *, .nv-root *::before, .nv-root *::after { box-sizing: border-box; }
/* No scroll-behavior here on purpose. The homepage drives Lenis, and a CSS
   smooth scroll on <html> fights it whenever this case study is open as an
   overlay — two authorities easing the same scroll. Standalone, native
   scrolling matches Freight. */
html:has(> body.nv-root) { -webkit-text-size-adjust: 100%; }
.nv-root {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--nv-fs-6);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
.nv-root img { display: block; max-width: 100%; height: auto; }
.nv-root :is(h1, h2, h3, h4, h5, p, figure, ol, ul, dl, dd) { margin: 0; }
.nv-root :is(ol, ul) { padding: 0; list-style: none; }
.nv-root a { color: inherit; }
/* :where() keeps this at class weight, so every .nv-* colour below still
   wins, while the homepage's own paragraph colour (overlay) does not. */
.nv-root :where(p) { color: inherit; }

.nv-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.nv-icon {
  width: 1em; height: 1em;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
  flex-shrink: 0;
}

.nv-skip {
  position: absolute; left: 16px; top: -60px; z-index: 200;
  padding: 10px 14px; border-radius: var(--r-inner);
  background: var(--ink); color: #fff; text-decoration: none; font-size: var(--nv-fs-4);
}
.nv-skip:focus { top: 16px; }
.nv-root :focus-visible { outline: 2px solid var(--granite); outline-offset: 3px; }

/* ---- Page chrome: progress rail + close ---------------------------------
   Copied from Freight Intelligence: a frosted round control that is white
   over the hero and turns dark once the page behind it is light
   (nivora-health.js toggles .is-on-light), and a 2px reading-progress
   rail along the top. */
.nv-progress {
  position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 100;
  opacity: 0; transition: opacity .2s ease; pointer-events: none;
}
.nv-progress span {
  display: block; width: 100%; height: 100%;
  background: #222; transform: scaleX(0); transform-origin: left;
}
.nv-progress.is-visible { opacity: 1; }
.nv-chrome {
  position: fixed; top: 24px; right: 24px; z-index: 100;
  display: flex; align-items: center; gap: 12px;
}
/* The chrome stays in the top-right corner at every width — it is the page's
   close affordance, and a close control that sits at the bottom of a phone
   screen reads as page content rather than chrome. Section titles do scroll
   underneath it; the tighter inset below keeps that to the title's trailing
   words rather than its first ones. */
@media (max-width: 600px) {
  .nv-chrome { top: 14px; right: 14px; gap: 8px; }
  .nv-chrome :is(.nv-close, .nv-theme-toggle) { width: 32px; height: 32px; }
}
.nv-close, .nv-theme-toggle {
  display: flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0; border-radius: 50%; cursor: pointer;
  color: #fff; font-size: var(--nv-fs-4);
  background: rgba(255, 255, 255, .16);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  border: 1px solid rgba(255, 255, 255, .24);
  transition: transform .16s var(--ease-out-quart), background-color .24s ease, color .24s ease, border-color .24s ease;
}
.nv-close .nv-icon { stroke-width: 1.8; }
.nv-close:hover, .nv-theme-toggle:hover { transform: scale(1.06); background: rgba(255, 255, 255, .24); }
.nv-chrome.is-on-light .nv-close, .nv-chrome.is-on-light .nv-theme-toggle {
  background: rgba(0, 0, 0, .06); border-color: rgba(0, 0, 0, .12); color: #222;
}

/* ---- Shared ------------------------------------------------------------ */
.nv-wrap {
  width: 100%;
  max-width: calc(var(--content) + 2 * var(--gutter));
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.nv-section { padding-top: var(--section-gap); }
.nv-center { display: flex; flex-direction: column; align-items: center; text-align: center; }

.nv-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(26px, 2.64vw, 38px);
  /* Negative, like the hero (-2.7px) and the closing statement (-1.2px).
     Positive tracking on uppercase display type at this size read as
     loose against every other heading on the page. */
  letter-spacing: -.4px;
  /* Tightening the glyphs also tightened the word gap, and on heavy
     uppercase a single space then reads as no space at all ("MORECASES").
     Word-spacing puts the separation back without loosening the letters. */
  word-spacing: .14em;
  text-wrap: balance;
  line-height: 1.2;
  text-transform: uppercase;
}
.nv-sub {
  max-width: 660px;
  margin-top: 20px;
  color: var(--muted);
  font-size: var(--nv-fs-6);
  line-height: 26px;
}
.nv-no, .nv-tag, .nv-cap {
  color: var(--faint);
  font-size: var(--nv-fs-1);
  font-weight: 600;
  letter-spacing: 1.6px;
  line-height: 1.2;
  text-transform: uppercase;
}
.nv-note { color: var(--muted); font-size: var(--nv-fs-1); line-height: 17px; }
.nv-note--md { font-size: var(--nv-fs-2); line-height: 19px; }

.nv-head {
  /* Top-aligned: aligned to the bottom, a three-line description pushed
     its title down and the gap above the section grew by the difference. */
  display: flex; align-items: flex-start; justify-content: space-between; gap: 60px;
}
.nv-head__desc {
  width: 560px; max-width: 100%;
  color: var(--muted); font-size: var(--nv-fs-5); line-height: 25px;
}
.nv-head__desc--sm { font-size: var(--nv-fs-4); line-height: 22px; }

/* ---- Hero ----------------------------------------------------------------
   Freight Intelligence's hero, value for value: a full-viewport cover,
   a frosted band dissolving up from the bottom, and the title with its
   meta row pinned bottom-left. */
.nv-hero { position: relative; }
.nv-hero__media {
  position: relative; width: 100%;
  height: 100vh;
  height: 100svh; /* svh: stays put while mobile browser chrome shows and hides */
  overflow: hidden;
  background: var(--granite);
}
.nv-root .nv-hero__media-img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.nv-hero__scrim { position: absolute; inset: 0; pointer-events: none; }
.nv-hero__scrim > span { position:absolute; inset:0; -webkit-backdrop-filter:blur(var(--blur)); backdrop-filter:blur(var(--blur)); -webkit-mask-image:linear-gradient(to bottom,transparent var(--start),#000 var(--end)); mask-image:linear-gradient(to bottom,transparent var(--start),#000 var(--end)); }
/* Start points are measured, not guessed: at 1440x900 the title's top edge
   sits at 72.8% of the media height, the tagline at 84.8%, the meta row at
   91.5%. Each layer begins just above the type it carries, so everything
   above 62% stays sharp photograph. It used to start at 40%, frosting about
   295px of the picture that no text ever sat on. */
.nv-hero__scrim > span:nth-child(1) { --blur:4px; --start:62%; --end:78%; }
.nv-hero__scrim > span:nth-child(2) { --blur:12px; --start:70%; --end:88%; }
.nv-hero__scrim > span:nth-child(3) { --blur:26px; --start:78%; --end:100%; }
@supports (backdrop-filter:blur(1px)) { .nv-hero__scrim::before { display:none; } }
/* The frost is a blurred copy of the cover, not a backdrop-filter: a mask
   on a backdrop-filtered element drops the effect entirely, and the mask
   is what lets the frost melt into the sharp photo with no seam. */
.nv-hero__scrim::before {
  content: "";
  position: absolute; inset: -80px;
  background: url("../../assets/nivora/export-v2/hero.jpg") center / cover no-repeat;
  filter: blur(26px) saturate(.92) brightness(.62);
  -webkit-mask-image: linear-gradient(to bottom, transparent 63%, rgba(0,0,0,.45) 73%, rgba(0,0,0,.88) 83%, #000 92%);
  mask-image: linear-gradient(to bottom, transparent 63%, rgba(0,0,0,.45) 73%, rgba(0,0,0,.88) 83%, #000 92%);
}
.nv-hero__scrim::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(to bottom,
    rgba(8, 9, 11, 0) 60%, rgba(8, 9, 11, .26) 72%, rgba(8, 9, 11, .60) 86%, rgba(8, 9, 11, .80) 100%);
}
.nv-hero__content {
  /* Sits on the same column as every section below (1240px centred, page
     gutter either side), so the title's left edge carries straight down
     the page instead of stepping in from 32px to 100px. */
  position: absolute; bottom: 36px;
  left: clamp(18px, 2.2vw, 36px);
  right: clamp(18px, 2.2vw, 36px);
  color: #fff;
}
.nv-hero__title {
  font-family: var(--font-display);
  font-size: var(--f-hero);
  font-weight: 600;
  line-height: 1.02;
  letter-spacing: -.035em;
  color: #fff;
}
.nv-hero__meta {
  display: flex; flex-wrap: wrap; gap: 40px;
  margin-top: 28px;
}
.nv-hero__meta li { display: flex; flex-direction: column; gap: 6px; }
.nv-meta__label {
  font-size: var(--nv-fs-2); line-height: 1.2; letter-spacing: .08em; text-transform: uppercase;
  color: rgba(255, 255, 255, .58);
}
.nv-meta__value {
  font-size: var(--nv-fs-4); line-height: 1.45; letter-spacing: -.02em;
  color: rgba(255, 255, 255, .96);
}
@media (max-width: 768px) {
  .nv-hero__content { bottom: 24px; }
  .nv-hero__meta { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
}

/* ---- Intro ------------------------------------------------------------- */
.nv-intro {
  display: flex; flex-direction: column; align-items: center; gap: 26px;
  max-width: calc(840px + 2 * var(--gutter));
  padding-top: var(--section-gap);
  text-align: center;
}
.nv-intro__lead { font-size: var(--nv-fs-12); line-height: 38px; letter-spacing: -.5px; }
.nv-intro__sub { max-width: 640px; color: var(--muted); font-size: var(--nv-fs-6); line-height: 26px; }
.nv-intro__nda {
  color: var(--faint); font-size: var(--nv-fs-1); font-weight: 600; letter-spacing: 1.4px; line-height: 16px;
  text-transform: uppercase;
}

/* ---- Challenge: friction map --------------------------------------------
   Desktop is the export's 1240x500 composition, positioned in percentages
   of that frame so it holds its shape as the column narrows. */
.nv-map {
  position: relative;
  width: 100%;
  margin-top: 70px;
  aspect-ratio: 1240 / 500;
  text-align: left;
}
.nv-map__orbit { position: absolute; inset: 0; }
.nv-map__ring {
  position: absolute; border-radius: 50%;
  box-shadow: inset 0 0 0 1px var(--line);
}
.nv-map__ring--1 { left: 20.16%; top: 11%;   width: 59.68%; height: 78%; }
.nv-map__ring--2 { left: 27.42%; top: 21%;   width: 45.16%; height: 58%; }
.nv-map__ring--3 { left: 34.68%; top: 30.4%; width: 30.65%; height: 39.2%; opacity: .8; }
.nv-map__glow {
  position: absolute; left: 41.94%; top: 30%; width: 16.13%; aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(closest-side, #C9F59ADE 0%, #C9F59A4D 45%, #C9F59A00 100%);
}
.nv-map__core {
  position: absolute; left: 45.81%; top: 39.6%; width: 8.39%; aspect-ratio: 1; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--granite); color: var(--signal);
  font-size: clamp(26px, 2.36vw, 34px);
}
.nv-map__node {
  position: absolute; width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 50%;
  background: var(--granite);
}
/* Each node sits ON the outer ring (centre 50%/50%, radii 29.84% x 39%
   of the map) at the height of its friction's title: 22% and 78% down,
   which puts it 20.77% either side of centre. The frictions below are
   placed so their titles centre on those same lines, and a hairline runs
   from each title to its node — so every dot visibly belongs to one
   friction instead of floating near it. */
.nv-map__node--1 { left: 29.23%; top: 22%; }
.nv-map__node--2 { left: 70.77%; top: 22%; }
.nv-map__node--3 { left: 29.23%; top: 78%; }
.nv-map__node--4 { left: 70.77%; top: 78%; }
.nv-map__link {
  position: absolute; height: 1px; margin-top: -.5px;
  background: var(--line);
}
.nv-map__link--1, .nv-map__link--3 { left: calc(20.16% + 16px); width: calc(9.07% - 24px); transform-origin: right center; }
.nv-map__link--2, .nv-map__link--4 { left: calc(70.77% + 8px); width: calc(9.07% - 24px); transform-origin: left center; }
.nv-map__link--1, .nv-map__link--2 { top: 22%; }
.nv-map__link--3, .nv-map__link--4 { top: 78%; }
.nv-map__hub {
  position: absolute; left: 35.48%; top: 65.2%; width: 29.03%;
  display: flex; flex-direction: column; gap: 6px; text-align: center;
}
.nv-map__hub-title { color: var(--ink); font-size: var(--nv-fs-7); font-weight: 600; letter-spacing: -.3px; line-height: 1.25; }
.nv-map__hub-body { color: var(--muted); font-size: var(--nv-fs-3); line-height: 20px; }
.nv-friction {
  position: absolute; width: 20.16%;
  display: flex; flex-direction: column; gap: 7px;
}
.nv-friction h3 { font-size: var(--nv-fs-8); font-weight: 600; letter-spacing: -.4px; line-height: 23px; }
.nv-friction p { color: var(--muted); font-size: var(--nv-fs-3); line-height: 20px; }
/* Title line is 23px, so the block starts 11.5px above its node's line. */
.nv-friction--1 { left: 0; top: calc(22% - 11.5px); }
.nv-friction--2 { right: 0; top: calc(22% - 11.5px); text-align: right; }
.nv-friction--3 { left: 0; top: calc(78% - 11.5px); }
.nv-friction--4 { right: 0; top: calc(78% - 11.5px); text-align: right; }

/* ---- Approach ---------------------------------------------------------- */
.nv-phases {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 20px;
  width: 100%; margin-top: 64px; text-align: left;
}
.nv-phase {
  display: flex; flex-direction: column; gap: 22px;
  padding: 34px; border-radius: var(--r-card); background: var(--plate);
}
.nv-phase h3 { font-size: var(--nv-fs-10); font-weight: 600; letter-spacing: -.4px; line-height: 1.25; }
.nv-phase p { margin-top: 6px; color: var(--muted); font-size: var(--nv-fs-4); line-height: 22px; }
.nv-orb {
  display: grid; place-items: center; flex-shrink: 0;
  width: 76px; height: 76px; border-radius: 50%;
  color: var(--granite); font-size: var(--nv-fs-13);
  background: radial-gradient(ellipse 50% 50% at 38% 30%, #E6FFC6 0%, #C9F59A 50%, #9FD26E 100%);
}
.nv-orb .nv-icon { stroke-width: 1.8; }
.nv-orb--linear { background: linear-gradient(147.68deg, #E6FFC6 -15.57%, #9FD26E 111.48%); }

/* ---- Solution screens ---------------------------------------------------- */
.nv-screens {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 56px 24px;
  margin-top: 56px;
}
.nv-screen { display: flex; flex-direction: column; gap: 22px; }
.nv-screen figcaption { display: flex; flex-direction: column; gap: 5px; }
/* Caption and screen are two rows shared across the pair, so a caption
   that wraps to two lines no longer drops its screen below its neighbour. */
@supports (grid-template-rows: subgrid) {
  .nv-screen { display: grid; grid-row: span 2; grid-template-rows: subgrid; row-gap: 22px; }
}
.nv-screen__label { display: flex; align-items: center; gap: 12px; }
.nv-screen__title { font-size: var(--nv-fs-9); font-weight: 600; letter-spacing: -.4px; }
.nv-screen__body { color: var(--muted); font-size: var(--nv-fs-4); line-height: 22px; }
/* Each screen is shown full width and cropped from the top, as in the
   export: the frame fixes the window, the image runs past its bottom. */
.nv-frame {
  aspect-ratio: 608 / 350;
  overflow: hidden;
  /* Tighter than the rest of the page's cards on purpose: these are captures
     of a product whose own cards are rounded, and a soft outer corner read
     as a second, competing radius. */
  border-radius: var(--r-frame);
  background: var(--plate);
  /* No drop shadow: the captures sit on the page rather than floating above
     it. The inset hairline stays — it is the frame's edge, not a shadow, and
     without it a screen whose own background is near-white has no boundary. */
  box-shadow: inset 0 0 0 1px var(--line);
}
.nv-frame__zoom {
  position: absolute; inset: 0; z-index: -1;
  transition: transform .7s var(--ease-out-quart);
}
/* Full width at its own proportions (at least the frame's height), so the
   long capture can be panned through the window by nivora-health.js. */
.nv-frame__zoom img {
  position: absolute; top: 0; left: 0;
  width: 100%; height: auto; min-height: 100%;
  object-fit: cover; object-position: top center;
  will-change: transform;
}
@media (hover: hover) and (pointer: fine) {
  .nv-screen:hover .nv-frame__zoom { transform: scale(1.03); }
}
.nv-frame { position: relative; isolation: isolate; }
.nv-frame::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  box-shadow: inset 0 0 0 1px var(--line); pointer-events: none;
}

/* ---- Design system ------------------------------------------------------- */
.nv-head--system { margin-top: clamp(56px, 5.2vw, 76px); }
.nv-system__title { font-size: var(--nv-fs-12); font-weight: 600; letter-spacing: -.6px; }
.nv-system {
  display: grid; grid-template-columns: minmax(0, 1fr) 420px; gap: 24px;
  margin-top: 56px;
}
.nv-system__col { display: flex; flex-direction: column; gap: 24px; min-width: 0; }
/* The last card in each column takes up the slack, so both columns end on
   the same line instead of 24px apart. */
.nv-system__col > .nv-card:last-child { flex: 1 1 auto; }
.nv-card {
  display: flex; flex-direction: column; gap: 22px;
  padding: 32px; border-radius: var(--r-card); background: var(--plate);
}
.nv-card.nv-components, .nv-card.nv-tokens, .nv-card.nv-patterns { gap: 20px; }

.nv-swatches { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 10px; }
.nv-swatches li { display: flex; flex-direction: column; gap: 9px; }
.nv-swatches li > span:last-child { display: flex; flex-direction: column; gap: 9px; }
.nv-chip { display: block; height: 72px; border-radius: var(--r-inner); background: var(--chip); }
.nv-swatches li:nth-child(2) .nv-chip { box-shadow: inset 0 0 0 1px var(--line); }
.nv-swatches b { font-size: var(--nv-fs-2); font-weight: 600; }
.nv-swatches small { color: var(--faint); font-size: var(--nv-fs-1); }

.nv-group { display: flex; flex-direction: column; gap: 11px; }
.nv-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.nv-row--tight { gap: 8px; }
.nv-btn {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 12px 18px; border-radius: var(--r-inner);
  font-size: var(--nv-fs-3); font-weight: 600; line-height: 1.2;
}
.nv-btn--granite { background: var(--granite); color: #fff; }
.nv-btn--signal { background: var(--signal); color: var(--ink); }
.nv-btn--white { background: #fff; color: var(--ink); }
.nv-btn--ghost { color: var(--muted); }
.nv-pill {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 13px; border-radius: var(--r-pill);
  background: #fff; color: var(--muted);
  font-size: var(--nv-fs-2); font-weight: 600; line-height: 1.2;
}
.nv-pill i { width: 6px; height: 6px; border-radius: 50%; background: var(--dot); }
.nv-pill--signal { background: var(--signal); color: var(--ink); }
.nv-pill--granite { background: var(--granite); color: #fff; }
.nv-row--inputs { flex-wrap: nowrap; }
.nv-field {
  display: flex; align-items: center; gap: 10px; flex: 1 1 auto; min-width: 0;
  padding: 13px 14px; border-radius: var(--r-inner); background: #fff;
  box-shadow: inset 0 0 0 1px var(--line);
  color: var(--faint); font-size: var(--nv-fs-3); line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.nv-field .nv-icon { font-size: var(--nv-fs-6); }
.nv-seg {
  display: flex; gap: 2px; flex-shrink: 0;
  padding: 4px; border-radius: var(--r-inner); background: #fff;
}
.nv-seg span { padding: 9px 13px; border-radius: var(--r-inner); color: var(--muted); font-size: var(--nv-fs-2); line-height: 1.2; white-space: nowrap; }
.nv-seg .is-on { background: #E9EDE4; color: var(--ink); font-weight: 600; }

.nv-tokens__grid {
  display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 20px;
}
.nv-token { display: flex; flex-direction: column; gap: 11px; grid-column: span 2; min-width: 0; }
.nv-token--layout, .nv-token--motion { grid-column: span 3; }
.nv-demo { display: flex; align-items: flex-end; gap: 8px; height: 48px; }
.nv-token--spacing .nv-demo i { width: var(--w); height: 44px; border-radius: var(--r-hair); background: var(--granite); flex-shrink: 0; }
.nv-token--radius .nv-demo i { width: 44px; height: 44px; border-radius: var(--r); background: #fff; flex-shrink: 0; }
.nv-token--elevation .nv-demo i { flex: 1; height: 44px; border-radius: var(--r-inner); background: #fff; }
.nv-token--elevation .nv-demo .is-raised { box-shadow: 0 3px 10px -2px #0E100F1F; }
.nv-token--elevation .nv-demo .is-overlay { box-shadow: 0 10px 28px -2px #0E100F1F; }
.nv-token--layout .nv-demo { gap: 4px; }
.nv-token--layout .nv-demo i { flex: 1; height: 44px; border-radius: var(--r-hair); background: #DCE4D8; }
.nv-token--motion .nv-demo { flex-direction: column; align-items: flex-start; justify-content: center; }
.nv-token--motion .nv-demo i { width: var(--w); max-width: 100%; height: 8px; border-radius: var(--r-pill); background: var(--granite); }

.nv-type__display { font-family: var(--font-product); font-weight: 700; font-size: var(--nv-fs-18); line-height: 1.2; }
.nv-rules > div {
  display: flex; align-items: center; gap: 16px;
  padding: 11px 0; border-top: 1px solid var(--line);
}
.nv-rules dt { width: 180px; flex-shrink: 0; font-size: var(--nv-fs-3); font-weight: 600; }
.nv-rules dd { color: var(--muted); font-size: var(--nv-fs-2); }
.nv-rules--patterns > div { align-items: flex-start; gap: 12px; }
.nv-rules--patterns dt { width: 92px; font-size: var(--nv-fs-2); }
.nv-rules--patterns dd { font-size: var(--nv-fs-1); line-height: 17px; }

.nv-icons { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 10px; }
.nv-icons li {
  display: grid; place-items: center; height: 56px; border-radius: var(--r-inner);
  background: #fff; color: var(--ink); font-size: var(--nv-fs-10);
}
.nv-icons .nv-icon { stroke-width: 1.75; }

/* ---- Impact ------------------------------------------------------------ */
.nv-stats {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 20px;
  margin-top: 56px;
}
.nv-stat {
  display: flex; flex-direction: column;
  padding: 30px; border-radius: var(--r-card); background: #fff;
  box-shadow: inset 0 0 0 1px var(--line);
}
.nv-stat--signal { background: var(--signal-soft); box-shadow: none; }
.nv-stat__top { display: flex; flex-direction: column; min-height:128px; gap:22px; }
.nv-stat__num {
  font-family: var(--font-display); font-weight: 700;
  font-size: var(--nv-fs-17); line-height: 54px; letter-spacing: -2px;
}
.nv-stat h3 { margin-top: 22px; font-size: var(--nv-fs-6); font-weight: 600; letter-spacing: -.3px; }
.nv-stat p { margin-top: 8px; color: var(--muted); font-size: var(--nv-fs-3); line-height: 21px; }
.nv-stat--signal p { color: #4A5551; }

.nv-graphic { display: flex; align-items: flex-end; gap: 6px; height: 56px; }
.nv-graphic--bars i { width: 12px; height: calc(var(--h) * 1px); border-radius: var(--r-hair); background: var(--granite); }
.nv-graphic--cells { display: grid; grid-template-columns: repeat(6, 14px); grid-auto-rows: 14px; gap: 6px; align-content: end; }
.nv-graphic--cells i { border-radius: var(--r-hair); background: var(--granite); }
.nv-graphic--cells i:nth-child(n+7) { background: var(--signal); }
.nv-graphic--tiers { flex-direction: column; align-items: flex-start; justify-content: flex-end; gap: 7px; }
.nv-graphic--tiers i { width: calc(var(--w) * 1px); height: 12px; border-radius: var(--r-hair); background: var(--granite); }
.nv-graphic--steps { align-items: center; gap: 0; height: 56px; }
.nv-graphic--steps i { width: 14px; height: 14px; border-radius: 50%; background: var(--granite); }
.nv-graphic--steps b { width: 26px; height: 2px; background: #21353266; }

/* ---- Closing ----------------------------------------------------------- */
.nv-closing { padding-top: var(--section-gap); }
.nv-closing__statement {
  max-width: 900px;
  font-size: clamp(24px, 2.5vw, 36px); font-weight: 600;
  line-height: 1.25; letter-spacing: -1.2px;
}
.nv-closing .nv-sub { margin-top: 22px; }

.nv-root .nv-frame { aspect-ratio:auto; }
/* Captions are aligned by a shared subgrid row, so the frame row is as tall
   as the tallest screen in the pair. With the frame stretched to that row but
   its image at natural height, a short capture left the plate showing below
   it — 288px under Sign in, 264px under Find care. The frame hugs its image
   instead: the pair's captions still line up and the shorter card simply ends
   earlier, rather than trailing an empty panel. */
/* The frame stretched to its grid row, which is as tall as the taller screen
   in the pair, while the image inside stayed at its natural height — so a
   short capture trailed an empty plate: 288px under Sign in, 264px under
   Find care. Hugging the image closes it. The shared subgrid still aligns
   each pair's captions and frame tops, so only the bottom edges differ.

   The remaining slack is handled by which cards share a row: see the order
   of the figures in index.html. */
.nv-root .nv-frame { align-self:start; }
/* Sign in opens the section across both columns and Nivora 360 closes it, so
   the run reads door, product, payoff. Sign in is also the only landscape
   capture of the six, which suits the full width far better than a narrow
   column, where it was the card that left the most empty space. A spanning
   figure has no neighbour to align with, so it drops the subgrid and sizes
   its own two rows. */
@media (min-width: 700px) {
  .nv-root .nv-screen--wide {
    grid-column:1 / -1;
    display:flex; flex-direction:column; gap:16px;
    grid-row:auto; grid-template-rows:none;
  }
}
.nv-root .nv-frame__zoom { position:relative; inset:auto; z-index:auto; }
.nv-root .nv-frame__zoom img { position:static; display:block; min-height:0; width:100%; height:auto; will-change:auto; }
.nv-root .nv-frame__zoom,.nv-root .nv-frame__zoom img { transform:none !important; transition:none !important; }
.nv-root .nv-frame::after { display:none; }
.nv-friction__icon { display:block; width:34px; height:34px; margin-bottom:14px; padding:7px; border-radius:var(--r-inner); background:#e5eddf; color:#294c38; }
.nv-map__orbit { mask-image:linear-gradient(transparent,#000 25%,#000 75%,transparent); }

/* Was 80px/80px, the only section not on --section-gap, which broke the
   page's vertical meter twice over. Matches every other section: the gap
   is carried on the top edge, bottom stays 0. */

/* Eases toward rest under the finger rather than staying fully pushed. */

/* ---- Next -------------------------------------------------------------- */
.nv-next { padding-top: var(--section-gap); }
.nv-root .nv-next > .nv-tag { padding-bottom:24px; }
.nv-next__list { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); margin-top: 48px; }
.nv-next__list li {
  display: flex; flex-direction: column; gap: 11px;
  padding: 24px 44px 0 0; border-top: 1px solid var(--line);
}
.nv-next__list h3 { font-size: var(--nv-fs-9); font-weight: 600; letter-spacing: -.4px; line-height: 25px; }
.nv-next__list p { color: var(--muted); font-size: var(--nv-fs-4); line-height: 22px; }

/* =====================================================================
   Tablet · <=1099px
   ===================================================================== */
@media (max-width: 1099px) {
  .nv-head { flex-direction: column; align-items: flex-start; gap: 16px; }
  .nv-head__desc { width: 100%; max-width: 640px; }

  /* The friction map needs its full width; below it the hub sits on top
     and the four frictions follow as a grid, as in the mobile export. */
  .nv-map { aspect-ratio: auto; margin-top: 40px; display: flex; flex-direction: column; align-items: center; }
  .nv-map__orbit {
    position: relative; inset: auto;
    width: 168px; height: 168px;
  }
  .nv-map__ring, .nv-map__node, .nv-map__link { display: none; }
  .nv-map__glow { left: 0; top: 0; width: 100%; }
  .nv-map__core { left: 23.8%; top: 23.8%; width: 52.4%; font-size: var(--nv-fs-14); }
  .nv-map__hub { position: static; width: 100%; margin-top: 14px; }
  .nv-map__hub-title { font-size: var(--nv-fs-6); }
  .nv-map__frictions {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 32px;
    width: 100%; margin-top: 26px;
  }
  .nv-friction {
    position: static; width: auto; text-align: left !important;
    gap: 6px; padding: 16px 0; border-top: 1px solid var(--line);
  }
  .nv-friction h3 { font-size: var(--nv-fs-6); letter-spacing: -.2px; line-height: 1.3; }

  .nv-phases { grid-template-columns: repeat(2, minmax(0, 1fr)); margin-top: 40px; }

  .nv-system { grid-template-columns: minmax(0, 1fr); }
  .nv-system__col--side { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .nv-system__col--side .nv-type { grid-row: span 2; }

  .nv-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  
  
  .nv-next__list li { padding-right: 28px; }
  .nv-rules--type dt { width: 58%; }
}

/* =====================================================================
   Mobile · <=699px — the 390px export
   ===================================================================== */
@media (max-width: 699px) {
  .nv-intro { gap: 18px; text-align: left; align-items: stretch; }
  .nv-intro__lead { font-size: var(--nv-fs-9); line-height: 26px; letter-spacing: -.3px; }
  .nv-intro__sub { font-size: var(--nv-fs-4); line-height: 22px; }
  .nv-intro__nda { font-size: var(--nv-fs-1); letter-spacing: 1px; line-height: 16px; }

  .nv-center { align-items: stretch; text-align: left; }
  .nv-title { letter-spacing: -.2px; }
  .nv-sub { margin-top: 14px; font-size: var(--nv-fs-4); line-height: 22px; }
  .nv-closing .nv-sub { font-size: var(--nv-fs-4); }

  .nv-map { margin-top: 26px; }
  .nv-map__frictions { grid-template-columns: minmax(0, 1fr); }

  .nv-phases { grid-template-columns: minmax(0, 1fr); gap: 12px; margin-top: 24px; }
  .nv-phase { flex-direction: row; align-items: flex-start; gap: 16px; padding: 22px; border-radius: var(--r-card); }
  .nv-phase h3 { font-size: var(--nv-fs-7); letter-spacing: -.3px; }
  .nv-phase p { margin-top: 4px; font-size: var(--nv-fs-3); line-height: 20px; }
  .nv-orb { width: 52px; height: 52px; font-size: var(--nv-fs-11); }

  .nv-head { gap: 14px; }
  .nv-head__desc { font-size: var(--nv-fs-3); line-height: 21px; }
  .nv-screens { grid-template-columns: minmax(0, 1fr); gap: 26px; margin-top: 26px; }
  .nv-screen, .nv-screen figcaption { gap: 10px; }
  .nv-screen__label { gap: 10px; }
  .nv-screen__title { font-size: var(--nv-fs-7); letter-spacing: -.3px; }
  .nv-screen__body { font-size: var(--nv-fs-3); line-height: 20px; }
  .nv-frame { aspect-ratio: 342 / 230; }

  .nv-head--system { margin-top: 40px; }
  .nv-system__title { font-size: var(--nv-fs-11); letter-spacing: -.5px; }
  .nv-system { gap: 12px; margin-top: 22px; }
  .nv-system__col, .nv-system__col--side { display: flex; gap: 12px; }
  .nv-card { gap: 16px !important; padding: 24px; border-radius: var(--r-card); }

  .nv-swatches { grid-template-columns: minmax(0, 1fr); }
  .nv-swatches li { flex-direction: row; align-items: center; gap: 12px; }
  .nv-swatches li > span:last-child { gap: 3px; }
  .nv-chip { width: 40px; height: 40px; border-radius: var(--r-inner); flex-shrink: 0; }
  .nv-swatches b { font-size: var(--nv-fs-3); }

  .nv-group { gap: 10px; }
  .nv-row { gap: 8px; }
  .nv-btn { flex: 1 1 calc(50% - 4px); padding: 11px 10px; font-size: var(--nv-fs-2); }
  .nv-pill { padding: 7px 11px; font-size: var(--nv-fs-1); }
  .nv-row--inputs { flex-direction: column; align-items: stretch; }
  .nv-field { padding: 12px 13px; gap: 9px; font-size: var(--nv-fs-2); }
  .nv-seg span { flex: 1; padding: 8px 6px; text-align: center; font-size: var(--nv-fs-1); }

  .nv-tokens__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px 14px; }
  .nv-token { gap: 9px; }
  .nv-token--spacing, .nv-token--radius, .nv-token--layout { grid-column: 1 / -1; }
  .nv-token--elevation, .nv-token--motion { grid-column: span 1; }
  .nv-token--spacing .nv-demo { height: 40px; }
  .nv-token--spacing .nv-demo i { height: 36px; }
  .nv-token--radius .nv-demo { height: 56px; }
  .nv-token--radius .nv-demo i { width: 56px; height: 56px; }
  .nv-token--elevation .nv-demo { gap: 6px; height: 30px; }
  .nv-token--elevation .nv-demo i { height: 30px; border-radius: var(--r-inner); }
  .nv-token--layout .nv-demo { gap: 3px; height: 30px; }
  .nv-token--layout .nv-demo i { height: 30px; }
  .nv-token--motion .nv-demo { gap: 7px; height: 34px; }
  .nv-token--motion .nv-demo i { height: 6px; width: calc(var(--w) * .69); }
  .nv-token--elevation { order: 4; }
  .nv-token--motion { order: 5; }
  .nv-token--layout { order: 6; }

  .nv-type__display { font-size: var(--nv-fs-16); }
  .nv-rules > div { gap: 10px; padding: 10px 0; }
  .nv-rules dt { width: 150px; font-size: var(--nv-fs-2); }
  .nv-rules dd { font-size: var(--nv-fs-1); }
  .nv-rules--patterns > div { flex-direction: column; gap: 3px; padding: 11px 0; }
  .nv-rules--patterns dt { width: auto; }

  .nv-icons { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
  .nv-icons li { height: 52px; font-size: var(--nv-fs-9); }

  .nv-stats { grid-template-columns: minmax(0, 1fr); gap: 12px; margin-top: 24px; }
  .nv-stat { padding: 24px; border-radius: var(--r-card); }
  .nv-stat__top { flex-direction: row-reverse; align-items: flex-end; justify-content: space-between; gap: 16px; }
  .nv-stat__num { font-size: var(--nv-fs-15); line-height: 44px; letter-spacing: -1.6px; }
  .nv-stat h3 { margin-top: 14px; font-size: var(--nv-fs-5); letter-spacing: 0; }
  .nv-stat p { margin-top: 6px; font-size: var(--nv-fs-3); line-height: 19px; }
  .nv-graphic { gap: 5px; height: auto; }
  .nv-graphic--bars i { width: 10px; height: calc(var(--h) * .88px); }
  .nv-graphic--cells { grid-template-columns: repeat(6, 12px); grid-auto-rows: 12px; gap: 5px; }
  .nv-graphic--cells i { border-radius: var(--r-hair); }
  .nv-graphic--tiers { gap: 6px; }
  .nv-graphic--tiers i { width: calc(var(--w) * .867px); height: 10px; }
  .nv-graphic--steps { gap: 0; }
  .nv-graphic--steps i { width: 12px; height: 12px; }
  .nv-graphic--steps b { width: 22px; }

  .nv-closing { gap: 16px; }
  .nv-closing__statement { letter-spacing: -.8px; line-height: 30px; text-align: center; }
  .nv-closing .nv-sub { margin-top: 0; text-align: center; }
  /* The mobile export drops the dark plate: the screen sits directly on
     the page, cropped, with the same raised shadow. */
  
  
  

  .nv-next__list { grid-template-columns: minmax(0, 1fr); margin-top: 28px; }
  .nv-next__list li { gap: 6px; padding: 16px 0; }
  .nv-next__list h3 { font-size: var(--nv-fs-6); letter-spacing: -.3px; line-height: 1.3; }
  .nv-next__list p { font-size: var(--nv-fs-3); line-height: 20px; }

  
  
  
  
  
  
}

/* ---- Motion helpers (nivora-health.js) ---------------------------------- */
.nv-word { display: inline-block; white-space: nowrap; }
.nv-char { display: inline-block; overflow: hidden; vertical-align: top; }
.nv-char > span { display: inline-block; }

/* ---- Opened in place on the homepage -----------------------------------
   The homepage stylesheets load alongside this one when the Work grid
   opens the case study as an overlay, and two of their rules are
   !important: every h1–h4 takes the homepage text colour, and main and
   its sections take the homepage's grey page colour. Both are pinned
   back here — the same thing Freight Intelligence does for its title. */
.nv-root #nv-content,
.nv-root #nv-content > * { background-color: var(--paper) !important; }
.nv-root :is(h1, h2, h3, h4) { color: var(--ink) !important; }
.nv-root .nv-hero__title { color: #fff !important; }
.nv-root :is(h2, h4).nv-tag { color: var(--faint) !important; }

/* tokens.css forces anything whose class contains "__ring" into a pill
   (border-radius: 999px !important). These are ellipses. */
:root .nv-map .nv-map__ring[class][class] { border-radius: 50% !important; }

/* ---- Tap targets --------------------------------------------------------
   The close control keeps its drawn size but gets a
   44px hit area, the minimum for a reliable tap. */
.nv-close { position: relative; }
.nv-close::before { content: ""; position: absolute; inset: -5px; }

/* ---- Hover (precise pointers only, so touch never sticks) -------------
   `translate` rather than `transform`: the entrance animations leave an
   inline transform on these cards, and the two properties compose. */
@media (hover: hover) and (pointer: fine) {
  .nv-phase, .nv-stat {
    transition: translate .45s var(--ease-out-quart), box-shadow .45s var(--ease-out-quart);
  }
  .nv-phase:hover, .nv-stat:hover {
    translate: 0 -3px;
    box-shadow: 0 18px 36px -24px rgba(14, 16, 15, .28);
  }
  .nv-stat:hover { box-shadow: inset 0 0 0 1px var(--line), 0 18px 36px -24px rgba(14, 16, 15, .28); }
  .nv-stat--signal:hover { box-shadow: 0 18px 36px -24px rgba(14, 16, 15, .28); }
  .nv-orb .nv-icon { transition: scale .45s var(--ease-out-quart); }
  .nv-phase:hover .nv-orb .nv-icon { scale: 1.14; }
}
.nv-graphic--bars i { transform-origin: 50% 100%; }
.nv-graphic--tiers i { transform-origin: 0 50%; }

/* Supplied expanded export, translated to fluid layout rather than a
   fixed 1440px artboard. Existing mobile reading order stays semantic. */
.nv-root .nv-hero__tagline { color:#ffffffd9; font-size:clamp(16px,1.4vw,20px); margin:16px 0 30px; }
.nv-root .nv-hero__title { font-size:clamp(40px,6.4vw,92px); line-height:1; text-transform:uppercase; }
/* The four approach cards: a green wash at the top that resolves into
   white behind the copy, a larger radius and a soft lift — the flat
   near-white plate read as an unfinished container. */
.nv-root .nv-phase {
  padding:0; overflow:hidden; gap:0;
  border-radius:var(--r-card);
  background:linear-gradient(180deg, #d8f2bb 0%, #e4f7d3 26%, #f4fbee 48%, #ffffff 64%);
  box-shadow:0 1px 2px rgba(14,16,15,.04), 0 18px 40px -18px rgba(14,16,15,.14);
}
.nv-root .nv-export-art { width:100% !important; height:160px !important; flex-shrink:0; background:transparent; }
.nv-root .nv-phase > div:last-child { padding:26px 26px 32px; }
.nv-root .nv-phase > .nv-export-art:first-child { padding:0; }
.nv-root .nv-map__takeaway { max-width:520px; margin:32px auto 0; text-align:center; }
.nv-root .nv-map__takeaway h3 { font-size:var(--nv-fs-10); margin-bottom:10px; }
.nv-root .nv-map__takeaway p { font-size:var(--nv-fs-4); color:var(--muted); line-height:1.6; }
.nv-root .nv-map__core { border-radius:26%; background:linear-gradient(145deg,#e2f9bf,#abd77e 55%,#7da854); color:#213532; box-shadow:0 12px 18px #21353226,inset 0 3px 5px #ffffffb3; }
.nv-root .nv-map__hub-body { text-transform:uppercase; letter-spacing:.14em; font-size:var(--nv-fs-1); }
.nv-root .nv-friction { display:grid; grid-template-columns:40px minmax(0,1fr); column-gap:16px; row-gap:8px; align-content:start; background:#fff; border-color:#f1f2ee; box-shadow:0 10px 30px #21353206; }
.nv-root .nv-friction__icon { grid-column:1; grid-row:1 / 3; width:40px; height:40px; padding:10px; margin:0; border-radius:var(--r-inner); background:#eaf0e2; color:#4e6046; }
.nv-root .nv-friction h3,.nv-root .nv-friction p { grid-column:2; }
.nv-root .nv-friction--2 .nv-friction__icon { background:#eaf0fa; }
.nv-root .nv-friction--3 .nv-friction__icon { background:#f4efe3; }
.nv-root .nv-friction--4 .nv-friction__icon { background:#f4e9e5; }
.nv-root .nv-map__core { border:1px solid #a0c575; box-shadow:inset 0 4px 5px #ffffff80,inset 0 -4px 4px #527d3026,0 18px 24px #21353220; background:linear-gradient(155deg,#c9e7a3 0%,#ddf8b8 28%,#b1d882 63%,#7fa751 100%); }
.nv-map__core::after { content:""; position:absolute; inset:5px; border:2px solid #e5ffc68c; border-radius:inherit; pointer-events:none; }
.nv-root .nv-map__core svg { width:44%; height:44%; }
/* Explicit component spacing outranks the scoped document reset. */
.nv-root .nv-title + .nv-sub { margin-top:24px; }
.nv-root .nv-sub--wide { max-width:none; width:100%; }
.nv-root .nv-phases,.nv-root .nv-stats { margin-top:48px; }
.nv-root .nv-friction { text-align:left; }
.nv-root .nv-head__desc--solution { width:640px; }

@media(max-width:1099px) { .nv-root .nv-head__desc--solution { width:100%; max-width:640px; } }
@media(max-width:600px) {
 .nv-root .nv-title + .nv-sub { margin-top:20px; }
 .nv-root .nv-phases,.nv-root .nv-stats { margin-top:32px; }
 
 
}
@media(min-width:1100px) {
  .nv-root .nv-map { aspect-ratio:1240/590; }
  .nv-root .nv-map__orbit { mask-image:linear-gradient(transparent 9%,#000 32%,#000 74%,transparent 99%); }
  :root .nv-root .nv-map .nv-map__ring[class][class] { border-radius:29% !important; top:57%; height:auto; aspect-ratio:1; translate:0 -50%; box-shadow:inset 0 0 0 1px #dce6d0; }
  .nv-root .nv-map__ring--1 { left:21%; width:58%; }
  .nv-root .nv-map__ring--2 { left:26%; width:48%; }
  .nv-root .nv-map__ring--3 { left:30%; width:40%; }
  .nv-root .nv-map__ring--4 { left:34%; width:32%; }
  .nv-root .nv-map__ring--5 { left:38%; width:24%; }
  .nv-root .nv-map__core { width:14.4%; left:42.8%; top:57%; translate:0 -50%; }
  .nv-root .nv-map__hub { top:1%; left:30%; width:40%; gap:14px; }
  .nv-root .nv-map__hub-title { font-size:var(--nv-fs-10); line-height:1.25; }
  .nv-root .nv-friction { padding:20px; border:1px solid #f1f2ee; border-radius:var(--r-inner); width:29%; }
  .nv-root .nv-friction h3 { font-size:var(--nv-fs-7); line-height:22px; }
  .nv-root .nv-friction--1 { left:5%; right:auto; top:17%; }
  .nv-root .nv-friction--2 { left:0; right:auto; top:51%; }
  .nv-root .nv-friction--3 { left:auto; right:5%; top:17%; }
  .nv-root .nv-friction--4 { left:auto; right:0; top:48%; }
  .nv-root .nv-map__takeaway { position:relative; margin:-10px auto 0; max-width:540px; }
  .nv-root .nv-map__node,.nv-root .nv-map__link { display:none; }
}
.nv-theme-toggle svg { width:14px; height:14px; fill:none; stroke:currentColor; stroke-width:1.6; stroke-linecap:round; }
.nv-theme__sun,.nv-theme__moon { transform-origin:12px 12px; transition:opacity .2s ease,transform .26s var(--ease-out-quart); }
.nv-theme__moon { opacity:0; transform:rotate(-40deg) scale(.6); }
.nv-root[data-theme="dark"] .nv-theme__sun { opacity:0; transform:rotate(40deg) scale(.6); }
.nv-root[data-theme="dark"] .nv-theme__moon { opacity:1; transform:rotate(0) scale(1); }

.nv-root[data-theme="dark"] .nv-chrome :is(.nv-close, .nv-theme-toggle) { background:rgba(18,18,18,.78); border-color:rgba(255,255,255,.24); color:#fff; box-shadow:0 8px 28px rgba(0,0,0,.28); }
.nv-root[data-theme="dark"] .nv-chrome :is(.nv-close, .nv-theme-toggle):hover { background:rgba(36,36,36,.92); }
.nv-root[data-theme="dark"] { --paper:#101513; --ink:#f4f6f0; --muted:#aeb9b3; --faint:#87958d; --plate:#18211e; --line:#31433c; --granite:#dff7c1; }
.nv-root[data-theme="dark"] .nv-section,.nv-root[data-theme="dark"] .nv-closing,.nv-root[data-theme="dark"] .nv-next{ color:var(--ink); }
.nv-root[data-theme="dark"] .nv-friction,.nv-root[data-theme="dark"] .nv-stat { background:#18211e; border-color:#31433c; }
.nv-root[data-theme="dark"] .nv-phase {
  border-color:#31433c;
  background:linear-gradient(180deg, #2c4632 0%, #22342a 30%, #1b2620 52%, #18211e 66%);
  box-shadow:0 1px 2px rgba(0,0,0,.2), 0 18px 40px -18px rgba(0,0,0,.45);
}
.nv-root[data-theme="dark"] .nv-friction p,.nv-root[data-theme="dark"] .nv-stat p,.nv-root[data-theme="dark"] .nv-sub { color:var(--muted); }
.nv-root[data-theme="dark"] .nv-map__ring { box-shadow:inset 0 0 0 1px #75956d66; }
.nv-root .nv-chrome .nv-close { color:#fff; }
.nv-root .nv-chrome.is-on-light .nv-close { color:var(--ink); }
.nv-root .nv-map__hub-title { white-space:nowrap; }
.nv-root[data-theme="dark"] :is(.nv-btn--granite,.nv-pill--granite) { background:var(--granite); color:#18211e; }
.nv-root[data-theme="dark"] :is(.nv-btn--signal,.nv-pill--signal) { color:#18211e; }
.nv-root[data-theme="dark"] :is(.nv-btn--white,.nv-field,.nv-seg,.nv-pill:not(.nv-pill--signal):not(.nv-pill--granite)) { background:#283730; color:var(--ink); }
.nv-root[data-theme="dark"] .nv-seg .is-on { background:#dff7c1; color:#18211e; }
.nv-root[data-theme="dark"] .nv-pill--granite i { background:#213532; }
@media(max-width:699px) {
 .nv-root .nv-stat__top { flex-direction:column; align-items:flex-start; min-height:52px; }
 .nv-root .nv-hero__content { left:16px; right:16px; }
}
@media(max-width:1099px) {
  .nv-root .nv-map__hub { order:-1; margin:0 0 24px; }
  .nv-root .nv-friction { padding:20px; border:1px solid var(--line); border-radius:var(--r-inner); background:#fff; }
}
@media(max-width:600px) {
  /* The shared card rule turns these to a row at this width, which suits an
     icon beside the copy but not this page's full-width export art: the copy
     was squeezed to 114px and then clipped by the card's overflow. */
  .nv-root .nv-phase { flex-direction:column; align-items:stretch; gap:0; }
  .nv-root .nv-export-art { height:140px !important; }
  .nv-root .nv-phase > div:last-child { padding:22px 22px 26px; }
  .nv-root .nv-map__takeaway { margin-top:24px; }
  .nv-root .nv-hero__meta { min-width:0; }
}

/* ---- Press feedback + reduced motion ----------------------------------
   Press states are in this page's own idiom — a small settle rather than
   Freight's scale pop — so the two case studies still feel like different
   products under the finger. */
.nv-root .nv-close:active, .nv-root .nv-theme-toggle:active { transform: scale(.94); }

/* The keyboard equivalent of the hover badge needs a visible boundary on
   the media itself, which hover gets for free from the pointer. */

/* Freight clamps motion globally; this page only silenced two rules, so
   every other CSS transition ignored the preference. Scoped to .nv-root so
   it cannot leak into the homepage when this opens as an overlay. */
@media (prefers-reduced-motion: reduce) {
  .nv-root, .nv-root *, .nv-root *::before, .nv-root *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .12s !important;
    scroll-behavior: auto !important;
  }
}

/* ---- Information architecture -------------------------------------------
   The export is a 3200x2000 artboard: pills at absolute coordinates, wires
   as SVG paths with hard-coded endpoints. Rebuilt here as a real grid with
   a wire layer that nivora-health.js draws from the measured pill edges, so
   the diagram is correct at any width and the wires can be animated.

   Type and colour are this page's tokens. Geometry follows the export's
   proportions: fully rounded pills, a tall destination row, children on a
   spine to their left, and a support rail across the foot.
   ------------------------------------------------------------------------- */
.nv-root .nv-ia { margin: clamp(56px, 7vw, 100px) 0 0; padding: 0; }
.nv-root .nv-ia__head { max-width: 780px; margin: 0 auto clamp(40px, 5vw, 68px); text-align: center; }
.nv-root .nv-ia__title {
  margin: 0;
  /* Geist, not the page's display face: this heading labels a diagram whose
     own labels are all Geist, so the two read as one object. */
  font-family: var(--font-body);
  font-size: clamp(24px, 2.7vw, 36px); font-weight: 600;
  letter-spacing: -.9px; line-height: 1.16; color: var(--ink);
  text-wrap: balance;
}
.nv-root .nv-ia__lede {
  margin: 9px 0 0;
  font-size: clamp(14px, 1.15vw, 16px); line-height: 1.6; color: var(--muted);
  text-wrap: pretty;
}

/* The board is plain page — the export has no container behind the diagram.
   The left inset is the gutter the child spines hang in. */
.nv-root .nv-ia__board { position: relative; }
.nv-root .nv-ia__wires {
  position: absolute; inset: 0; width: 100%; height: 100%;
  overflow: visible; pointer-events: none;
}

/* Access row ------------------------------------------------------------- */
.nv-root .nv-ia__access {
  display: flex; flex-wrap: wrap; gap: 10px;
  margin: 0 0 clamp(64px, 7vw, 104px); padding: 0; list-style: none;
}
.nv-root .nv-ia__pill {
  padding: 12px 22px; border-radius: 999px;
  background: var(--pill);
  font-size: clamp(12.5px, 1vw, 14.5px); font-weight: 500; color: var(--granite);
  white-space: nowrap;
}
.nv-root .nv-ia__pill--group { background: var(--signal-soft); font-weight: 600; }
.nv-root .nv-ia__pill--signal { background: var(--signal); font-weight: 600; }

/* Destination columns ---------------------------------------------------- */
.nv-root .nv-ia__cols {
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: clamp(18px, 2.3vw, 34px);
  margin: 0; padding: 0; list-style: none;
  align-items: start;
}
.nv-root .nv-ia__col { min-width: 0; }
.nv-root .nv-ia__dest {
  display: flex; align-items: center; justify-content: center;
  margin: 0; padding: 0 14px; min-height: clamp(44px, 4.2vw, 58px);
  border-radius: 999px;
  background: var(--signal);
  font-size: clamp(13px, 1.2vw, 17px); font-weight: 600; color: var(--granite);
  letter-spacing: -.2px; text-align: center; line-height: 1.2;
}
.nv-root .nv-ia__dest--home { background: var(--granite); color: var(--paper); }
.nv-root .nv-ia__dest--data { background: var(--data-mid); }
.nv-root .nv-ia__scope {
  margin: clamp(7px, .7vw, 9px) 0 clamp(16px, 1.7vw, 22px) clamp(16px, 1.7vw, 24px);
  font-size: clamp(11.5px, 1vw, 14px); line-height: 1.4; color: var(--muted);
  /* Two lines reserved: inset to clear the spine, the longest label wraps,
     and without this its column's children sat lower than the rest. */
  min-height: 2.8em;
  text-align: center;
}

.nv-root .nv-ia__kids {
  margin: 0 0 0 clamp(16px, 1.7vw, 24px); padding: 0; list-style: none;
  display: grid; gap: clamp(14px, 1.5vw, 22px);
}
.nv-root .nv-ia__kid {
  display: flex; align-items: center; justify-content: center;
  padding: 12px 14px; min-height: clamp(48px, 4.4vw, 60px);
  border-radius: 999px;
  background: var(--pill);
  font-size: clamp(11px, .95vw, 13.5px); line-height: 1.35; color: var(--granite);
  text-align: center;
}
/* Claims is the plan-share column, so it carries Data blue and its outline. */
.nv-root .nv-ia__col:nth-child(3) .nv-ia__kid {
  background: var(--data-soft);
  box-shadow: inset 0 0 0 1.5px var(--data);
}

.nv-root .nv-ia__rail {
  display: flex; align-items: center; justify-content: center;
  margin: clamp(64px, 7vw, 104px) 0 0; padding: 16px 24px;
  min-height: clamp(48px, 4.2vw, 58px);
  border-radius: 999px;
  background: var(--granite);
  font-size: clamp(12.5px, 1.1vw, 16px); font-weight: 500; color: var(--paper);
  text-align: center;
}

/* Wires ------------------------------------------------------------------ */
.nv-root .nv-ia__wire {
  fill: none; stroke: #8E9D94; stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
}
.nv-root .nv-ia__wire--entry { stroke: #648B48; stroke-width: 1.75; }
.nv-root .nv-ia__wire--support { stroke-dasharray: 2 7; }
/* Priming for the draw-on: set from JS so the diagram renders at rest when
   scripting is off or reduced motion is asked for. */
.nv-root .nv-ia.is-armed .nv-ia__wire { opacity: 0; }
.nv-root .nv-ia.is-armed :is(.nv-ia__pill, .nv-ia__dest, .nv-ia__scope, .nv-ia__kid, .nv-ia__rail) {
  opacity: 0;
}

/* Five columns need real width. Two at tablet, one on phones; the wires are
   redrawn for whatever layout is current. */
@media (max-width: 1000px) {
  .nv-root .nv-ia__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(56px, 7vw, 76px) clamp(28px, 4vw, 40px); }
  .nv-root .nv-ia__board { padding-right: 30px; }
  .nv-root .nv-ia__kids,
  .nv-root .nv-ia__scope { margin-left: 22px; }
  .nv-root .nv-ia__access { margin-bottom: clamp(40px, 5vw, 56px); }
  .nv-root .nv-ia__rail { margin-top: clamp(40px, 5vw, 56px); }
}
/* The IA tree is a wide, wire-drawn diagram: below 600px it cannot be read
   at any size that still fits, and the phase list above it already carries
   the same point in prose. The whole figure — head, board and all — is
   hidden there rather than substituted with a stripped-down list, which
   only repeated what the copy had just said. */
@media (max-width: 600px) {
  .nv-root .nv-ia { display: none; }
}

/* Dark theme flips --granite to a light green, which would leave the labels
   light on the light neutral pills. The colour coding is kept as drawn —
   signal green and Data blue mean the same in either theme — so only the
   neutral fill darkens and every tinted pill takes dark ink. */
.nv-root[data-theme="dark"] { --pill: #283730; }
.nv-root[data-theme="dark"] :is(.nv-ia__pill, .nv-ia__kid) { color: var(--ink); }
.nv-root[data-theme="dark"] :is(.nv-ia__pill--signal, .nv-ia__pill--group, .nv-ia__dest),
.nv-root[data-theme="dark"] .nv-ia__col:nth-child(3) .nv-ia__kid { color: #18211e; }
.nv-root[data-theme="dark"] :is(.nv-ia__dest--home, .nv-ia__rail) { background: var(--granite); color: #18211e; }
.nv-root[data-theme="dark"] .nv-ia__wire { stroke: #87958d; }
.nv-root[data-theme="dark"] .nv-ia__wire--entry { stroke: #9ccb76; }

/* ---- Friction map, tablet and phone ---------------------------------------
   The ring styling only ever existed inside a min-width:1100px block, while a
   shared rule hid rings, nodes and links at 1099px and under — so the case
   study's spiral simply never rendered below desktop. It is rebuilt here for
   the narrow layout: a square orbit large enough for the rings to read around
   the core, concentric and centred rather than the desktop frame's offsets.
   Nodes and links stay hidden, as they are on desktop too.
   --------------------------------------------------------------------------- */
@media (max-width: 1099px) {
  .nv-root .nv-map__orbit {
    position: relative; inset: auto;
    width: min(320px, 78vw); height: auto; aspect-ratio: 1;
    mask-image: linear-gradient(transparent 1%, #000 20%, #000 80%, transparent 99%);
  }
  .nv-root .nv-map__ring { display: block; }
  :root .nv-root .nv-map .nv-map__ring[class][class] {
    left: 50%; top: 50%; height: auto; aspect-ratio: 1;
    translate: -50% -50%;
    border-radius: 29% !important;
    box-shadow: inset 0 0 0 1px #dce6d0;
  }
  .nv-root .nv-map__ring--1 { width: 100%; opacity: .55; }
  .nv-root .nv-map__ring--2 { width: 84%;  opacity: .7; }
  .nv-root .nv-map__ring--3 { width: 68%;  opacity: .85; }
  .nv-root .nv-map__ring--4 { width: 52%;  opacity: 1; }
  .nv-root .nv-map__ring--5 { width: 36%;  opacity: 1; }
  .nv-root .nv-map__glow {
    left: 50%; top: 50%; width: 62%; height: 62%; translate: -50% -50%;
  }
  .nv-root .nv-map__core {
    left: 50%; top: 50%; width: 30%; height: auto; translate: -50% -50%;
    font-size: clamp(24px, 7vw, 32px);
  }

  /* The frictions are cards at this width, so they need room between them
     rather than a shared border doing the separating. */
  .nv-root .nv-map__frictions { gap: 14px 20px; margin-top: 30px; }
  .nv-root .nv-friction { border-top: 0; gap: 8px; }
}

/* ---- Phone typography and rhythm ------------------------------------------
   The narrow layout had drifted: section titles and card titles sat close
   enough in size that the hierarchy flattened, body copy ran at three
   different sizes across blocks that read as siblings, and eyebrow labels
   were the same weight as the body they introduced.

   One scale, four steps, with a single body size under it:

     section title   30px / 1.08   -0.6px
     block title     22px / 1.18   -0.4px   (system + closing statements)
     card title      17px / 1.28   -0.2px   (phase, friction, screen, IA)
     body            14px / 1.55            (every description)
     eyebrow         11px / 600 / 1.4px tracking, uppercase

   Line length is capped so a description never runs the full bleed, and the
   gap under a head is larger than the gap inside it, so a title binds to its
   own description rather than to the content below.
   --------------------------------------------------------------------------- */
@media (max-width: 600px) {
  .nv-root .nv-title { font-size: var(--nv-fs-14); line-height: 1.08; letter-spacing: -.6px; }
  .nv-root .nv-sub,
  .nv-root .nv-head__desc,
  .nv-root .nv-intro__sub { font-size: var(--nv-fs-4); line-height: 1.55; }
  .nv-root .nv-sub { margin-top: 12px; max-width: 34em; }

  .nv-root :is(.nv-system__title, .nv-closing__statement, .nv-map__hub-title) {
    font-size: var(--nv-fs-11); line-height: 1.18; letter-spacing: -.4px;
  }
  .nv-root :is(.nv-phase h3, .nv-friction h3, .nv-screen__title, .nv-ia__title) {
    font-size: var(--nv-fs-7); line-height: 1.28; letter-spacing: -.2px;
  }
  .nv-root :is(.nv-phase p, .nv-friction p, .nv-screen__body, .nv-ia__lede) {
    font-size: var(--nv-fs-4); line-height: 1.5;
  }
  .nv-root :is(.nv-intro__nda, .nv-map__eyebrow) {
    font-size: var(--nv-fs-1); font-weight: 600; line-height: 1.4; letter-spacing: 1.4px;
  }

  /* A head's own parts sit closer together than the head sits to its
     content, so the title reads as belonging to its description. */
  .nv-root .nv-head { gap: 10px; }
  .nv-root .nv-phases,
  .nv-root .nv-stats,
  .nv-root .nv-screens { margin-top: 30px; }
  .nv-root .nv-map { margin-top: 34px; }
}

/* ---- Live prototype ---------------------------------------------------
   The stage itself is css/device-morph.css; this only places it in the
   closing section. */
.nv-root .nv-proto { width: 100%; margin-top: 56px; padding-bottom: 0; }
@media (max-width: 760px) { .nv-root .nv-proto { margin-top: 36px; } }

