/* ─────────────────────────────────────────────────────────────────────────
   RIVET — design language v2, "Bone"

   The product is a board; the page is the bench it sits on. The ground and
   the accent are both dials — see "the two dials" below and
   assets/css/theme.css — and the shipped default is BONE (#f5f6f8) with the
   accent at #ff9838. Nothing here follows prefers-color-scheme: the page is
   whatever the page was built to be, not whatever the visitor's OS says.

   v1 was near-black (#08090b) with copper #e08a45; `substrate` still holds
   those values and the picker still offers them. The page went light so the
   product — which is dark, and stays dark, in the app windows and the 3D
   captures — has something to sit on rather than dissolving into the ground.

   One accent. It is spent on the primary action, on the via ticks that open
   each scene, and on almost nothing else. Green, blue and red on this page
   belong to the renders and to the board editor — they are the app's own
   layer colours, not the brand's.

   TWO typefaces, and width is the device in both.

   DISPLAY IS ANYBODY (SIL OFL, Etcétera). Archivo held this job and the owner's
   note on it was exact: the essence was right and the face was too common — a
   grotesque you have already seen on every second developer-tool page this
   year. Anybody keeps the thing that mattered, a real `wdth` axis running 50 to
   150, and spends it on squared counters and flat terminals that read as
   drawn-to-a-grid rather than as a default. It is the headline face and the
   section labels; it never sets a paragraph.

   TEXT IS ARCHIVO, unchanged. It is a good text face, the site is set in it
   already, and swapping both would have been a redesign rather than a
   correction.

   Monospace appears only where the text is literally machine data: net names,
   counts, filenames, model ids. Never as decoration.
   ───────────────────────────────────────────────────────────────────────── */

@font-face {
  font-family: 'Anybody';
  src: url('../fonts/anybody.woff2') format('woff2');
  font-weight: 100 900;
  font-stretch: 50% 150%;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Anybody';
  src: url('../fonts/anybody-ext.woff2') format('woff2');
  font-weight: 100 900;
  font-stretch: 50% 150%;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Archivo';
  src: url('../fonts/archivo.woff2') format('woff2');
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Archivo';
  src: url('../fonts/archivo-ext.woff2') format('woff2');
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ── the two dials ────────────────────────────────────────────────────────
   Everything on this page is derived from a GROUND (a six-step neutral ramp
   plus its ink) and one ACCENT. Both are stored as bare `R G B` triplets so
   that any of them can be used at an alpha without a second variable, and so
   the picker in assets/js/theme.js only ever has to write two things:
   `--accent-rgb` on :root and `data-ground` on <html>.

   Add a ground by copying a block below and giving it a name; nothing else in
   either stylesheet needs to know it exists. `data-tone` is the one thing a
   rule may branch on — light grounds need the 3D captures put on a dark stage,
   because those captures carry the app's own dark backdrop and no amount of
   CSS makes a photograph of a dark room look like a photograph of a light one.
   ───────────────────────────────────────────────────────────────────────── */

:root {
  --accent-rgb: 255 152 56;   /* #ff9838. The picker overwrites this one line. */
  --on-accent-rgb: 26 14 2;   /* ink ON the accent; the picker flips it by contrast */

  /* the 3D viewer's own backdrop, measured off the captures — see README */
  --stage-top: #16181e;
  --stage-bot: #08080a;
  --stage-fade: var(--void-rgb);   /* light tones point this at the stage instead */
  --plate-shadow-a: .95;
}

/* ── grounds ─────────────────────────────────────────────────────────────── */

[data-ground="substrate"] {                 /* near-black, warm-shifted */
  --void-rgb:   8 9 11;
  --sub-rgb:    11 13 16;
  --card-rgb:   16 19 25;
  --card2-rgb:  21 25 34;
  --line-rgb:   28 33 42;
  --line2-rgb:  42 50 62;
  --fg-rgb:     238 240 243;
  --fg2-rgb:    164 172 184;
  --fg3-rgb:    109 118 131;
  --sheen-rgb:  255 255 255;
  --shadow-rgb: 0 0 0;
  --glow-a: .18;
  --sheen-a: .022;
}

[data-ground="ink"] {                        /* pure black, colder, higher contrast */
  --void-rgb:   0 0 0;
  --sub-rgb:    7 7 8;
  --card-rgb:   13 13 15;
  --card2-rgb:  18 18 21;
  --line-rgb:   28 28 32;
  --line2-rgb:  46 46 52;
  --fg-rgb:     246 246 247;
  --fg2-rgb:    170 170 176;
  --fg3-rgb:    112 112 120;
  --sheen-rgb:  255 255 255;
  --shadow-rgb: 0 0 0;
  --glow-a: .2;
  --sheen-a: .026;
}

[data-ground="paper"] {                      /* warm white, the drawing printed */
  --void-rgb:   248 246 241;
  --sub-rgb:    255 253 249;
  --card-rgb:   255 255 255;
  --card2-rgb:  250 247 241;
  --line-rgb:   226 220 209;
  --line2-rgb:  198 190 176;
  --fg-rgb:     23 21 19;
  --fg2-rgb:    88 84 78;
  --fg3-rgb:    132 126 117;
  --sheen-rgb:  255 255 255;
  --shadow-rgb: 60 48 34;
  --glow-a: .13;
  --sheen-a: .5;
}

/* BONE IS THE SHIPPED GROUND. It leads `:root` so a page renders correctly in
   the half-second before theme.js has written data-ground, and so a browser
   with JS off still gets the real design rather than the old near-black.
   `data-tone="light"` is written into the markup for the same reason. */
:root, [data-ground="bone"] {                /* cool white, flatter, more clinical */
  --void-rgb:   245 246 248;
  --sub-rgb:    255 255 255;
  --card-rgb:   255 255 255;
  --card2-rgb:  247 248 250;
  --line-rgb:   222 226 232;
  --line2-rgb:  194 200 209;
  --fg-rgb:     16 18 23;
  --fg2-rgb:    82 89 100;
  --fg3-rgb:    124 132 144;
  --sheen-rgb:  255 255 255;
  --shadow-rgb: 22 30 48;
  --glow-a: .12;
  --sheen-a: .5;
}

/* ── what the rest of the stylesheet actually uses ───────────────────────── */

:root {
  --void:   rgb(var(--void-rgb));
  --sub:    rgb(var(--sub-rgb));
  --card:   rgb(var(--card-rgb));
  --card-2: rgb(var(--card2-rgb));
  --line:   rgb(var(--line-rgb));
  --line-2: rgb(var(--line2-rgb));

  --fg:   rgb(var(--fg-rgb));
  --fg-2: rgb(var(--fg2-rgb));
  --fg-3: rgb(var(--fg3-rgb));

  --cu:      rgb(var(--accent-rgb));
  --cu-hi:   color-mix(in oklab, var(--cu) 74%, rgb(var(--sheen-rgb)));
  --cu-deep: color-mix(in oklab, var(--cu) 70%, #000);
  --cu-glow: rgb(var(--accent-rgb) / var(--glow-a));
  --cta-ink: rgb(var(--on-accent-rgb));

  /* borrowed from the app's own semantics, used only where they mean it.
     Red is DRC's and nothing else's — it never appears as decoration. */
  --drc: #e0574a;
  --ok:  #59c48d;

  --sans: 'Archivo', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', sans-serif;
  /* Archivo is the fallback rather than a system face: if Anybody has not
     arrived, the headline should still be the site's own grotesque and still
     honour `wdth`, not drop to San Francisco at width 100. */
  --display: 'Anybody', 'Archivo', -apple-system, BlinkMacSystemFont, sans-serif;
  --mono: ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, monospace;

  --maxw: 1300px;
  --gut: clamp(20px, 4vw, 56px);
  --ease: cubic-bezier(.16, 1, .3, 1);
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  background: var(--void);
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  /* Delay has to go as well as duration. The nav panel closes with
     `visibility 0s linear .2s` so the fade has something to fade during;
     with the duration collapsed and the DELAY left in place, the panel looked
     shut while still catching clicks for 200ms. Nothing here is staged for
     effect once motion is off, so zero is right for every delay. */
  *, *::before, *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
    transition-delay: 0s !important;
    animation-delay: 0s !important;
  }
}

body {
  margin: 0;
  background: var(--void);
  color: var(--fg);
  font-family: var(--sans);
  font-variation-settings: 'wdth' 100;
  font-size: 17px;
  line-height: 1.6;
  letter-spacing: -.005em;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Grain. A real film grain, not a texture image: one inline SVG turbulence
   fixed over the whole page at 3.5%. It stops the large flat panels from
   banding on an OLED and it is the single cheapest way to make a dark page
   look printed rather than rendered. */
body::after {
  content: '';
  position: fixed;
  inset: -50%;
  z-index: 9999;
  pointer-events: none;
  opacity: var(--grain-a, .035);
  mix-blend-mode: var(--grain-blend, normal);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23n)'/%3E%3C/svg%3E");
}

img, svg, video, canvas { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
::selection { background: var(--cu); color: var(--cta-ink); }

:focus-visible {
  outline: 2px solid var(--cu);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ── type scale ───────────────────────────────────────────────────────────
   Display runs expanded and tight. The width axis is what makes these read
   as engineered rather than merely large. */

.d1, .d2, .d3 {
  font-family: var(--display);
  /* Anybody's width axis is wider than Archivo's, and 118 in it is a good deal
     more expanded than 118 was — 110 lands where the old headline sat. */
  font-variation-settings: 'wdth' 110;
  font-weight: 600;
  letter-spacing: -.03em;
  line-height: .98;
  margin: 0;
  text-wrap: balance;
}
.d1 { font-size: clamp(2.6rem, 5.4vw, 4.9rem); }
.d2 { font-size: clamp(1.9rem, 3.3vw, 3.1rem); line-height: 1.04; }
.d3 { font-size: clamp(1.45rem, 2.5vw, 2.1rem); letter-spacing: -.022em; line-height: 1.1; }

/* The label device: condensed, caps, sans. Never monospace — a mono caps
   eyebrow is the single most overused "make it look designed" move there is,
   and it reads as exactly that. Width does the work here instead. */
.label {
  font-family: var(--display);
  font-variation-settings: 'wdth' 68;
  font-weight: 640;
  font-size: 12px;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--fg-3);
  margin: 0;
}

.lede {
  font-size: clamp(1.05rem, 1.5vw, 1.32rem);
  line-height: 1.5;
  color: var(--fg-2);
  letter-spacing: -.012em;
  max-width: 44ch;
  margin: 0;
}
.lede b, .body b { color: var(--fg); font-weight: 600; }
.body { color: var(--fg-2); margin: 0; max-width: 56ch; }

.data { font-family: var(--mono); font-size: .82em; letter-spacing: -.01em; }

/* ── shell ───────────────────────────────────────────────────────────────── */

.wrap { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 var(--gut); }
.bleed { width: 100%; padding: 0 var(--gut); }

section { position: relative; }
.scene { padding: clamp(72px, 8vw, 124px) 0; }

/* A scene opens with a hairline and a via: an annular ring with a drilled
   centre, which is the one piece of board vocabulary small enough to use as
   punctuation. */
.rule {
  display: flex;
  align-items: center;
  gap: 14px;
  padding-bottom: clamp(28px, 4vw, 54px);
  border-top: 1px solid var(--line);
  padding-top: 20px;
  position: relative;
}
.rule::before {
  content: '';
  position: absolute;
  top: -4.5px;
  left: 0;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--void);
  border: 2px solid var(--cu);
}
.rule .label { padding-left: 22px; }
.rule .label + .label { margin-left: auto; padding-left: 0; color: var(--line-2); }

/* ── nav ─────────────────────────────────────────────────────────────────── */

/* `body > nav`, NOT a bare `nav`. A bare element selector for one specific
   component is a landmine in a site that also uses <nav> semantically: the
   docs sidebar and the on-this-page list are both <nav>, and they inherited
   `position: fixed; height: 62px` from here — which laid the whole docs
   sidebar out across the top of the window, on top of the real bar. The
   footer already had a `footer nav` reset patching the same wound; scoping to
   a direct child of body fixes the class of bug instead of the instances.
   Every page in this site opens with the bar as the first child of <body>. */
body > nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  height: 62px;
  display: flex;
  align-items: center;
  transition: background .4s var(--ease), border-color .4s var(--ease);
  border-bottom: 1px solid transparent;
}
body > nav.stuck {
  background: rgb(var(--void-rgb) / .78);
  backdrop-filter: saturate(160%) blur(18px);
  -webkit-backdrop-filter: saturate(160%) blur(18px);
  border-bottom-color: var(--line);
}
body > nav .wrap { display: flex; align-items: center; justify-content: space-between; gap: 20px; }

.brand { display: flex; align-items: center; gap: 9px; }
.brand svg { width: 21px; height: auto; color: var(--fg); }
.brand span {
  font-family: var(--display);
  font-variation-settings: 'wdth' 104;
  font-weight: 660;
  letter-spacing: -.02em;
  font-size: 16.5px;
}
.brand span i { font-style: normal; color: var(--fg-3); font-weight: 600; }

.navlinks { display: flex; align-items: center; gap: 26px; }
/* :not(.cta) matters — a bare `.navlinks a` is more specific than `.cta` and
   was quietly repainting the download button's ink to the muted grey. */
.navlinks a:not(.cta) {
  font-size: 14px; color: var(--fg-3); font-weight: 500;
  transition: color .22s var(--ease);
}
.navlinks a:not(.cta):hover { color: var(--fg); }
@media (max-width: 720px) { .navlinks a:not(.cta) { display: none; } }

/* Sign in. It survives further down than the other bar links do, because on a
   phone it is the only way a subscriber reaches their account at all — the
   drawer holds the marketing pages, not this. It goes at 480px, where the
   brand and the Download pill have used the width up. */
.navlinks a.signin { font-size: 14px; font-weight: 520; color: var(--fg-2); }
.navlinks a.signin:hover { color: var(--fg); }
@media (max-width: 720px) { .navlinks a.signin { display: inline; } }
@media (max-width: 480px) { .navlinks a.signin { display: none; } }

/* ── nav menu ─────────────────────────────────────────────────────────────
   Centre column of links, two of which open a panel.

   THE OPEN STATE IS `aria-expanded="true"` ON THE TRIGGER, AND NOTHING ELSE.
   It used to be `:hover, :focus-within`, with no script anywhere on the nav —
   so the panel could be visibly open while the button still said
   `aria-haspopup` and no `aria-expanded` at all. A screen reader was told
   nothing had happened; Escape did nothing; a click did nothing. Hover now
   goes through assets/js/rivet.js, which sets the same attribute the keyboard
   sets, so THE PICTURE AND THE ANNOUNCEMENT ARE THE SAME BIT. They cannot
   drift, because there is only one of them. Do not add a `:hover` rule that
   opens a panel — it would reintroduce exactly the state this replaced.

   The trigger keeps a transparent bridge under it (::after) so the pointer can
   cross the gap into the panel without it closing underneath. That bridge is
   the entire reason this pattern usually feels broken elsewhere. */

.navmid {
  display: flex;
  align-items: center;
  gap: 4px;
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
}

.navitem { position: relative; }
.navitem > a, .navitem > button {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 34px;
  padding: 0 11px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  font: inherit;
  font-size: 14px;
  font-weight: 520;
  letter-spacing: -.008em;
  color: var(--fg-2);
  cursor: pointer;
  transition: color .2s var(--ease), background .2s var(--ease);
}
.navitem > a:hover, .navitem > button:hover,
.navitem > [aria-expanded="true"] { color: var(--fg); }
.navitem > button svg { width: 9px; opacity: .55; transition: transform .25s var(--ease); }
.navitem > [aria-expanded="true"] svg { transform: rotate(180deg); }

/* A keyboard user has to be able to see where they are. The bar is small and
   dark-on-light, so the ring is the accent rather than the browser default. */
.navtrig:focus-visible,
.navmenu a:focus-visible,
.navitem > a:focus-visible,
.navburger:focus-visible {
  outline: 2px solid var(--cu);
  outline-offset: 2px;
  border-radius: 8px;
}

.navitem.has-menu::after {          /* the bridge */
  content: '';
  position: absolute;
  left: 0; right: 0; top: 100%;
  height: 14px;
}

.navmenu {
  position: absolute;
  top: calc(100% + 12px);
  left: 50%;
  min-width: 268px;
  padding: 7px;
  border-radius: 14px;
  border: 1px solid var(--line);
  background: rgb(var(--sub-rgb) / .93);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  box-shadow: 0 22px 48px -22px rgb(var(--shadow-rgb) / .3), 0 2px 8px -3px rgb(var(--shadow-rgb) / .16);
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, -6px);
  /* `visibility 0s linear .2s`, NOT `visibility .2s`. A transitioned
     visibility stays `hidden` for the whole duration, and AN ELEMENT THAT IS
     visibility:hidden CANNOT TAKE FOCUS — so pressing ArrowDown on the
     trigger opened the panel and then failed to move focus into it, silently,
     because .focus() on a hidden element is a no-op. The second press worked,
     which is the kind of bug a keyboard user reports as "it needs two
     presses" and a mouse user never sees at all.
     Zero delay on the way in, .2s on the way out, so the panel is focusable
     the instant it opens and still gets to fade when it closes. */
  transition: opacity .2s var(--ease), transform .24s var(--ease), visibility 0s linear .2s;
}
.navtrig[aria-expanded="true"] + .navmenu {
  opacity: 1; visibility: visible; transform: translate(-50%, 0);
  transition-delay: 0s;
}

.navmenu a {
  display: block;
  padding: 9px 11px;
  border-radius: 9px;
  transition: background .16s var(--ease);
}
.navmenu a:hover { background: rgb(var(--fg-rgb) / .05); }
.navmenu a strong {
  display: block;
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: -.014em;
  color: var(--fg);
}
.navmenu a span {
  display: block;
  margin-top: 1px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--fg-3);
}
.navmenu a em {
  font-style: normal;
  margin-left: 6px;
  font-size: 10px;
  font-weight: 620;
  letter-spacing: .03em;
  text-transform: uppercase;
  color: var(--cu-deep);
  vertical-align: 1px;
}

/* ── the Product mega-menu ────────────────────────────────────────────────
   A picture per surface, because "Board layout" and "3D & fabrication" are
   two words each and the difference between them is entirely visual. The
   thumbnails are real captures cut down to 480px in assets/nav/ rather than
   the full-size shots — a 700 KB screenshot behind a closed menu is a tax on
   every page load for something most visitors never open.

   NOTE FOR THE RESOLUTION GATE: tools/check-image-resolution.js skips any
   image whose computed visibility is hidden, which every one of these is
   until the menu opens — so it CANNOT measure them and they are not in its
   count. They are cut at 480px against a 152px slot (3.1x) deliberately,
   because nothing is watching. If the slot ever grows past 240px, that is
   below the 2x floor with no gate to say so. */
.navmenu.mega {
  min-width: 0;
  width: min(900px, calc(100vw - 48px));
  padding: 16px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 248px;
  gap: 18px;
}
.mega-h { margin: 0 0 10px 4px; }
.mega-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.navmenu.mega .mega-card { padding: 7px; }
.navmenu.mega .mega-shot {
  display: block;
  aspect-ratio: 16 / 10;
  border-radius: 7px;
  overflow: hidden;
  border: 1px solid var(--line);
  background: rgb(var(--fg-rgb) / .04);
  margin-bottom: 9px;
}
.navmenu.mega .mega-shot img { display: block; width: 100%; height: 100%; object-fit: cover; }
.navmenu.mega .mega-card strong { display: block; font-size: 13.5px; font-weight: 600; letter-spacing: -.014em; color: var(--fg); }
.navmenu.mega .mega-card span { display: block; margin-top: 3px; font-size: 12px; line-height: 1.45; color: var(--fg-3); }
.navmenu.mega .mega-card strong em {
  font-style: normal; margin-left: 6px; font-size: 10px; font-weight: 620;
  letter-spacing: .03em; text-transform: uppercase; color: var(--cu-deep); vertical-align: 1px;
}
.navmenu.mega .mega-card:hover, .navmenu.mega .mega-feat:hover, .navmenu.mega .mega-list a:hover { background: rgb(var(--fg-rgb) / .05); }
.navmenu.mega .mega-card, .navmenu.mega .mega-feat, .navmenu.mega .mega-list a { border-radius: 9px; transition: background .16s var(--ease); }

.mega-rail {
  display: flex;
  flex-direction: column;
  border-left: 1px solid var(--line);
  padding-left: 18px;
}
.navmenu.mega .mega-feat { display: block; padding: 7px; margin-bottom: 16px; }
.navmenu.mega .mega-feat strong { display: block; font-size: 13.5px; font-weight: 600; letter-spacing: -.014em; color: var(--fg); }
.navmenu.mega .mega-feat span { display: block; margin-top: 3px; font-size: 12px; line-height: 1.45; color: var(--fg-3); }
.mega-list { display: flex; flex-direction: column; }
.navmenu.mega .mega-list a { padding: 7px 9px; font-size: 13px; font-weight: 520; color: var(--fg-2); }
.navmenu.mega .mega-list a:hover { color: var(--fg); }
.navmenu.mega .mega-list a em {
  font-style: normal; margin-left: 6px; font-size: 10px; font-weight: 620;
  letter-spacing: .03em; text-transform: uppercase; color: var(--cu-deep);
}

/* ── the burger, and the drawer it opens ──────────────────────────────────
   Below 1000px `.navmid` was `display: none` and there was no other control —
   Product, Docs, Pricing and Resources simply did not exist on a phone. The
   SAME `.navmid` is the drawer now, so there is no second copy of the links
   to fall out of step with the first. */
.navburger {
  display: none;
  width: 34px; height: 34px;
  padding: 0 7px;
  border: 0; border-radius: 9px;
  background: transparent;
  cursor: pointer;
  flex-direction: column; justify-content: center; gap: 4px;
}
.navburger span {
  display: block; height: 1.5px; width: 100%;
  background: var(--fg); border-radius: 2px;
  transition: transform .26s var(--ease), opacity .18s var(--ease);
}
.navburger[aria-expanded="true"] span:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
.navburger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.navburger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-5.5px) rotate(-45deg); }

.navscrim {
  position: fixed; inset: 0; z-index: 98;
  background: rgb(var(--shadow-rgb) / .34);
  opacity: 0; transition: opacity .28s var(--ease);
}
.navscrim.on { opacity: 1; }

@media (max-width: 1000px) {
  .navburger { display: flex; }

  .navmid {
    position: fixed;
    inset: 62px 0 0 auto;
    z-index: 99;
    width: min(370px, 88vw);
    transform: translateX(100%);
    left: auto;
    display: block;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 14px 16px 40px;
    background: var(--sub);
    border-left: 1px solid var(--line);
    transition: transform .3s var(--ease);
    overscroll-behavior: contain;
  }
  body.nav-open .navmid { transform: translateX(0); }
  /* Closed drawer must be unreachable by Tab, not merely off-screen. */
  body:not(.nav-open) .navmid { visibility: hidden; }

  .navitem { border-bottom: 1px solid var(--line); }
  .navitem:last-child { border-bottom: 0; }
  .navitem > a, .navitem > .navtrig {
    width: 100%; height: 46px; padding: 0 6px;
    border-radius: 0; font-size: 15.5px; font-weight: 560;
    justify-content: space-between;
  }
  .navitem.has-menu::after { display: none; }

  /* The panel becomes an accordion in flow. Same attribute, same bit. */
  .navmenu, .navmenu.mega {
    position: static;
    width: auto; min-width: 0;
    transform: none;
    padding: 0 0 10px;
    border: 0; background: none; box-shadow: none;
    backdrop-filter: none; -webkit-backdrop-filter: none;
    display: none;
    grid-template-columns: 1fr;
  }
  .navtrig[aria-expanded="true"] + .navmenu { display: block; transform: none; }

  .navmenu.mega .mega-cards { grid-template-columns: 1fr 1fr; gap: 4px; }
  /* .mega-shot is also a <span>, so put it back after hiding the blurb. */
  .navmenu.mega .mega-card span { display: none; }
  .navmenu.mega .mega-card .mega-shot { display: block; }
  /* The tag orphans onto its own line in a 153px card; the Download row in
     the Resources list below already says it. */
  .navmenu.mega .mega-card strong em { display: none; }
  .mega-rail { border-left: 0; border-top: 1px solid var(--line); padding: 14px 0 0; margin-top: 12px; }
  .navmenu.mega .mega-feat { display: none; }   /* the drawer is a way through, not a shop window */
  .mega-h { margin-top: 4px; }
}

/* ── buttons ─────────────────────────────────────────────────────────────── */

/* SMALLER THAN THEY WERE. These were 52 px tall with 15.5 px type sitting
   directly under a 5.4 rem headline, and the owner's read was that the pair
   dominated the fold. They are the primary action, not the loudest object on
   the page — the product below them is. Linear, Vercel and Cursor all land
   between 38 and 44; this is 44. */
.cta {
  --h: 44px;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  height: var(--h);
  padding: 0 22px;
  border-radius: 999px;
  background: var(--cu);
  color: var(--cta-ink);
  font-weight: 630;
  font-size: 14.5px;
  letter-spacing: -.012em;
  overflow: hidden;
  isolation: isolate;
  box-shadow: 0 1px 0 rgb(var(--sheen-rgb) / .22) inset, 0 10px 34px -12px var(--cu-glow);
  transition: transform .22s var(--ease), box-shadow .3s var(--ease), background .3s var(--ease);
}
/* The sheen is a real light source moving across a metal face, not a
   generic shimmer: it runs once on hover, in the CTA's own copper. */
.cta::after {
  content: '';
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(100deg, transparent 30%, rgb(var(--sheen-rgb) / .5) 50%, transparent 70%);
  transform: translateX(-120%);
  transition: transform .62s var(--ease);
}
.cta:hover { background: var(--cu-hi); transform: translateY(-1px); box-shadow: 0 1px 0 rgb(var(--sheen-rgb) / .3) inset, 0 16px 44px -14px var(--cu-glow); }
.cta:hover::after { transform: translateX(120%); }
.cta:active { transform: translateY(0); }
.cta.sm { --h: 34px; padding: 0 16px; font-size: 13.5px; }

.ghost {
  display: inline-flex; align-items: center; gap: 8px;
  height: 44px; padding: 0 20px;
  border-radius: 999px;
  border: 1px solid var(--line-2);
  color: var(--fg-2);
  font-weight: 560; font-size: 14.5px;
  transition: border-color .25s var(--ease), color .25s var(--ease), background .25s var(--ease);
}
.ghost:hover { border-color: var(--fg-3); color: var(--fg); background: rgb(var(--fg-rgb) / .04); }
.ghost .arw { transition: transform .3s var(--ease); }
.ghost:hover .arw { transform: translateX(3px); }

.acts { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.under { font-size: 13.5px; color: var(--fg-3); margin: 0; line-height: 1.55; }
.under a { color: var(--fg-2); border-bottom: 1px solid var(--line-2); }
.under a:hover { color: var(--cu-hi); border-color: var(--cu-deep); }

/* ── reveal ──────────────────────────────────────────────────────────────── */

.rv { opacity: 0; transform: translateY(20px); }
.rv.in {
  opacity: 1; transform: none;
  transition: opacity .8s var(--ease), transform .8s var(--ease);
}
.rv.r1 { transition-delay: .07s; }
.rv.r2 { transition-delay: .14s; }
.rv.r3 { transition-delay: .21s; }
.rv.r4 { transition-delay: .28s; }
@media (prefers-reduced-motion: reduce) { .rv { opacity: 1; transform: none; } }

/* ── footer ──────────────────────────────────────────────────────────────── */

footer { border-top: 1px solid var(--line); padding: 56px 0 44px; }
footer .wrap { display: flex; flex-wrap: wrap; gap: 32px 60px; justify-content: space-between; }
footer .label { color: var(--line-2); }
footer nav { position: static; height: auto; display: block; border: 0; }
.fcol { display: flex; flex-direction: column; gap: 9px; font-size: 14px; }
.fcol a { color: var(--fg-3); transition: color .2s var(--ease); }
.fcol a:hover { color: var(--fg); }
