/* ---------------------------------------------------------------------------
   7K Calculator — palette sampled from the bot logo and its gradient artwork.
   --------------------------------------------------------------------------- */
:root {
  --bg: #04100f;
  --bg-elev: #082926;
  --bg-elev-2: #0c3833;
  --line: #14463f;

  --text: #eaf7f1;
  --text-dim: #9ebdb4;

  --green: #00d95a;
  --mint: #02ef8e;
  --aqua: #02e5aa;
  --teal: #01b595;
  --cyan: #0192a7;
  --blue: #0b93e7;
  --emerald: #00ad6e;
  --emerald-dark: #017767;

  --on-green: #04100f; /* dark text on green surfaces keeps contrast >= 4.5:1 */
  --danger: #ff8a7a;

  --radius: 14px;
  --gutter: 16px;
  --maxw: 1080px;

  color-scheme: dark;
}

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

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: Inter, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  overflow-x: hidden;
}

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

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

img {
  max-width: 100%;
  height: auto;
}

:focus-visible {
  outline: 3px solid var(--mint);
  outline-offset: 3px;
  border-radius: 6px;
}

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

.wrap--narrow {
  max-width: 640px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--green);
  color: var(--on-green);
  padding: 10px 16px;
  font-weight: 600;
  z-index: 10;
}

.skip-link:focus {
  left: 8px;
  top: 8px;
}

/* --- Header ---------------------------------------------------------------- */
.header {
  position: relative;
  overflow: hidden;
  padding: 56px 0 64px;
  text-align: center;
}

/*
  Aurora backdrop, in two parts:
  - three colour blobs, each on its own layer, drifting on its own timing;
  - one fixed overlay above them (scrim + contrast pocket + fade down to --bg),
    never animated, so the text keeps its contrast and the header dissolves into
    the page with no cut-off line.
  The 404 page reuses the same markup, hence the grouped selectors.
*/
.header::before,
.header::after,
.page-404::before,
.page-404::after,
.header__glow::before,
.header__glow::after {
  content: '';
  position: absolute;
  pointer-events: none;
}

/* Blob 1 — green / mint, anchored in the top-left corner. Every stop stays in
   its own hue family and fades straight to transparent: mixing a neighbouring
   colour into the tail is what turned the whole header into one flat teal. */
.header::before,
.page-404::before {
  inset: -14%;
  background: radial-gradient(
    72% 82% at 12% 8%,
    color-mix(in srgb, var(--mint) 90%, transparent) 0%,
    color-mix(in srgb, var(--green) 66%, transparent) 26%,
    color-mix(in srgb, var(--green) 28%, transparent) 54%,
    transparent 80%
  );
  animation: blob-a 12s ease-in-out infinite alternate;
}

.header__glow {
  position: absolute;
  inset: -14%;
  pointer-events: none;
}

/* Blob 2 — aqua / teal / cyan, on the right edge at mid height. */
.header__glow::before {
  inset: 0;
  background: radial-gradient(
    66% 88% at 90% 44%,
    color-mix(in srgb, var(--aqua) 86%, transparent) 0%,
    color-mix(in srgb, var(--teal) 62%, transparent) 26%,
    color-mix(in srgb, var(--cyan) 28%, transparent) 54%,
    transparent 80%
  );
  animation: blob-b 18s ease-in-out infinite alternate;
}

/* Blob 3 — blue, anchored in the bottom-left corner. */
.header__glow::after {
  inset: 0;
  background: radial-gradient(
    70% 74% at 15% 72%,
    color-mix(in srgb, var(--blue) 90%, transparent) 0%,
    color-mix(in srgb, var(--blue) 64%, transparent) 26%,
    color-mix(in srgb, var(--blue) 28%, transparent) 54%,
    transparent 80%
  );
  animation: blob-c 25s ease-in-out infinite alternate;
}

/*
  Fixed overlay, painted above every blob and below the content:
  1. an elliptical fade to --bg — its contour is a curve, not a straight line,
     so the bottom edge dissolves organically and colour still rides up in
     places instead of being cut by a horizontal rule,
  2. a faint centre pocket, far too light to read as a grey patch,
  3. a light scrim.
*/
.header::after,
.page-404::after {
  inset: 0;
  z-index: 0;
  background:
    radial-gradient(
      136% 98% at 42% 0%,
      transparent 78%,
      color-mix(in srgb, var(--bg) 40%, transparent) 88%,
      color-mix(in srgb, var(--bg) 85%, transparent) 95%,
      var(--bg) 100%
    ),
    radial-gradient(
      58% 66% at 50% 42%,
      color-mix(in srgb, var(--bg) 10%, transparent) 0%,
      color-mix(in srgb, var(--bg) 5%, transparent) 46%,
      transparent 78%
    ),
    linear-gradient(
      color-mix(in srgb, var(--bg) 14%, transparent),
      color-mix(in srgb, var(--bg) 14%, transparent)
    );
}

/* Slow, low-amplitude drifts. Different periods mean the composition only
   repeats every half hour or so, never in an obvious loop. */
@keyframes blob-a {
  from {
    transform: translate3d(-3%, -2%, 0) scale(1);
  }
  to {
    transform: translate3d(4%, 3%, 0) scale(1.08);
  }
}

@keyframes blob-b {
  from {
    transform: translate3d(3%, 2%, 0) scale(1.07);
  }
  to {
    transform: translate3d(-4%, -2%, 0) scale(1);
  }
}

@keyframes blob-c {
  from {
    transform: translate3d(-2%, 2%, 0) scale(1.05);
  }
  to {
    transform: translate3d(4%, -3%, 0) scale(1);
  }
}

@media (prefers-reduced-motion: reduce) {
  .header::before,
  .page-404::before,
  .header__glow::before,
  .header__glow::after {
    animation: none;
    transform: none;
  }
}

.header__inner {
  position: relative;
  z-index: 1;
}

.header__logo {
  width: 108px;
  height: 108px;
  filter: drop-shadow(0 12px 28px rgba(0, 173, 110, 0.35));
}

.header__title {
  font-size: clamp(2.25rem, 8vw, 3.5rem);
  font-weight: 900;
  margin: 18px 0 10px;
  /* Layered shadow instead of a dark plate behind the text. */
  text-shadow: 0 1px 2px rgba(4, 16, 15, 0.6), 0 2px 12px rgba(4, 16, 15, 0.8),
    0 4px 28px rgba(4, 16, 15, 0.7);
}

.header__subtitle {
  max-width: 44ch;
  margin: 0 auto 28px;
  color: var(--text);
  font-size: clamp(1rem, 3.4vw, 1.125rem);
  text-shadow: 0 1px 2px rgba(4, 16, 15, 0.7), 0 2px 14px rgba(4, 16, 15, 0.85),
    0 4px 30px rgba(4, 16, 15, 0.7);
}

.header__note {
  margin: 16px 0 0;
  font-size: 0.875rem;
  color: var(--text);
  text-shadow: 0 1px 2px rgba(4, 16, 15, 0.7), 0 2px 14px rgba(4, 16, 15, 0.85),
    0 4px 30px rgba(4, 16, 15, 0.7);
}

/* --- Buttons --------------------------------------------------------------- */
.btn {
  display: inline-block;
  border: 0;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--mint), var(--green) 55%, var(--emerald));
  color: var(--on-green);
  font: inherit;
  font-weight: 800;
  letter-spacing: -0.01em;
  padding: 15px 34px;
  cursor: pointer;
  text-decoration: none;
  box-shadow: 0 10px 26px rgba(0, 217, 90, 0.24);
  transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease;
}

.btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 14px 32px rgba(0, 217, 90, 0.32);
}

.btn:active {
  transform: translateY(0);
}

.btn[disabled] {
  filter: grayscale(0.4) brightness(0.8);
  cursor: progress;
  transform: none;
}

.btn--cta {
  font-size: 1.0625rem;
}

.btn--submit {
  width: 100%;
  margin-top: 4px;
}

/* --- Sections -------------------------------------------------------------- */
.section {
  padding: 64px 0;
}

.section--form {
  background: linear-gradient(180deg, transparent, rgba(8, 41, 38, 0.6) 18%, rgba(8, 41, 38, 0.6));
  border-top: 1px solid var(--line);
}

.section__title {
  font-size: clamp(1.6rem, 5.5vw, 2.25rem);
  font-weight: 800;
}

.section__lead {
  color: var(--text-dim);
  max-width: 60ch;
  margin: 12px 0 32px;
}

/* --- Feature cards --------------------------------------------------------- */
.features {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 16px;
  grid-template-columns: 1fr;
}

.card {
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 22px;
}

.card__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border-radius: 11px;
  margin-bottom: 14px;
  background: rgba(0, 217, 90, 0.12);
  border: 1px solid rgba(2, 229, 170, 0.35);
  color: var(--aqua);
}

.card__icon svg {
  width: 22px;
  height: 22px;
}

.card__title {
  font-size: 1.0625rem;
  font-weight: 800;
  margin-bottom: 6px;
}

.card__text {
  margin: 0;
  color: var(--text-dim);
  font-size: 0.9375rem;
}

.shot {
  margin: 32px 0 0;
}

.shot img {
  border-radius: var(--radius);
  border: 1px solid var(--line);
}

.shot figcaption {
  margin-top: 10px;
  color: var(--text-dim);
  font-size: 0.875rem;
}

/* --- Form ------------------------------------------------------------------ */
.form {
  display: grid;
  gap: 18px;
}

.field label {
  display: block;
  font-weight: 600;
  font-size: 0.9375rem;
  margin-bottom: 7px;
}

.field__optional {
  color: var(--text-dim);
  font-weight: 400;
}

.req {
  color: var(--mint);
}

input[type='text'],
input[type='email'],
textarea {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 11px;
  color: var(--text);
  font: inherit;
  padding: 13px 14px;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

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

input::placeholder,
textarea::placeholder {
  color: #6f8f87;
}

input:hover,
textarea:hover {
  border-color: var(--bg-elev-2);
}

input:focus,
textarea:focus {
  border-color: var(--aqua);
  box-shadow: 0 0 0 3px rgba(2, 229, 170, 0.18);
  outline: none;
}

.field--invalid input,
.field--invalid textarea {
  border-color: var(--danger);
}

.field__hint {
  margin: 6px 0 0;
  font-size: 0.8125rem;
  color: var(--text-dim);
  text-align: right;
}

.field__error {
  margin: 6px 0 0;
  font-size: 0.875rem;
  color: var(--danger);
  min-height: 0;
}

.field__error:empty {
  display: none;
}

.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form__status {
  margin: 4px 0 0;
  font-size: 0.9375rem;
}

.form__status:empty {
  display: none;
}

.form__status[data-state='error'] {
  color: var(--danger);
}

.form__status[data-state='success'] {
  color: var(--mint);
}

.form-success {
  background: var(--bg-elev);
  border: 1px solid rgba(2, 229, 170, 0.4);
  border-radius: var(--radius);
  padding: 26px;
  text-align: center;
}

.form-success h3 {
  font-size: 1.25rem;
  font-weight: 800;
  margin-bottom: 8px;
}

.form-success p {
  margin: 0;
  color: var(--text-dim);
}

.privacy {
  margin: 22px 0 0;
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--text-dim);
}

/* --- Footer ---------------------------------------------------------------- */
.footer {
  border-top: 1px solid var(--line);
  padding: 32px 0 40px;
}

.footer__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  color: var(--text-dim);
  font-size: 0.875rem;
}

.footer__inner p {
  margin: 10px 0 0;
}

.footer__inner strong {
  color: var(--text);
}

/* Bot logo / owner avatar, side by side with a hairline separator. */
.footer__marks {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
}

.footer__mark {
  display: block;
  width: 28px;
  height: 28px;
}

.footer__mark--avatar {
  border-radius: 50%;
  object-fit: cover;
}

.footer__sep {
  font-size: 1rem;
  font-weight: 300;
  line-height: 1;
  color: var(--text-dim);
  opacity: 0.55;
}

/* Kingdoms band, above the logos. The list is in the DOM once and crosses the
   band from one edge to the other, over and over. It restarts the instant it
   has cleared the left edge, while nothing is on screen, so the jump back to
   the right cannot be seen. app.js measures the band and fills in the two stop
   positions and the duration, which keeps the speed even on any screen. */
.marquee {
  --marquee-fade: 56px;
  width: 100%;
  margin-bottom: 18px;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(
    90deg,
    transparent,
    #000 var(--marquee-fade),
    #000 calc(100% - var(--marquee-fade)),
    transparent
  );
  mask-image: linear-gradient(
    90deg,
    transparent,
    #000 var(--marquee-fade),
    #000 calc(100% - var(--marquee-fade)),
    transparent
  );
}

/* No list (or no JS): no empty strip above the logos. */
.marquee:not(:has(.marquee__item)),
.marquee[hidden] {
  display: none;
}

.marquee__track {
  display: flex;
  align-items: center;
  width: max-content;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Added once the stop positions are measured, so nothing scrolls half-built.
   Half a cycle in is exactly the moment the list sits centred, so the negative
   delay opens on readable kingdoms instead of mid-entry. */
.marquee.is-ready .marquee__track {
  animation: marquee-pass var(--marquee-duration, 30s) linear infinite;
  animation-delay: calc(var(--marquee-duration, 30s) / -2);
  will-change: transform;
}

@keyframes marquee-pass {
  from {
    transform: translate3d(var(--marquee-from, 100%), 0, 0);
  }

  to {
    transform: translate3d(var(--marquee-to, -100%), 0, 0);
  }
}

.marquee__item {
  display: inline-flex;
  align-items: center;
  font-size: 0.8125rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
  color: var(--text-dim);
  white-space: nowrap;
}

/* Kept at the normal weight, so the values stand out against them. */
.marquee__item::after {
  content: '\2022';
  margin: 0 15px;
  font-weight: 400;
  color: var(--emerald);
  opacity: 0.8;
}

/* A separator, not a terminator: the list runs through once. */
.marquee__item:last-child::after {
  content: none;
}

/* Reduced motion: the plain list, centred and still, never animated. */
.marquee.is-static .marquee__track {
  width: 100%;
  flex-wrap: wrap;
  justify-content: center;
}

/* --- 404 ------------------------------------------------------------------- */
.page-404 {
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  text-align: center;
  position: relative;
  overflow: hidden;
  padding: 40px 0;
}

/* Lift the content above the backdrop layers, as .header__inner does on the home page. */
.page-404 .wrap {
  position: relative;
  z-index: 1;
}

.page-404 .code {
  font-size: clamp(3.5rem, 18vw, 6rem);
  font-weight: 900;
  line-height: 1;
  background: linear-gradient(120deg, var(--mint), var(--green) 40%, var(--blue));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* The glyphs are transparent, so an inherited text-shadow would paint a dark
     smudge behind them; a drop-shadow follows the painted gradient instead. */
  text-shadow: none;
  filter: drop-shadow(0 2px 14px rgba(4, 16, 15, 0.8));
}

.page-404 h1 {
  text-shadow: 0 1px 2px rgba(4, 16, 15, 0.6), 0 2px 12px rgba(4, 16, 15, 0.8),
    0 4px 28px rgba(4, 16, 15, 0.7);
}

.page-404 p {
  /* --text-dim would sit at 3.9:1 on the colourful backdrop; --text plus the
     same layered shadow as the header keeps it readable. */
  color: var(--text);
  max-width: 38ch;
  margin: 12px auto 28px;
  text-shadow: 0 1px 2px rgba(4, 16, 15, 0.7), 0 2px 14px rgba(4, 16, 15, 0.85),
    0 4px 30px rgba(4, 16, 15, 0.7);
}

/* --- Hover glow ------------------------------------------------------------ */
/*
  Desktop pointers only — a touch device would latch the glow on after a tap.
  Everything here is pure paint (a gradient, a drop-shadow): nothing resizes,
  moves or reflows, the light simply sits on top. Duration is left to the
  global prefers-reduced-motion rule at the end of this file, which cuts every
  transition to 0.01ms without removing the effect.
*/
@media (hover: hover) and (pointer: fine) {
  /*
    Spotlight running along the outline. isolation makes the card a stacking
    context, which is what lets the overlay below sit at z-index -1: painted
    over the card's own border, never over its contents.
  */
  .card {
    position: relative;
    isolation: isolate;
  }

  /*
    A second, bright border laid exactly over the card's own — inset: -1px
    stretches this box from the padding box back out to the border box, so the
    two outlines coincide to the pixel. It carries no background: the inside of
    the card is never touched.

    What makes it a spotlight is the mask: app.js writes --mouse-x / --mouse-y
    on every frame of the move, and the mask only lets through the stretch of
    outline near that point, fading out along the edge. Only the opacity is
    transitioned, so the light fades in and out but follows the cursor with no
    lag of its own.
  */
  .card::before {
    content: '';
    position: absolute;
    inset: -1px;
    z-index: -1;
    border: 1.5px solid rgba(2, 239, 142, 0.85);
    border-radius: inherit;
    opacity: 0;
    transition: opacity 260ms ease-out;
    pointer-events: none;
    -webkit-mask-image: radial-gradient(
      circle at var(--mouse-x, 50%) var(--mouse-y, 50%),
      #000 0,
      rgba(0, 0, 0, 0.5) 55px,
      transparent 130px
    );
    mask-image: radial-gradient(
      circle at var(--mouse-x, 50%) var(--mouse-y, 50%),
      #000 0,
      rgba(0, 0, 0, 0.5) 55px,
      transparent 130px
    );
  }

  .card:hover::before {
    opacity: 1;
  }

  /*
    drop-shadow rather than box-shadow: it follows the round logo instead of
    drawing a halo around its square box. The first shadow is the one the logo
    already carries and never changes.
  */
  .header__logo {
    filter:
      drop-shadow(0 12px 28px rgba(0, 173, 110, 0.35))
      drop-shadow(0 0 14px rgba(2, 239, 142, 0))
      drop-shadow(0 0 32px rgba(0, 173, 110, 0));
    transition: filter 260ms ease-out;
  }

  .header__logo:hover {
    filter:
      drop-shadow(0 12px 28px rgba(0, 173, 110, 0.35))
      drop-shadow(0 0 14px rgba(2, 239, 142, 0.45))
      drop-shadow(0 0 32px rgba(0, 173, 110, 0.32));
  }
}

/* Reduced motion: app.js stops following the cursor, so the spotlight would
   sit wherever it was last left — it stays off instead. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: reduce) {
  .card:hover::before {
    opacity: 0;
  }
}

/* --- Responsive ------------------------------------------------------------ */
@media (min-width: 640px) {
  .features {
    grid-template-columns: repeat(2, 1fr);
  }

  .header {
    padding: 80px 0 88px;
  }

  .section {
    padding: 80px 0;
  }

  .btn--submit {
    width: auto;
    justify-self: start;
    padding-inline: 42px;
  }
}

@media (min-width: 960px) {
  .features {
    grid-template-columns: repeat(3, 1fr);
  }

  .header__logo {
    width: 128px;
    height: 128px;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
