/* Home — the geminiaudio.live front page.
 *
 * Tokens only (docs/rules/11-visual-design.md). Three consequences worth knowing
 * before you edit:
 *   - No literal colors, so brand tints are built with color-mix() over --brand-*
 *     rather than a literal alpha function. check-tokens.js does not strip
 *     multi-line block comments before it scans, so even naming that function in a
 *     comment fails the build. This one did.
 *   - Every font-size must START with var(), so there is no clamp() here.
 *     Responsive type steps between tokens in the media queries at the bottom
 *     instead, which is the intent of the rule.
 *   - A var() naming a token no theme defines is dropped silently by CSS and
 *     caught loudly by npm run lint. Check tokens/vocabulary.md before inventing.
 *
 * The four --brand-* hues are decoration only: a demo's identity, never a state.
 * The status strip carries state in a glyph and a word as well as a hue, so rule
 * 11 #5 (status is never carried by color alone) holds there too.
 *
 * Structure: the three installations are horizontal editorial bands, not a row of
 * equal cards. The evening has three acts of different weight and they read as a
 * programme, top to bottom, the way the floor is actually walked.
 */

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

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--text-md);
  line-height: var(--leading-normal);
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }

:focus-visible {
  outline: var(--border-thick) solid var(--focus);
  outline-offset: var(--space-1);
  border-radius: var(--radius-sm);
}

/* Screen-reader-only, for the headings that structure the page without appearing. */
.vh {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ── the four-hue edge ───────────────────────────────────────────────────── */

.spectrum {
  height: var(--space-1);
  background: linear-gradient(
    to right,
    var(--brand-blue) 0 25%,
    var(--brand-red) 25% 50%,
    var(--brand-yellow) 50% 75%,
    var(--brand-green) 75% 100%
  );
}

/* ── shell ───────────────────────────────────────────────────────────────── */

.topbar,
main,
.foot {
  max-width: 68rem;
  margin-inline: auto;
  padding-inline: var(--space-6);
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  padding-block: var(--space-5);
}

.brand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.brand-dots {
  display: grid;
  grid-template-columns: repeat(2, var(--space-2));
  gap: 2px;
}

.brand-dots i {
  width: var(--space-2);
  height: var(--space-2);
  border-radius: var(--radius-pill);
}

.brand-dots i:nth-child(1) { background: var(--brand-blue); }
.brand-dots i:nth-child(2) { background: var(--brand-red); }
.brand-dots i:nth-child(3) { background: var(--brand-green); }
.brand-dots i:nth-child(4) { background: var(--brand-yellow); }

.brand-name {
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: 500;
  letter-spacing: var(--tracking-tight);
}

.topnav {
  display: flex;
  gap: var(--space-5);
  font-size: var(--text-sm);
  color: var(--text-faint);
}

.topnav a { border-bottom: var(--border) solid transparent; padding-bottom: 2px; }
.topnav a:hover { color: var(--text); border-bottom-color: var(--stroke-strong); }

/* ── lede ────────────────────────────────────────────────────────────────── */

.lede {
  padding-block: var(--space-8) var(--space-6);
  max-width: 50rem;
}

.kicker {
  margin: 0 0 var(--space-4);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
}

.lede h1 {
  margin: 0 0 var(--space-5);
  font-family: var(--font-display);
  font-size: var(--text-5xl);
  font-weight: 700;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  text-wrap: balance;
}

.sub {
  margin: 0 0 var(--space-6);
  max-width: 38rem;
  font-size: var(--text-lg);
  color: var(--text-dim);
}

.dateline {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--text-faint);
}

.dateline-date { color: var(--text); }
.dateline-sep { color: var(--stroke-strong); }
.dateline-count strong {
  font-size: var(--text-md);
  color: var(--text);
}

/* ── the live status strip ───────────────────────────────────────────────── */

.status {
  padding: var(--space-5) var(--space-6);
  border: var(--border) solid var(--stroke);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

.status-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}

.status-head h2 {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
}

.status-when {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-faint);
}

.status-list {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-3) var(--space-5);
  margin: 0;
  padding: 0;
  list-style: none;
}

.svc {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas:
    'glyph label'
    'glyph state'
    '.     detail';
  column-gap: var(--space-3);
  align-items: baseline;
}

.svc-glyph {
  grid-area: glyph;
  font-size: var(--text-xs);
  line-height: var(--leading-normal);
  color: var(--stroke-strong);
}

.svc-label {
  grid-area: label;
  font-size: var(--text-sm);
  font-weight: 500;
}

.svc-state {
  grid-area: state;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-dim);
}

/* An empty detail row still holds its line, so a service with nothing to add
 * keeps its state word on the same baseline as the ones that do. */
.svc-detail:empty::before { content: '\200b'; }

.svc-detail {
  grid-area: detail;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-faint);
}

.svc[data-state='online'] .svc-glyph { color: var(--ok); }
.svc[data-state='degraded'] .svc-glyph { color: var(--warn); }
.svc[data-state='offline'] .svc-glyph { color: var(--danger); }

.svc-loading .svc-label,
.svc-wide {
  color: var(--text-faint);
  font-size: var(--text-sm);
}

.svc-wide { grid-column: 1 / -1; }

/* ── the floor: three acts ───────────────────────────────────────────────── */

.section-h {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 500;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
}

.floor { padding-block: var(--space-7) var(--space-6); }
.floor > .section-h { margin-bottom: var(--space-5); }

.act {
  display: grid;
  grid-template-columns: 22rem 1fr;
  gap: var(--space-6);
  padding-block: var(--space-6);
  border-top: var(--border-thick) solid var(--stroke);
  position: relative;
}

/* The demo's own hue, carried by the rule that opens its band. Identity, never
 * state - nothing on this page changes color to tell you something is wrong. */
.act[data-hue='blue'] { border-top-color: var(--brand-blue); }
.act[data-hue='red'] { border-top-color: var(--brand-red); }
.act[data-hue='green'] { border-top-color: var(--brand-green); }

.act:last-of-type { border-bottom: var(--border) solid var(--stroke); }

/* The hue arrives as a wash from the leading edge on hover — the band's own
 * identity surfacing, rather than a permanent colored rule sitting on every row. */
.act::before {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-base) var(--ease-out);
}

.act[data-hue='blue']::before {
  background: linear-gradient(to right, color-mix(in srgb, var(--brand-blue) 8%, transparent), transparent 45%);
}
.act[data-hue='red']::before {
  background: linear-gradient(to right, color-mix(in srgb, var(--brand-red) 8%, transparent), transparent 45%);
}
.act[data-hue='green']::before {
  background: linear-gradient(to right, color-mix(in srgb, var(--brand-green) 8%, transparent), transparent 45%);
}

.act:hover::before,
.act:focus-within::before { opacity: 1; }

.act-id { position: relative; }

.act-id h3 {
  margin: 0 0 var(--space-2);
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 500;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

.act-scale {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-faint);
}

.act-body {
  position: relative;
  max-width: 40rem;
}

.act-copy {
  margin: 0 0 var(--space-4);
  font-size: var(--text-lg);
  color: var(--text-dim);
}

.act-go { margin: 0; }

.act-go a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--accent);
  border-bottom: var(--border) solid color-mix(in srgb, var(--accent) 35%, transparent);
  padding-bottom: 2px;
}

.act-go a:hover { border-bottom-color: var(--accent); }

.act-arrow { transition: transform var(--dur-fast) var(--ease-out); }
.act-go a:hover .act-arrow { transform: translateX(var(--space-1)); }

/* ── the back of the house: lab + operations ─────────────────────────────── */

.back {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: var(--space-8);
  padding-block: var(--space-6) var(--space-8);
}

.back-head { margin-bottom: var(--space-5); }
.back-head .section-h { margin-bottom: var(--space-3); }

.back-note {
  margin: 0;
  max-width: 34rem;
  font-size: var(--text-sm);
  color: var(--text-dim);
}

.rail {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: var(--border) solid var(--stroke);
}

.rail li { border-bottom: var(--border) solid var(--stroke); }

.rail a {
  display: block;
  padding: var(--space-4) 0;
  /* transform, not padding: animating a layout property thrashes layout on every
   * frame, and this list is long enough for that to show. */
  transition: transform var(--dur-fast) var(--ease-out);
}

.rail a:hover { transform: translateX(var(--space-3)); }

.rail strong {
  display: block;
  margin-bottom: var(--space-1);
  font-size: var(--text-md);
  font-weight: 500;
}

.rail span {
  display: block;
  max-width: 42rem;
  font-size: var(--text-sm);
  color: var(--text-faint);
}

.rail code {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}

.rail-tight strong { font-size: var(--text-sm); }

/* ── foot ────────────────────────────────────────────────────────────────── */

.foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-6) var(--space-7);
  border-top: var(--border) solid var(--stroke);
  font-size: var(--text-sm);
  color: var(--text-faint);
}

.foot p { margin: 0; }
.foot-dim { font-family: var(--font-mono); font-size: var(--text-xs); }

/* ── one authored entrance ───────────────────────────────────────────────── */

/* The default is the finished state, so a failed script or a blocked module leaves
 * a fully readable page. is-settled only replays the arrival. */
.is-settled .lede > *,
.is-settled .status,
.is-settled .act {
  animation: settle var(--dur-slower) var(--ease-out) backwards;
}

.is-settled .lede .kicker  { animation-delay: 0ms; }
.is-settled .lede h1       { animation-delay: 40ms; }
.is-settled .lede .sub     { animation-delay: 90ms; }
.is-settled .lede .dateline { animation-delay: 130ms; }
.is-settled .status        { animation-delay: 180ms; }
.is-settled .act:nth-of-type(1) { animation-delay: 240ms; }
.is-settled .act:nth-of-type(2) { animation-delay: 300ms; }
.is-settled .act:nth-of-type(3) { animation-delay: 360ms; }

@keyframes settle {
  from { opacity: 0; transform: translateY(var(--space-4)); filter: blur(6px); }
  to   { opacity: 1; transform: none; filter: blur(0); }
}

/* ── responsive ──────────────────────────────────────────────────────────── */

@media (max-width: 60rem) {
  .lede h1 { font-size: var(--text-4xl); }
  .act { grid-template-columns: 16rem 1fr; gap: var(--space-5); }
  .act-id h3 { font-size: var(--text-2xl); }
  .back { grid-template-columns: 1fr; gap: var(--space-7); }
  .status-list { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 40rem) {
  .topbar, main, .foot { padding-inline: var(--space-5); }
  .lede { padding-block: var(--space-7) var(--space-6); }
  .lede h1 { font-size: var(--text-3xl); }
  .sub { font-size: var(--text-md); }
  .act { grid-template-columns: 1fr; gap: var(--space-4); }
  .act-copy { font-size: var(--text-md); }
  .status { padding: var(--space-4) var(--space-5); }
  .status-list { grid-template-columns: 1fr; gap: var(--space-4); }
  .foot { flex-direction: column; gap: var(--space-2); }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .is-settled .lede > *,
  .is-settled .status,
  .is-settled .act { animation: none; }
  .act::before,
  .act-arrow,
  .rail a { transition: none; }
  .rail a:hover { transform: none; }
}
