/* NCloud design tokens.
 *
 * Depth comes from light and translucency, never from borders and drop
 * shadows stacked on flat cards. Six rules govern everything here:
 *
 *   1. Saturate, don't just blur — colour from the wash must carry through.
 *   2. One hairline, top-lit — a glass panel's top edge catches more light.
 *   3. Spend the accent three times — any more and the material disappears.
 *   4. One curve everywhere — cubic-bezier(.32,.72,0,1).
 *   5. Transform and opacity only — animating width or filter costs layout.
 *   6. Not Inter — the previous version used it, and a platform meant to look
 *      unlike everything else should not open with the web's most common face.
 */

:root {
  /* Ground and ink */
  --ground:        #070b0f;
  --text:          #e9eef3;
  --text-secondary:#8d9aa7;

  /* The accent is spent exactly three times: primary action, active
     indicator, focus ring. */
  --accent:        #3d7bfd;
  --good:          #35c48a;
  --warn:          #e8b13c;
  --danger:        #f2564a;

  /* Materials. The alpha is what makes them glass; the blur radius is what
     distinguishes them from each other. */
  --mat-chrome:    rgba(255 255 255 / 0.045);   /* sidebars, panels */
  --mat-raised:    rgba(255 255 255 / 0.065);   /* composer, menus  */
  --mat-overlay:   rgba(255 255 255 / 0.085);   /* modals, palette  */
  --mat-inset:     rgba(0 0 0 / 0.22);          /* input wells      */

  --blur-chrome:   24px;
  --blur-raised:   30px;
  --blur-overlay:  40px;
  --saturate:      140%;

  /* Rule 2: the hairline is brighter on top than on the sides. A uniform
     1px border is the flat-looking shortcut. */
  --edge-top:      rgba(255 255 255 / 0.16);
  --edge-side:     rgba(255 255 255 / 0.06);

  --radius:        16px;
  --radius-sm:     10px;

  --curve:         cubic-bezier(.32, .72, 0, 1);
  --fast:          160ms;
  --medium:        280ms;

  /* Rule 6. A grotesque with real character, with a system stack behind it
     so nothing shifts if the webfont never arrives. */
  --font: "Söhne", "Neue Haas Grotesk", ui-sans-serif, -apple-system,
          "Segoe UI Variable Text", "Segoe UI", Roboto, sans-serif;
  --font-mono: ui-monospace, "SF Mono", "Cascadia Code", Menlo, monospace;
}

/* The design commits to a dark ground. Light mode is a later decision, so
   this palette is stated once rather than half-defined in a media query. */

* { box-sizing: border-box; }

html { color-scheme: dark; }

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--ground);
  color: var(--text);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

/* The ambient wash. Two wide, soft gradients — the colour that the panels'
   saturate() picks up. Fixed, so scrolling does not repaint it. */
.wash {
  position: fixed;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(60rem 40rem at 12% -10%, rgba(61 123 253 / 0.28), transparent 60%),
    radial-gradient(50rem 38rem at 88% 8%,  rgba(53 196 138 / 0.16), transparent 62%),
    radial-gradient(45rem 45rem at 60% 110%, rgba(120 80 255 / 0.14), transparent 60%);
}

main {
  max-width: 46rem;
  margin: 0 auto;
  padding: clamp(2rem, 6vw, 5rem) 1.25rem 4rem;
  display: grid;
  gap: 1.25rem;
}

.masthead h1 {
  margin: 0;
  font-size: clamp(2rem, 6vw, 2.75rem);
  font-weight: 600;
  letter-spacing: -0.022em;
}

.subtitle {
  margin: 0.35rem 0 0;
  color: var(--text-secondary);
}

/* The panel is the material, and the only place the recipe appears. */
.panel {
  background: var(--mat-chrome);
  backdrop-filter: blur(var(--blur-chrome)) saturate(var(--saturate));
  -webkit-backdrop-filter: blur(var(--blur-chrome)) saturate(var(--saturate));
  border-radius: var(--radius);
  border: 1px solid var(--edge-side);
  border-top-color: var(--edge-top);
  padding: 1.4rem 1.5rem;
}

.panel h2 {
  margin: 0 0 0.35rem;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.lede { margin: 0 0 1rem; }

code {
  font-family: var(--font-mono);
  font-size: 0.88em;
  background: var(--mat-inset);
  padding: 0.1em 0.4em;
  border-radius: 5px;
}

/* Status dot. Its colour is the whole signal, so it never animates size —
   rule 5, transform and opacity only. */
.dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-secondary);
  flex: none;
  transition: background var(--fast) var(--curve), opacity var(--fast) var(--curve);
}

[data-state="pending"] .dot { opacity: 0.5; animation: pulse 1.4s var(--curve) infinite; }
[data-state="ok"]      .dot { background: var(--good); }
[data-state="failed"]  .dot { background: var(--danger); }

@keyframes pulse { 50% { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

.result {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.85rem 1rem;
  border-radius: var(--radius-sm);
  background: var(--mat-inset);
  font-variant-numeric: tabular-nums;
}

.facts {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.3rem 1rem;
  margin: 1rem 0 0;
  font-size: 0.875rem;
}

.facts dt { color: var(--text-secondary); }
.facts dd { margin: 0; font-family: var(--font-mono); }

.services {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.5rem;
}

.services li {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.6rem 0.85rem;
  border-radius: var(--radius-sm);
  background: var(--mat-inset);
}

.metric {
  margin-left: auto;
  color: var(--text-secondary);
  font-family: var(--font-mono);
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
}

.footnote, footer {
  color: var(--text-secondary);
  font-size: 0.85rem;
}

.footnote { margin: 1rem 0 0; }
footer { text-align: center; }

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