/* ============================================================
   mZero: shared design layer
   Loaded AFTER each page's inline <style>, so this file is
   authoritative. Page files must not redefine anything here:
   tokens, page shell, header, footer, buttons, focus, type scale.
   ============================================================ */

/* iOS Safari inflates text in some containers on rotation unless this is
   pinned; without it a landscape iPhone can reflow mid-page. */
html{-webkit-text-size-adjust:100%;text-size-adjust:100%}

/* Brand typefaces are served locally so first render does not wait on a
   third-party font host. System fallbacks remain in the stacks below. */
@font-face{font-family:"IBM Plex Mono";src:url("../fonts/IBMPlexMono-Regular-Latin1-v2.5.0.woff2") format("woff2");font-weight:400;font-style:normal;font-display:swap;unicode-range:U+0020-007E,U+00A0-00FF,U+0131,U+0152-0153,U+02C6,U+02DA,U+02DC,U+2013-2014,U+2018-201A,U+201C-201E,U+2020-2022,U+2026,U+2030,U+2039-203A,U+2044,U+20AC,U+2122,U+2212,U+FB01-FB02}
@font-face{font-family:"Neue Haas Grotesk Display Pro";src:url("../fonts/HaasGrotDispR-45Light.woff2") format("woff2");font-weight:200 300;font-style:normal;font-display:swap}
@font-face{font-family:"Neue Haas Grotesk Display Pro";src:url("../fonts/HaasGrotDispR-55Roman.woff2") format("woff2");font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"Neue Haas Grotesk Display Pro";src:url("../fonts/HaasGrotDispR-65Medium.woff2") format("woff2");font-weight:500 600;font-style:normal;font-display:swap}
@font-face{font-family:"Neue Haas Grotesk Display Pro";src:url("../fonts/HaasGrotDispR-75Bold.woff2") format("woff2");font-weight:700;font-style:normal;font-display:swap}

:root{
  /* Four brand colours, and nothing outside them. The ground is the light
     grey, the ink is the near-black, the forest carries every accent, and the
     sage is the one quiet fill. Each step below is either one of the four or a
     blend of two of them -- no fifth hue enters the page. */
  --brand-ink:#101010;
  --brand-ground:#dbdbdd;
  --brand-forest:#55685a;
  --brand-sage:#9ca49d;

  /* Surface */
  --bg:var(--brand-ground);
  /* The accent thinned .16 over the ground -- the same step the homepage's
     goal cards and terminal window sit on, so a panel is one colour sitewide. */
  --panel:#c6c9c8;
  --ink:var(--brand-ink);
  /* The three quiet steps run ink -> forest rather than ink -> grey, so text
     that weakens also warms toward the accent instead of going flat. Contrast
     on the ground: 7.5:1, 5.3:1, 4.3:1. */
  --dim:#3a423c;
  --mut:#4b5a4e;
  --muted:var(--brand-forest);

  /* One hairline. Ink at low alpha, the inverse of the white it was on dark. */
  --line:rgba(16,16,16,.13);
  --line-strong:rgba(16,16,16,.24);

  --accent:var(--brand-forest);
  /* What sits on the accent. The palette pairs the forest with the light grey,
     so bands and large accent type use it at 4.3:1 -- fine above 24px, which is
     the only size this pairing is used at. Small controls do not use it: the
     forest is a mid-tone, so both black (4.1:1) and light grey (4.3:1) sit too
     close to it for 14px type. Buttons take --btn-* below instead. */
  --accent-ink:var(--brand-ground);
  --accent-hover:#46564a;
  /* Primary controls: near-black ground, light-grey label, 13.8:1. The two ends
     of the palette, which is the only pairing in it that carries small type. */
  --btn-bg:var(--brand-ink);
  --btn-ink:var(--brand-ground);
  --btn-bg-hover:#262a27;
  --link-underline:rgba(85,104,90,.45);
  /* Darkened to carry on a light ground at 5.9:1; the dark theme's #ff8585 was
     drawn to sit on black and washes out here. */
  --error:#8c2f2f;
  --error-tint:rgba(140,47,47,.09);

  --mono:"IBM Plex Mono", ui-monospace, monospace;
  --sans:"Neue Haas Grotesk Display Pro","Neue Haas Grotesk Text Pro","Haas Grotesk","Helvetica Neue",Helvetica,Arial,sans-serif;

  /* Page shell: every page uses this measure and gutter */
  --shell:1240px;
  --col:900px;      /* the reading column inside the shell */
  --gutter:28px;
  --header-h:64px;
  /* Offset for anything that sticks below the sticky page header */
  --stick:calc(var(--header-h) + 24px);

  /* Type scale */
  --fs-display:clamp(36px,5vw,64px);   /* page h1 + major section h2 */
  --fs-section:clamp(34px,4.5vw,56px); /* feature h2 */
  --fs-sub:clamp(22px,2.4vw,28px);     /* h3 in prose */
  /* Scaled with --fs-body when it went 15px to 18px. The small end had been set
     against a 15px body, so leaving it put opened a gap the scale was never
     drawn with: captions and mono labels sat a third under the prose instead of
     a step under it, and the lede was a 2px step above body rather than a real
     one. Each is the old value times roughly 1.2, the same move body made. */
  --fs-lede:22px;      /* was 20 */
  --fs-body:18px;      /* was 15 */
  --fs-small:16px;     /* was 13.5 */
  --fs-micro:15px;     /* was 13 */
  --fs-label:12px;     /* was 10 */

  --ease:cubic-bezier(.4,0,.2,1);
}

@media(max-width:720px){
  :root{--gutter:16px}
}

/* Smooth scrolling is scoped to :focus-within so it applies to in-page anchor
   clicks but not to the initial load. scroll-behavior:smooth on the root
   suppresses the browser's own #fragment jump when the page reflows during
   font loading, which left every deep link stranded at the top of the page. */
@media (prefers-reduced-motion: no-preference){
  html:focus-within{scroll-behavior:smooth}
}
@media (prefers-reduced-motion: reduce){
  html,html:focus-within{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;transition-duration:.001ms !important}
}

body{
  margin:0;
  background:
    radial-gradient(1000px 520px at 50% -10%, rgba(85,104,90,.07), transparent 55%),
    var(--bg);
  color:var(--ink);
  font-family:var(--sans);
  font-size:var(--fs-body);
  line-height:1.65;
  -webkit-font-smoothing:antialiased;
}
::selection{background:var(--accent);color:var(--bg)}
.sr-only{
  position:absolute!important;width:1px!important;height:1px!important;padding:0!important;
  margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;
  white-space:nowrap!important;border:0!important;
}
.skip-link{
  position:fixed;left:var(--gutter);top:10px;z-index:1000;
  padding:10px 14px;border-radius:6px;
  background:var(--accent);color:var(--accent-ink);
  font-family:var(--sans);font-size:14px;font-weight:500;text-decoration:none;
  transform:translateY(calc(-100% - 18px));
  transition:transform .16s var(--ease);
}
.skip-link:focus{transform:translateY(0);outline:2px solid var(--ink);outline-offset:2px}

/* ------------------------------------------------------------
   Page shell
   Header, main and footer all resolve to the same left edge.
   The header/footer rules stay full-bleed; their CONTENT aligns
   with the content column via the padding formula below.
   ------------------------------------------------------------ */
.shell,
header,
/* The rule runs the full width of the viewport; the content inside it sits in
   the same reading column as the page above, rather than out on the shell
   gutter 142px to its left. Footer is full-width, so here the centring maths
   is correct -- see .mz-form-page for why it is not correct on `main`. */
footer{
  padding-inline:max(var(--gutter), calc((100% - var(--col)) / 2));
}

/* The shell is one column: header, a single content element, footer. On a page
   with little in it -- login, onboarding -- the footer used to stop where the
   content stopped and float mid-viewport with the background running on below
   it. A minimum height on the body plus an auto top margin on the footer sits
   it on the bottom edge instead. Long pages are untouched: an auto margin only
   absorbs space that is left over, and past one viewport there is none.

   Scoped to bodies that carry a footer, which is every page but atlas.html and
   community-model.html -- those two are full-viewport app shells at
   height:100vh with overflow:hidden, and have no footer to push. The scoped
   footer selector also has to outrank `footer{margin:0}` further down. */
body:has(> footer){
  min-height:100vh;
  min-height:100dvh;
  display:flex;flex-direction:column;
}
body:has(> footer) > footer{margin-top:auto}

/* A column flex container stretches its items across the cross axis only while
   their inline margins are not auto -- and `main` below, plus docs.html's
   .layout, centre themselves with margin:0 auto. So they stopped stretching and
   fell back to fit-content, which never resolves below min-content: privacy.html
   holds a table with min-width:460px inside an overflow-x:auto wrapper, so its
   min-content is 492px and `main` took 492px on a 375px phone. The wrapper then
   had all the room it needed and never scrolled, so the whole page scrolled
   sideways instead and the right edge of every paragraph was cut off, on every
   phone size. A definite width restores block behaviour; max-width still caps
   these and the auto margins still centre them. min-width:0 is NOT the fix --
   flexbox's automatic minimum size applies to the main axis, which is vertical
   here. The skip link is left out on purpose: it is position:fixed, and a width
   would stretch it across the viewport when focused.

   box-sizing is spelled out rather than assumed: careers.html is the one page
   with no global border-box reset and this file sets none, so there the width
   landed outside the gutter padding and pushed the page 32px wide at every
   phone size. */
body:has(> footer) > header,
body:has(> footer) > main,
body:has(> footer) > footer,
body:has(> footer) > .layout{width:100%;box-sizing:border-box}

main{
  /* Pages with a narrower reading measure set --measure in their own
     :root. They cannot override `main` directly. This file loads last. */
  max-width:var(--measure, var(--shell));
  width:100%;min-width:0;box-sizing:border-box;
  margin:0 auto;
  padding-inline:var(--gutter);
  /* One vertical rhythm for interior pages. index.html opens with a
     full-viewport hero and resets this to 0. */
  padding-block:clamp(64px,9vh,88px) clamp(96px,14vh,120px);
}

/* An inner reading measure: narrow prose/forms nest INSIDE the
   shell so the shell edge never moves between pages. */
.measure-prose{max-width:760px}
.measure-form{max-width:520px;margin-inline:auto}
.measure-wide{max-width:960px}

/* ------------------------------------------------------------
   Header
   ------------------------------------------------------------ */
header{
  position:sticky;top:0;z-index:50;
  height:64px;
  /* Never let the header absorb a layout squeeze. about.html is a column flex
     body with html,body{height:100%}, so the container's height is definite; when
     the statement runs taller than the viewport the flex algorithm shrinks every
     shrinkable item to compensate, and this height:64px collapsed to 22px -- the
     nav's own min-content -- while every other page kept 64. The footer survived
     only because its height comes from padding, which cannot shrink past
     min-content. flex-shrink:0 fixes it here rather than on that one page, so the
     next page to adopt a flex body does not rediscover it. */
  flex-shrink:0;
  display:flex;align-items:center;justify-content:center;
  gap:clamp(16px,2.4vw,34px);
  border-bottom:1px solid var(--line);
  background:rgba(219,219,221,.88);
  backdrop-filter:blur(10px);
  -webkit-backdrop-filter:blur(10px);
  max-width:none;margin:0;
}

/* Wordmark + links matched to the homepage topbar: centred, mono, caps, mint. */
.wm{
  display:flex;align-items:center;gap:9px;
  font-family:var(--mono);font-size:12.5px;letter-spacing:.19em;text-transform:uppercase;
  color:var(--accent);text-decoration:none;
}
/* Matched to .foot-mark. The same mark reading one size in the header and
   another in the footer made the page look like it had two logos. */
.wm svg{height:16px;width:auto;display:block}
/* Same single fill as .foot-mark: the accent, with the page showing through
   the counter and the slash. */
.wm .mark-body{fill:var(--accent)}

header nav{display:flex;align-items:center;gap:clamp(18px,2.3vw,32px);flex-wrap:wrap}
header nav a{
  font-family:var(--mono);font-size:12.5px;letter-spacing:.15em;text-transform:uppercase;
  color:var(--ink);text-decoration:none;transition:color .16s var(--ease);width:max-content;
}
header nav a sup{
  position:relative;top:-.42em;margin-left:.16em;font-size:.58em;line-height:0;
  letter-spacing:0;color:currentColor;opacity:.72;
}
header nav a:hover{color:var(--accent)}
header nav a[aria-current="page"]{color:var(--accent)}

/* Hamburger toggle: hidden on desktop, shown on mobile. */
.nav-toggle{
  display:none;width:44px;height:44px;margin-right:-10px;
  flex-direction:column;align-items:center;justify-content:center;gap:5px;
  background:none;border:0;cursor:pointer;color:var(--ink);
}
.nav-toggle span{display:block;width:20px;height:1.5px;background:currentColor;border-radius:2px;
  transition:transform .22s var(--ease),opacity .18s var(--ease)}
header.nav-open .nav-toggle span:nth-child(1){transform:translateY(6.5px) rotate(45deg)}
header.nav-open .nav-toggle span:nth-child(2){opacity:0}
header.nav-open .nav-toggle span:nth-child(3){transform:translateY(-6.5px) rotate(-45deg)}

/* Privacy link for the full-viewport atlas pages. They lock body scroll and run
   a three-column app to the bottom of the window, so the site footer -- which is
   where every other page offers the privacy policy -- has nowhere to sit. They
   are published and reachable, so the offer still has to be made.
   Pinned to the header rather than added to the nav: the primary navigation is
   exactly four links on every page, asserted in test/site-navigation.test.js, and
   a fifth would break it. Absolute, so it leaves the header's centred flex row
   alone. The left edge is clear at every width -- the wordmark and nav sit in the
   centre on desktop, and below 720px the wordmark hides while the hamburger goes
   right. Only pages carrying the markup show it. */
.privacy-note{
  position:absolute;left:clamp(14px,2vw,26px);top:50%;transform:translateY(-50%);
  font-family:var(--mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--mut);text-decoration:none;white-space:nowrap;
}
.privacy-note:hover{color:var(--ink)}
.privacy-note:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:2px}

@media(max-width:720px){
  .nav-toggle{display:inline-flex}
  /* The wordmark stays. It is the only link back to index.html on every inner
     page -- the four nav links do not include home and the footer's "mZero" is a
     span, not an anchor -- so hiding it here left mobile visitors with no route
     to the homepage at all. Wordmark left, hamburger right; the nav panel is
     absolutely positioned, so it is unaffected by the change of justification. */
  header{justify-content:space-between}
  /* The mark itself is 24x22, well under the 44px touch minimum, and it is now
     the only way home. Padding grows the tap target without changing how the mark
     looks; the negative inline margin pulls the visual edge back onto the gutter
     so the header still reads as aligned. */
  .wm{padding:13px;margin-inline:-13px}
  /* Tracks .foot-mark's stacked size, on the same breakpoint, so header and
     footer stay one mark at every width. */
  .wm svg{height:22px}
  header nav{
    position:absolute;top:calc(100% + 10px);left:var(--gutter);right:var(--gutter);z-index:49;
    flex-direction:column;align-items:stretch;gap:2px;
    padding:8px 6px 12px;
    background:var(--panel);border:1px solid var(--line);border-radius:12px;
    box-shadow:0 24px 44px rgba(16,16,16,.20);
    opacity:0;visibility:hidden;transform:translateY(-8px);
    transition:opacity .2s var(--ease),transform .2s var(--ease),visibility .2s;
  }
  header.nav-open nav{opacity:1;visibility:visible;transform:none}
  header nav a{padding:13px 14px;font-size:16px}
  .privacy-note{left:50%;transform:translate(-50%,-50%)}
}

/* Coarse-pointer tablets keep the compact desktop header, but each link still
   needs a full touch target. Padding expands the hit area without changing the
   type or switching a wide tablet to the phone menu. */
@media (pointer:coarse) and (min-width:721px){
  header nav a{display:inline-flex;align-items:center;min-height:44px;padding-inline:8px}
}

/* ------------------------------------------------------------
   Buttons: one system.
   `.button` is the portal's class name, aliased here so the signed-in
   workspace uses the same geometry as the public site.
   ------------------------------------------------------------ */
.btn,.button{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:44px;height:44px;padding:0 22px;
  /* The same 8px as .mz-control below. These were a full pill, which read as a
     different family from the fields they sit under -- a 42px-tall pill is a
     21px radius against the field's 8px, directly beneath it on every form.
     login.html's own .login-btn was already drawn at 8px. */
  border-radius:8px;
  font-family:var(--sans);font-size:14px;font-weight:500;
  text-decoration:none;border:none;cursor:pointer;
  box-shadow:0 0 0 1px rgba(16,16,16,.10);
  transition:transform .12s var(--ease),background-color .18s var(--ease),
             color .18s var(--ease),box-shadow .18s var(--ease);
}
.btn:hover,.button:hover{
  box-shadow:0 0 0 1px rgba(16,16,16,.16), 0 10px 28px rgba(16,16,16,.14);
}
.btn:active,.button:active{transform:scale(.98)}
.btn:disabled,.button:disabled{cursor:not-allowed;opacity:.45;transform:none}

.btn-primary{background:var(--btn-bg);color:var(--btn-ink)}
.btn-primary:hover{background:var(--btn-bg-hover);color:var(--btn-ink)}
.btn-secondary,.button{background:rgba(16,16,16,.05);color:var(--ink);box-shadow:0 0 0 1px var(--line)}
.btn-secondary:hover,.button:hover{background:rgba(16,16,16,.09)}
.button.primary{background:var(--btn-bg);color:var(--btn-ink);box-shadow:0 0 0 1px rgba(16,16,16,.10)}
.button.primary:hover:not(:disabled){background:var(--btn-bg-hover);color:var(--btn-ink)}

/* ------------------------------------------------------------
   Focus: one visible ring everywhere, keyboard only
   ------------------------------------------------------------ */
:where(a,button,summary,[tabindex]):focus-visible{
  outline:2px solid var(--accent);
  outline-offset:3px;
  border-radius:4px;
}
main[tabindex="-1"]:focus{outline:none}

/* Underlined text links use the Careers email treatment everywhere: mint text,
   a quiet mint rule at rest, a full-strength rule on hover, and the shared
   keyboard-focus ring above. Component/button/navigation links remain in their
   own systems and are deliberately not selected here. */
.shot figcaption a,
.statement .source a,
.support a,
.mz-form-lede a,
.mz-form-notice a,
.check a,
.mz-check a,
.answer a,
.login-note a,
.session-guide a,
.consent a,
.content section a:not(.card):not(.btn),
.identity-link:not([aria-disabled="true"]),
.shipping-status,
.upload-get,
.back-link{
  color:var(--accent);
  text-decoration:none;
  border-bottom:1px solid var(--link-underline);
  transition:border-bottom-color .18s var(--ease);
}
.shot figcaption a:hover,
.statement .source a:hover,
.support a:hover,
.mz-form-lede a:hover,
.mz-form-notice a:hover,
.check a:hover,
.mz-check a:hover,
.answer a:hover,
.login-note a:hover,
.session-guide a:hover,
.consent a:hover,
.content section a:not(.card):not(.btn):hover,
.identity-link:not([aria-disabled="true"]):hover,
.shipping-status:hover,
.upload-get:hover,
.back-link:hover{
  color:var(--accent);
  border-bottom-color:var(--accent);
  opacity:1;
}
/* Form fields get a plain grey focus, not the mint ring. */
input:focus,input:focus-visible,
select:focus,select:focus-visible,
textarea:focus,textarea:focus-visible{
  outline:none;
  border-color:rgba(16,16,16,.38);
  box-shadow:0 0 0 2px rgba(85,104,90,.30);
}

/* ------------------------------------------------------------
   Forms: Request Access is the canonical form language.

   The `.mz-*` classes are intentionally opt-in. Public application forms,
   authenticated portal controls and operational forms can share one visual
   system without changing the behaviour of unrelated inputs or widgets.
   ------------------------------------------------------------ */
.mz-form{--mz-input:#e9e9ea;font-family:var(--sans)}

.mz-form-section{
  padding:0 0 34px;
  margin:0 0 34px;
  border:0;
  border-bottom:1px solid var(--line);
}
/* shipping-form.html wraps its sections in a <fieldset> it disables while the
   record loads, so a direct-child selector never reaches them and the last
   section kept the divider meant to separate it from a following one --
   drawing a second hairline 54px above the actions row's own border. */
.mz-form>.mz-form-section:last-of-type,
.mz-form>fieldset>.mz-form-section:last-of-type{margin-bottom:0;padding-bottom:0;border-bottom:0}
.mz-section-heading{
  margin:0 0 24px;
  font-family:var(--mono);
  font-size:11px;
  font-weight:400;
  letter-spacing:.12em;
  line-height:1.4;
  text-transform:uppercase;
  color:var(--accent);
}
.mz-section-copy{
  max-width:620px;
  margin:-14px 0 24px;
  color:var(--dim);
  font-size:14px;
  line-height:1.55;
}
.mz-form-head{margin-bottom:0}

.mz-field{
  display:flex;
  flex-direction:column;
  gap:8px;
  min-width:0;
  margin:0 0 24px;
  padding:0;
  border:0;
}
.mz-field:last-child{margin-bottom:0}
.mz-label,
.mz-field>label,
.mz-field>legend{
  display:block;
  margin:0;
  font-family:var(--sans);
  font-size:14px;
  font-weight:400;
  letter-spacing:0;
  line-height:1.5;
  text-transform:none;
  color:var(--dim);
}
.mz-hint{
  margin:0;
  color:var(--dim);
  font-size:13px;
  line-height:1.4;
  opacity:.8;
}

.mz-control{
  width:100%;
  padding:13px 14px;
  border:1px solid var(--line);
  border-radius:8px;
  outline:none;
  background:var(--mz-input);
  color:var(--ink);
  font-family:var(--sans);
  /* The body role of the type ladder, not a literal: a field's value is read
     the same way as the prose around it. Clears the 16px iOS
     no-zoom-on-focus threshold. */
  font-size:var(--fs-body);
  /* Definite, not `normal`. A select's intrinsic content box is shorter than
     an input's, so with `normal` the two boxes came out 50px and 46px -- side
     by side in a .mz-pair that reads as a misalignment even when their tops
     agree. A number both control types resolve the same way puts every field
     on one height. */
  line-height:1.2;
  transition:border-color .15s var(--ease),box-shadow .15s var(--ease),background-color .15s var(--ease);
}
.mz-control::placeholder{color:var(--dim);opacity:.28}
.mz-control:focus,.mz-control:focus-visible{
  outline:none;
  border-color:rgba(16,16,16,.38);
  box-shadow:0 0 0 2px rgba(85,104,90,.30);
}
.mz-control[aria-invalid="true"]{border-color:var(--error)}
.mz-control:disabled,.mz-control[readonly]{cursor:not-allowed;opacity:.5}
select.mz-control{
  cursor:pointer;
  appearance:none;
  -webkit-appearance:none;
  padding-right:38px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none'%3E%3Cpath d='M1 1.5l5 5 5-5' stroke='%238a8f98' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right 14px center;
}
select.mz-control option{background:var(--mz-input,#e9e9ea);color:var(--ink)}
textarea.mz-control{min-height:130px;resize:vertical;line-height:1.55}

/* Each option is a 44px row for the touch target while its label is ~20px of
   text, so a 12px gap read as ~36px of air once the options stacked. The row
   height does the separating; the gap only has to keep the hit areas apart. */
.mz-checks{display:flex;flex-direction:column;gap:2px;margin-top:4px}
.mz-check{
  display:flex;
  align-items:flex-start;
  gap:10px;
  min-height:44px;
  margin:0;
  padding:2px 0;
  color:var(--ink);
  cursor:pointer;
}
.mz-check>input{
  width:18px;
  height:18px;
  min-width:18px;
  margin-top:2px;
  accent-color:var(--ink);
  cursor:pointer;
}
.mz-check>input:focus,
.mz-check>input:focus-visible{outline:2px solid var(--accent);outline-offset:-3px;box-shadow:none}
.mz-check>span{font-size:14px;line-height:1.45;color:var(--ink)}
.mz-check-confirmation{display:grid;grid-template-columns:20px minmax(0,1fr);column-gap:14px}

.mz-form-note{
  margin-top:2px;
  padding:14px 16px;
  border-left:2px solid var(--accent);
  background:var(--panel);
  color:var(--dim);
  font-size:13px;
  line-height:1.55;
}
.mz-form-actions{display:flex;align-items:center;flex-wrap:wrap;gap:14px;margin-top:8px}
.mz-form-error{
  margin-top:16px;
  padding:8px 12px;
  border-left:2px solid var(--error);
  background:var(--error-tint);
  color:var(--error);
  font-size:13px;
  line-height:1.45;
}
.mz-form-error:empty{display:none}
.mz-form-message{
  min-height:20px;
  margin:0;
  color:var(--dim);
  font-size:13px;
  line-height:1.45;
}
.mz-form-message.error{
  margin-top:16px;
  padding:8px 12px;
  border-left:2px solid var(--error);
  background:var(--error-tint);
  color:var(--error);
}
.mz-form-message:empty{display:none}
.mz-form-success{
  display:none;
  margin-bottom:40px;
  padding:24px;
  border:1px solid var(--accent);
  border-radius:8px;
}
.mz-form-success h3{margin-bottom:6px}
.mz-form-success p{color:var(--dim);font-size:14px}
.mz-form-success.show{display:block}

.mz-file-control{
  border:1px dashed rgba(16,16,16,.26);
  border-radius:8px;
  background:var(--mz-input,#e9e9ea);
  transition:border-color .15s var(--ease),background-color .15s var(--ease);
}
.mz-file-control:hover,.mz-file-control.dragging{border-color:var(--line-strong)}
.mz-file-control:focus,.mz-file-control:focus-visible{
  outline:none;
  border-color:rgba(16,16,16,.38);
}

/* ------------------------------------------------------------
   Guided forms -- opt-in, on top of the language above

   A long form on one centred column with four type roles, sections that
   open as they are answered, and errors stated in place. Opt in by putting
   .mz-form-page on <main> and .mz-form-guided on the <form>; everything
   here is scoped to that class, so the portal and onboarding keep the
   quieter 11px mono heading they were drawn with.

   The four roles, and nothing between them:
     --fs-display  the title
     --fs-sub      section heads
     --fs-body     all prose and every field -- lede, section copy, labels,
                   legends, values, the status line
     --fs-label    mono meta -- the required marker, subfield captions, the
                   waiting note

   These pages had run to ten sizes, most a point or two apart: lede 22,
   section copy 14, label 14, hint 13, required 12, value 16, status 13,
   notice 14. Nothing was being said by the difference.
   ------------------------------------------------------------ */
.mz-form-page,
.portal-page,
.faq-page{
  /* Just the gutter. `main` above already caps at --shell and centres itself
     with margin:0 auto, so adding the shell-centring maths here centred it
     twice: past 1240px the padding grew with the viewport and ate the content
     box, collapsing this 900px column to 524px at 1900px wide and sliding it
     right. The formula belongs on a full-width element, which this is not. */
  padding-inline:var(--gutter);
  /* The closing measure is the flow's, not a separate page-bottom scale. It
     used to be clamp(64px,9vh,104px) -- 81px against a 54px band at a 900px
     viewport -- and on the two pages that END in an action (access.html's
     Submit, the portal's bucket link) that put the button visibly off-centre
     between its own rule and the footer's. 6vh here is the same clamp the
     guided form's sections use, so the two track each other at every height. */
  padding-block:clamp(72px,11vh,132px) clamp(48px,6vh,68px);
  display:grid;grid-template-columns:minmax(0,var(--col));justify-content:center;
  gap:clamp(44px,6.5vh,76px);
}
.mz-form-page>.mz-form-head h1,
.faq-page>.mz-form-head h1{margin:0 0 clamp(22px,2.8vh,32px)}
.mz-form-lede{margin:0;max-width:620px;color:var(--ink);font-size:var(--fs-body);line-height:1.55}
/* access.html runs a second lede under the first. At margin:0 the two ran
   together as one block, so the sign-in line read as a fourth sentence of the
   paragraph above it rather than a separate offer. */
.mz-form-lede+.mz-form-lede{margin-top:clamp(16px,2vh,22px)}

.mz-form-guided .mz-section-copy,
.mz-form-guided .mz-label,
.mz-form-guided .mz-field>label,
.mz-form-guided .mz-field>legend,
.mz-check>span{font-size:var(--fs-body);line-height:1.55}

/* Mono meta. --fs-label is 12px, so these are the one deliberate step down. */
.mz-form-guided .mz-form-note,
.mz-form-guided .mz-hint,
.mz-form-guided .mz-required::after,
.mz-form-guided .mz-gate-note{
  font-family:var(--mono);font-size:var(--fs-label);letter-spacing:.06em;
  line-height:1.5;color:var(--muted);opacity:1;
}
.mz-form-guided .mz-required::after{content:" (required)"}

/* Section heads carry the accent at Medium. 600 maps to the same
   HaasGrotDispR-65Medium file as 500, so this is a real weight rather than a
   synthesised bold. They are the only landmarks in a long scroll, so they
   take the ladder's section-head step instead of the 11px mono. */
.mz-form-guided .mz-section-heading{
  margin:0 0 16px;
  font-family:var(--sans);font-size:var(--fs-sub);font-weight:600;
  letter-spacing:-.02em;line-height:1.25;text-transform:none;color:var(--accent);
}
/* 34px between sections and 24px under a heading were drawn against an 11px
   mono heading. At --fs-sub, and with a section that may be showing nothing
   but its heading and a waiting note, they read tight. */
.mz-form-guided{--mz-section-gap:clamp(48px,6vh,68px)}
.mz-form-guided .mz-form-section{padding-bottom:var(--mz-section-gap);margin-bottom:var(--mz-section-gap)}
.mz-form-guided .mz-form-section.mz-form-section-compact-after{
  --mz-section-compact-gap:clamp(22px,3vh,32px);
  padding-bottom:var(--mz-section-compact-gap);margin-bottom:var(--mz-section-compact-gap);
}
.mz-form-guided>.mz-form-section:last-of-type,
.mz-form-guided>fieldset>.mz-form-section:last-of-type{padding-bottom:0;margin-bottom:0;border-bottom:0}
.mz-form-no-dividers .mz-form-section{border-bottom:0}
/* The capacity note is context, not an alert. The panel and the accent bar
   gave it more weight than the question it belongs to, so it drops to the
   mono meta step the hints use and carries the accent as colour instead.
   This sits after the mono group above, which would otherwise mute it. */
.mz-form-guided .mz-form-note{
  margin-top:10px;padding:0;border-left:0;background:none;
  color:var(--accent);
}
.mz-form-guided .mz-section-copy{margin:0 0 clamp(28px,3.4vh,38px);max-width:66ch}

/* Two short entries share a row where they belong together. The pair owns
   the rhythm rather than the fields inside it: .mz-field:last-child zeroes
   its own margin, which on a collapsed pair left 24px between the two
   halves and nothing at all between one pair and the next. */
.mz-pair{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 24px;margin:0 0 24px}
.mz-pair>.mz-field{margin:0}

/* A pair's two labels are rarely the same length, so one of them wraps --
   "Legal name of institution or company (required)" takes two lines where
   "Department or laboratory (required)" takes one -- and .mz-field packs its
   children from the top, so the two controls started at different heights.
   The grid item already stretches to the row, so an auto margin above the
   control spends that spare height on the gap instead: labels stay
   top-aligned, controls line up on the row's bottom edge. Below 760px the
   pair is one column per row, so there is no spare height and the margin
   does nothing. Dropped while the pair is showing an error, because
   .mz-field-error sits directly after the control -- with the margin on, the
   clean field's control would bottom-align against the error text rather
   than against its neighbour's control. */
.mz-pair:not(:has(.mz-field-error))>.mz-field>.mz-control,
.mz-subgrid:not(:has(.mz-field-error))>.mz-field>.mz-control{margin-top:auto}
.mz-subgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:16px 24px}
.mz-subgrid>.mz-field{margin:0}

/* Short choices read across the row rather than down it. Opt in per group:
   a consent paragraph must stay stacked, a Yes/No pair should not. */
/* 32px between options read as one run of text at these label lengths --
   "No, but we have reliable access to one" sat almost against the option
   beside it. The column gap is the widest of the three measures so the
   choices separate faster horizontally than they stack vertically. */
.mz-checks-inline{flex-direction:row;flex-wrap:wrap;gap:18px 56px}

/* A section still waiting keeps its heading, so the shape of the form stays
   visible, and hides its fields until the one above it is answered. */
.mz-form-guided .mz-form-section.locked .mz-fields{display:none}
.mz-form-guided .mz-form-section.locked .mz-section-heading,
.mz-form-guided .mz-form-section.locked .mz-section-copy{opacity:.4}
.mz-form-guided .mz-gate-note{display:none;margin:0;text-transform:uppercase}
/* Research carries no section copy, so its note inherited only the heading's
   16px while every other section's note sat on the copy's 31px -- the waiting
   line changed height depending on whether the section happened to have a
   sentence. The note now sits on the same measure either way; the margins
   collapse, so this wins over the heading's smaller one. */
.mz-form-guided .mz-section-heading+.mz-gate-note{margin-top:clamp(28px,3.4vh,38px)}
.mz-form-guided .mz-form-section.locked .mz-gate-note{display:block}
/* Only the first locked section says it. Every section below it is locked too,
   so "complete the section above" pointed at something the reader cannot act
   on either -- the same sentence four times, three of them untrue. The note
   rides the boundary and moves down on its own as each section opens. */
.mz-form-guided .mz-form-section.locked~.mz-form-section.locked .mz-gate-note{display:none}

/* The browser paints these with accent-color:var(--ink), which on this
   background makes an unchecked radio a solid white disc and a checked one a
   white ring around a white dot -- and an unchecked checkbox a solid white
   square. The states are nearly the same shape. Drawn explicitly instead, so
   checked is unmistakable. Not scoped to .mz-form-guided: the defect is in
   every form on the site, the portal's upload destination included. */
.mz-check>input[type="radio"],
.mz-check>input[type="checkbox"]{
  appearance:none;-webkit-appearance:none;
  width:20px;height:20px;min-width:20px;margin-top:.22em;
  border:1px solid var(--line-strong);background:transparent;
  display:grid;place-content:center;
  transition:border-color .15s var(--ease);
}
.mz-check>input[type="radio"]{border-radius:50%}
.mz-check>input[type="checkbox"]{border-radius:4px}
.mz-check>input[type="radio"]::before{
  content:"";width:10px;height:10px;border-radius:50%;background:var(--accent);
  transform:scale(0);transition:transform .12s var(--ease);
}
/* A tick, drawn from two borders on a rotated box. */
.mz-check>input[type="checkbox"]::before{
  content:"";width:11px;height:6px;margin-top:-2px;
  border-left:2px solid var(--accent);border-bottom:2px solid var(--accent);
  transform:rotate(-45deg) scale(0);transition:transform .12s var(--ease);
}
.mz-check>input[type="radio"]:hover,
.mz-check>input[type="checkbox"]:hover{border-color:rgba(16,16,16,.45)}
.mz-check>input[type="radio"]:checked,
.mz-check>input[type="checkbox"]:checked{border-color:var(--accent)}
.mz-check>input[type="radio"]:checked::before{transform:scale(1)}
.mz-check>input[type="checkbox"]:checked::before{transform:rotate(-45deg) scale(1)}
.mz-check>span{color:var(--dim)}
.mz-check:has(input:checked)>span{color:var(--ink)}
.mz-check:has(input:disabled){cursor:not-allowed;opacity:.58}

/* Errors: the field says what is wrong, in place, and the line by the button
   says how many there are. */
.mz-field-error{
  margin-top:10px;font-family:var(--mono);font-size:var(--fs-label);
  letter-spacing:.06em;line-height:1.5;color:var(--error);
}
.mz-form-guided .mz-control[aria-invalid="true"]{
  border-color:var(--error);box-shadow:0 0 0 1px rgba(140,47,47,.34);
}
.mz-form-guided .mz-field:has([aria-invalid="true"])>.mz-label,
.mz-form-guided .mz-field:has([aria-invalid="true"])>.mz-hint,
.mz-form-guided .mz-field:has([aria-invalid="true"])>legend{color:var(--error)}

.mz-form-guided .mz-form-actions{
  margin-top:var(--mz-section-gap);padding-top:var(--mz-section-gap);
  border-top:1px solid var(--line);
}
/* A form that drops its section dividers should not keep the one above the
   actions row: it is the only rule left on the page, so it reads as a stray
   line rather than the close of a series. Same specificity as the rule above,
   so it has to sit after it. The margin and the padding were one measure each
   side of that rule -- with no rule between them they stack to 108px and the
   button drifts off the form, so only the margin survives. */
.mz-form-no-dividers .mz-form-actions{border-top:0;padding-top:0}
.mz-form-guided .mz-form-actions .btn{
  min-width:260px;height:60px;padding-inline:36px;
  font-size:var(--fs-body);font-weight:500;
}
/* Following the actions row, the notice sets the space UNDER the submit, and
   at 31px against the band's own 54px above it the button sat high in its
   band. Elsewhere the notice keeps its own quieter measure. */
.mz-form-guided .mz-form-actions+.mz-form-notice{margin-top:var(--mz-section-gap)}
.mz-form-notice{margin-top:clamp(28px,3.4vh,38px);max-width:70ch;color:var(--dim);font-size:var(--fs-body);line-height:1.55}

@media(max-width:760px){
  .mz-pair{grid-template-columns:minmax(0,1fr);gap:24px}
}
@media(max-width:600px){
  .mz-pair{gap:22px;margin-bottom:22px}
}
@media(max-width:720px){
  .mz-form-guided .mz-form-actions{align-items:stretch;flex-direction:column}
  /* Half the column, not all of it: a full-bleed submit read as a banner
     across the bottom of the form rather than a button. fit-content is the
     floor -- "Submit shipping details" needs more than half of a 390px screen,
     and at a flat 50% the label wrapped inside the 60px button. */
  .mz-form-guided .mz-form-actions .btn{width:50%;min-width:fit-content}
}

@media(max-width:600px){
  .mz-form-section{padding-bottom:30px;margin-bottom:30px}
  .mz-field{margin-bottom:22px}
}

/* ------------------------------------------------------------
   Type scale
   ------------------------------------------------------------ */
.page-title{
  font-size:var(--fs-display);font-weight:300;
  letter-spacing:-.035em;line-height:1.05;
}
.page-lede{
  font-size:var(--fs-lede);color:var(--dim);
  line-height:1.55;margin-top:18px;max-width:620px;
}
.eyebrow{
  font-family:var(--mono);font-size:var(--fs-label);
  letter-spacing:.22em;text-transform:uppercase;color:var(--mut);
}

/* ------------------------------------------------------------
   Heading ladder: three roles, one definition.

     h1  page title    --fs-display  36→64px   300
     h2  section head  --fs-sub      22→28px   400
     h3  sub-head                       17px   500

   Weight drops and tracking loosens as the steps get smaller, so
   rank reads from size and colour rather than from boldness.

   Component headings (card titles, figure labels, the homepage's
   statement heads) legitimately sit outside this ladder and override
   it with class selectors, which outrank these element rules whatever
   the load order. What pages must NOT do is restate the ladder itself
   with the same values — that is how it drifted apart before.
   ------------------------------------------------------------ */
h1{font-size:var(--fs-display);font-weight:300;letter-spacing:-.035em;line-height:1.05}
h2{font-size:var(--fs-sub);font-weight:400;letter-spacing:-.02em;line-height:1.25}
h3{font-size:17px;font-weight:500;letter-spacing:-.01em;line-height:1.35}

/* ------------------------------------------------------------
   Components carried over from the homepage
   ------------------------------------------------------------ */
.stats .stat{transition:background .2s var(--ease)}
.stats .stat:hover{background:rgba(16,16,16,.04)}

.summary-item{transition:transform .2s var(--ease),background .2s var(--ease)}
.summary-item:hover{transform:translateY(-2px);background:rgba(16,16,16,.035)}

.feature-visual{transition:border-color .2s var(--ease),box-shadow .2s var(--ease)}
.feature-visual:hover{
  border-color:var(--line-strong);
  box-shadow:0 16px 48px rgba(16,16,16,.16);
}

/* FAQ accordion */
details{
  border-radius:12px;
  transition:border-color .2s var(--ease),background .2s var(--ease);
}
details:hover{border-color:var(--line-strong);background:rgba(16,16,16,.035)}
summary{padding:20px 22px;font-size:16px;transition:color .2s var(--ease)}
summary::-webkit-details-marker{display:none}
summary::after{
  content:"+";font-size:20px;font-weight:400;color:var(--dim);
  transition:transform .2s var(--ease),color .2s var(--ease);
}
details[open] summary::after{transform:rotate(45deg);color:var(--accent)}
.answer{font-size:var(--fs-body);color:var(--dim);line-height:1.7}
.answer ul{margin:8px 0 14px 18px}
.answer li{margin-bottom:6px}

/* ------------------------------------------------------------
   Footer: same edge as content on every page
   ------------------------------------------------------------ */
footer{
  max-width:none;margin:0;
  padding-block:44px;
  border-top:1px solid var(--line);
  display:flex;justify-content:space-between;align-items:center;
  flex-wrap:wrap;gap:16px;
  font-size:var(--fs-micro);color:var(--mut);
}
footer a{color:var(--dim);text-decoration:none;transition:color .18s var(--ease)}
footer a:hover{color:var(--ink)}

.foot-brand{display:flex;align-items:center;flex-wrap:wrap;gap:12px}
/* The mark is a knockout: a solid 'd' with ZERO cut out of it. The letters take
   the page ground so they read as cut out rather than drawn, which means the one
   piece of markup works on this dark page and on the light homepage alike. */
.foot-mark{display:block;height:16px;width:auto;flex:none;margin-top:-1px}
.foot-mark .mark-body{fill:var(--accent)}
.foot-brand .tag{color:var(--dim)}
/* Fine print, not destinations: mono, a step down in size, and one stop dimmer
   than a footer link. Mono sets optically larger than the sans at the same px,
   so 13.5 here sits level with the 15px statement beside it rather than under
   it. The type is on the container so the copyright span inherits it; only the
   colour needs restating on the anchor, to outrank `footer a`. */
.foot-links{
  --foot-gap:20px;
  display:flex;align-items:center;gap:var(--foot-gap);flex-wrap:wrap;
  font-family:var(--mono);font-size:13.5px;color:var(--mut);
}
.foot-links a{color:var(--mut)}
.foot-links a:hover{color:var(--ink)}
/* A separator, so "mZero Labs Privacy" does not read as one phrase. It rides on
   the copyright rather than the anchor to stay out of the link's text and hit
   area, and its margin tracks the flex gap so the dot sits centred between the
   two at either breakpoint. */
.foot-copy::after{content:"\00b7";margin-left:var(--foot-gap)}

@media(max-width:720px){
  footer{flex-direction:column;align-items:flex-start;gap:20px}
  /* Three lines rather than two: the mark, then the statement, then the
     copyright and Privacy together on the last.
     Beside the text the mark read as a bullet belonging to the sentence; on its
     own line it reads as the mark, so it is a little larger here. margin-top is
     an optical nudge for sitting next to text and is not wanted once stacked. */
  .foot-brand{flex-direction:column;align-items:flex-start;gap:14px}
  .foot-mark{height:22px;margin-top:0}
  .foot-links{--foot-gap:16px}
}
