@font-face {
  font-family: "Manrope";
  src: url("fonts/manrope-latin-var.woff2") format("woff2-variations");
  font-weight: 200 800;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("fonts/ibm-plex-mono-latin-400.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("fonts/ibm-plex-mono-latin-600.woff2") format("woff2");
  font-weight: 600;
  font-display: swap;
}
/* guarder.io — the public site.
 *
 * Hand-written CSS, no framework and no build step: this page has to load fast
 * on a bad link and keep rendering when everything else is down, including the
 * hub it sells. The only thing it asks the network for beyond itself is four
 * self-hosted font files (see fonts/README.md) and they are optional.
 *
 * The palette is the app's own, token for token, so the site and the product
 * read as one thing: light --bg #f4f7fb / dark --bg #070d1a, accent #1d6fe0 /
 * #4d9bff, one blue plus the four status hues and nothing else. Both skins
 * follow prefers-color-scheme; there is no toggle, because a marketing page
 * has no session to remember a choice in.
 */

/* ------------------------------------------------------------------ fonts */





/* ----------------------------------------------------------------- tokens */
:root {
  --bg: #f4f7fb;
  --panel: #ffffff;
  --panel2: #eef3fa;
  --line: #dbe4f0;
  --ink: #0f1a2b;
  --mute: #5b6b82;
  --ok: #16a34a;
  --warn: #e0b000;
  --crit: #e02424;
  --acc: #1d6fe0;
  --accink: #ffffff;
  --shadow: 0 8px 28px rgba(15, 26, 43, 0.1);
  --radius: 14px;
  --font-sans: Manrope, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, Menlo, Consolas, monospace;
  /* A marketing page is read at arm's length, not scanned like a dashboard,
     so the base size is a step up from the app's 13.5px. */
  --fs: 16px;
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #070d1a;
    --panel: #0d1628;
    --panel2: #121d33;
    --line: #1e2c47;
    --ink: #e8eef8;
    --mute: #8fa3c2;
    --ok: #34d16a;
    --warn: #f5c518;
    --crit: #ff5a5a;
    --acc: #4d9bff;
    --accink: #04101f;
    --shadow: 0 10px 40px rgba(0, 0, 0, 0.55);
    --radius: 10px;
    color-scheme: dark;
  }
}

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

html {
  /* Anchor links from the nav land below the sticky header instead of under
     it. `scroll-behavior` is deliberately inside the reduced-motion guard
     further down rather than here. */
  scroll-padding-top: 84px;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--fs);
  line-height: 1.55;
  -webkit-text-size-adjust: 100%;
}

img,
svg {
  max-width: 100%;
}

h1,
h2,
h3 {
  line-height: 1.15;
  margin: 0 0 12px;
  letter-spacing: -0.015em;
}

h1 {
  font-size: clamp(30px, 6vw, 50px);
  font-weight: 700;
}

h2 {
  font-size: clamp(23px, 4vw, 32px);
  font-weight: 700;
}

h3 {
  font-size: 18px;
  font-weight: 600;
}

p {
  margin: 0 0 14px;
}

a {
  color: var(--acc);
}

code,
kbd {
  font-family: var(--font-mono);
  font-size: 0.9em;
}

/* Visible focus everywhere, on the accent, never removed. */
:focus-visible {
  outline: 3px solid var(--acc);
  outline-offset: 2px;
  border-radius: 4px;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--panel);
  color: var(--ink);
  border: 1px solid var(--acc);
  border-radius: 8px;
  padding: 10px 14px;
  z-index: 20;
}

.skip:focus {
  left: 12px;
  top: 12px;
}

/* ---------------------------------------------------------------- layout */
.wrap {
  width: 100%;
  max-width: 1080px;
  margin: 0 auto;
  padding: 0 20px;
}

section {
  padding: 68px 0;
  border-top: 1px solid var(--line);
}

section > .wrap > p.lede {
  color: var(--mute);
  max-width: 62ch;
  font-size: 1.05em;
}

/* ---------------------------------------------------------------- header */
.top {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
}

.top .wrap {
  display: flex;
  align-items: center;
  gap: 16px;
  min-height: 60px;
  flex-wrap: wrap;
  padding-top: 8px;
  padding-bottom: 8px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  font-weight: 700;
  font-size: 18px;
  color: var(--ink);
  text-decoration: none;
}

.brand svg {
  width: 26px;
  height: 26px;
  flex: none;
}

.top nav {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  margin-left: auto;
  align-items: center;
}

.top nav a {
  color: var(--mute);
  text-decoration: none;
  font-size: 14px;
  padding: 6px 9px;
  border-radius: 8px;
}

.top nav a:hover {
  color: var(--ink);
  background: var(--panel2);
}

/* ---------------------------------------------------------------- buttons */
.btn {
  display: inline-block;
  font: inherit;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  padding: 11px 20px;
  border-radius: 10px;
  border: 1px solid var(--acc);
  background: var(--acc);
  color: var(--accink);
}

.btn:hover {
  filter: brightness(1.08);
}

.btn.ghost {
  background: var(--panel);
  color: var(--acc);
}

.btn.ghost:hover {
  background: var(--panel2);
  filter: none;
}

.btn.small {
  padding: 8px 14px;
  font-size: 14px;
}

.btn[disabled] {
  opacity: 0.6;
  cursor: progress;
}

/* ------------------------------------------------------------------- hero */
.hero {
  border-top: none;
  padding: 76px 0 64px;
}

.hero h1 {
  max-width: 24ch;
}

.hero .sub {
  font-size: clamp(17px, 2.4vw, 21px);
  color: var(--mute);
  max-width: 56ch;
  margin-bottom: 26px;
}

.cta-row {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  align-items: center;
}

.cta-note {
  color: var(--mute);
  font-size: 14px;
  margin: 16px 0 0;
}

/* ------------------------------------------------------------------ cards */
.grid {
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  margin-top: 26px;
}

.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 18px 20px;
}

.card h3 {
  display: flex;
  align-items: center;
  gap: 9px;
}

.card p {
  color: var(--mute);
  margin: 0;
  font-size: 15px;
}

.dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex: none;
  background: var(--acc);
}

.dot.ok {
  background: var(--ok);
}

.dot.warn {
  background: var(--warn);
}

.dot.crit {
  background: var(--crit);
}

/* ------------------------------------------------------------------ steps */
.steps {
  counter-reset: step;
  list-style: none;
  margin: 26px 0 0;
  padding: 0;
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}

.steps li {
  counter-increment: step;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 18px 20px;
}

.steps li::before {
  content: counter(step);
  font-family: var(--font-mono);
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--panel2);
  color: var(--acc);
  border: 1px solid var(--line);
  font-weight: 600;
  margin-bottom: 10px;
}

.steps li p {
  color: var(--mute);
  margin: 0;
  font-size: 15px;
}

pre.cmd {
  font-family: var(--font-mono);
  font-size: 13.5px;
  background: var(--panel2);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 12px 14px;
  margin: 22px 0 0;
  overflow-x: auto;
}

/* ----------------------------------------------------------------- pricing */
.tiers {
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  margin-top: 26px;
  align-items: start;
}

.tier {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  height: 100%;
}

.tier h3 {
  margin: 0;
}

.tier .price {
  font-family: var(--font-mono);
  font-size: 26px;
  font-weight: 600;
}

.tier .price span {
  font-size: 13px;
  color: var(--mute);
  font-weight: 400;
}

.tier p {
  color: var(--mute);
  font-size: 14.5px;
  margin: 0;
  flex: 1;
}

.tier .btn {
  text-align: center;
}

/* ------------------------------------------------------- eyebrows & accents */
/* The small pill above the hero headline and the plain eyebrow above a
   section heading. Both are labels, not headings, so neither is an <h*>. */
.pill {
  display: inline-block;
  margin: 0 0 18px;
  padding: 6px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel);
  color: var(--mute);
  font-size: 13.5px;
  font-weight: 600;
}

.eyebrow {
  margin: 0 0 10px;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--acc);
}

/* The payoff half of a two-tone headline. Colour is never the only signal:
   it is always the second line of the sentence, so the meaning survives
   greyscale, high-contrast mode and a stylesheet that failed to load. */
.hl {
  color: var(--acc);
}

/* ------------------------------------------------------------- live panel */
.panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
}

.panel-head {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 14px 18px;
  border-bottom: 1px solid var(--line);
  background: var(--panel2);
}

.panel-title {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0;
}

.live-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ok);
  flex: none;
}

/* When the feed cannot be reached the dot stops claiming otherwise: grey,
   and still, whatever the motion preference says. */
.panel.offline .live-dot {
  background: var(--mute);
  animation: none;
}

/* The poll stamp. `margin-left:auto` puts it at the far end, and the fixed
   min-width means "1 min ago" and "14 min ago" occupy the same space -- the
   header must not reflow every time the panel refreshes. */
.poll {
  margin: 0 0 0 auto;
  min-width: 15ch;
  text-align: right;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--mute);
}

/* The panel's height is fixed by this, not by its contents: the fallback
   line, the placeholder rows and eight real rows all occupy the same box, so
   nothing on the page below moves when the feed arrives or goes away. */
.feed-body {
  min-height: 480px;
  display: flex;
  flex-direction: column;
}

.feed-fallback {
  margin: 0;
  padding: 22px 18px;
  color: var(--mute);
  font-size: 14.5px;
  max-width: 68ch;
}

.feed {
  list-style: none;
  margin: 0;
  padding: 0;
}

.feed-row {
  display: grid;
  grid-template-columns: 58px minmax(150px, 1.3fr) 2fr 70px;
  gap: 12px;
  align-items: center;
  min-height: 56px;
  padding: 8px 18px;
  border-bottom: 1px solid var(--line);
  font-size: 14px;
}

.feed-row:last-child {
  border-bottom: none;
}

.badge {
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-align: center;
  padding: 3px 0;
  border-radius: 5px;
  border: 1px solid currentColor;
  color: var(--acc);
}

.badge.ok { color: var(--ok); }
.badge.warn { color: var(--warn); }
.badge.crit { color: var(--crit); }

.feed-what {
  min-width: 0;
}

.feed-what b {
  display: block;
  font-weight: 600;
}

.feed-what span {
  display: block;
  color: var(--mute);
  font-size: 12.5px;
}

.feed-detail {
  color: var(--mute);
  min-width: 0;
  overflow-wrap: anywhere;
}

.feed-when {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--mute);
  text-align: right;
  white-space: nowrap;
}

/* A row with no data yet: the same geometry, nothing to read. Bars rather
   than text so it is never mistaken for a real notice, and aria-hidden in
   the markup so a screen reader is not read eight empty rows. */
.feed-row.skel .bar {
  display: block;
  height: 9px;
  border-radius: 4px;
  background: var(--panel2);
  border: 1px solid var(--line);
}

.feed-row.skel .bar.short { width: 45%; }

.panel-foot {
  margin: 0;
  padding: 12px 18px;
  border-top: 1px solid var(--line);
  background: var(--panel2);
  color: var(--mute);
  font-size: 12.5px;
}

/* ---------------------------------------------------------------- quotes */
.quotes {
  list-style: none;
  margin: 26px 0 10px;
  padding: 0;
  display: grid;
  gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}

.quotes li {
  background: var(--panel);
  border: 1px solid var(--line);
  border-left: 3px solid var(--acc);
  border-radius: var(--radius);
  padding: 16px 18px;
  font-size: 16px;
  font-style: italic;
  color: var(--ink);
}

.quotes-note {
  color: var(--mute);
  font-size: 13px;
  margin: 0 0 22px;
}

/* --------------------------------------------------------- pricing trial */
.trial {
  background: var(--panel);
  border: 1px solid var(--acc);
  border-radius: var(--radius);
  padding: 20px 22px;
  margin: 0 0 22px;
  max-width: 68ch;
}

.trial p {
  color: var(--mute);
  margin: 0 0 12px;
}

.trial p:last-child {
  margin-bottom: 0;
}

.trial strong {
  color: var(--ink);
}

.tier .price .then {
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 400;
  color: var(--mute);
  margin-right: 6px;
}

/* --------------------------------------------------------------------- faq */
.faq {
  margin-top: 26px;
  display: grid;
  gap: 10px;
}

.faq details {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 4px 18px;
}

.faq summary {
  cursor: pointer;
  font-weight: 600;
  padding: 14px 0;
  list-style: none;
}

.faq summary::-webkit-details-marker {
  display: none;
}

.faq summary::before {
  content: "+";
  font-family: var(--font-mono);
  color: var(--acc);
  margin-right: 10px;
  font-weight: 700;
}

.faq details[open] summary::before {
  content: "\2212";
}

.faq details > p {
  color: var(--mute);
  margin: 0 0 14px;
  max-width: 72ch;
}

/* -------------------------------------------------------------------- form */
.form-panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 22px;
  margin-top: 24px;
  max-width: 640px;
  box-shadow: var(--shadow);
}

.field {
  display: block;
  margin-bottom: 14px;
}

.field > span {
  display: block;
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 5px;
}

.field .hint {
  font-weight: 400;
  color: var(--mute);
}

input,
select,
textarea {
  font: inherit;
  width: 100%;
  color: var(--ink);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 9px 11px;
}

textarea {
  min-height: 84px;
  resize: vertical;
}

/* The honeypot. Off-screen rather than display:none, and aria-hidden with
   tabindex=-1, so a keyboard or screen-reader user can never reach it while a
   naive form-filling bot still sees a plain text input to fill in. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form-msg {
  margin: 14px 0 0;
  font-size: 15px;
  min-height: 1.55em;
}

.form-msg.ok {
  color: var(--ok);
}

.form-msg.bad {
  color: var(--crit);
}

/* ------------------------------------------------------------------ footer */
footer {
  border-top: 1px solid var(--line);
  background: var(--panel);
  padding: 30px 0;
  color: var(--mute);
  font-size: 14.5px;
}

footer .wrap {
  display: flex;
  gap: 16px 26px;
  flex-wrap: wrap;
  align-items: center;
}

footer .sp {
  flex: 1;
}

/* ------------------------------------------------------------------ narrow */
@media (max-width: 640px) {
  section {
    padding: 46px 0;
  }

  .hero {
    padding: 44px 0 40px;
  }

  .top nav {
    /* The in-page nav is a convenience, not the only way through the page —
       below 640px it would wrap into three rows above the fold, so it is
       dropped and the sections are simply scrolled to. "Sign in" stays. */
    margin-left: auto;
  }

  .top nav a.jump {
    display: none;
  }

  .cta-row .btn {
    /* Full-width taps, but never wider than the viewport. */
    flex: 1 1 100%;
    text-align: center;
  }

  /* Four columns do not fit in 375px, so a row becomes two lines: badge +
     headline + age across the top, the detail underneath. */
  .feed-row {
    grid-template-columns: 54px 1fr 66px;
    min-height: 100px;
    align-content: center;
    padding: 10px 14px;
  }

  /* Placed explicitly, both of them: with the detail moved to its own line
     the age would otherwise be auto-placed onto a third line of its own. */
  .feed-when {
    grid-column: 3;
    grid-row: 1;
  }

  .feed-detail {
    grid-column: 2 / 4;
    grid-row: 2;
    font-size: 13px;
    /* Always two lines' worth, clamped below to no more: with the headline
       and the subject each a single line, that makes every row exactly the
       same height whatever the hub sends -- which is what makes the reserved
       height a fact rather than a guess. */
    min-height: 40px;
  }

  /* Two lines each at most, so every row is exactly the same height whatever
     the hub sends -- which is what makes the reserved height below correct
     rather than a guess that a long sentence can overflow. */
  .feed-what b,
  .feed-detail {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }

  /* Eight rows of this height is most of a phone screen, so the panel shows
     the five newest and the caption still says newest first. The rows are in
     the DOM either way; hiding them here keeps the markup identical across
     widths and means no JavaScript has to know the viewport. */
  .feed-row:nth-child(n + 6) {
    display: none;
  }

  .feed-body {
    /* Five rows at the height fixed above. */
    min-height: 570px;
  }

  .panel-head,
  .panel-foot,
  .feed-fallback {
    padding-left: 14px;
    padding-right: 14px;
  }

  .poll {
    min-width: 0;
  }
}

/* --------------------------------------------------------- reduced motion */
@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }

  .card,
  .tier {
    transition: border-color 0.15s ease;
  }

  /* The one animation on the site, and it is off by default for anyone who
     asked for less motion -- the dot is still green and still says "live". */
  .live-dot {
    animation: breathe 2.4s ease-in-out infinite;
  }

  @keyframes breathe {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.35; }
  }
}

.card:hover,
.tier:hover {
  border-color: var(--acc);
}
