/* ============================================================
   Amplify™ — Platform landing
   Brand tokens lifted from amplify.wearesomewhere.net
   ============================================================ */

:root {
  /* --- Brand palette (source of truth: main site) --- */
  --black:         #000000;
  --white:         #ffffff;
  --green:         #02fd00;
  --dark-green:    #000d00;

  /* --- Derived surfaces --- */
  --surface:       #04120480;
  --surface-hover: #0721049c;
  --hairline:      #ffffff1f;
  --hairline-soft: #ffffff12;

  /* --- Text --- */
  --ink:           var(--white);
  --ink-dim:       #ffffffa8;
  --ink-faint:     #ffffff5c;

  /* --- Motion --- */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --dur:  0.5s;

  /* --- Rhythm --- */
  --radius: 16px;
  --pad-x: clamp(1.25rem, 5vw, 3.5rem);

  /* --- Tile watermark ---
     Kept as tokens so the mark can be retuned without hunting through rules.
     Insets are positive, so the mark sits fully inside the card rather than
     bleeding off it — legibility of the destination won out over the crop. */
  --mark-size: 58%;
  --mark-inset-x: 3%;
  --mark-inset-y: 0%;
  --mark-opacity: 0.03;
  --mark-opacity-hover: 0.075;
  --mark-stroke: 0.7;
}

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

html, body { height: 100%; }

body {
  margin: 0;
  background-color: var(--dark-green);
  color: var(--ink);
  font-family: Poppins, "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 400;
  font-synthesis-weight: none;
  overflow-x: hidden;

  /* Beautiful text rendering */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-feature-settings: "kern" 1, "liga" 1, "calt" 1;
  font-kerning: normal;
}

a { color: inherit; text-decoration: none; }
svg { display: block; }

:focus-visible {
  outline: 2px solid var(--green);
  outline-offset: 4px;
  border-radius: 6px;
}

/* ============================================================
   Ambient background layers
   ============================================================ */

.ambience {
  position: fixed;
  inset: 0;
  pointer-events: none;
  overflow: hidden;   /* glows are wider than the viewport by design — clip them */
  z-index: 0;
}

.glow {
  position: absolute;
  border-radius: 50%;
  filter: blur(90px);
  will-change: transform;
}

/* Electric-green key light — sits behind the headline, lighting it from within.
   38% tracks the optical centre of the masthead across viewport sizes. */
.glow--primary {
  top: 38%;
  left: 50%;
  width: min(112vw, 1120px);
  aspect-ratio: 2.3 / 1;
  translate: -50% -50%;
  background: radial-gradient(
    ellipse at center,
    rgba(2, 253, 0, 0.20) 0%,
    rgba(2, 253, 0, 0.075) 40%,
    transparent 70%
  );
  animation: breathe 13s var(--ease) infinite;
}

/* Bounce light — a wide, shallow wash rising from off the bottom edge.
   Mostly below the fold so only the upper falloff shows. Kept well under the key
   light so it grounds the composition without competing with the headline. */
.glow--secondary {
  bottom: 0;
  left: 50%;
  width: min(150vw, 1600px);
  aspect-ratio: 3 / 1;
  translate: -50% 50%;
  background: radial-gradient(
    ellipse at center,
    rgba(2, 253, 0, 0.16) 0%,
    rgba(2, 253, 0, 0.055) 45%,
    transparent 74%
  );
  animation: breathe 17s var(--ease) infinite reverse;
}

@keyframes breathe {
  0%, 100% { transform: scale(1)    translateY(0);     opacity: 0.85; }
  50%      { transform: scale(1.12) translateY(1.5vh); opacity: 1;    }
}

/* Faint technical grid — depth without noise */
.grid-lines {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(to right,  rgba(255, 255, 255, 0.028) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255, 255, 255, 0.028) 1px, transparent 1px);
  background-size: 76px 76px;
  mask-image: radial-gradient(ellipse 78% 62% at 50% 42%, #000 20%, transparent 100%);
  -webkit-mask-image: radial-gradient(ellipse 78% 62% at 50% 42%, #000 20%, transparent 100%);
}

/* Top/bottom fade — mirrors the main site's section gradients */
.vignette {
  position: absolute;
  inset: 0;
  background-image: linear-gradient(
    180deg,
    var(--dark-green) 0%,
    transparent 12%,
    transparent 86%,
    var(--dark-green) 100%
  );
}

/* Fine film grain for a premium, non-flat surface */
.grain {
  position: absolute;
  inset: -50%;
  opacity: 0.035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ============================================================
   Stage — the single-screen frame
   ============================================================ */

.stage {
  position: relative;
  z-index: 1;
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  grid-template-rows: 1fr auto;
  justify-items: center;
  gap: clamp(1.25rem, 3vh, 2rem);
  padding:
    calc(clamp(1.5rem, 4vh, 3rem) + env(safe-area-inset-top))
    var(--pad-x)
    calc(clamp(1.25rem, 3vh, 2.25rem) + env(safe-area-inset-bottom));
  max-width: 1240px;
  margin-inline: auto;
}

/* The masthead + tiles read as one optical group, centred in the viewport;
   the colophon stays pinned to the bottom edge. */
.content {
  align-self: center;
  width: 100%;
  min-width: 0;
  display: grid;
  justify-items: center;
  /* Deliberately wider than the masthead's internal gap so masthead and tiles
     stay legible as two separate groups. */
  gap: clamp(2.1rem, 5.2vh, 3.9rem);
}

/* ---------- Masthead ---------- */

.masthead {
  text-align: center;
  display: grid;
  justify-items: center;
  /* Wordmark sits directly above the headline, so it needs enough air to read as
     its own tier — the jump from ~1.4rem/600 to ~3.1rem/300 is large, and both are
     now light-to-medium weights, so the gap is what separates them. */
  gap: clamp(1.4rem, 3.2vh, 2.4rem);
  max-width: 100%;
  min-width: 0;
  animation: rise 0.9s var(--ease) both;
}

/* The wordmark is the logo — no accompanying mark. Set in the accent green, with a
   faint bloom so the saturated green reads as lit rather than flat on the dark
   ground. */
.wordmark {
  display: inline-block;
  font-size: clamp(1.15rem, 1.6vw, 1.4rem);
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--green);
  text-shadow: 0 0 22px rgba(2, 253, 0, 0.35);
  transition: opacity 0.35s var(--ease);
}
.wordmark:hover { opacity: 0.72; }

/* Tinted green rather than white, so the ™ recedes without going off-palette. */
.wordmark sup {
  font-size: 0.48em;
  font-weight: 500;
  vertical-align: super;
  margin-left: 0.12em;
  color: rgba(2, 253, 0, 0.5);
  text-shadow: none;
}

/* A question has no rhetorical pivot, so the previous bold/light two-line split
   would break it at an arbitrary point. It's set instead as a single line in the
   lighter weight: that suits the conversational tone, and letting the headline sit
   back lets the tiles — the actual content of a routing page — carry the weight. */
.headline {
  margin: 0;
  font-size: clamp(1.6rem, 4.4vw, 3.1rem);
  font-weight: 300;
  line-height: 1.12;
  /* Light weights need looser tracking than bold at display size. */
  letter-spacing: -0.022em;
  text-wrap: balance;
  /* Generous, so font-size and the container govern where it wraps. */
  max-width: 30ch;
}

/* ============================================================
   Tiles
   ============================================================ */

.tiles {
  width: 100%;
  min-width: 0;
  align-self: center;
  display: grid;
  /* minmax(0, 1fr) — never let tile content force a track wider than the screen */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(0.7rem, 1.3vw, 1.15rem);
}

.tile {
  --mx: 50%;
  --my: 0%;

  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-width: 0;

  display: grid;
  /* The mark is absolutely positioned, so only body and arrow are in flow. */
  grid-template-rows: 1fr auto;
  gap: clamp(0.85rem, 2vh, 1.5rem);

  padding: clamp(1.15rem, 2.1vw, 1.6rem);
  min-height: clamp(9.5rem, 22vh, 13.5rem);

  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background-color: var(--surface);
  /* Faint green cast in the corner the mark occupies — keeps an accent at rest
     now that the icon chip is gone. */
  background-image: radial-gradient(
    circle at 100% 0%,
    rgba(2, 253, 0, 0.055),
    transparent 62%
  );
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);

  transition:
    border-color 0.45s var(--ease),
    background-color 0.45s var(--ease),
    transform 0.45s var(--ease),
    box-shadow 0.45s var(--ease);

  animation: rise 0.9s var(--ease) both;
  animation-delay: calc(0.14s + var(--i) * 0.075s);
}

/* Cursor-tracked sheen */
.tile::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0;
  background: radial-gradient(
    380px circle at var(--mx) var(--my),
    rgba(2, 253, 0, 0.13),
    transparent 62%
  );
  transition: opacity 0.45s var(--ease);
}

/* Top hairline highlight — catches the key light */
.tile::after {
  content: "";
  position: absolute;
  inset-inline: 12%;
  top: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(2, 253, 0, 0.55), transparent);
  opacity: 0;
  transition: opacity 0.45s var(--ease);
}

.tile:hover,
.tile:focus-visible {
  transform: translateY(-5px);
  border-color: rgba(2, 253, 0, 0.42);
  background-color: var(--surface-hover);
  box-shadow:
    0 22px 48px -18px rgba(0, 0, 0, 0.85),
    0 0 0 1px rgba(2, 253, 0, 0.07),
    0 0 44px -10px rgba(2, 253, 0, 0.22);
}

.tile:hover::before,
.tile:focus-visible::before,
.tile:hover::after,
.tile:focus-visible::after { opacity: 1; }

.tile:active { transform: translateY(-2px) scale(0.994); }

/* ---------- Tile internals ---------- */

/* The icon is an oversized watermark sitting in the card's empty upper-right area,
   clear of the title and description, which are bottom-aligned. */
.tile__icon {
  position: absolute;
  top: var(--mark-inset-y);
  right: var(--mark-inset-x);
  width: var(--mark-size);
  aspect-ratio: 1 / 1;
  z-index: -1;                    /* behind the text, above the cursor sheen */
  color: var(--green);
  opacity: var(--mark-opacity);
  transition: opacity 0.5s var(--ease), transform 0.5s var(--ease);
}
.tile__icon svg { width: 100%; height: 100%; }

/* CSS beats the stroke-width presentation attribute. At this scale the authored
   1.6 would render as a heavy slab, so it is thinned back to a hairline. */
.tile__icon :is(path, circle, rect, line) { stroke-width: var(--mark-stroke); }

/* Lit by the pointer, with a small drift so it reads as responding to the light. */
.tile:hover .tile__icon {
  opacity: var(--mark-opacity-hover);
  transform: translate(-2%, 2%) scale(1.04);
}

.tile__body {
  display: grid;
  align-content: end;
  gap: 0.3rem;
  min-width: 0;
}

.tile__title {
  display: flex;
  align-items: center;
  gap: 0.55em;
  font-size: clamp(1.05rem, 1.55vw, 1.28rem);
  font-weight: 600;
  letter-spacing: -0.022em;
  line-height: 1.15;
}

.tile__desc {
  font-size: clamp(0.775rem, 0.95vw, 0.845rem);
  font-weight: 300;
  line-height: 1.45;
  letter-spacing: 0.004em;
  color: var(--ink-dim);
  text-wrap: pretty;
}

.tile__go {
  width: 1.65rem;
  height: 1.65rem;
  color: var(--ink-faint);
  transition: color 0.45s var(--ease), transform 0.45s var(--ease);
}
.tile__go svg { width: 100%; height: 100%; }

.tile:hover .tile__go {
  color: var(--green);
  transform: translateX(5px);
}

/* Live pulse on the Status tile */
/* Colour is driven by [data-status], which the script in index.html sets from the
   Uptime Kuma API. It starts as "unknown" and must never reach green without a
   successful read — a green pulse asserts that services are up. */
.pulse {
  position: relative;
  width: 7px;
  height: 7px;
  flex: none;
  color: var(--ink-faint);          /* unknown, until proven otherwise */
}
.pulse[data-status="up"]          { color: var(--green); }
.pulse[data-status="degraded"]    { color: #ffb020; }
.pulse[data-status="down"]        { color: #ff4d4d; }
.pulse[data-status="maintenance"] { color: #3a9bff; }

.pulse i {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 9px currentColor;
}
.pulse::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: currentColor;
  animation: ping 2.4s var(--ease) infinite;
}

/* No glow and no ping while unknown — a pulsing dot implies live data. */
.pulse[data-status="unknown"] i { box-shadow: none; }
.pulse[data-status="unknown"]::after { animation: none; opacity: 0; }

@keyframes ping {
  0%   { transform: scale(1);   opacity: 0.65; }
  70%  { transform: scale(3.2); opacity: 0;    }
  100% { transform: scale(3.2); opacity: 0;    }
}

/* ============================================================
   Colophon
   ============================================================ */

.colophon {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  font-size: clamp(0.7rem, 0.85vw, 0.775rem);
  font-weight: 300;
  letter-spacing: 0.02em;
  color: var(--ink-faint);
  animation: rise 0.9s var(--ease) 0.5s both;
}

.colophon a { transition: color 0.3s var(--ease); }
.colophon a:hover { color: var(--green); }

.colophon__dot {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.55;
}

/* ============================================================
   Entrance
   ============================================================ */

@keyframes rise {
  from { opacity: 0; transform: translateY(18px); filter: blur(6px); }
  to   { opacity: 1; transform: none;             filter: blur(0);   }
}

/* ============================================================
   Responsive — must always fit one screen
   ============================================================ */

/* Tablet / small laptop: 2 × 2 */
@media (max-width: 860px) {
  .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Phone: compact 2 × 2 tiles */
@media (max-width: 560px) {
  .stage { gap: clamp(1.3rem, 3.2vh, 2rem); }

  .tile {
    min-height: 0;
    gap: 0.7rem;
    padding: 1rem 0.95rem;
    grid-template-rows: auto;
    /* Size is a % of card width so it already scales down, but the 2 × 2 cards are
       much shorter than they are wide — trimmed slightly so the mark doesn't run
       the full height of the card. */
    --mark-size: 52%;
  }

  /* Arrow is redundant on touch — the whole tile is the target */
  .tile__go { display: none; }

  .tile__title { font-size: 1.02rem; }
  .tile__desc  { font-size: 0.745rem; line-height: 1.38; }

  /* Deliberately wraps to two balanced lines rather than sitting one pixel from
     the edge — a near-miss single line is fragile across phone widths. */
  .headline { font-size: clamp(1.5rem, 7vw, 2.1rem); max-width: 16ch; }
}

/* Short / landscape phones: tighten aggressively so nothing is cut off */
@media (max-height: 620px) and (max-width: 900px) {
  .stage { gap: 1rem; }
  .content { gap: 1.2rem; }
  .masthead { gap: 0.7rem; }
  .headline { font-size: clamp(1.35rem, 4.4vh, 1.9rem); }
  .tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .tile { padding: 0.85rem; gap: 0.5rem; }
  .tile__desc { display: none; }
  .tile__go { display: none; }
}

/* ---------- Accessibility ---------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .tile:hover, .tile:focus-visible { transform: none; }
}

@media (prefers-contrast: more) {
  :root {
    --ink-dim: #ffffffd6;
    --ink-faint: #ffffff9e;
    --hairline: #ffffff4d;
  }
}
