/* --------------------------------------------------------------------------
   Noxere — the public page
   --------------------------------------------------------------------------

   Loaded after app.css and depends on it. Every colour, radius and easing here
   is one of the panel's own custom properties, so the page and the product a
   customer signs into cannot drift apart: change --accent once and both move.

   What is different is scale, not language. A panel is read at arm's length by
   somebody who already bought; a page is scanned by somebody deciding. So the
   type is larger, the rhythm slower, and there is one action per screenful —
   the same components, given room.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   1. Shell
   -------------------------------------------------------------------------- */

.site {
  --site-page: 1120px;
  --gutter: 24px;
}

.wrap {
  width: 100%;
  max-width: var(--site-page);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.wrap-tight { max-width: 760px; }

/* Deliberately NOT scroll-behavior: smooth.
   It reads as the obvious way to do this and it fights the one below it: the
   rule applies to every programmatic scroll too, so a script moving the page a
   frame at a time has each of its sixty steps taken as a fresh animation to be
   eased into, each one interrupting the last. The result stutters. The glide is
   run in JavaScript instead, where its duration and its easing can be chosen,
   and where "the reader asked for less motion" can actually be honoured. */

/* And they stop below the bar rather than under it — a heading hidden by the
   thing that scrolled you to it is the usual way this goes wrong. */
section[id] { scroll-margin-top: 96px; }

/* --------------------------------------------------------------------------
   2. Header

   The panel's own floating rail, brought out to the page: a bar that sits on
   the content with a margin around it rather than a strip welded to the top of
   the window. It is the first thing a visitor sees and the first thing they see
   again after they buy, so it is the same object in both places — a different
   header on the way in and on the way back reads as two different products.
   -------------------------------------------------------------------------- */

.site-head {
  position: sticky;
  top: var(--rail-gap);
  z-index: 60;
  padding: 0 var(--gutter);
  margin-top: var(--rail-gap);
}

.site-bar {
  max-width: var(--site-page);
  margin: 0 auto;
  padding: 10px 12px 10px 14px;
  display: flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: rgba(13, 14, 16, .78);
  backdrop-filter: saturate(150%) blur(18px);
  -webkit-backdrop-filter: saturate(150%) blur(18px);
  transition: background .3s var(--ease), border-color .3s var(--ease),
              box-shadow .3s var(--ease);
}

/* Once the page has moved, the bar has content behind it rather than beside it,
   so it takes a little more weight to stay legible. */
.site-head.is-stuck .site-bar {
  background: rgba(13, 14, 16, .93);
  border-color: var(--line-2);
  box-shadow: 0 18px 40px -28px rgba(0, 0, 0, 1);
}

.site-mark {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding-right: 6px;
  font-size: 15px;
  font-weight: 560;
  letter-spacing: -.012em;
  color: var(--fg);
  text-decoration: none;
}

.site-mark img { display: block; width: 26px; height: 26px; }

/* Centred between the two ends rather than pinned to one of them. */
.site-nav { display: flex; align-items: center; gap: 4px; margin: 0 auto; }

.site-nav a {
  display: flex;
  align-items: center;
  height: 38px;
  padding: 0 14px;
  border-radius: 10px;
  font-size: 14px;
  font-weight: 460;
  color: var(--fg-3);
  text-decoration: none;
  white-space: nowrap;
  transition: color .2s var(--ease), background .2s var(--ease);
}

.site-nav a:hover { color: var(--fg); background: var(--surface-2); }

/* The section being read, marked by fill and ink only — an outline on top of a
   fill draws a second shape and the item stops looking selected. */
.site-nav a[aria-current] { color: var(--fg); background: var(--surface-2); }

.site-cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 38px;
  padding: 0 15px;
  border: 1px solid var(--line-3);
  border-radius: 10px;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--fg);
  text-decoration: none;
  white-space: nowrap;
  transition: border-color .2s var(--ease), background .2s var(--ease);
}

.site-cta:hover { border-color: var(--accent-edge); background: var(--accent-wash); }
.site-cta svg { width: 15px; height: 15px; opacity: .9; }

/* On a narrow screen the anchors go and the two ends stay — the way in matters
   more than a table of contents for a page this short. */
@media (max-width: 780px) {
  .site-nav { display: none; }
  .site-mark span { display: none; }
  .site-bar { justify-content: space-between; }
}

/* --------------------------------------------------------------------------
   3. Hero
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  padding: 86px 0 64px;
  text-align: center;
  overflow: hidden;
}

/* One soft light behind the headline. Not decoration for its own sake: the page
   is nearly black and the video below it is bright, so without a gradient in
   between the eye jumps straight past the words. */
.hero::before {
  content: "";
  position: absolute;
  top: -220px;
  left: 50%;
  width: 900px;
  height: 620px;
  transform: translateX(-50%);
  background: radial-gradient(closest-side, var(--accent-wash), transparent 72%);
  pointer-events: none;
}

.hero > * { position: relative; }

/* The marks alone, with no pill around them.
   A frame is a container, and a container with nothing in it but two logos
   invites the reader to look for the missing label. Without it they read as
   what they are: where this runs. */
.hero-kicker {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 26px;
}

/* The platform marks, in ink rather than in the accent — they say where it
   runs, which is a fact about the product, not the one action on the page. */
/* No divider now that there is nothing on the other side of it. */
.hero-kicker .plat {
  display: inline-flex;
  align-items: center;
  gap: 13px;
  color: var(--fg);
}

/* Half again as large. At 14px they were details on a badge; at 21px, and with
   nothing around them, they are the statement. */
.hero-kicker .plat svg { width: 21px; height: 21px; display: block; }

.hero-h {
  margin: 0;
  font-size: clamp(38px, 6.4vw, 68px);
  line-height: 1.04;
  font-weight: 600;
  letter-spacing: -.035em;
}

/* The three beats of the slogan, so each lands on its own. */
.hero-h span { display: inline-block; }
.hero-h span + span { margin-left: .28em; }
.hero-h .on { color: var(--accent); }

.hero-sub {
  max-width: 620px;
  margin: 22px auto 0;
  font-size: clamp(15.5px, 1.7vw, 18px);
  line-height: 1.65;
  color: var(--fg-2);
}

.hero-acts {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-top: 34px;
  flex-wrap: wrap;
}

.hero-note {
  margin-top: 14px;
  font-size: 13px;
  color: var(--fg-3);
}

/* --------------------------------------------------------------------------
   4. The video

   Given a frame rather than dropped on the page, because the thing it shows is
   a dark application on a dark background — without an edge it dissolves into
   the page and reads as an image that failed to load.
   -------------------------------------------------------------------------- */

.stage {
  margin-top: 54px;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  background: linear-gradient(180deg, var(--surface) 0%, var(--bg-raise) 100%);
  box-shadow: 0 40px 120px -40px rgba(0, 0, 0, .9);
}

.stage-in {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--bg);
}

.stage video,
.stage img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Shown until there is a file to play. Says what it is rather than pretending
   to be a player that does nothing when pressed. */
.stage-soon {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  gap: 12px;
  justify-items: center;
  background:
    radial-gradient(closest-side at 50% 42%, var(--accent-wash), transparent 70%),
    var(--surface);
  color: var(--fg-3);
  font-size: 13.5px;
}

.stage-soon .ring {
  width: 58px; height: 58px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line-2);
  border-radius: 50%;
  color: var(--fg-2);
}

/* --------------------------------------------------------------------------
   5. Sections
   -------------------------------------------------------------------------- */

.band { padding: 84px 0; }
.band-line { border-top: 1px solid var(--line); }

.band-head { max-width: 640px; margin: 0 auto 46px; text-align: center; }

.band-head h2 {
  margin: 0;
  font-size: clamp(26px, 3.4vw, 36px);
  line-height: 1.18;
  font-weight: 570;
  letter-spacing: -.025em;
}

.band-head p {
  margin: 14px 0 0;
  font-size: 15.5px;
  line-height: 1.65;
  color: var(--fg-2);
}

/* Three to a row, said explicitly rather than left to auto-fit.
   auto-fit decides the count from the available width, which on a wide screen
   made a fourth column and left the last row holding one card on its own — a
   grid that looks like it lost something. The count is a property of the
   content here, so it is written down. */
.grid {
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

@media (max-width: 980px) { .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px) { .grid { grid-template-columns: 1fr; } }

.feat {
  padding: 26px 24px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  transition: border-color .25s var(--ease), transform .25s var(--ease);
}

.feat:hover { border-color: var(--line-2); transform: translateY(-2px); }

.feat-i {
  width: 34px; height: 34px;
  display: grid;
  place-items: center;
  margin-bottom: 16px;
  border: 1px solid var(--line-2);
  border-radius: 10px;
  color: var(--accent);
}

.feat-i svg { width: 16px; height: 16px; }

.feat h3 {
  margin: 0 0 7px;
  font-size: 15.5px;
  font-weight: 540;
  letter-spacing: -.01em;
}

.feat p { margin: 0; font-size: 14px; line-height: 1.68; color: var(--fg-2); }

/* --------------------------------------------------------------------------
   6. Steps
   -------------------------------------------------------------------------- */

.steps { display: grid; gap: 2px; max-width: 720px; margin: 0 auto; }

.step {
  display: flex;
  gap: 20px;
  padding: 24px 0;
  border-bottom: 1px solid var(--line);
}

.step:last-child { border-bottom: 0; }

.step-n {
  flex-shrink: 0;
  width: 30px; height: 30px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line-2);
  border-radius: 50%;
  font-size: 12.5px;
  color: var(--fg-2);
  font-variant-numeric: tabular-nums;
}

.step h3 { margin: 3px 0 6px; font-size: 15.5px; font-weight: 540; }
.step p  { margin: 0; font-size: 14px; line-height: 1.68; color: var(--fg-2); }

/* --------------------------------------------------------------------------
   7. Price

   A panel rather than a paragraph with a button under it. Somebody arriving
   here has already decided they are interested; what they are doing now is
   checking what the money buys, which is a list they read across, not prose.
   -------------------------------------------------------------------------- */

.price {
  margin: 0 auto;
  border: 1px solid var(--line-2);
  border-radius: var(--r-xl);
  background:
    radial-gradient(closest-side at 50% -10%, var(--accent-wash), transparent 68%),
    var(--surface);
  overflow: hidden;
}

.price-top {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
  padding: 32px 34px 26px;
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}

.price-what { display: grid; gap: 6px; justify-items: end; text-align: right; }

.price-plan {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--fg-3);
}

.price-plan i {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--accent);
}

.price-what strong { font-size: 17px; font-weight: 540; letter-spacing: -.01em; }

.price-fig { text-align: left; }

.price-n {
  font-size: 54px;
  line-height: 1;
  font-weight: 600;
  letter-spacing: -.04em;
}

.price-n small { font-size: 16px; font-weight: 450; color: var(--fg-3); letter-spacing: 0; }

.price-per { margin-top: 6px; font-size: 12.5px; color: var(--fg-3); }

/* Two columns, because six lines in one column reads as a long list and six
   across two reads as a specification. */
/* Three columns across the full width, because the list is the argument here:
   twelve lines stacked in one narrow column reads as terms and conditions, and
   the same twelve laid out across reads as what is in the box. */
.price-list {
  margin: 0;
  padding: 30px 34px 6px;
  list-style: none;
  display: grid;
  gap: 14px 34px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

@media (max-width: 980px) { .price-list { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.price-list li {
  display: flex;
  gap: 11px;
  font-size: 14px;
  line-height: 1.5;
}

.price-list svg { flex-shrink: 0; width: 15px; height: 15px; margin-top: 3px; color: var(--accent); }

/* Name over description, not name then dash then description.
   Run together on one line the two read as a single sentence and the eye has to
   parse it to find out which part is the thing being offered; stacked, the
   column can be scanned by its first lines alone and the second lines are there
   for whoever wants them. */
.price-list span { display: grid; gap: 3px; }
.price-list b { color: var(--fg); font-weight: 520; letter-spacing: -.005em; }
.price-list b + * ,
.price-list b ~ span { color: var(--fg-3); }
.price-list li > span { color: var(--fg-3); }
.price-list li > span > b { color: var(--fg); }

/* The button keeps a sane width even when the panel is wide — a call to action
   stretched across 1100px reads as a banner rather than a thing to press. */
.price-act { padding: 30px 34px 34px; }
.price-act .btn { max-width: 420px; margin: 0 auto; }

@media (max-width: 620px) {
  .price-top  { padding: 26px 22px 22px; }
  .price-list { padding: 24px 22px 2px; grid-template-columns: 1fr; }
  .price-act  { padding: 22px 22px 26px; }
  .price-what { justify-items: start; text-align: left; }
}

/* --------------------------------------------------------------------------
   8. Footer
   -------------------------------------------------------------------------- */

.site-foot {
  padding: 40px 0 56px;
  border-top: 1px solid var(--line);
}

.site-foot-in {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  flex-wrap: wrap;
  font-size: 13px;
  color: var(--fg-3);
}

.site-foot a { color: var(--fg-3); text-decoration: none; }
.site-foot a:hover { color: var(--fg-2); }
.site-foot nav { display: flex; gap: 20px; }

/* --------------------------------------------------------------------------
   9. Entrance

   The panel's own .rise, kept in step with it. Anything that has already
   scrolled past is not animated — a section that fades in after the reader has
   arrived at it reads as a page still loading.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  .up {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity .6s var(--ease), transform .6s var(--ease);
  }

  .up.in { opacity: 1; transform: none; }
}
