/* ---------------------------------------------------------------------------
   The two faces of the 3 Point Forward system, self-hosted.

   Self-hosted rather than linked, because the application's CSP is
   font-src 'self' with no CDN allowed, and because a webfont request to a third
   party on every page load is a request a customer's brokerage data does not
   need to be adjacent to.

   Variable, so one file covers every weight the page uses. The build step
   content-hashes these like every other asset, so they carry a one-year
   immutable cache.
   --------------------------------------------------------------------------- */
@font-face {
  font-family: "Space Grotesk";
  src: url("/fonts/grotesk-var.06408904.woff2") format("woff2-variations"),
       url("/fonts/grotesk-var.06408904.woff2") format("woff2");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
  /* Latin only. Anything outside this range falls to the stack below it rather
     than downloading a subset nothing on this site renders. */
  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: "Inter";
  src: url("/fonts/inter-var.3100e775.woff2") format("woff2-variations"),
       url("/fonts/inter-var.3100e775.woff2") format("woff2");
  font-weight: 100 900;
  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;
}

/* ---------------------------------------------------------------------------
   Tophat — the front door.
   Palette and radii are lifted from the 3 Point Forward system the product
   already ships, so the site and the software look like one company made both.
   Navy carries every action. Gold is an accent and never a control: it reads
   1.68:1 on paper and cannot carry small text or a state boundary.
   --------------------------------------------------------------------------- */
:root {
  --paper:      #f7f8fb;
  --white:      #ffffff;
  --ink:        #1a2230;
  --ink-2:      #525c6e;
  --line:       #e7e9f0;
  --navy:       #1f347f;
  --navy-deep:  #14235c;
  --navy-bright:#2b46b8;
  --navy-tint:  #eef1fb;
  --gold:       #f5b81f;
  --gold-tint:  #fdf4dd;
  --on-gold:    #26200a;
  --night:      #07182b;
  --night-2:    #0f2a46;

  --ground:     var(--paper);
  --card:       var(--white);
  --text:       var(--ink);
  --text-2:     var(--ink-2);
  --rule:       var(--line);
  --brand:      var(--navy);
  --brand-tint: var(--navy-tint);
  --on-brand:   #ffffff;
  --shadow:     0 12px 30px -22px rgba(20, 35, 92, .35);
  --shadow-lg:  0 40px 80px -50px rgba(20, 35, 92, .55);

  --r-sm: 8px;  --r: 11px;  --r-lg: 14px;  --r-pill: 100px;
  --maxw: 1200px;
  --ease: cubic-bezier(.16, 1, .3, 1);

  --ui: "Inter", ui-sans-serif, "Segoe UI Variable Text", "Segoe UI", system-ui,
        -apple-system, "Helvetica Neue", Arial, sans-serif;
  --display: "Space Grotesk", "Inter", ui-sans-serif, "Segoe UI Variable Display",
             system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "Cascadia Mono", "Consolas", "SF Mono", Menlo, monospace;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ground: #07182b; --card: #0f2a46; --text: #eef5fc; --text-2: #b0c6db;
    --rule: #1e3a55; --brand: #42ddef; --brand-tint: #12314f; --on-brand: #042028;
    --shadow: 0 12px 30px -18px rgba(0,0,0,.75);
    --shadow-lg: 0 44px 96px -40px rgba(0,0,0,.9);
  }
}
:root[data-theme="dark"] {
  --ground: #07182b; --card: #0f2a46; --text: #eef5fc; --text-2: #b0c6db;
  --rule: #1e3a55; --brand: #42ddef; --brand-tint: #12314f; --on-brand: #042028;
  --shadow: 0 12px 30px -18px rgba(0,0,0,.75);
  --shadow-lg: 0 44px 96px -40px rgba(0,0,0,.9);
}

* { box-sizing: border-box; }
body {
  margin: 0; background: var(--ground); color: var(--text);
  font-family: var(--ui); font-size: 17px; line-height: 1.62;
  -webkit-font-smoothing: antialiased; overflow-x: hidden;
}
img { max-width: 100%; display: block; }
/* A <picture> chooses which file the <img> inside it loads and has no other job.
   Left at its default inline display it becomes a box in the layout, and every
   rule below that sizes an image through its parent (.hero__img img at 100% of
   an absolutely positioned container, .shot__f img at 100% of an aspect-ratio
   box) would be measuring against that wrapper instead. display: contents makes
   the element generate no box at all, so the <img> is laid out by the container
   the markup put it in and the rules further down mean what they say. */
picture { display: contents; }
a { color: var(--brand); }

/* 600 rather than 700. Space Grotesk's bold is a poster weight; its semibold
   is the one that reads as considered at these sizes. Only reachable because
   the face loading is variable, so every value on the axis is available. */
h1, h2, h3, .fig { font-family: var(--display); font-weight: 600; letter-spacing: -.022em; text-wrap: balance; }
/* 1.02 put the descenders of g, p and y within a pixel of the line below,
   which is what makes tight setting look smeared instead of tight. */
h1 { font-size: clamp(2.3rem, 1.45rem + 3.4vw, 3.9rem); line-height: 1.07; margin: 0;
     font-weight: 640; letter-spacing: -.028em; }
h2 { font-size: clamp(1.7rem, 1.25rem + 1.8vw, 2.6rem); line-height: 1.1; margin: 0 0 .5em; }
h3 { font-size: 1.16rem; line-height: 1.3; margin: 0 0 .35em; letter-spacing: -.012em; }
p  { margin: 0 0 1em; max-width: 62ch; }
.lede { font-size: clamp(1.05rem, .96rem + .4vw, 1.28rem); color: var(--text-2); line-height: 1.55;
        /* Narrower than the 62ch p inherits: the same character count set larger
           is a physically wider column, and this was measuring past 75. */
        max-width: 56ch; }

.wrap { max-width: var(--maxw); margin-inline: auto; padding-inline: clamp(20px, 5vw, 40px); }
.eyebrow {
  font-size: .78rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--brand); margin: 0 0 .9em;
}
section { padding-block: clamp(64px, 9vw, 128px); }

/* ---- masthead ----------------------------------------------------------- */
.mast {
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: center; gap: 20px;
  padding: 14px clamp(20px, 5vw, 40px);
  background: color-mix(in srgb, var(--ground) 82%, transparent);
  backdrop-filter: blur(14px); border-bottom: 1px solid transparent;
  transition: border-color .3s var(--ease), background .3s var(--ease);
}
.mast[data-stuck] { border-bottom-color: var(--rule); }
.logo { display: flex; align-items: center; gap: 11px; font-family: var(--display);
        font-weight: 700; font-size: 1.16rem; letter-spacing: -.02em; color: var(--text);
        text-decoration: none; margin-right: auto; }
.logo svg { width: 30px; height: 30px; flex: none; }
.mast nav { display: none; gap: 26px; font-size: .93rem; }
.mast nav a { color: var(--text-2); text-decoration: none; transition: color .2s var(--ease); }
.mast nav a:hover { color: var(--text); }
@media (min-width: 860px) { .mast nav { display: flex; } }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5em;
  min-height: 44px; padding: 0 20px; border-radius: var(--r);
  font-family: var(--ui); font-size: .95rem; font-weight: 600; letter-spacing: -.005em;
  text-decoration: none; border: 1px solid transparent; cursor: pointer;
  transition: transform .18s var(--ease), background .18s var(--ease), border-color .18s var(--ease);
}
.btn--primary { background: var(--brand); color: var(--on-brand); }
.btn--primary:hover { transform: translateY(-2px); }
.btn--ghost { border-color: var(--rule); color: var(--text); background: transparent; }
.btn--ghost:hover { border-color: var(--brand); transform: translateY(-2px); }
.btn--light { background: var(--white); color: var(--navy-deep); }
.btn--light:hover { transform: translateY(-2px); }
/*
 * background is stated because this modifier is now used on <button> as well as
 * <a>. A button carries the user agent's own ButtonFace background, which is a
 * light grey, and this rule sets white text on it: the tour's controls rendered
 * as unreadable grey slabs. On an anchor the declaration changes nothing.
 */
.btn--wire { border-color: rgba(255,255,255,.34); color: #fff; background: transparent; }
.btn--wire:hover { border-color: var(--gold); color: var(--gold); transform: translateY(-2px); }
:where(a, button, input):focus-visible { outline: 2px solid var(--navy-bright); outline-offset: 3px; border-radius: 4px; }

/* ---- hero --------------------------------------------------------------- */
/* The hero carried a photograph and now carries the screen wall instead. Two
   backgrounds behind one headline was muddy, and of the two the one showing the
   actual product is the better argument. The gradient is what the photograph
   used to provide: a ground dark enough for white type at the top, opening out
   toward the bottom where the wall fades. */
.hero { position: relative; isolation: isolate; color: #fff; padding: 0; overflow: hidden;
  background: radial-gradient(120% 80% at 76% 8%, #14305a 0%, #0b1e38 42%, #07182b 100%);
        min-height: min(88vh, 760px); display: grid; align-items: end; }
.hero__img { position: absolute; inset: 0; z-index: -2; }
.hero__img img { width: 100%; height: 100%; object-fit: cover; object-position: 62% 42%;
                 animation: drift 26s var(--ease) infinite alternate; }
@keyframes drift { from { transform: scale(1.06) translate3d(0,0,0); } to { transform: scale(1.15) translate3d(-1.6%, -1.4%, 0); } }
/* ---- the hero screen wall -------------------------------------------------
 *
 * Three columns of real product screens on a plane tilted away from the reader,
 * scrolling continuously.
 *
 * THE FIRST VERSION OF THIS DRIFTED FOURTEEN PIXELS OVER FORTY SECONDS, on the
 * theory that motion you can see in a hero is motion you have to look away from
 * to read. That was the wrong call for this page: below the threshold of
 * noticing is indistinguishable from not moving, and what the hero is for is
 * conveying that there is a live system behind the headline.
 *
 * So it scrolls, properly. The outer columns travel up and the middle one down,
 * at 46, 61 and 53 seconds -- deliberately not multiples of each other, so the
 * three never sync back up into a pattern the eye can lock on to.
 *
 * SEAMLESS BECAUSE EACH COLUMN CONTAINS ITS SCREENS TWICE and moves exactly
 * -50% of its own height. At the end of a cycle the second copy sits precisely
 * where the first started, so there is no jump to hide.
 *
 * ONLY transform IS ANIMATED, so this runs on the compositor and can never
 * cause layout. The perspective lives on the parent, once, which is what makes
 * three columns read as one surface seen from an angle rather than three
 * unrelated skewed strips.
 */
.wall {
  position: absolute; inset: -10% -6% auto -6%; z-index: -1;
  height: 125%;
  perspective: 1400px; perspective-origin: 50% 22%;
  pointer-events: none;
  -webkit-mask-image: radial-gradient(120% 92% at 62% 26%, #000 38%, transparent 78%);
          mask-image: radial-gradient(120% 92% at 62% 26%, #000 38%, transparent 78%);
}
.wall__in {
  position: absolute; inset: 0;
  transform: rotateX(30deg) rotateZ(-12deg) scale(1.14);
  transform-style: preserve-3d;
  display: grid;
  /*
   * minmax(0, 1fr), NOT 1fr.
   *
   * `1fr` is shorthand for `minmax(auto, 1fr)`, and `auto` as a minimum
   * resolves to the item's min-content size. A column of 900px-wide screenshots
   * has a min-content width of 900px, so three of them refused to shrink below
   * 2700px, the tracks blew out, and the images rendered at several times their
   * intended size -- one column measured 43,504 pixels tall.
   *
   * A zero minimum lets the fraction actually do the dividing.
   */
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(14px, 2.2vw, 30px);
  padding: 0 2%;
  opacity: .46;
}

/* A column is taller than the plane on purpose: it has to hold two copies of
   its screens so the loop has somewhere to come back from. overflow is visible
   because .wall already masks the edges. */
.wall__col {
  display: grid;
  grid-auto-rows: max-content;
  gap: clamp(14px, 2.2vw, 30px);
  align-content: start;
  min-width: 0;
  will-change: transform;
}
.wall__col--1 { animation: wall-up   46s linear infinite; }
.wall__col--2 { animation: wall-down 61s linear infinite; }
.wall__col--3 { animation: wall-up   53s linear infinite; }

@keyframes wall-up   { from { transform: translate3d(0, 0, 0); }    to { transform: translate3d(0, -50%, 0); } }
@keyframes wall-down { from { transform: translate3d(0, -50%, 0); } to { transform: translate3d(0, 0, 0); } }

.wall__t {
  border-radius: 10px; overflow: hidden;
  box-shadow: 0 30px 60px -30px rgba(0, 0, 0, .85);
  outline: 1px solid rgba(255, 255, 255, .07);
}
.wall__t img, .wall__t picture { display: block; width: 100%; height: auto; }

/*
 * THE PHONE GETS ITS OWN COMPOSITION, NOT THE DESKTOP ONE SHRUNK.
 *
 * Three columns at 375px is mush, so it drops to two, tilts harder because the
 * plane has to resolve in a third of the width, and moves out from behind the
 * headline where there is no room beside the text the way there is on a desk.
 * It keeps scrolling: the phone is where most people meet a link.
 */
@media (max-width: 760px) {
  .wall {
    inset: -6% -34% auto 24%;
    height: 108%;
    perspective: 900px; perspective-origin: 40% 18%;
    -webkit-mask-image: radial-gradient(140% 86% at 62% 22%, #000 30%, transparent 74%);
            mask-image: radial-gradient(140% 86% at 62% 22%, #000 30%, transparent 74%);
  }
  .wall__in {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
    transform: rotateX(38deg) rotateZ(-18deg) scale(1.2);
    opacity: .34;
  }
  .wall__col { gap: 12px; }
  /* The third column would sit almost entirely off-screen and is four image
     downloads for nothing. */
  .wall__col--3 { display: none; }
  .wall__t { border-radius: 7px; }
}

@media (max-width: 420px) {
  .wall { inset: -4% -46% auto 32%; }
  .wall__in { grid-template-columns: minmax(0, 1fr); opacity: .3; }
  .wall__col--2 { display: none; }
}

/* Asked for stillness, the plane holds its angle and stops. */
@media (prefers-reduced-motion: reduce) {
  .wall__col { animation: none; }
}

.hero__veil {
  position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(102deg, rgba(7,17,38,.96) 0%, rgba(20,35,92,.86) 40%, rgba(20,35,92,.22) 72%, rgba(20,35,92,.06) 100%),
    linear-gradient(0deg, rgba(7,17,38,.72) 0%, rgba(7,17,38,0) 46%);
}
/*
 * width: 100% because .hero is a grid.
 *
 * .wrap carries margin-inline: auto to centre itself, which is right in normal
 * flow. As a GRID ITEM those auto margins beat the default stretch, so the
 * element takes its fit-content width and the margins absorb the rest: the
 * wrap measured 509px inside a 1265px hero and the headline sat wherever its
 * own longest line put it, roughly a third of the way across and aligned with
 * nothing below it. Every section further down starts at the wrap edge.
 *
 * Stretching it back to full width lets max-width: 1200px do the job it was
 * written to do, and the hero headline now begins on the same vertical as the
 * rest of the page.
 */
.hero__in { width: 100%; padding-block: clamp(96px, 14vw, 150px) clamp(52px, 7vw, 84px); }
.hero__c { max-width: 40ch; }
.hero h1 { color: #fff; }
.hero h1 em { font-style: normal; color: var(--gold); }
.hero .lede { color: #d5deee; margin-top: 1.1em; max-width: 44ch; }
.hero__cta { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 2rem; }
.hero__note { margin-top: 1.9rem; font-size: .84rem; color: #9fb2cc; letter-spacing: .01em; max-width: 46ch; }

.tag { display: inline-flex; align-items: center; gap: .6em; padding: 6px 14px 6px 10px;
       border-radius: var(--r-pill); background: rgba(255,255,255,.1);
       border: 1px solid rgba(255,255,255,.2); font-size: .8rem; font-weight: 600;
       letter-spacing: .04em; text-transform: uppercase; color: #fff; margin-bottom: 1.5rem; }
.tag b { color: var(--gold); font-weight: 600; }

/* ---- reveal ------------------------------------------------------------- */
.rv { opacity: 0; transform: translateY(26px); transition: opacity .8s var(--ease), transform .8s var(--ease); }
.rv[data-in] { opacity: 1; transform: none; }
.rv--d1 { transition-delay: .09s; } .rv--d2 { transition-delay: .18s; } .rv--d3 { transition-delay: .27s; }

/* ---- the running dashboard ---------------------------------------------- */
.stage { background: linear-gradient(180deg, var(--night) 0%, #0b2039 100%); color: #eef5fc; }
.stage .eyebrow { color: var(--gold); }
.stage h2 { color: #fff; }
.stage .lede { color: #b0c6db; }
.stage__head { display: grid; gap: 8px; margin-bottom: clamp(32px, 5vw, 54px); }

.app {
  border-radius: var(--r-lg); overflow: hidden; background: var(--paper);
  box-shadow: var(--shadow-lg), 0 0 0 1px rgba(255,255,255,.09);
  color: var(--ink); container-type: inline-size;
}
.app__bar { display: flex; align-items: center; gap: 8px; padding: 11px 15px;
            background: #fff; border-bottom: 1px solid var(--line); }
.app__dots { display: flex; gap: 6px; }
.app__dots i { width: 10px; height: 10px; border-radius: 50%; background: #d9dee9; }
.app__url { margin-inline: auto; font-family: var(--mono); font-size: .74rem; color: #525c6e;
            background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-pill);
            padding: 4px 15px; }
.app__body { display: grid; grid-template-columns: 1fr; }
@container (min-width: 800px) { .app__body { grid-template-columns: 208px 1fr; } }

.rail { background: #fff; border-right: 1px solid var(--line); padding: 16px 12px; display: none; }
@container (min-width: 800px) { .rail { display: block; } }
.rail__b { display: flex; align-items: center; gap: 9px; padding: 0 8px 15px;
           font-family: var(--display); font-weight: 700; letter-spacing: -.02em; font-size: 1.02rem; }
.rail__b svg { width: 24px; height: 24px; }
.rail a { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: var(--r-sm);
          font-size: .84rem; color: var(--ink-2); text-decoration: none; font-weight: 500; }
.rail a[data-on] { background: var(--navy-tint); color: var(--navy); font-weight: 600; }
.rail a i { width: 7px; height: 7px; border-radius: 2px; background: currentColor; opacity: .5; flex: none; }
.rail a[data-on] i { opacity: 1; }

.canvas { padding: clamp(16px, 2.4cqw, 26px); display: grid; gap: 16px; min-width: 0; }
.canvas__h { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.canvas__h h4 { margin: 0; font-family: var(--display); font-size: 1.3rem; letter-spacing: -.02em; }
.canvas__h span { font-size: .82rem; color: #525c6e; }

.stats { display: grid; gap: 12px; grid-template-columns: repeat(2, 1fr); }
@container (min-width: 640px) { .stats { grid-template-columns: repeat(4, 1fr); } }
.stat { position: relative; background: #fff; border: 1px solid var(--line); border-radius: var(--r);
        padding: 14px 15px 14px 20px; overflow: hidden; }
/* The block runs the full height, square on the left, rounded on the right.
   This is the product's own card signature, reproduced exactly. */
.stat::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 5px;
                background: var(--tone, var(--navy)); border-radius: 0 4px 4px 0; }
.stat b { display: block; font-family: var(--display); font-size: clamp(1.15rem, 2.4cqw, 1.7rem);
          letter-spacing: -.03em; font-variant-numeric: tabular-nums; line-height: 1.12; }
.stat span { display: block; font-size: .73rem; color: #525c6e; margin-top: 3px; line-height: 1.3; }
.stat u { display: inline-block; margin-top: 7px; font-size: .68rem; text-decoration: none;
          font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--tone, var(--navy)); }

.duo { display: grid; gap: 16px; grid-template-columns: 1fr; }
@container (min-width: 760px) { .duo { grid-template-columns: 1.35fr 1fr; } }
.panel { background: #fff; border: 1px solid var(--line); border-radius: var(--r); padding: 16px 17px; min-width: 0; }
.panel h5 { margin: 0 0 2px; font-family: var(--display); font-size: .97rem; letter-spacing: -.012em; }
.panel p.sub { margin: 0 0 14px; font-size: .76rem; color: #525c6e; }

.bars { display: grid; gap: 11px; }
.bar__t { display: flex; justify-content: space-between; font-size: .76rem; margin-bottom: 4px; }
.bar__t b { font-variant-numeric: tabular-nums; font-weight: 600; }
.bar__t span { color: #525c6e; }
.bar__r { height: 9px; border-radius: var(--r-pill); background: var(--navy-tint); overflow: hidden; }
.bar__f { height: 100%; width: 0; border-radius: var(--r-pill); background: var(--tone, var(--navy));
          transition: width 1.5s var(--ease); }
[data-lit] .bar__f { width: var(--w); }

.chain { display: grid; gap: 0; }
.step { display: grid; grid-template-columns: 26px 1fr; gap: 11px; padding-bottom: 15px; position: relative; }
.step:last-child { padding-bottom: 0; }
.step::before { content: ""; position: absolute; left: 12.5px; top: 24px; bottom: 0; width: 2px; background: var(--line); }
.step:last-child::before { display: none; }
.step i { grid-row: 1 / 3; width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center;
          background: var(--paper); border: 2px solid var(--line); color: #525c6e;
          font-size: .75rem; font-weight: 700; font-style: normal; z-index: 1;
          transition: background .45s var(--ease), border-color .45s var(--ease), color .45s var(--ease); }
.step b { font-size: .84rem; font-weight: 600; display: block; }
.step span { font-size: .73rem; color: #525c6e; }
[data-lit] .step[data-done] i { background: var(--navy); border-color: var(--navy); color: #fff; }
[data-lit] .step[data-now] i { background: #fff; border-color: var(--gold); color: var(--navy); box-shadow: 0 0 0 4px var(--gold-tint); }
[data-lit] .step[data-done] i { transition-delay: calc(var(--k) * .16s); }

.caption { margin: 18px auto 0; text-align: center; font-size: .82rem; color: #8fa6c2; max-width: 66ch; }

/* ---- portfolio ---------------------------------------------------------- */
.folio { display: grid; gap: clamp(18px, 2.4vw, 28px); grid-template-columns: 1fr; }
@media (min-width: 760px) { .folio { grid-template-columns: repeat(2, 1fr); } }
.shot { position: relative; border-radius: var(--r-lg); overflow: hidden; background: var(--card);
        border: 1px solid var(--rule); box-shadow: var(--shadow); }
.shot--wide { grid-column: 1 / -1; }
.shot__f { position: relative; overflow: hidden; aspect-ratio: 3 / 2; }
.shot--wide .shot__f { aspect-ratio: 21 / 9; }
.shot__f img { width: 100%; height: 100%; object-fit: cover;
               transform: scale(1.03); transition: transform 1.1s var(--ease); }
.shot:hover .shot__f img, .shot:focus-within .shot__f img { transform: scale(1.09); }
.shot__b { padding: 18px 20px 22px; }
.shot__b h3 { margin-bottom: .3em; }
.shot__b p { font-size: .93rem; color: var(--text-2); margin: 0; max-width: 52ch; }
.shot__k { position: absolute; top: 14px; left: 14px; z-index: 2;
           background: rgba(7,17,38,.82); backdrop-filter: blur(6px); color: #fff;
           font-size: .75rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
           padding: 6px 12px; border-radius: var(--r-pill); }

/* ---- capability list ---------------------------------------------------- */
.grid3 { display: grid; gap: clamp(20px, 2.6vw, 34px); grid-template-columns: 1fr; }
@media (min-width: 700px) { .grid3 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1020px) { .grid3 { grid-template-columns: repeat(3, 1fr); } }
.cap { border-top: 2px solid var(--brand); padding-top: 16px; }
.cap h3 { margin-bottom: .3em; }
.cap p { font-size: .95rem; color: var(--text-2); margin: 0; }

/* ---- proof strip -------------------------------------------------------- */
.proof { background: var(--brand-tint); border-block: 1px solid var(--rule); }
.proof__g { display: grid; gap: 26px; grid-template-columns: repeat(2, 1fr); }
@media (min-width: 880px) { .proof__g { grid-template-columns: repeat(4, 1fr); } }
.proof .fig { font-size: clamp(1.7rem, 1.2rem + 1.8vw, 2.5rem); letter-spacing: -.035em;
              font-variant-numeric: tabular-nums; line-height: 1; margin: 0 0 6px; color: var(--text); }
.proof p { font-size: .87rem; color: var(--text-2); margin: 0; }

/* ---- pricing ------------------------------------------------------------ */
.tiers { display: grid; gap: 18px; grid-template-columns: 1fr; align-items: start; }
@media (min-width: 880px) { .tiers { grid-template-columns: repeat(3, 1fr); } }
.tier { background: var(--card); border: 1px solid var(--rule); border-radius: var(--r-lg);
        padding: 26px 24px 28px; box-shadow: var(--shadow); position: relative; }
.tier--pick { border-color: var(--brand); box-shadow: var(--shadow-lg); }
.tier__k { font-size: .75rem; font-weight: 700; letter-spacing: .13em; text-transform: uppercase;
           color: var(--brand); margin: 0 0 10px; }
.tier__p { font-family: var(--display); font-size: 2.3rem; letter-spacing: -.035em; line-height: 1; margin: 0; }
.tier__p small { font-family: var(--ui); font-size: .88rem; font-weight: 500; letter-spacing: 0; color: var(--text-2); }
.tier__s { font-size: .87rem; color: var(--text-2); margin: 8px 0 18px; }
.tier ul { list-style: none; margin: 0 0 22px; padding: 0; display: grid; gap: 9px; }
.tier li { font-size: .91rem; padding-left: 22px; position: relative; color: var(--text-2); }
.tier li::before { content: ""; position: absolute; left: 0; top: .52em; width: 9px; height: 9px;
                   border-radius: 2px; background: var(--brand); }
.tier .btn { width: 100%; }
.flag { position: absolute; top: -11px; right: 20px; background: var(--gold); color: var(--on-gold);
        font-size: .75rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
        padding: 5px 12px; border-radius: var(--r-pill); }

/* ---- close -------------------------------------------------------------- */
.close { background: linear-gradient(112deg, var(--night) 0%, var(--navy-deep) 100%); color: #fff; }
.close h2 { color: #fff; }
.close p { color: #c3d1e6; }
.close .eyebrow { color: var(--gold); }
.close__cta { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 1.8rem; }



@media (prefers-reduced-motion: reduce) {
  .hero__img img { animation: none; transform: scale(1.05); }
  .rv { opacity: 1; transform: none; transition: none; }
  .shot__f img, .bar__f, .step i, .btn { transition: none; }
  .shot:hover .shot__f img { transform: scale(1.03); }
  * { scroll-behavior: auto; }
}

/* ---- masthead controls -------------------------------------------------- */
.mast__act { display: flex; align-items: center; gap: 8px; }
/*
 * Sign in was display:none below 560px, so on a phone a returning customer
 * had no way into the product from the front door. It is now present at every
 * width and drawn as a control rather than as body text beside a filled
 * button, because a bare grey link next to a solid navy button does not read
 * as something you can press.
 */
.mast__in {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: 0 16px; border-radius: var(--r);
  border: 1px solid var(--rule); background: var(--card);
  color: var(--text); text-decoration: none;
  font-size: .93rem; font-weight: 600; white-space: nowrap;
  transition: border-color .2s var(--ease), color .2s var(--ease), transform .18s var(--ease);
}
.mast__in:hover { border-color: var(--brand); color: var(--brand); transform: translateY(-1px); }

/* On a narrow screen the three controls have to share 375px with the
   wordmark. Signing in is what a returning customer came for, so it keeps its
   full label and the primary shortens instead of either one wrapping. */
@media (max-width: 560px) {
  .mast { gap: 10px; padding-inline: 16px; }
  .mast__act { gap: 6px; }
  .mast__in, .mast .btn { padding-inline: 12px; font-size: .88rem; }
  .mast .btn--primary .full { display: none; }
}
@media (min-width: 561px) { .mast .btn--primary .short { display: none; } }
.mast__in:hover { color: var(--text); }

/* RENAMED FROM .hero__in, WHICH ALREADY MEANT SOMETHING ELSE.
   .hero__in is the hero_s inner padding wrapper and has been since the first
   draft. Adding a second rule under the same name put text-decoration:
   underline on that wrapper, and because decoration is painted onto every
   descendant rather than inherited, the headline, the lead paragraph and both
   buttons were all underlined. Every one of them still computed
   text-decoration-line: none, which is why inspecting the h1 said nothing was
   wrong. A class name is a namespace; this one was already taken. */
.hero__signin { color: #fff; text-decoration: underline; text-underline-offset: 3px;
                text-decoration-thickness: 1px; }
.hero__signin:hover { color: var(--gold); }

/* ---- footer ------------------------------------------------------------- */
footer { border-top: 1px solid var(--rule); padding-block: clamp(40px, 5vw, 64px) 34px;
         font-size: .9rem; color: var(--text-2); }
.foot__top { display: grid; gap: clamp(28px, 4vw, 48px); grid-template-columns: 1fr;
             padding-bottom: clamp(28px, 3.5vw, 42px); }
@media (min-width: 620px)  { .foot__top { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 980px)  { .foot__top { grid-template-columns: 2fr 1fr 1fr 1fr; } }
.foot__id .logo { margin-bottom: 12px; }
.foot__id p { font-size: .89rem; max-width: 34ch; margin: 0; }
.foot__col { display: grid; align-content: start; gap: 9px; }
.foot__col h2 { font-family: var(--ui); font-size: .75rem; font-weight: 700; letter-spacing: .13em;
                text-transform: uppercase; color: var(--text); margin: 0 0 3px; }
.foot__col a { color: var(--text-2); text-decoration: none; font-size: .9rem; width: fit-content;
               transition: color .2s var(--ease); }
.foot__col a:hover { color: var(--brand); text-decoration: underline; text-underline-offset: 3px; }
.foot__bar { border-top: 1px solid var(--rule); padding-top: 22px; display: flex;
             flex-wrap: wrap; gap: 10px 26px; align-items: baseline; }
.foot__bar p { margin: 0; font-size: .84rem; max-width: none; }
.foot__bar p:first-child { margin-right: auto; }
.foot__bar a { color: var(--text-2); }
.foot__legalinks { display: flex; gap: 20px; }

/* ---- long-form legal pages ---------------------------------------------- */
.doc { padding-block: clamp(44px, 6vw, 84px) clamp(56px, 7vw, 96px); }
.doc__h { border-bottom: 1px solid var(--rule); padding-bottom: clamp(22px, 3vw, 34px);
          margin-bottom: clamp(30px, 4vw, 48px); }
.doc__h h1 { font-size: clamp(2rem, 1.4rem + 2.2vw, 3rem); }
.doc__h p { margin: .8em 0 0; color: var(--text-2); }
.doc__b { max-width: 74ch; }
.doc__b h2 { font-size: clamp(1.25rem, 1.05rem + .8vw, 1.6rem); margin: 2.2em 0 .5em;
             scroll-margin-top: 90px; }
.doc__b h2:first-child { margin-top: 0; }
.doc__b h3 { margin: 1.7em 0 .4em; font-size: 1.03rem; }
.doc__b p, .doc__b li { color: var(--text-2); }
.doc__b ul { padding-left: 1.15em; margin: 0 0 1.1em; }
.doc__b li { margin-bottom: .45em; }
.doc__b strong { color: var(--text); font-weight: 600; }
.doc__toc { background: var(--brand-tint); border: 1px solid var(--rule); border-radius: var(--r-lg);
            padding: 20px 24px; margin-bottom: clamp(28px, 3.4vw, 42px); }
.doc__toc h2 { margin: 0 0 10px; font-size: .74rem; letter-spacing: .13em; text-transform: uppercase;
               font-family: var(--ui); color: var(--text); }
.doc__toc ol { margin: 0; padding-left: 1.3em; columns: 2; column-gap: 30px; font-size: .9rem; }
.doc__toc li { margin-bottom: .3em; break-inside: avoid; }
@media (max-width: 560px) { .doc__toc ol { columns: 1; } }
.doc__note { background: var(--card); border: 1px solid var(--rule); border-left: 4px solid var(--brand);
             border-radius: 0 var(--r) var(--r) 0; padding: 16px 20px; margin: 1.6em 0; }
.doc__note p:last-child { margin-bottom: 0; }

/* ---- type settings ------------------------------------------------------- */
/*
 * These were previously carried on individual rules and set for the intended
 * faces while a substitute was actually rendering. Now that the real ones load,
 * they are collected here so the reasoning sits in one place.
 */

/* Inter ships old-style figures off by default but its tabular set is what makes
   a column of money line up. Applied to the page rather than per widget, because
   the failure mode is a number somewhere nobody thought to annotate. */
body { font-variant-numeric: tabular-nums; font-feature-settings: "cv05" 1, "cv11" 1; }
/* cv05 gives the lower-case l a tail and cv11 opens the a, both of which stop
   Il1 and a/o collapsing into each other at the small sizes used in the cards. */

/* Running text wants proportional figures, not tabular: a date or a price inside
   a sentence should not sit in a monospaced slot. */
p, li, .lede, .shot__b p, .cap p, .doc__b p, .doc__b li, .tier__s {
  font-variant-numeric: proportional-nums;
}

/*
 * Optical sizing and tracking. Space Grotesk is a wide display face and takes
 * real negative tracking at large sizes; it needs LESS of it as the size drops,
 * and none at all at body size. The single -0.022em that used to apply to every
 * heading was too tight on h3 and not tight enough on h1.
 */
h1 { letter-spacing: -0.032em; }
h2 { letter-spacing: -0.022em; }
h3 { letter-spacing: -0.008em; }
.fig, .tier__p { letter-spacing: -0.03em; }
.eyebrow, .tier__k, .foot__col h2, .doc__toc h2, .shot__k { letter-spacing: 0.12em; }

/* Inter's default line height is tight for long-form reading. The legal pages
   are the only place on this site where somebody reads several hundred words in
   a row, and they get the loosest setting for that reason. */
.doc__b p, .doc__b li { line-height: 1.72; }

/* Stop a heading breaking one word onto its own line, which is the single most
   common way a well-set page still looks amateur. */
h1, h2, h3, .fig { text-wrap: balance; }
p, .lede { text-wrap: pretty; }

/* Hyphenation off. A justified-looking rag is better than a hyphen in a product
   name, and nothing here is justified. */
h1, h2, h3, p, li { hyphens: none; }

/* ---- touch targets ------------------------------------------------------- */
/*
 * WCAG 2.5.8 wants 24px minimum and the practical floor on a phone is nearer 44,
 * because a fingertip is about 10mm and people are usually walking.
 *
 * The footer's column links measured 23px tall: text height and nothing else.
 * They are list-like navigation rather than links inside a sentence, so the
 * inline exemption does not cover them. Padding rather than a min-height on the
 * anchor, so the target grows around the text and the visual rhythm of the
 * column is preserved. The gap shrinks to compensate, so the block does not get
 * taller overall.
 *
 * The links in the copyright line ARE inside sentences and are exempt, but they
 * get a little vertical room anyway: on a phone they sit right at the bottom of
 * a long page, which is exactly where a mis-tap is most annoying.
 */
.foot__col { gap: 2px; }
.foot__col a { display: flex; align-items: center; min-height: 40px; }
.foot__legalinks a { display: inline-flex; align-items: center; min-height: 36px; }

/* The wordmark is the way back to the top of the site and was 30px. */
.mast .logo, footer .logo { min-height: 44px; }
.mast .logo { align-items: center; }

@media (max-width: 620px) {
  /* Two columns rather than one long ladder of forty-pixel rows, which on a
     phone pushed the copyright line off the end of a very long scroll. */
  .foot__top { grid-template-columns: repeat(2, 1fr); }
  .foot__id { grid-column: 1 / -1; }
}


/* ---- the product tour ---------------------------------------------------- */
/*
 * TWO LAYOUTS FOR ONE PIECE OF MARKUP.
 *
 * The page ships as an ordered list: six screenshots, each with a heading and
 * two paragraphs under it. That is the whole tour, readable top to bottom, and
 * it is what a crawler, a printer, and a browser with the script blocked all
 * get. None of the rules below are needed for it to make sense.
 *
 * site/js/tour.js sets data-live on the section once it has confirmed it can
 * drive the thing, and the [data-live] rules turn that list into a player:
 * one step at a time, controls revealed, progress bar running. Hiding a step
 * BEFORE the script has proved it can bring it back is how a page ends up
 * showing one screenshot and no way to reach the other five, so every
 * hiding rule here is behind that attribute.
 *
 * The stage is dark on both themes. The screenshots are of the light interface,
 * and floating them on the light page ground makes the panel edges disappear;
 * a dark surround reads as a screen being shown rather than as an image that
 * failed to load its border.
 */
/*
 * padding-block is reset, not omitted. There is a bare `section` rule earlier in
 * this stylesheet giving every section clamp(64px, 9vw, 128px) of vertical
 * padding, which is right for the full-bleed bands on the home page and wrong
 * here: this section sits inside .doc, which has already paid for that space, so
 * the tour opened with 115 pixels of nothing above the first screenshot.
 *
 * The element selector is doing its job for the page it was written for. This is
 * the page that has to say otherwise.
 */
.tour { margin-block: clamp(28px, 4vw, 44px); padding-block: 0; }
.tour:focus { outline: none; }
.tour:focus-visible { outline: 2px solid var(--brand); outline-offset: 6px; border-radius: var(--r-lg); }

.tour__reel { list-style: none; margin: 0; padding: 0; display: grid; gap: clamp(40px, 6vw, 72px); }

.tour__fig { margin: 0; display: grid; gap: clamp(16px, 2vw, 22px); }

/* The screen itself, in its browser furniture. */
.tour__shot {
  position: relative;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--night);
  box-shadow: var(--shadow-lg), 0 0 0 1px rgba(148, 170, 195, .22);
}
.tour__shot img,
.tour__shot picture { display: block; width: 100%; height: auto; }

/* The address bar. A label rather than a decoration: it names the route each
   screen actually lives at, which is the question people ask second. */
.tour__url {
  display: block;
  font-family: var(--mono);
  font-size: .74rem;
  line-height: 1;
  color: #7f9ab6;
  background: #0d2137;
  border-bottom: 1px solid rgba(255, 255, 255, .08);
  padding: 11px 16px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The highlight, built by the script only for steps carrying data-spot. The
   ring plus a very large spread shadow dims everything outside it without
   needing a second element to do the dimming. */
.tour__spot {
  position: absolute;
  border: 2px solid var(--gold);
  border-radius: var(--r-sm);
  pointer-events: none;
  box-shadow: 0 0 0 9999px rgba(4, 14, 26, .46);
  transition: opacity .5s var(--ease);
}

.tour__fig figcaption { max-width: 68ch; }
.tour__n {
  font-family: var(--display);
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--brand);
  margin: 0 0 .5em;
}
.tour__fig h3 { font-size: clamp(1.15rem, 1rem + .7vw, 1.5rem); margin: 0 0 .5em; }
.tour__fig figcaption p { color: var(--text-2); margin: 0 0 .7em; }
.tour__fig figcaption p:last-child { margin-bottom: 0; }

/* ---- the controls -------------------------------------------------------- */
.tour__bar { height: 3px; background: var(--rule); border-radius: var(--r-pill); overflow: hidden; margin-top: 20px; }
.tour__bar i { display: block; height: 100%; width: 0; background: var(--brand); border-radius: var(--r-pill); }

.tour__panel {
  margin-top: 18px;
  background: var(--night);
  border-radius: var(--r-lg);
  padding: clamp(16px, 2.4vw, 22px);
  display: grid;
  gap: 14px;
}
.tour__ctl { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.tour__note { margin: 0; font-size: .82rem; color: #7f9ab6; }

/* .btn--wire is authored for the hero, which is also dark, so it is correct
   here without a variant. Pressed state is the one thing it has no opinion
   about, and a toggle that does not show its state is a toggle people press
   twice. */
.tour__ctl .btn[aria-pressed="true"] { border-color: var(--gold); color: var(--gold); }

.tour__dots { display: flex; flex-wrap: wrap; gap: 6px; }
.tour__dot {
  width: 38px; height: 6px; padding: 0; border: 0; cursor: pointer;
  border-radius: var(--r-pill); background: #1e3a55;
  transition: background .3s var(--ease);
}
.tour__dot[data-on] { background: var(--brand); }
.tour__dot:hover { background: var(--gold); }
.tour__dot:focus-visible { outline: 2px solid var(--brand); outline-offset: 4px; }
/*
 * A six-pixel bar is a two-millimetre target and this row sits under the video
 * on a phone. The bar stays six pixels; the hit area is grown to 44 with a
 * pseudo-element, which is the one way to do it that does not change the
 * rhythm of the row.
 */
.tour__dot { position: relative; }
.tour__dot::after { content: ""; position: absolute; inset: -19px -3px; }

.tour__cta { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 1.2em; }
.doc__h--mid { border-bottom: 0; margin-top: clamp(40px, 5vw, 64px); }

/* ---- player mode --------------------------------------------------------- */
/*
 * Everything from here down applies only once the script has taken over. The
 * steps stack in one place and cross-fade; the reel is given the aspect ratio
 * of the capture so the caption below it does not jump as the image swaps.
 */
[data-live] .tour__reel { display: block; position: relative; }
[data-live] .tour__step { position: absolute; inset: 0 0 auto; opacity: 0; pointer-events: none;
  transition: opacity .55s var(--ease); }
[data-live] .tour__step[data-on] { position: relative; opacity: 1; pointer-events: auto; }

/*
 * THE SCREENS CROSS-FADE. THE WORDS DO NOT.
 *
 * Both steps exist during the half second the fade takes, stacked at the same
 * origin. On the screenshots that reads as a dissolve, which is what it is
 * meant to be. On the caption underneath it reads as two different paragraphs
 * printed over each other, because they are different lengths and the lines do
 * not align -- the first build of this page had "Every building, one record"
 * sitting through the middle of the sentence it was replacing.
 *
 * visibility is deliberately left out of the transition, so it flips at once
 * while opacity is still easing. The picture dissolves; the text just changes.
 */
[data-live] .tour__step figcaption { visibility: hidden; }
[data-live] .tour__step[data-on] figcaption { visibility: visible; }
[data-live] .tour__spot { transition: opacity .5s var(--ease), top .8s var(--ease),
  left .8s var(--ease), width .8s var(--ease), height .8s var(--ease); }

@media (prefers-reduced-motion: reduce) {
  [data-live] .tour__step,
  .tour__spot,
  .tour__dot { transition: none; }
}

@media (max-width: 620px) {
  /* The address bar is the first thing to go: on a narrow screen it is a
     truncated string that tells nobody anything. */
  .tour__url { display: none; }
  .tour__ctl .btn { flex: 1 1 calc(50% - 4px); }
}
