/* ==========================================================================
   Site stylesheet — single file, no build step.
   Edit the tokens in :root to rebrand the whole site.
   ========================================================================== */

:root {
  /* Brand ---------------------------------------------------------------- */
  --brand:        #2e5fa8;   /* primary — links, buttons, accents           */
  --brand-dark:   #1f4478;   /* hover / active                              */
  --brand-tint:   #edf3fe;   /* very light background wash                  */
  --logo-box:     #a8c9fc;   /* the square in the wordmark                  */
  --accent:       #137a6b;   /* selected states — distinct from --brand     */
  --accent-dark:  #0e5b50;
  --accent-tint:  #e4f2ef;   /* the --brand-tint of the accent hue          */

  /* Neutrals ------------------------------------------------------------- */
  --ink:          #141a24;   /* body text                                   */
  --ink-muted:    #5a6577;   /* secondary text                              */
  --line:         #d6deea;   /* borders, rules                              */
  --bg:           #ffffff;
  --bg-alt:       #f5f8fc;

  /* Type ----------------------------------------------------------------- */
  --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* Spacing / layout ----------------------------------------------------- */
  --space:      1rem;
  --space-lg:   2rem;
  --space-xl:   4rem;
  --measure:    68ch;        /* max line length for readable prose          */
  --container:  68rem;       /* max page width                              */
  --radius:     6px;
}

/* Reset-ish ---------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 1.0625rem;
  line-height: 1.6;
  color: var(--ink);
  background: var(--bg);
}

img, svg, video { max-width: 100%; height: auto; display: block; }

h1, h2, h3 { line-height: 1.25; margin: 0 0 0.5em; font-weight: 650; }
h1 { font-size: 2.25rem; letter-spacing: -0.015em; }
h2 { font-size: 1.5rem; margin-top: 2em; }
h3 { font-size: 1.125rem; margin-top: 1.5em; }

p, ul, ol, dl { margin: 0 0 1em; max-width: var(--measure); }
li { margin-bottom: 0.35em; }

a { color: var(--brand); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--brand-dark); }

hr { border: 0; border-top: 1px solid var(--line); margin: var(--space-lg) 0; }

/* Focus visibility — do not remove, it is what keyboard users rely on. */
:focus-visible { outline: 3px solid var(--brand); outline-offset: 2px; }

.thumb { margin: auto; height: 100px; }
/* Skip link ---------------------------------------------------------------- */
.skip-link {
  position: absolute; left: -9999px;
  background: var(--brand); color: #fff; padding: 0.6em 1em; z-index: 100;
}
.skip-link:focus { left: 0.5rem; top: 0.5rem; }

/* Layout ------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--space);
}

main { padding-block: var(--space-xl); }

.section { padding-block: var(--space-xl); }
.section--alt { background: var(--bg-alt); }

/* Header / nav ------------------------------------------------------------- */
.site-header {
  border-bottom: 1px solid var(--line);
  background: var(--bg);
}
.site-header .container {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space);
  padding-block: 0.85rem;
}


/* Logo ---------------------------------------------------------------------
   The SVG is inlined by _includes/logo.njk, so its parts can be coloured from
   here. Change these two rules and every logo on the site follows. */
.logo {
  display: inline-flex;
  align-items: center;
  margin-right: auto;
  text-decoration: none;
}

.logo-svg {
  --logo-h: 48px;
  display: inline;
  height: var(--logo-h);
  width: auto;
}

.logo-svg .logo-ink    { fill: var(--ink); }
.logo-svg .logo-accent { fill: var(--brand); }

.logo:hover .logo-accent { fill: var(--brand-dark); }

.logo-svg-sm {
  --logo-h: 1.1rem;
  display: inline;
  height: var(--logo-h);
  width: auto;
}

@media (max-width: 30rem) { .logo-svg { --logo-h: 23px; } }

.site-nav ul {
  display: flex;
  flex-wrap: wrap;
  align-items: top;
  gap: 0.35rem 1.25rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.site-nav a {
  color: var(--ink-muted);
  text-decoration: none;
  font-size: 0.95rem;
}
.site-nav a:hover { color: var(--brand); }
/* Add class="current" to the nav link of the page you are on. */
.site-nav a.current { color: var(--ink); font-weight: 600; }
/* The nav's call-to-action button: needed because .site-nav a is more specific
   than .btn and would otherwise win on colour. */
.site-nav a.btn { color: #fff; }
.site-nav a.btn:hover { color: #fff; }

/* Nav group box ------------------------------------------------------------ */
.nav-group {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
}

/* Beats `.site-nav ul` (0,1,1) — a bare .nav-group__items would lose to it.
   The padding is small because each link now carries its own; the tighter gap
   keeps the two hover blocks reading as one control rather than two islands. */
.site-nav .nav-group__items {
  padding: 0.2rem 0.3rem;
  gap: 0.15rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

/* The links inside the Products box get the dropdown's hover: a tinted block,
   not just a colour change. A background needs somewhere to sit, so the link
   has to become a padded block — an inline <a> would tint only the glyphs.
   `.current` keeps the tint permanently, so the page you are on reads the same
   way as the one you are pointing at. */
.site-nav .nav-group__items a {
  display: block;
  padding: 0.35rem 0.6rem;
  border-radius: 4px;
}
.site-nav .nav-group__items a:hover,
.site-nav .nav-group__items a:focus-visible {
  background: var(--brand-tint);
  color: var(--brand);
}
.site-nav .nav-group__items a.current { background: var(--brand-tint); }

/* The global `li { margin-bottom: 0.35em }` (near the top of this file) applies
   to nav list items too. In the Products box it pushes the row off-centre; in
   the dropdown it opens a gap between the stacked items. Zero it here rather
   than editing the global rule, which every other list on the site relies on. */
.site-nav li { margin-bottom: 0; }

.nav-group__title {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-muted);
  white-space: nowrap;
}
/* Nav hover menu ------------------------------------------------------------
   Opened by :hover for a mouse and :focus-within for a keyboard, with no
   JavaScript. The parent stays a real link to the section index, so a touch
   device — which has no hover — taps through to a page that lists the same
   children rather than hitting a dead end. Below the breakpoint the menu is
   not rendered at all for that reason; the footer carries the sub-links there.

   `position: relative` on the <li> is what the absolutely positioned menu
   hangs from, and the menu's own padding-top (rather than a `top` offset)
   keeps the pointer inside the hover area on the way down — a gap there is the
   classic reason a dropdown closes as you reach for it. */
.nav-item { position: relative; align-self: start; }

.nav-item__caret {
  display: inline-block;
  margin-left: 0.3em;
  border: 0.26em solid transparent;
  border-top-color: currentColor;
  border-bottom: 0;
  vertical-align: 0.08em;
}

.nav-menu {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 20;
  min-width: 12rem;
  margin: 0;
  padding: 0.45rem 0 0;          /* the hover bridge — do not turn into `top` */
  list-style: none;
}

/* Beats `.site-nav ul` (0,1,1), which would otherwise impose flex on it. */
.site-nav .nav-menu {
  display: none;
  flex-direction: column;
  gap: 0;
}

@media (min-width: 46rem) {
  .site-nav .nav-item:hover > .nav-menu,
  .site-nav .nav-item:focus-within > .nav-menu { display: flex; }
}

.nav-menu li {
  background: var(--bg);
  border: 1px solid var(--line);
  border-bottom: 0;
}
.nav-menu li:first-child { border-radius: var(--radius) var(--radius) 0 0; }
.nav-menu li:last-child {
  border-bottom: 1px solid var(--line);
  border-radius: 0 0 var(--radius) var(--radius);
}

.site-nav .nav-menu a {
  display: block;
  padding: 0.5rem 0.85rem;
  white-space: nowrap;
}
.site-nav .nav-menu a:hover,
.site-nav .nav-menu a:focus-visible { background: var(--brand-tint); color: var(--brand); }

/* Sub-links under a footer nav item. */
.footer-sub {
  list-style: none;
  margin: 0.2rem 0 0;
  padding-left: 0.9rem;
}
.footer-sub a { font-size: 0.9rem; }

/* Buttons ------------------------------------------------------------------ */
.btn {
  display: inline-block;
  padding: 0.25em 0.9em;
  border: 1px solid var(--brand);
  border-radius: var(--radius);
  background: var(--brand);
  color: #fff;
  font: inherit;
  font-size: 0.98rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}
.btn:hover { background: var(--brand-dark); border-color: var(--brand-dark); color: #fff; }

.btn--ghost { background: transparent; color: var(--brand); }
.btn--ghost:hover { background: var(--brand-tint); color: var(--brand-dark); }

/* Hero --------------------------------------------------------------------- */
.hero { background: var(--brand-tint); padding-block: var(--space-xl); }
.hero p.lead { font-size: 1.2rem; color: var(--ink-muted); }
.hero .actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: var(--space-lg); }
 
/* Hero with a background photo ---------------------------------------------
   Opt in per page by setting `heroImage:` in the front matter, which the
   template turns into an inline custom property:
 
     <section class="hero hero--image" style="--hero-image: url('/assets/…')">
 
   The path is passed as a variable rather than written into this file, so one
   rule serves every page and no page needs its own CSS.
 
   Two things make the text readable over an arbitrary photo. The scrim — the
   dark gradient layered ABOVE the image in the same `background` shorthand —
   guarantees contrast no matter how light or busy the picture is; without it
   a white headline lands on whatever happens to be behind it. And the
   background-color underneath is a solid brand tone, so a photo that is slow,
   missing or mistyped leaves legible white-on-dark rather than white-on-white.
 
   Tune the scrim opacities to taste: heavier for a busy photo, lighter for a
   calm one. Keep the left value higher than the right — the text column sits
   on that side. */
.hero--image {
  background:
    linear-gradient(to right, rgba(9, 22, 32, 0.89), rgba(9, 22, 32, 0.62)),
    var(--hero-image, none) var(--hero-position, center) / cover no-repeat,
    var(--brand-dark);
  color: #fff;
}
 
.hero--image h1 { color: #fff; font-size: 2.3rem; font-weight: 700; }
.hero--image p.lead { color: rgba(255, 255, 255, 0.88); }
.hero--image a { color: #fff; }
 
/* The ghost button is drawn in brand blue, which disappears against the
   scrim — restate it in white for this context only. */
.hero--image .btn--ghost { border-color: rgba(255, 255, 255, 0.8); color: #fff; }
.hero--image .btn--ghost:hover { background: #fff; color: var(--brand-dark); }
 
/* The system diagram takes its colours from the page palette, so on a dark
   hero it would vanish. Give the figure a light panel and it renders exactly
   as it does on the plain hero, caption and links included. */
.hero--image .hero__figure {
  background: rgba(255, 255, 255, 0.94);
  padding: var(--space);
  border-radius: var(--radius);
}
.hero--image .hero__figure figcaption { color: var(--ink-muted); }
.hero--image .hero__figure a { color: var(--brand); }
 
/* Background images are dropped by most print settings, which would leave
   white text on white paper. */
@media print {
  .hero--image { background: none; color: var(--ink); }
  .hero--image h1,
  .hero--image p.lead,
  .hero--image a { color: var(--ink); }
}
 
/* Hero diagram ------------------------------------------------------------- */
.hero__grid {
  display: grid;
  gap: var(--space-lg);
  align-items: center;
}
 
@media (min-width: 54rem) {
  .hero__grid { grid-template-columns: 1fr 1.05fr; gap: var(--space-xl); }
}
 
.hero__figure { margin: 0; }
 
.hero__figure figcaption {
  margin-top: 0.75rem;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--ink-muted);
}
 
/* The diagram takes its colours from here, so it follows the palette. */
.dia { width: 100%; height: auto; }
 
.dia-panel   { fill: var(--bg); stroke: var(--line); stroke-width: 1.5; }
.dia-hw path,
.dia-hw rect { fill: var(--bg); stroke: var(--brand); stroke-width: 2.5;
               stroke-linejoin: round; }
.dia-hw--solid rect { fill: var(--brand); }
.dia-node    { fill: var(--brand); }
.dia-led     { fill: var(--bg); opacity: 0.9; }
.dia-link path { fill: none; stroke: var(--brand); stroke-width: 2;
                 stroke-dasharray: 2 6; stroke-linecap: round; }
.dia-arrow path { fill: none; stroke: var(--ink-muted); stroke-width: 2; }
.dia-arrowhead  { fill: var(--ink-muted); }
.dia-cloud path { fill: var(--bg); stroke: var(--accent); stroke-width: 2.5;
                  stroke-dasharray: 7 5; stroke-linejoin: round; }
.dia-bars rect  { fill: var(--accent); }
 
.dia-label   { fill: var(--ink); font-size: 17px; font-weight: 600;
               font-family: var(--font); }
.dia-sub     { fill: var(--ink-muted); font-size: 14px; font-family: var(--font); }
.dia-eyebrow { fill: var(--ink-muted); font-size: 13px; font-weight: 600;
               letter-spacing: 0.08em; text-transform: uppercase;
               font-family: var(--font); }

/* Card grid ---------------------------------------------------------------- */
.grid {
  display: grid;
  gap: var(--space-lg);
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  margin-block: var(--space-lg);
}

.subgrid {
  display: grid;
  gap: var(--space);
  grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
  margin-block: var(--space);
  text-align: center;
}

card {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--space-lg);
  background: var(--bg);
}
.card h3 { margin-top: 0; }
.card p:last-child { margin-bottom: 0; }
/* Pushes a trailing action link to the bottom edge so tiles in a row line up. */
.card > p:last-child { margin-top: auto; }
.card > ul:last-child { margin-bottom: 0; }

/* Content tiles -------------------------------------------------------------
   NOTE: this rule used to read `subcard {` — a typo that made it an unknown
   ELEMENT selector, so it matched nothing and every .card on the site rendered
   with no border, no padding and no background. If tiles ever look bare again,
   check this selector first.

   The tile is built from four cheap effects that read as "designed" without
   costing legibility: a tinted top edge that lights up on hover, a very soft
   two-layer shadow, a barely-there gradient so the surface is not dead flat,
   and a small lift on hover. Everything is driven by the existing tokens, so
   rebranding through :root still carries the whole set. */
.card {
  position: relative;
  display: flex;              /* lets a trailing link pin to the bottom edge   */
  flex-direction: column;
  padding: 1.35rem 1.25rem 1.25rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background:
    linear-gradient(180deg, var(--bg) 0%, var(--bg-alt) 100%);
  /* Two layers: a tight one for the edge, a wide soft one for the float. A
     single large shadow reads as blur; two read as depth. */
  box-shadow:
    0 1px 2px rgba(16, 32, 45, 0.05),
    0 8px 20px -12px rgba(16, 32, 45, 0.18);
  overflow: hidden;           /* keeps the accent bar inside the radius        */
  transition: box-shadow 160ms ease, border-color 160ms ease;
}

/* The accent bar. A pseudo-element rather than a border so it can be animated
   and clipped by the card's own radius. scaleX from the left reads as the tile
   "filling in" rather than a bar appearing from nowhere. */
.card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: linear-gradient(90deg, var(--brand), var(--accent));
  transform: scaleX(0.999);
  transform-origin: left;
  opacity: 0.45;
  transition: opacity 160ms ease;
}

.card:hover,
.card:focus-within {
  border-color: color-mix(in srgb, var(--brand) 35%, var(--line));
  box-shadow:
    0 2px 4px rgba(16, 32, 45, 0.06),
    0 18px 34px -16px rgba(16, 32, 45, 0.32);
}

.card:hover::before,
.card:focus-within::before { opacity: 1; }

.card:hover h3 a,
.card:focus-within h3 a { color: var(--brand-dark); }

/* A tile the whole page is meant to look at — use sparingly, one per grid. */
.card--feature {
  background: linear-gradient(180deg, var(--brand-tint) 0%, var(--bg) 65%);
  border-color: color-mix(in srgb, var(--brand) 30%, var(--line));
}
.card--feature::before { opacity: 1; height: 4px; }

/* Older browsers without color-mix() keep the plain line colour; everything
   else about the hover still works. */
@supports not (color: color-mix(in srgb, red 50%, blue)) {
  .card:hover, .card:focus-within { border-color: var(--brand); }
  .card--feature { border-color: var(--brand); }
}

/* Nothing moves on hover any more — the border, shadow and accent carry it —
   so reduced motion only has the colour fade left to switch off. */
@media (prefers-reduced-motion: reduce) {
  .card, .entry { transition: none; }
}

/* A card is a surface, not a sheet of paper — never print the decoration.
   The :hover/:focus-within selectors are repeated here on purpose: they are
   specificity 0,2,0 and would otherwise beat a bare `.card` even inside a
   print media query, so a page printed while a tile happened to be hovered
   would still carry its shadow. */
@media print {
  .card,
  .card:hover,
  .card:focus-within,
  .entry,
  .entry:hover,
  .entry:focus-within {
    box-shadow: none;
    background: none;
    border-color: var(--line);
  }
  .card::before { display: none; }
}

/* Media block (product row: image + text) ---------------------------------- */
.media {
  display: grid;
  gap: var(--space-lg);
  grid-template-columns: 1fr;
  align-items: start;
  margin-block: var(--space-xl);
}
@media (min-width: 46rem) {
  .media { grid-template-columns: 1fr 1fr; }
}
.media__figure {
  margin: 0;
  aspect-ratio: 4 / 3;
  background: var(--bg);
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  display: grid;
  place-items: center;
  color: var(--ink-muted);
  font-size: 0.9rem;
}


/* Product photo gallery ----------------------------------------------------
   A horizontal scroller with snap points, not a stack of absolutely-positioned
   slides. That is the whole trick: the browser does the panning, the swiping,
   the momentum and the keyboard scrolling, and gallery.js only adds arrows,
   dots and a counter on top. It also means the gallery works before — and
   without — the script.

   All shots are framed to --gallery-ratio and fitted with `contain`, so a
   portrait and a landscape photo in the same product still line up and the box
   never changes height as you scroll. Change the ratio here, once. */
   .gallery { margin: 0; --gallery-ratio: 4 / 3; }

   .gallery__frame { position: relative; }
   
   .gallery__track {
     display: flex;
     list-style: none;
     margin: 0;
     padding: 0;
     overflow-x: auto;
     overscroll-behavior-x: contain;   /* swiping the strip won't page-back */
     scroll-snap-type: x mandatory;
     scrollbar-width: none;            /* the dots and arrows are the affordance */
     border-radius: var(--radius);
   }
   .gallery__track::-webkit-scrollbar { display: none; }
   .gallery__track:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
   
   .gallery__slide {
     flex: 0 0 100%;
     scroll-snap-align: center;
     margin: 0;
   }
   
   .gallery__slide img {
     display: block;
     width: 100%;
     aspect-ratio: var(--gallery-ratio);
     object-fit: contain;
     background: var(--bg-alt);
     border: 1px solid var(--line);
     border-radius: var(--radius);
   }
   
   .gallery__cap {
     margin: 0.45em 0 0;
     padding-inline: 0.2rem;
     font-size: 0.8rem;
     color: var(--ink-muted);
   }
   
   /* `appearance: none` for the same reason as .chip — macOS Safari otherwise
      keeps a faint bevel on a <button> however you style it. */
   .gallery__arrow {
     position: absolute;
     top: calc(50% - 1.1rem);          /* centred on the image, not the caption */
     z-index: 1;
     appearance: none;
     -webkit-appearance: none;
     width: 2.25rem;
     height: 2.25rem;
     display: grid;
     place-items: center;
     padding: 0;
     border: 1px solid var(--line);
     border-radius: 999px;
     background: rgba(255, 255, 255, 0.92);
     color: var(--ink);
     font: inherit;
     font-size: 1.35rem;
     line-height: 1;
     cursor: pointer;
   }
   .gallery__arrow--prev { left: 0.5rem; }
   .gallery__arrow--next { right: 0.5rem; }
   .gallery__arrow:hover:not(:disabled) { border-color: var(--brand); color: var(--brand); }
   .gallery__arrow:disabled { opacity: 0.3; cursor: default; }
   
   .gallery__bar {
     display: flex;
     align-items: center;
     justify-content: space-between;
     gap: 0.75rem;
     margin-top: 0.6rem;
   }
   
   .gallery__dots { display: flex; gap: 0.35rem; }
   
   .gallery__dot {
     appearance: none;
     -webkit-appearance: none;
     width: 0.6rem;
     height: 0.6rem;
     padding: 0;
     border: 1px solid var(--line);
     border-radius: 999px;
     background: var(--bg);
     cursor: pointer;
   }
   .gallery__dot:hover { border-color: var(--brand); }
   .gallery__dot[aria-current="true"] { background: var(--brand); border-color: var(--brand); }   

/* Forms -------------------------------------------------------------------- */
.form { max-width: 38rem; }

.field { margin-bottom: var(--space-lg); }

.field label {
  display: block;
  font-weight: 600;
  font-size: 0.95rem;
  margin-bottom: 0.35em;
}

.field .hint {
  display: block;
  font-weight: 400;
  font-size: 0.85rem;
  color: var(--ink-muted);
  margin-top: 0.2em;
}

.field input[type="text"],
.field input[type="email"],
.field input[type="tel"],
.field input[type="url"],
.field select,
.field textarea {
  width: 100%;
  padding: 0.6em 0.7em;
  font: inherit;
  color: var(--ink);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.field textarea { min-height: 8rem; resize: vertical; }

.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--brand); }

.field--check { display: flex; gap: 0.6rem; align-items: flex-start; }
.field--check input { margin-top: 0.35em; }
.field--check label { font-weight: 400; font-size: 0.92rem; }

fieldset {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--space);
  margin: 0 0 var(--space-lg);
}
legend { font-weight: 600; font-size: 0.95rem; padding-inline: 0.4em; }
fieldset .field:last-child { margin-bottom: 0; }

.required { color: #b3261e; }

/* Honeypot: hidden from humans, visible to naive bots. Never use display:none
   alone if you care about a few smarter bots — this combination is standard. */
.hp {
  position: absolute !important;
  left: -9999px !important;
  width: 1px; height: 1px;
  overflow: hidden;
}

/* Spec lists (product pages) ----------------------------------------------- */
.specs {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.35em 1.5em;
  margin: 0 0 var(--space-lg);
  font-size: 0.95rem;
}
.specs dt { color: var(--ink-muted); }
.specs dd { margin: 0; }
.specs__list { list-style: none; margin: 0; padding: 0; }
.specs__list li { margin-bottom: 0.15em; }

/* Availability matrix (analytics page) ------------------------------------- */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Wide tables scroll inside their own box, never the page. */
/* position: relative keeps visually-hidden labels inside the table's own
   scroll box; without it they are placed against the page and widen it. */
.scroller { position: relative; overflow-x: auto; margin-bottom: 0.75em; }

.matrix {
  border-collapse: collapse;
  min-width: 34rem;
  font-size: 0.95rem;
}

.matrix th,
.matrix td {
  padding: 0.6em 0.9em;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}

.matrix thead th {
  border-bottom: 2px solid var(--rule-firm, var(--ink-muted));
  font-size: 1.2rem;
  white-space: nowrap;
}

.matrix tbody th { font-weight: 600; max-width: 26rem; }

.matrix__note {
  display: block;
  font-weight: 400;
  font-size: 0.85rem;
  color: var(--ink-muted);
}

.matrix__head {
  font-weight: 200;
  align-items: bottom;

  background: var(--bg-alt)
}

.matrix__data {
  font-weight: 200;
  align-items: center:
}


.alternative-link {
  color: var(--brand);
  font-size: 1.3rem;
  text-decoration: none;
  font-weight: 200;
  align-items: bottom;
}

.alternative-link:hover {
  font-weight: 400;
}
.alternative-link-lg {
  color: var(--brand);
  font-size: 1.6rem;
  text-decoration: none;
  font-weight: 500;
  align-items: bottom;
}

.alternative-link-lg:hover {
  font-weight: 600;
}

/* Marks are centred under their column heading. */
.matrix td { text-align: center; width: 15%; white-space: nowrap; }
.matrix__yes { color: var(--accent, #1f6f63); font-size: 1.5rem; }
.matrix__no  { color: var(--line); }

.matrix tbody tr:hover { background: var(--bg-alt); }


/* Publications (research page) --------------------------------------------- */
/* Tag names here are phrases, not single words, so they are set as readable
   pills rather than tracked uppercase labels — three fit on a card row. */
.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin: 0 0 0.7em;
  max-width: var(--measure);
}
 
.tag {
  display: inline-block;
  padding: 0.15em 0.6em;
  border-radius: 999px;
  background: var(--brand-tint);
  color: var(--brand-dark);
  font-size: 0.78rem;
  font-weight: 500;
  white-space: nowrap;
}
 
.tag--sm { font-size: 0.72rem; padding: 0.1em 0.5em; }
 
/* Grouped publication tags -------------------------------------------------
   Printed Garment → Analysis → Other. Two things carry the grouping: a wider
   gap between groups than within one, and a colour per category. The colour is
   what still reads as a group after a long tag list wraps onto a second line,
   where the gap alone would be ambiguous.
 
   The gap on .tags--grouped is the BETWEEN-group gap; .taggroup sets its own,
   tighter one for the chips inside it. Row gap stays at 0.3rem so wrapped
   lines don't drift apart. */
.tags--grouped { gap: 0.3rem 0.85rem; align-items: baseline; }
.taggroup { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.3rem; }
 
/* "Garment:" / "Analyses:" / "Other:". Baseline alignment above is what stops
   this plain text from sitting at the top of the taller pills beside it. */
.taggroup__label {
  font-size: 0.78rem;
  color: var(--ink-muted);
  white-space: nowrap;
}
.tags--sm .taggroup__label { font-size: 0.72rem; }
 
/* Garment keeps the original .tag look, so nothing on the site changes tone;
   the other two are stated in full rather than inherited, so reordering this
   block can't silently change one of them. */
.tag--garment  { background: var(--brand-tint);              color: var(--brand-dark); }
.tag--analysis { background: var(--accent-tint, #e8f1ef);    color: var(--accent-dark, #15544a); }
.tag--other    { background: var(--bg-alt);                  color: var(--ink-muted); }
 
.pub .tags { margin: 0.35em 0 0; }
 
.badge {
  display: inline-block;
  padding: 0.05em 0.4em;
  border: 1px solid var(--brand);
  border-radius: 3px;
  color: var(--brand);
  font-size: 0.7rem;
  font-weight: 700;
  vertical-align: 0.15em;
}
 
h3.year {
  margin-top: 1.75em;
  padding-bottom: 0.25em;
  border-bottom: 1px solid var(--line);
  font-size: 1rem;
  color: var(--ink-muted);
  font-weight: 600;
  max-width: var(--measure);
}
 
.pubs { list-style: none; margin: 0.75em 0 0; padding: 0; max-width: var(--measure); }
.pub__title { margin: 0 0 0.15em; font-weight: 600; }
.pub__meta { margin: 0; }
 

/* List entries (publications, posts) ----------------------------------------
   A quieter relative of .card. Both are surfaces you can hover, and they share
   the border, the radius and the way the edge tints — so a row of them reads
   as the same system. What a list entry deliberately does NOT take from .card
   is the theatre: no gradient, no accent bar, no floating shadow. A card is one
   of three or four things competing for a glance; an entry is one of twenty
   being read down a column, and at that density the same decoration stops
   being emphasis and becomes noise.

   `.pub` and `.post-card` both carry it, so the research list and the blog
   list cannot drift apart. Use `.entry` directly for any future list of the
   same kind. */
.pub,
.post-card,
.entry {
  padding: 0.5rem 1rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--bg);
  /* One tight layer only. The card's second, wide layer is what makes it look
     lifted off the page — exactly the effect a dense list should not have. */
  box-shadow: 0 1px 2px rgba(16, 32, 45, 0.04);
  transition: box-shadow 160ms ease, border-color 160ms ease;
}

.pub:hover,  .pub:focus-within,
.post-card:hover, .post-card:focus-within,
.entry:hover, .entry:focus-within {
  border-color: color-mix(in srgb, var(--brand) 30%, var(--line));
  box-shadow: 0 1px 3px rgba(16, 32, 45, 0.09);
}

@supports not (color: color-mix(in srgb, red 50%, blue)) {
  .pub:hover, .post-card:hover, .entry:hover { border-color: var(--brand); }
}

.pub  { margin-bottom: 0.6em; }
.pub:last-child { margin-bottom: 0; }
.pub .tags:last-child { margin-bottom: 0; }

/* Tag filter (research page) ------------------------------------------------ */
[hidden] { display: none !important; }
 
.filterbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin: 1.25rem 0 0.75rem;
}
 
.filterbar__label {
  font-size: 0.8rem;
  color: var(--ink-muted);
  margin-right: 0.35rem;
}
 
/* `appearance: none` is what removes the operating system's own button
   rendering — on macOS Safari a <button> keeps a faint bevel/inner shadow even
   after you set your own border and background, which reads as an emboss. */
.chip {
  appearance: none;
  -webkit-appearance: none;
  font: inherit;
  font-size: 0.7rem;
  padding: 0.3em 0.5em;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg);
  color: var(--ink-muted);
  cursor: pointer;
}
 
.chip:hover { border-color: var(--brand); color: var(--brand); }
 
/* Selected filters use --accent, not --brand, so an active filter never reads
   as just another link or button.
   The selector is scoped to .filterbar (specificity 0,3,0) so it outranks
   .chip:hover (0,2,0) no matter where the two rules sit in this file, and each
   var() carries a literal fallback so the rule still works if the --accent
   tokens in :root are ever missing. */
/* Border of a selected chip. `transparent` keeps the 1px so the chip does not
   change size, but draws no edge — the pill reads as one flat colour. For a
   defined rim instead, use var(--accent-dark, #15544a); for a light outline on
   the fill, use #fff. Do not use border-width: 0 — the chip would shrink by 2px
   and the row would shift as you click. */
.filterbar .chip[aria-pressed="true"] {
  background: var(--accent, #1f6f63);
  border-color: transparent;
  color: #fff;
  font-weight: 500;
}
 
.filterbar .chip[aria-pressed="true"]:hover {
  background: var(--accent-dark, #15544a);
  border-color: transparent;
  color: #fff;
}

.filterbar .chip:disabled {
  opacity: 0.35;
  cursor: default;
}

.filtebar .chip:disabled:hover { border-color: var(--line); color: var(--ink-muted); }


/* Set well apart from the tag chips: it acts on them rather than being one. */
.filterbar .chipgroup {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
}
 
/* The label lives inside its group so the two never wrap apart. */
.chipgroup .filterbar__label { margin-right: 0.15rem; }
 
/* Sets one group of chips apart from the next. */
.filterbar__sep {
  width: 1px;
  align-self: stretch;
  min-height: 1.4em;
  margin-inline: 0.7rem;
  background: var(--line);
}
 
.chip__count {
  display: inline-block;
  margin-left: 0.25em;
  opacity: 0.65;
  font-variant-numeric: tabular-nums;
}
 
.chip--reset {
  margin-left: 2.5rem;
  border-style: dashed;
}
 
/* A button that reads as a link — used for the counts on the area cards. */
.linkbtn {
  font: inherit;
  font-size: 0.95rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--brand);
  cursor: pointer;
}
.linkbtn:hover { color: var(--brand-dark); text-decoration: underline; }
 
.card__action { margin-bottom: 0; }
 

/* Notices ------------------------------------------------------------------ */
.notice {
  border-left: 3px solid var(--brand);
  background: var(--brand-tint);
  padding: var(--space);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: 0.95rem;
  max-width: var(--measure);
}

/* Footer ------------------------------------------------------------------- */
.site-footer {
  border-top: 1px solid var(--line);
  background: var(--bg-alt);
  padding-block: var(--space-lg);
  font-size: 0.9rem;
  color: var(--ink-muted);
}
.site-footer .container {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space) var(--space-lg);
  justify-content: space-between;
}
.site-footer ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 1rem; }
.site-footer a { color: var(--ink-muted); }
.site-footer a:hover { color: var(--brand); }

/* Utilities ---------------------------------------------------------------- */
.lead { font-size: 1.15rem; color: var(--ink-muted); }
.muted { color: var(--ink-muted); }
.small { font-size: 0.9rem; }
.stack > * + * { margin-top: var(--space); }
.center { text-align: center; }

/* Print -------------------------------------------------------------------- */
@media print {
  .site-header, .site-footer, .btn { display: none; }
  body { font-size: 11pt; }
}

/* Resources pages ----------------------------------------------------------
   FAQ, instructions and media share these. Nothing here is page-specific, so
   a fourth resource page inherits the lot. */

/* Contents list at the top of a long page. */
.faq-toc ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.1rem;
  list-style: none;
  margin: 0 0 var(--space-lg);
  padding: 0;
  font-size: 0.9rem;
}

/* <details>/<summary> rather than JavaScript: it is searchable by the browser's
   own find-in-page in current browsers, keyboard-operable for free, and prints
   open. The marker is left as the browser draws it — a custom one is one more
   thing to get wrong in a nested list. */
.faq { max-width: var(--measure); margin-bottom: var(--space-lg); }

.faq__item {
  border-bottom: 1px solid var(--line);
  padding: 0.15rem 0;
}
.faq__item summary {
  padding: 0.6rem 0;
  cursor: pointer;
  font-weight: 500;
}
.faq__item summary:hover { color: var(--brand); }
.faq__item[open] summary { color: var(--brand-dark); }
.faq__answer { padding: 0 0 0.6rem 1.1rem; }
.faq__answer p { margin: 0 0 0.5em; }

/* An editorial note that is meant to be seen while the site is being written,
   and to look wrong enough that it never ships by accident. Delete the `todo`
   field in the source data and it disappears. */
.todo {
  border-left: 3px solid #c98a00;
  background: #fff8e6;
  padding: 0.4rem 0.7rem;
  font-size: 0.85rem;
  color: #6b4b00;
}

/* Numbered procedure. The counter sits outside the text column so wrapped
   lines line up under each other rather than under the number. */
.steps {
  max-width: var(--measure);
  padding-left: 1.3rem;
}
.steps > li { margin-bottom: 0.7em; }

.boilerplate {
  max-width: var(--measure);
  margin: 0 0 var(--space-lg);
  padding: 0.9rem 1.1rem;
  border-left: 3px solid var(--brand);
  background: var(--bg-alt);
}
.boilerplate p { margin: 0; }

.media-thumb {
  max-width: 100%;
  height: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.logo-swatch {
  display: grid;
  place-items: center;
  padding: 1.2rem;
  background: var(--bg-alt);
  border-radius: var(--radius);
}

/* Garments page ------------------------------------------------------------ */
.garments-diagram {
  margin: 0 0 var(--space-lg);
  max-width: 46rem;
}
.garments-diagram figcaption {
  margin-top: 0.75rem;
  font-size: 0.9rem;
  color: var(--ink-muted);
}

/* A short aside that should read as a statement of fact, not decoration. */
.notice {
  max-width: var(--measure);
  padding: 0.7rem 1rem;
  border-left: 3px solid var(--brand);
  background: var(--brand-tint);
}

/* Blog ----------------------------------------------------------------------
   Named for the folder, not for the section: the public name lives in
   src/_data/blog.json and can change without touching any of these rules. */

.post-list {
  display: grid;
  gap: 0.6rem;                 /* tiles sit close; the border does the dividing */
  margin-bottom: var(--space-lg);
  max-width: var(--measure);
}

/* Border, radius and padding come from the shared .pub/.post-card/.entry rule
   further up; only the things specific to a post belong here. */
.post-card h3:first-of-type { margin-top: 0.1em; }
.post-card h3 { margin: 0.1em 0 0.35em; }
.post-card h3 a { text-decoration: none; }
.post-card h3 a:hover { text-decoration: underline; }
.post-card p { margin-bottom: 0.5em; }

/* Date and byline line, used on the index, the post and the front page. */
.post__meta {
  margin: 0;
  font-size: 0.85rem;
  color: var(--ink-muted);
}

/* A draft is only ever visible while previewing locally, so it is marked
   loudly enough that it cannot be mistaken for a published post. */
.post__draft {
  padding: 0.05em 0.4em;
  border-radius: 3px;
  background: #fff4e0;
  color: #7a5200;
  font-size: 0.85em;
}

.post { max-width: 58rem; }
.post__header { margin-bottom: var(--space-lg); }
.post__body { max-width: var(--measure); }
.post__body h2 { margin-top: 1.6em; }
.post__body img { border-radius: var(--radius); }

.post__figure { margin: 0 0 var(--space-lg); }
.post__figure img { border-radius: var(--radius); }
.post__figure figcaption {
  margin-top: 0.5rem;
  font-size: 0.85rem;
  color: var(--ink-muted);
}

.post__related {
  max-width: var(--measure);
  margin-top: var(--space-lg);
  padding: 0.9rem 1.1rem;
  border-left: 3px solid var(--brand);
  background: var(--bg-alt);
}
.post__related h2 { margin-top: 0; font-size: 1.05rem; }
.post__related ul { margin-bottom: 0; }

/* Previous / next. `justify-content: space-between` with an empty first <div>
   is what keeps "Older" hard right on the newest post, where there is no
   newer one to sit opposite it. */
.post-nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space);
  margin: var(--space-lg) 0;
  padding-top: var(--space);
  border-top: 1px solid var(--line);
  font-size: 0.95rem;
}
.post-nav__older { text-align: right; }

/* Compact list used where posts are a sidebar to something else — the product
   pages, for instance. */
.post-links { list-style: none; margin: 0 0 1em; padding: 0; }
.post-links li { margin-bottom: 0.6em; }

/* Front-matter sample on the index. */
.codeblock {
  max-width: var(--measure);
  overflow-x: auto;
  padding: 0.9rem 1.1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-alt);
  font-size: 0.85rem;
  line-height: 1.5;
}

/* Key figures ---------------------------------------------------------------
   The two- or three-up statistic strip at the top of a product or analysis
   page: a headline number and the one sentence that gives it meaning. It is
   the same device as the printed product sheet, so the page and the PDF a
   customer downloads read the same way. Four items is a table, not a strip. */
.figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 2px;
  max-width: var(--measure);   /* one column with the prose it introduces */
  margin: 0 0 var(--space-lg);
}

.figure-stat {
  background: var(--brand-tint);
  padding: 0.85rem 1.1rem;
}

/* The number. Brand-dark rather than brand: it is text on a tint, and it has
   to carry contrast at this size. */
.figure-stat__value {
  display: block;
  font-size: 1.45rem;
  font-weight: 700;
  line-height: 1.15;
  color: var(--brand-dark);
}

.figure-stat__label {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.9rem;
  line-height: 1.45;
}

/* Label and value rows ------------------------------------------------------
   For lists where the value is a sentence rather than a short figure; .specs
   above is for short values and sets its own narrow first column. Hairline
   rules between the rows, label in ink so it reads as a heading. */
.deflist {
  display: grid;
  grid-template-columns: minmax(9rem, 15rem) 1fr;
  margin: 0 0 var(--space-lg);
  border-top: 1px solid var(--line);
  font-size: 0.97rem;
}

.deflist dt {
  grid-column: 1;
  padding: 0.7rem 1.5rem 0.7rem 0;
  border-bottom: 1px solid var(--line);
  font-weight: 600;
}

.deflist dd {
  grid-column: 2;
  margin: 0;
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--line);
}

/* One column on a narrow screen: the label keeps its rule only at the bottom
   of the pair, so a row still reads as one block. Both dt and dd have to be
   moved into column 1 — an explicit `grid-column: 2` would otherwise conjure an
   implicit second column and the single-column layout would never appear. */
@media (max-width: 34rem) {
  .deflist { grid-template-columns: 1fr; }
  .deflist dt { grid-column: 1; padding: 0.7rem 0 0; border-bottom: 0; }
  .deflist dd { grid-column: 1; padding-top: 0.15rem; }
}

/* Two tiles and an orphan read as a broken row, so below the breakpoint the
   figures stack instead. */
@media (max-width: 30rem) {
  .figures { grid-template-columns: 1fr; }
}

/* Eyebrow -------------------------------------------------------------------
   Small tracked capitals above a heading — the label style already used by the
   navigation group titles and by every Momega document. */
.eyebrow {
  margin-bottom: 0.3rem;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* Figure panels -------------------------------------------------------------
   A lettered set of drawings with one caption, as in a paper: "Figure 1A, 1B".
   Each drawing ships in a wide and a narrow version and CSS shows one of them,
   so the lettering inside a figure stays readable on a phone instead of
   shrinking with the page. The drawings themselves come from
   tools/bims-figures.py and tools/motor-figures.py, and take their colours
   from the .dia-* and .chart-*
   rules below. */
.figure-panel {
  max-width: var(--measure);
  margin: var(--space-lg) 0;
  padding: 1.25rem 1.25rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.figure-panel__part + .figure-panel__part {
  margin-top: 1.75rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
}

.figure-panel__label {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  margin: 0 0 0.9rem;
  font-weight: 600;
}

/* The panel letter: a small brand-blue square, echoing the tile in the logo. */
.figure-panel__letter {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 4px;
  background: var(--brand);
  color: #fff;
  font-size: 0.8rem;
  font-weight: 700;
}

.figure-panel__art svg { display: block; width: 100%; height: auto; }
.figure-panel__art--narrow { display: none; }

@media (max-width: 34rem) {
  .figure-panel { padding: 1rem 0.75rem 0.75rem; }
  .figure-panel__art--wide { display: none; }
  .figure-panel__art--narrow { display: block; }
}

.figure-panel figcaption {
  margin-top: 1.25rem;
  font-size: 0.9rem;
  line-height: 1.55;
  color: var(--ink-muted);
}

/* The numbers behind a chart, one click away — for screen readers, and for the
   reviewer who wants the values rather than the picture. */
.figure-panel__data { margin-top: 0.75rem; font-size: 0.9rem; }
.figure-panel__data summary { cursor: pointer; color: var(--brand); }
.figure-panel__data table { border-collapse: collapse; margin-top: 0.6rem; }
.figure-panel__data th,
.figure-panel__data td {
  padding: 0.3rem 1rem 0.3rem 0;
  border-bottom: 1px solid var(--line);
  text-align: left;
  font-variant-numeric: tabular-nums;
}

/* Figure drawings -----------------------------------------------------------
   Steps, notes and the result scale in the process diagrams. */
.dia-box    { fill: var(--bg); stroke: var(--line); stroke-width: 1.5; }
.dia-note   { fill: var(--ink-muted); font-size: 12.5px; font-family: var(--font); }
.dia-scale  { stroke: var(--line); }
.dia-scale-start { stop-color: var(--brand-tint); }
.dia-scale-end   { stop-color: var(--brand); }
.dia-marker { fill: var(--ink); }

/* Chart marks ---------------------------------------------------------------
   Reference bands in one hue at stacked opacities (outer, middle, inner), the
   median in brand-dark, the clinical cut-off dashed, and the individual in ink
   so it stands clear of every band. Points carry a surface ring where they sit
   on the line. Open points are the second state of the same series. */
.chart-grid    { stroke: var(--line); stroke-width: 1; }
.chart-tick    { fill: var(--ink-muted); font-size: 13px; font-family: var(--font); }
.chart-band    { fill: var(--brand); fill-opacity: 0.12; }
.chart-median  { fill: none; stroke: var(--brand-dark); stroke-width: 2; }
.chart-cutoff  { fill: none; stroke: var(--ink-muted); stroke-width: 1.5; stroke-dasharray: 5 4; }
.chart-subject { fill: none; stroke: var(--ink); stroke-width: 2; stroke-linejoin: round; }
.chart-point   { fill: var(--ink); stroke: var(--bg); stroke-width: 2; }
.chart-point--open { fill: var(--bg); stroke: var(--ink); }

/* Posture categories ---------------------------------------------------------
   Used by the posture and growth-chart figures (tools/motor-figures.py).
   The postures are ordinal — lying to standing — so they share one hue in a
   light-to-dark ramp; carrying is not a posture of the infant's own and is
   neutral grey. Segment labels switch to white on the three dark steps. */
.chart-posture--supine   { fill: #d3e1f7; }
.chart-posture--side     { fill: #afc8ef; }
.chart-posture--prone    { fill: #86aae2; }
.chart-posture--crawl    { fill: #5c89d0; }
.chart-posture--sitting  { fill: var(--brand); }
.chart-posture--standing { fill: var(--brand-dark); }
.chart-posture--carrying { fill: #c9ced6; }
.chart-seg,
.dia-chip  { fill: var(--ink); font-size: 12.5px; font-weight: 600; font-family: var(--font); }
.chart-seg--on-dark,
.dia-chip--on-dark { fill: #fff; }
.dia-label--small  { font-size: 15px; }

/* Garments page -------------------------------------------------------------
   Garment and sensor cards: a thumbnail beside the title, then the specs and
   what the garment measures. .grid--wide gives two roomier columns. */
.grid--wide { grid-template-columns: repeat(auto-fit, minmax(22rem, 1fr)); }
@media (max-width: 30rem) {
  .grid--wide { grid-template-columns: 1fr; }
}
.garment-card__head {
  display: flex;
  gap: 1rem;
  align-items: center;
  margin-bottom: 0.9rem;
}
.garment-card__head h3 { margin: 0 0 0.2rem; }
.garment-card__head .garment-card__summary { margin: 0; color: var(--ink-muted); }
.garment-card__img-link { flex: none; }
.garment-card__img {
  display: block;
  width: 104px;
  height: 104px;
  object-fit: contain;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
}
.garment-card__specs { margin-bottom: 0.9rem; }
.garment-card .eyebrow { margin: 0 0 0.35rem; }
.garment-card__list { padding-left: 1.1rem; margin-bottom: 1rem; }
.garment-card__list li { margin-bottom: 0.2em; }

/* Side-by-side comparison table. */
.compare {
  border-collapse: collapse;
  width: 100%;
  min-width: 34rem;
  font-size: 0.95rem;
}
.compare th,
.compare td {
  padding: 0.65em 0.9em;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
}
.compare thead th {
  border-bottom: 2px solid var(--ink-muted);
  font-size: 1.1rem;
}
.compare tbody th {
  width: 9rem;
  font-weight: 600;
  color: var(--ink-muted);
}
.compare td { width: calc((100% - 9rem) / 2); }

/* A text-only card: the body starts under the heading instead of being pushed
   to the bottom edge (that push is meant for a trailing action link). */
.card--text > p:last-child { margin-top: 0; }

/* On a phone the comparison stacks: one block per row, each value labelled
   with its garment, instead of a table that has to be scrolled sideways. */
@media (max-width: 34rem) {
  .compare { min-width: 0; }
  .compare thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .compare, .compare tbody, .compare tr, .compare th, .compare td { display: block; width: auto; }
  .compare tr { padding: 0.6em 0; border-bottom: 1px solid var(--line); }
  .compare th, .compare td { padding: 0.2em 0; border: 0; }
  .compare tbody th { color: var(--ink); }
  .compare td::before {
    content: attr(data-label);
    display: block;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-muted);
  }
}

/* System diagram (home hero, garments page) ---------------------------------
   Drawn by tools/system-diagram.py in a wide and a narrow version; CSS shows
   one of them, so the lettering stays readable on a phone. */
.dia-swap--narrow { display: none; }
@media (max-width: 34rem) {
  .dia-swap--wide { display: none; }
  .dia-swap--narrow { display: block; }
}
.dia-garment { fill: #dbe8fd; stroke: var(--brand); stroke-width: 2; }
.dia-band    { fill: #a8c9fc; stroke: var(--brand); stroke-width: 2; }
.dia-seam    { stroke: var(--brand); }
.dia-sensor  { fill: var(--ink); stroke: var(--bg); }
.dia-phone   { fill: var(--bg); stroke: var(--ink); stroke-width: 2.5; }
.dia-screen  { fill: var(--brand-tint); }
.dia-appbar  { fill: var(--brand); }
.dia-row     { fill: var(--line); }
.dia-tick    { stroke: var(--accent); }
.dia-record  { fill: var(--brand); }
.dia-record-stop { fill: var(--bg); }
.dia-bracket { stroke: var(--ink-muted); }
.chart-axis  { stroke: var(--ink-muted); }
.dia-note--lg { font-size: 14px; }

/* Products hover panels -----------------------------------------------------
   The two entries in the Products box (Garments, Analytics) open a panel
   listing what is inside that section: products for Garments, analyses grouped
   by garment for Analytics. Built on the same .nav-menu machinery as the
   Resources dropdown — shown on :hover and :focus-within, no JavaScript, and
   only above the breakpoint, where a pointer exists.

   The panel hangs from the link's own <li>, so it opens directly under the
   item that was pointed at; its padding-top is the hover bridge across the
   box's border. */
.nav-group { position: relative; }
.nav-group__item { position: relative; }

.site-nav .nav-panel {
  display: none;
  position: absolute;
  top: 100%;
  left: -0.3rem;
  z-index: 20;
  min-width: 15rem;
  padding-top: 0.5rem;          /* the hover bridge — do not turn into `top` */
}

/* Shared section-block styling. NOTE: no `padding` here — this selector beats
   the plain .nav-panel__title class below, so setting padding in this rule
   would make the title's own padding impossible to change. Each child sets its
   own: the list below, the heading in .nav-panel__title. */
.site-nav .nav-panel > ul,
.site-nav .nav-panel > p {
  display: block;               /* beats `.site-nav ul { display: flex }` */
  margin: 0;
  list-style: none;
  border: 1px solid var(--line);
  border-bottom: 0;
}

.site-nav .nav-panel > ul { padding: 0; }

.site-nav .nav-panel > :first-of-type { border-radius: var(--radius) var(--radius) 0 0; }
.site-nav .nav-panel > :last-child {
  border-bottom: 1px solid var(--line);
  border-radius: 0 0 var(--radius) var(--radius);
}

/* The Resources dropdown draws a border per item; in a sectioned panel the
   border belongs to the section, so turn the per-item one off. */
.site-nav .nav-panel li {
  background: none;
  border: 0;
  border-radius: 0;
}

.site-nav .nav-panel {
  background: var(--bg);
}
.nav-panel__title {
  padding: 0.5rem 0.85rem 0.5rem; /* top | left+right | bottom */
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-muted);
  background: var(--bg-alt);
}

.site-nav .nav-panel a {
  display: block;
  padding: 0.4rem 0.85rem;
  white-space: nowrap;
}
.site-nav .nav-panel a:hover,
.site-nav .nav-panel a:focus-visible { background: var(--brand-tint); color: var(--brand); }
.site-nav .nav-panel a.current { background: var(--brand-tint); }

/* The one-line description under an entry: long enough to say which analysis
   is which, so it is clamped rather than allowed to set the panel's width. */
.nav-panel__note {
  display: block;
  max-width: 19rem;
  font-size: 0.7rem;
  font-weight: 400;
  line-height: 1.15;
  color: var(--ink-muted);
  white-space: normal;
  /* Two lines at most: the note says which item is which, it does not have to
     repeat the whole summary, and a tall menu is hard to point at. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

.nav-panel--wide { min-width: 19rem; }

/* A panel near the right edge of the bar would otherwise run off the page. */
.nav-group__item:last-child .nav-panel { left: auto; right: -0.3rem; }

@media (min-width: 46rem) {
  .site-nav .nav-group__item:hover > .nav-panel,
  .site-nav .nav-group__item:focus-within > .nav-panel { display: block; }
}

/* Sleep states (NAPPA figures, tools/nappa-figures.py) ------------------------
   Wake to deep sleep on the same light-to-dark ramp as the postures: the
   states are ordinal, so one hue, stepped. Activity bars in the arousal
   schematic are neutral until they cross the threshold. */
.chart-state--wake  { fill: #d3e1f7; }
.chart-state--light { fill: #5c89d0; }
.chart-state--deep  { fill: var(--brand-dark); }
.chart-bar          { fill: var(--line); }
.chart-bar--over    { fill: var(--brand); }
.chart-window       { fill: var(--bg); stroke: var(--line); }
.chart-window--on   { fill: var(--brand-dark); }
