/* Nexivo link site: the shared layer.

   This file is the whole site's design system, and every page loads it
   first — the front door, /connect/, /share/, the invite page at /j/<code>,
   the watching page at /s/<code>, and the one-line 404. A page stylesheet
   that loads after it may add what only that page has; it may not restate a
   colour, a radius or a shadow. Before this, three stylesheets each kept a
   private copy of the palette and the site read as three products stitched
   together. One copy, here.

   The register is "Midnight Aurora": a near-black canvas with one coloured
   bloom behind the top of the page, glass cards with a lit top edge, and
   exactly one gradient object per page. The bloom is what stops a dark page
   reading as an absence of light rather than a room with a light in it.

   The accent is not invented. #4F7BFF → #7C5CFF is the Nexivo mark's own
   gradient, already sitting in the inline <svg> at the top of every page;
   the site simply promotes it from a 26px logo to the colour the whole
   thing is organised around.

   Still one scheme, deliberately — dark, now, rather than light. Someone is
   standing at a computer or holding a phone, deciding whether to show a
   stranger their screen. They are here for one decision and then gone, so
   nothing a decision is made on moves: no hover lift on things that cannot
   be clicked, and no card or button that animates while it is being read.
   The room is allowed to be alive — the aurora drifts, a dot grid catches
   it, a horizon glows along the foot of the window — and the front door
   alone has a picture that plays (home.css). All of it stops dead under
   prefers-reduced-motion.

   Saying `color-scheme: dark` is what makes the browser's own furniture —
   scrollbars, form controls, the overscroll gutter — agree with the page
   underneath them instead of flashing white at the edges. */

/* Plus Jakarta Sans, self-hosted. Copy this block verbatim, comment and all,
   into each stylesheet that needs the family; it is the one place the file
   name and the weight range are written down, and the stylesheets must not
   drift apart.

   Self-hosted because the page's CSP is `default-src 'none'` with
   `font-src 'self'` (see _headers): a Google Fonts stylesheet or a gstatic
   request would simply be blocked. It is also the right answer on its own -
   a font served from this origin tells nobody else that someone opened the
   page to reach their Mac.

   One variable file carries every weight the site uses, and because the axis
   is continuous the site sets 550, 650 and 750 where a static family would
   have to round to 600 or 700. Asking for any of them costs no second
   request. Declaring the whole 200-800 range lets the browser interpolate
   rather than synthesise a fake bold, which is what would wreck the ID's
   tabular figures.

   `font-display: swap` means the ID is readable in the fallback stack from
   the first paint - someone standing at a borrowed computer never waits on a
   typeface. Pair it with a fallback whose metrics are close, so the swap is
   a change of texture and not a reflow:

     --font: "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont,
       "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

   The url is root-absolute on purpose: the stylesheets sit at different
   depths (assets/site.css, assets/css/connect.css) and a relative url would
   have to differ between them.

   `unicode-range` is the latin subset Google cuts, stated honestly: anything
   outside it falls back to the system stack instead of rendering as tofu.
   Provenance and how to refresh the file: assets/fonts/VENDORED.txt. */
@font-face {
  font-family: "Plus Jakarta Sans";
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url("/assets/fonts/plus-jakarta-sans-v12-latin-var.woff2") format("woff2");
  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;
}

:root {
  color-scheme: dark;

  /* ---- The canvas ---------------------------------------------------- */

  /* Four steps of dark, and they are steps rather than a ramp: the page,
     the card on it, the thing inset into that card, and the hover under
     the inset. A fifth would be a depth nobody can name. */
  --void: #05070F;
  --paper: #070A14;
  --surface: #0F1426;
  --surface-2: #151B31;
  --surface-3: #1C2340;

  /* The rail is glass rather than a slab now, so it is an rgba: the bloom
     passes through it and the page feels lit from above the chrome rather
     than under it. --rail-solid is what a browser without backdrop-filter
     gets instead, matched to the rail sitting over --paper. */
  --rail: rgb(7 10 20 / 0.72);
  --rail-solid: #0A0E1C;
  --rail-ink: #E7EDF8;
  --rail-muted: #8FA0C0;

  /* ---- Ink ------------------------------------------------------------ */

  /* Contrast on --surface (#0F1426), which is the darkest ground any of
     these ever sits on:
       --ink    16.8:1   --ink-2  9.6:1   --muted  5.4:1   --faint  2.9:1
     The light build had to apologise for --muted at 4.35:1 and confine it to
     glyphs. On this ground it clears AA at any size and carries words again;
     --faint takes over the glyph-and-hairline work, and carries none. */
  --ink: #F2F5FF;
  --ink-2: #B7C2DC;
  --muted: #8090B0;
  --faint: #5A6785;

  /* ---- Hairlines ------------------------------------------------------ */

  /* White at three alphas rather than three greys: a hairline over a card
     and the same hairline over the page have to look like one line, and
     only a translucent one does. */
  --line: rgb(255 255 255 / 0.09);
  --line-soft: rgb(255 255 255 / 0.055);
  --line-loud: rgb(255 255 255 / 0.17);

  /* ---- The accent ----------------------------------------------------- */

  /* The mark's own two stops. --grad is the only gradient on the site, and
     the note below says how often it may appear. */
  --accent: #4F7BFF;
  --accent-2: #7C5CFF;
  --accent-ink: #FFFFFF;
  --accent-soft: rgb(79 123 255 / 0.14);
  --accent-line: rgb(124 92 255 / 0.42);
  --grad: linear-gradient(118deg, #4F7BFF 0%, #7C5CFF 100%);
  --grad-soft: linear-gradient(118deg, rgb(79 123 255 / 0.18), rgb(124 92 255 / 0.18));

  /* The mark's stops, named separately: the page stylesheets fill the
     <svg>'s gradient from these, so the mark in the rail and the mark in the
     app cannot drift apart through a forgotten hex. */
  --mark-a: #4F7BFF;
  --mark-b: #7C5CFF;

  /* ---- States --------------------------------------------------------- */

  /* Re-cut for a near-black ground. The light build's #16A34A and #B45309
     were chosen to sit on white paper and go muddy down here; these are the
     same three hues carried up until they read as green, amber and red
     against --surface. */
  --ok: #35D399;
  --warn: #FFB661;
  --danger: #FF6B81;

  /* ---- The scene ------------------------------------------------------ */

  /* The front door draws a laptop, and the laptop draws someone else's
     desktop. These are the only colours on the site that are not the
     canvas, the ink or the mark: the metal of the machine, and the light
     mode of a stranger's screen, which is deliberately NOT this site's
     palette so the picture reads as their computer and not ours. They live
     here with every other colour, so home.css stays free of hexes. */
  --metal-hi: #A9B2CB;
  --metal: #444C66;
  --metal-lo: #171B29;
  --bezel: #030409;
  --desk-a: #0F3D73;
  --desk-b: #1B7FA3;
  --desk-c: #4B34A8;
  --win: #F3F6FC;
  --win-ink: #1A2240;
  --win-line: #D6DDEC;
  --win-soft: #E6EBF6;

  /* ---- The front door's night ---------------------------------------- */

  /* The front door is a long scroll rather than one card, and its room is a
     night sky over a floor of light instead of the aurora. --sky is the
     iPhone app's launch-screen navy, so the site and the app open on the
     same colour; --night is the ground the sky fades into. --accent-hi is
     the mark's blue lifted until it carries large type on --night (8.4:1):
     the second line of every heading there. --floor-dot is one point of the
     floor the laptop stands on. */
  --night: #04060D;
  --sky: #0A1D47;
  --sky-glow: rgb(37 78 190 / 0.42);
  --accent-hi: #86A2FF;
  --floor-dot: rgb(150 176 255 / 0.5);
  /* The light the link is made of: --ice is its spark and the brightest
     points on the planet, --lavender the far end of the headings' second
     line, between the mark's violet and white. */
  --ice: #C9D6FF;
  --lavender: #C7BBFF;

  /* ---- Lift ----------------------------------------------------------- */

  /* One shadow for the whole site, as before: a card is lifted off the page
     or it is not, and there is no second elevation to learn. What changed is
     what lift MEANS on a dark ground. A grey blur under a black card is
     invisible; what reads is a lit top edge and a deep drop, so the token
     carries both and the inset highlight comes first. */
  --shadow:
    inset 0 1px 0 rgb(255 255 255 / 0.07),
    0 2px 6px rgb(0 0 0 / 0.4),
    0 28px 70px -28px rgb(0 0 0 / 0.85);
  --shadow-lift:
    inset 0 1px 0 rgb(255 255 255 / 0.1),
    0 2px 8px rgb(0 0 0 / 0.45),
    0 36px 90px -30px rgb(0 0 0 / 0.9);

  /* A card's fill is a shallow top-down sheen laid over --surface, which is
     what makes glass read as glass rather than as a lighter rectangle.
     Used as: background: var(--card-fill), var(--surface); */
  --card-fill: linear-gradient(180deg, rgb(255 255 255 / 0.055), rgb(255 255 255 / 0.015));

  /* The accent's own light. Only the primary button and the completed ID
     rule spend it. */
  --glow: 0 10px 34px -10px rgb(79 123 255 / 0.55);
  --glow-strong: 0 14px 46px -12px rgb(99 104 255 / 0.7);

  /* ---- Shape and space ------------------------------------------------ */

  --radius-card: 24px;
  --radius-control: 14px;
  --radius-inset: 16px;
  --radius-pill: 999px;
  --gutter: 16px;

  --font: "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
    Roboto, "Helvetica Neue", Arial, sans-serif;

  /* ---- Motion --------------------------------------------------------- */

  /* Two durations and one curve. Every animation on the site answers a state
     change; the reduce block at the foot of this file turns all of them into
     the state change itself. */
  --ease: cubic-bezier(0.2, 0.7, 0.3, 1);
  --fast: 140ms;
  --slow: 420ms;
}

/* Where the gradient lands.

   The old rule survives the repaint: the moment two things carry the
   gradient, neither of them means anything. The budget is one gradient
   OBJECT per page, plus the mark in the rail, plus the primary button.

     /            the "Get a link to send" button. The front door is also
                  the one page that is a story rather than a form, and it
                  spends light where the story needs it: the thread the link
                  draws down the page, and the second line of each heading
                  (home.css). Its fork still has exactly one gradient object.
     /connect/    the rule under the nine digits, and Connect
     /share/      the "Share this screen" button
     /s/<code>    the sharer's Computer ID
     /j/<code>    the inviting Mac's Computer ID

   .code below — the code out of the link itself — deliberately does not take
   it. The gradient marks a Computer ID, the number that names a machine, and
   nothing else. */

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  background: var(--paper);
}

/* The paper lives on <html> so the grid below can sit between it and
   everything else: body is transparent, and a page that needs a solid
   ground (view.css's stage) paints one on body and covers both layers. */
body {
  position: relative;
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  background: transparent;
  color: var(--ink-2);
  font: 400 16px/1.62 var(--font);
  -webkit-font-smoothing: antialiased;
}

/* ---- The aurora ------------------------------------------------------- */

/* The page's one light source: three wide radial blooms behind the top of
   the canvas, in the mark's two colours and the deep blue between them. It
   is the single difference between a dark page and a page that is dark, and
   it is why the headline under it looks lit rather than merely white.

   It hangs off body::before rather than a div because no page has an element
   for it and none should have to grow one — the markup here is the same
   markup the light build shipped.

   `position: fixed` also keeps it out of flow, which matters: body carries
   `display: grid` on the one-line pages (.plain), and an in-flow ::before
   would become a grid item and push the sentence off centre.

   Gradients, not an image: the CSP is `img-src 'self'` with no `data:`, so a
   noise or mesh texture could not be fetched or inlined even if it wanted
   to. Three overlapping radials do the same work and cost nothing.

   The layer starts at the top of the VIEWPORT, not above it, and its two
   bright centres sit at 14% and 6% of its own height rather than at 0% and
   -8%. Hung higher — as it first was — the core of every radial landed a
   couple of hundred pixels off the top of the screen and what survived was
   hidden behind the rail, so the page read as flat black and the bloom was
   only really visible as the card being lighter than the paper. A light
   source you cannot see is not a light source.

   The light drifts. Over forty seconds the blooms wander a few percent and
   breathe, slowly enough that nobody reading a sentence sees it move, only
   that the room is alive. The reduce block at the foot of this file stops it
   dead at its first frame. */
body::before {
  content: "";
  position: fixed;
  inset: -6vh -14vw auto;
  height: 96vh;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(48vw 40vh at 22% 18%, rgb(124 92 255 / 0.36), transparent 70%),
    radial-gradient(44vw 36vh at 80% 10%, rgb(79 123 255 / 0.32), transparent 68%),
    radial-gradient(72vw 46vh at 50% 4%, rgb(44 72 180 / 0.22), transparent 74%),
    radial-gradient(30vw 24vh at 62% 46%, rgb(27 127 163 / 0.12), transparent 72%);
  animation: aurora-drift 40s ease-in-out infinite alternate;
  will-change: transform;
}

@keyframes aurora-drift {
  0% {
    transform: translate3d(0, 0, 0) scale(1);
  }
  50% {
    transform: translate3d(4vw, 2vh, 0) scale(1.06);
  }
  100% {
    transform: translate3d(-3vw, -1vh, 0) scale(1.02);
  }
}

/* The floor under the light: a dot grid, lit only where the aurora is and
   gone by the fold, so it reads as a surface the light is falling on rather
   than as graph paper. Static on purpose - one moving layer is a room, two
   are a screensaver. It hangs off <html> so body::before paints over it. */
html::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: radial-gradient(rgb(255 255 255 / 0.11) 1px, transparent 1.4px);
  background-size: 26px 26px;
  background-position: 50% 0;
  -webkit-mask-image: radial-gradient(80vw 70vh at 50% 0%, #000 0%, transparent 78%);
  mask-image: radial-gradient(80vw 70vh at 50% 0%, #000 0%, transparent 78%);
}

/* The horizon: a low, wide glow along the foot of the window, the
   aurora's reflection on the floor. With it the bottom of a short page is
   a place rather than where the light ran out. It sits at z-index -1, under
   the transparent body and over <html>'s paper, so any page that paints a
   solid body (view.css's stage) or a fixed viewer covers it without being
   asked to. */
body::after {
  content: "";
  position: fixed;
  inset: auto -10vw 0;
  height: 55vh;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(60% 70% at 50% 100%, rgb(79 123 255 / 0.16), transparent 70%),
    radial-gradient(30% 40% at 30% 100%, rgb(124 92 255 / 0.12), transparent 70%);
}

/* Everything the pages put at the top level stands in front of the bloom.
   The viewer and the stage — the two full-window surfaces that show someone
   else's screen — are not in this list: they take the window at a higher
   layer from their own stylesheets, and the light has no business on a
   picture of a desktop. */
.rail,
.sheet,
.shell,
main,
noscript,
.home-aside,
.footnote {
  position: relative;
  z-index: 1;
}

[hidden] {
  display: none !important;
}

svg {
  flex: none;
}

/* A ring, not a glow: 2px of the accent, held off the control so a rounded
   corner still reads (the outline follows the element's own radius, which is
   why this rule must not set one). :focus-visible only, so a mouse click on
   a button does not leave a ring behind it. On this ground the accent needs
   one step of lift to clear the surfaces it lands on, so the ring is the
   lighter of the two stops rather than the blue. */
:focus-visible {
  outline: 2px solid var(--accent-2);
  outline-offset: 2px;
}

/* Used by more than one page, and by connect.css before this file existed
   for it. Stated once here so a page stylesheet does not have to. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---- The rail --------------------------------------------------------- */

/* The app's window chrome. It used to be the one dark band on a light page
   and had to announce itself; now the page is dark and the rail's job is the
   opposite — to be the glass the bloom shows through, so the mark sits in
   the light rather than on a slab in front of it. It carries the mark and,
   on a computer, the one piece of live state the page has. */

.rail {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--rail);
  -webkit-backdrop-filter: blur(22px) saturate(140%);
  backdrop-filter: blur(22px) saturate(140%);
  border-bottom: 1px solid var(--line);
  color: var(--rail-ink);
  padding: calc(env(safe-area-inset-top) + 14px)
    calc(env(safe-area-inset-right) + var(--gutter)) 14px
    calc(env(safe-area-inset-left) + var(--gutter));
}

/* Glass that is not being blurred is just a translucent panel with the page
   sliding under it, which looks like a bug. Where the filter is unsupported
   the rail goes solid instead. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .rail {
    background: var(--rail-solid);
  }
}

.rail-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  max-width: 592px;
  margin: 0 auto;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: inherit;
  text-decoration: none;
}

.mark {
  width: 26px;
  height: 26px;
}

.wordmark {
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1;
}

/* The rail's two links out, "How to use" and "Download", on the pages
   anyone may arrive at: the front door, the guide, the download page and
   the legal pages. They are chrome, not content, so they take the rail's
   own muted ink and light up only under the pointer or when one names the
   page you are on. Here rather than in a page sheet because several pages
   carry them and the rail is this file's. */
.rail-nav {
  display: flex;
  align-items: center;
  gap: 4px;
}

.rail-link {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 36px;
  padding: 6px 12px;
  border-radius: var(--radius-pill);
  color: var(--rail-muted);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  transition: color var(--fast) var(--ease), background-color var(--fast) var(--ease);
}

.rail-link svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.rail-link[aria-current="page"] {
  color: var(--rail-ink);
  background: rgb(255 255 255 / 0.07);
  box-shadow: inset 0 0 0 1px var(--line);
}

@media (hover: hover) {
  .rail-link:hover {
    color: var(--rail-ink);
    background: rgb(255 255 255 / 0.06);
  }
}

/* A 375-pixel phone has room for the mark and one labelled link, not two.
   Below 420 pixels Download keeps its glyph and gives its word to screen
   readers only (the .visually-hidden rules, scoped to this width), so the
   rail never wraps and How to use keeps its label. */
@media (max-width: 419px) {
  .rail-download {
    padding: 6px 10px;
  }

  .rail-download span {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
}

/* ---- The sheet and the card ------------------------------------------- */

.sheet {
  max-width: calc(560px + 2 * var(--gutter));
  margin: 0 auto;
  padding: clamp(24px, 9vh, 76px) calc(env(safe-area-inset-right) + var(--gutter))
    calc(env(safe-area-inset-bottom) + 32px)
    calc(env(safe-area-inset-left) + var(--gutter));
}

.card {
  background: var(--card-fill), var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow);
  padding: 28px 22px 26px;
  position: relative;
}

/* Where the aurora catches the card: a short lit hairline across the
   middle of its top edge, in the mark's two colours. It is the card's only
   ornament and the thing that makes the glass read as lit from above. */
.card::before {
  content: "";
  position: absolute;
  left: 14%;
  right: 14%;
  top: -1px;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgb(124 92 255 / 0.75), rgb(79 123 255 / 0.75), transparent);
  pointer-events: none;
}

/* ---- Type ------------------------------------------------------------- */

/* Bigger and tighter than the light build, and further from the body text
   under it. On a dark ground a heading set at the old 1.7rem/600 reads as
   another paragraph; the contrast between display and body is what gives the
   page a top. */

h1 {
  margin: 0;
  color: var(--ink);
  font-size: clamp(1.9rem, 4.4vw, 3rem);
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -0.03em;
  text-wrap: balance;
}

.lead {
  margin: 12px 0 0;
  max-width: 62ch;
  color: var(--ink-2);
  font-size: clamp(1rem, 1.6vw, 1.125rem);
  line-height: 1.6;
  letter-spacing: -0.005em;
  text-wrap: pretty;
}

.lead strong {
  color: var(--ink);
  font-weight: 600;
}

/* ---- The badge --------------------------------------------------------- */

/* A tile, not a medallion: it says which kind of thing the page is talking
   about (a phone, a screen, a warning) and then gets out of the way. Inset
   into the card rather than lifted off it, because it is a label. */

.badge {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  margin: 0 0 18px;
  border-radius: 14px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--accent);
}

.badge svg {
  width: 24px;
  height: 24px;
}

.badge-warn {
  background: rgb(255 182 97 / 0.12);
  border-color: rgb(255 182 97 / 0.34);
  color: var(--warn);
}

.badge-ok {
  background: rgb(53 211 153 / 0.12);
  border-color: rgb(53 211 153 / 0.34);
  color: var(--ok);
}

.badge svg,
.callout-icon svg,
.footnote svg {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ---- The invite code --------------------------------------------------- */

/* The code from the link, shown so it can be read against the Mac. It takes
   the display register - heavy, tabular, roomy - but not the gradient: that
   marks a Computer ID, the number that names a machine, and nothing else. */

.code-block {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  margin: 24px 0 0;
}

.code-label {
  color: var(--muted);
  font-size: 13px;
  font-weight: 550;
  letter-spacing: 0.02em;
}

.code {
  max-width: 100%;
  overflow-wrap: anywhere;
  color: var(--ink);
  font-size: clamp(1.6rem, 6vw, 2rem);
  font-weight: 750;
  line-height: 1.2;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
}

/* ---- Buttons ----------------------------------------------------------- */

.button {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  width: 100%;
  min-height: 52px;
  padding: 12px 22px;
  border: 0;
  border-radius: var(--radius-control);
  font-family: inherit;
  font-size: 17px;
  font-weight: 600;
  line-height: 1.25;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  transition: background-color var(--fast) var(--ease),
    border-color var(--fast) var(--ease), color var(--fast) var(--ease),
    box-shadow var(--fast) var(--ease), transform var(--fast) var(--ease);
}

/* The page's one gradient object, and the only thing on it with its own
   light. The inset highlight along the top edge is what keeps a flat
   gradient from looking printed on. */
.primary {
  margin-top: 24px;
  background: var(--grad);
  color: var(--accent-ink);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.22), var(--glow);
}

.secondary {
  min-height: 46px;
  padding: 10px 18px;
  background: rgb(255 255 255 / 0.03);
  border: 1px solid var(--line-loud);
  color: var(--ink-2);
  font-size: 15px;
}

.secondary[aria-disabled="true"] {
  color: var(--faint);
  background: transparent;
  border-color: var(--line);
  cursor: default;
}

@media (hover: hover) {
  .primary:hover {
    box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.28), var(--glow-strong);
    transform: translateY(-1px);
  }

  .secondary:hover:not([aria-disabled="true"]) {
    background: rgb(255 255 255 / 0.06);
    border-color: var(--accent-line);
    color: var(--ink);
  }
}

.primary:active {
  transform: translateY(0);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.18), var(--glow);
}

.status {
  margin: 14px 0 0;
  color: var(--ink);
  font-size: 15px;
}

/* Kept in the page while empty, so a screen reader hears it when it fills. */
.status:empty {
  margin: 0;
}

/* ---- Steps -------------------------------------------------------------- */

.steps {
  margin: 24px 0 0;
  padding: 0;
  list-style: none;
  counter-reset: step;
}

.steps li {
  counter-increment: step;
  position: relative;
  padding: 7px 0 7px 36px;
  color: var(--ink-2);
  font-size: 15px;
}

.steps li::before {
  content: counter(step);
  position: absolute;
  top: 9px;
  left: 0;
  display: grid;
  place-items: center;
  width: 23px;
  height: 23px;
  border-radius: 50%;
  background: var(--surface-3);
  border: 1px solid var(--line);
  color: var(--ink-2);
  font-size: 13px;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}

.steps strong {
  color: var(--ink);
  font-weight: 600;
}

/* ---- Callouts ----------------------------------------------------------- */

/* Inset into the card, not lifted off it: a callout is a quieter surface
   than the card it sits in, so it goes down a step and takes no shadow. */

.callout {
  display: grid;
  grid-template-columns: 28px 1fr;
  gap: 12px;
  align-items: start;
  margin-top: 24px;
  padding: 16px;
  border-radius: var(--radius-inset);
  background: var(--surface-2);
  border: 1px solid var(--line-soft);
}

/* invite.js adds this when the app did not open: the install step is now the
   thing to read, and it says so by taking the accent ring for itself. */
.callout.attention {
  border-color: var(--accent-line);
  box-shadow: 0 0 0 3px rgb(79 123 255 / 0.14);
}

.callout-icon {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 9px;
  background: var(--surface-3);
  border: 1px solid var(--line);
  color: var(--accent);
}

.callout-icon svg {
  width: 17px;
  height: 17px;
  stroke-width: 1.9;
}

.callout-text {
  margin: 2px 0 0;
  color: var(--ink-2);
  font-size: 15px;
  line-height: 1.55;
}

.callout-text strong {
  color: var(--ink);
  font-weight: 600;
}

/* Under the icon and the text, the callout's full width. */
.callout-action {
  grid-column: 1 / -1;
  margin-top: 4px;
}

/* ---- The rule between two choices ---------------------------------------- */

/* A hairline with one word on it. It separates two ways to do a thing
   without becoming a third thing to read: the word is small and quiet, and
   the lines are the same hairline as everything else.
 *
 * It lives here rather than on one page because more than one page forks:
 * the front door (Connect to someone's PC / Show someone your screen) and
 * the page at the other end of the link, which offers the person whose
 * screen it is the same choice from their side (SPEC.md §10.4). */

.or {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 28px auto 24px;
  color: var(--faint);
  font-size: 12px;
  font-weight: 550;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.or::before,
.or::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}

/* ---- Footnote ------------------------------------------------------------ */

/* The promise the whole page rests on. It sits outside the card, where a
   footnote belongs, and it is the last thing read before the decision. */

.footnote {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 20px 0 0;
  color: var(--muted);
  font-size: 14px;
}

.footnote svg {
  width: 17px;
  height: 17px;
  color: var(--ok);
}

/* ---- Privacy and Terms --------------------------------------------------- */

/* The two documents every public page links to, in one quiet line under its
   last words: smaller than the footnote and in the same muted ink, because
   nobody comes to the page for them but everybody must be able to find
   them. Centred where the page's own last line is centred: the guide, the
   legal pages, the 404 and /connect/'s foot. */

.legal-links {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 20px;
  margin: 16px 0 0;
  font-size: 13px;
}

.legal-links a {
  color: var(--muted);
  text-decoration: underline;
  text-decoration-color: var(--line-loud);
  text-underline-offset: 3px;
  transition: color var(--fast) var(--ease);
}

.legal-links a[aria-current="page"] {
  color: var(--ink-2);
  text-decoration: none;
}

.plain .legal-links,
.foot .legal-links,
body[data-page="help"] .legal-links,
body[data-page="legal"] .legal-links {
  justify-content: center;
}

@media (hover: hover) {
  .legal-links a:hover {
    color: var(--ink);
  }
}

/* ---- noscript, and the one-line pages (/, 404) --------------------------- */

noscript h1 {
  margin-bottom: 10px;
}

.plain {
  display: grid;
  place-items: center;
  min-height: 100vh;
  min-height: 100dvh;
  padding: 24px var(--gutter);
}

.plain p {
  margin: 0;
  max-width: 44ch;
  color: var(--ink-2);
  text-align: center;
  text-wrap: pretty;
}

@media (min-width: 600px) {
  .rail {
    padding-top: calc(env(safe-area-inset-top) + 16px);
    padding-bottom: 16px;
  }

  .card {
    padding: 36px 34px 32px;
  }
}

/* Every transition and animation on the site answers a state change, so
   under reduce they become the state change itself, with no exceptions. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }

  /* The one transform the reduce block has to undo rather than shorten: a
     button that lifts on hover is a movement, not a fade. */
  .primary:hover {
    transform: none;
  }
}

/* ---- The App Store badge ------------------------------------------------ */

/* Apple's artwork, as Apple draws it: never recoloured, restyled or
   cropped, at least 40px tall, with clear space around it a quarter of its
   height. So this rule only sizes it and spaces it; the focus ring follows
   the badge's own rounded corners. */
.store-badge {
  display: block;
  width: fit-content;
  margin-top: 24px;
  border-radius: 9px;
  line-height: 0;
  -webkit-tap-highlight-color: transparent;
}

.store-badge img {
  display: block;
  width: auto;
  height: 48px;
}

/* Windows High Contrast and forced-colors: the bloom, the glass and the
   gradient are all decoration the OS is entitled to throw away, and the
   hairlines have to come back as real borders so the cards still have
   edges. */
@media (forced-colors: active) {
  html::before,
  body::before,
  body::after,
  .card::before {
    display: none;
  }

  .card,
  .callout,
  .badge,
  .secondary {
    border-color: CanvasText;
  }

  .primary {
    background: Highlight;
    color: HighlightText;
    box-shadow: none;
  }
}
