/* Meridian — meridian.org.in
   Single committed theme. This is an instrument panel, not a document:
   there is no light mode, by choice. */

/* ---------------------------------------------------------------- fonts --
   IBM Plex, latin-1 subset, self-hosted. No CDN, no Google Fonts, no
   external request at runtime — see _headers, where the CSP enforces it.
   SIL OFL-1.1; licence text ships in /fonts/OFL.txt.                       */

@font-face {
  font-family: "IBM Plex Sans";
  src: url("/fonts/IBMPlexSans-Regular.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("/fonts/IBMPlexSans-Medium.woff2") format("woff2");
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fonts/IBMPlexMono-Regular.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}

/* --------------------------------------------------------------- tokens -- */

:root {
  --bg:      #08090D;
  --surface: #101319;
  --rule:    #1E2229;
  --ink:     #E8E6E1;   /* warm off-white, never pure white */
  --muted:   #6E7480;

  /* Semantic, not decorative. These three appear on link lines in the
     animation and in the legend that explains them. Nowhere else. */
  --signal:  #6BB88A;   /* above horizon — link acquired */
  --alert:   #B8544F;   /* below horizon — no link */
  --trace:   #C99A4E;   /* predicted / next pass */

  --sans: "IBM Plex Sans", system-ui, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, monospace;

  --pad: clamp(1.5rem, 4vw, 4rem);

  /* Content reveal. SETTLE_MS in main.js must match --reveal-at. */
  --reveal-at: 4200ms;
  --reveal-dur: 600ms;
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
}

/* ---------------------------------------------------------------- reset -- */

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

html { background: var(--bg); color-scheme: dark; }

body {
  margin: 0;
  min-height: 100svh;
  overflow-x: clip;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* --------------------------------------------------------------- canvas --
   Fixed behind everything. The globe's centre and radius are computed in
   main.js, which is what lets it bleed off the top-right edge.            */

#scene {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
}

/* --------------------------------------------------------------- layout --
   Asymmetric on purpose. Masthead top-left, content anchored lower-left,
   colophon along the bottom. Nothing is centred.                          */

.page {
  position: relative;
  z-index: 1;
  min-height: 100svh;
  padding: var(--pad);
  display: grid;
  /* minmax(0, 1fr) rather than the implicit auto column. An auto track is
     sized from its items' max-content contribution, so a wide unbreakable run
     can push the track past the container; with overflow-x: clip on the body
     that surfaces as text sliced off at the edge instead of as a scrollbar.
     Pinning the minimum to 0 makes that impossible by construction. */
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto 1fr auto;
  gap: clamp(2.5rem, 6vh, 5rem);
}

.page > *, .colophon > *, .content > * { min-width: 0; }

/* Hairline rules divide. No boxes, no cards, no borders around content. */
.masthead  { border-bottom: 1px solid var(--rule); padding-bottom: 1.25rem; }
.colophon  { border-top:    1px solid var(--rule); padding-top:    1.25rem; }

.masthead {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.mark {
  width: 1.5rem;
  height: 1.5rem;
  flex: none;
  color: var(--ink);
}

.wordmark {
  margin: 0;
  font-size: clamp(0.8125rem, 1.4vw, 0.9375rem);
  font-weight: 500;
  letter-spacing: 0.38em;
  text-indent: 0.38em;   /* compensates the trailing letter-space */
  text-transform: uppercase;
  line-height: 1;
}

/* ------------------------------------------------------------- content -- */

.content {
  align-self: end;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(1.25rem, 2.5vh, 2rem);
  max-width: 34rem;
}

.content p { margin: 0; }

.lede {
  font-size: clamp(1.75rem, 3.6vw, 2.75rem);
  font-weight: 400;
  line-height: 1.12;
  letter-spacing: -0.025em;
  text-wrap: balance;
  max-width: 22ch;
}

.body {
  font-size: clamp(0.9375rem, 1.1vw, 1.0625rem);
  line-height: 1.65;
  color: var(--muted);
  max-width: min(44ch, 100%);
}

/* The single call to action. A link, drawn as a link — no button, no fill. */
.cta {
  display: inline-flex;
  align-items: baseline;
  gap: 0.6em;
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  padding-bottom: 0.45rem;
  border-bottom: 1px solid var(--rule);
  transition: border-color 180ms var(--ease-out), color 180ms var(--ease-out);
}
.cta:hover,
.cta:focus-visible { border-bottom-color: var(--ink); }

.cta .arrow { transition: transform 220ms var(--ease-out); }
.cta:hover .arrow { transform: translateX(0.25em); }

:focus-visible {
  outline: 1px solid var(--ink);
  outline-offset: 5px;
}

/* ------------------------------------------------------------ colophon -- */

.colophon {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.5rem 3rem;
}

.meta,
.legend {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

.meta { margin: 0; }
.meta .dot { color: var(--rule); padding-inline: 0.35em; }

/* The legend is the key to the animation's colours, and the only place on
   the page besides the canvas where those three colours appear. */
.legend {
  margin: 0;
  display: grid;
  gap: 0.4rem;
}

.legend-row {
  display: flex;
  align-items: center;
  gap: 0.65rem;
}

.legend dt,
.legend dd { margin: 0; }

.legend dd { color: var(--rule); }
.legend dd::before { content: "— "; }

.legend dt { display: flex; align-items: center; gap: 0.55rem; color: var(--muted); }

/* Drawn as a 1px line, because that is exactly what it labels. */
.swatch {
  display: block;
  width: 1.375rem;
  height: 1px;
  flex: none;
}
.swatch-signal { background: var(--signal); }
.swatch-alert  { background: var(--alert); }
.swatch-trace  { background: var(--trace); }

/* --------------------------------------------------------------- reveal --
   Done in CSS, not JS, deliberately: the content then appears even if
   main.js fails to load or is blocked. JS only ever cancels it (.intro-done),
   never causes it.                                                         */

@keyframes reveal {
  from { opacity: 0; transform: translateY(0.75rem); }
  to   { opacity: 1; transform: none; }
}

.reveal {
  animation: reveal var(--reveal-dur) var(--ease-out) var(--reveal-at) both;
}

.masthead        { animation-delay: var(--reveal-at); }
.content .lede   { animation-delay: calc(var(--reveal-at) + 120ms); }
.content .body   { animation-delay: calc(var(--reveal-at) + 240ms); }
.content p:last-child { animation-delay: calc(var(--reveal-at) + 360ms); }
.colophon        { animation-delay: calc(var(--reveal-at) + 480ms); }

/* Intro skipped, or never ran. Content is simply present. */
.intro-done .reveal { animation: none; }

/* ---------------------------------------------------------- responsive --
   Below this width the globe sits above the content at reduced scale
   (main.js repositions it). It is never hidden.                           */

@media (max-width: 840px) {
  .page { gap: clamp(2rem, 5vh, 3rem); }
  .lede { max-width: 20ch; }
  .colophon { flex-direction: column; align-items: flex-start; gap: 1.25rem; }

  /* Tracked uppercase mono is what runs out of room first. At 360px the
     content box is 312px, and at the wide setting the metadata line measures
     343px and a legend row with its gloss about 350px. Tightened here they
     come to 295px and 245px. Measured, not guessed. */
  .meta, .legend { font-size: 0.625rem; letter-spacing: 0.1em; }
  .meta .dot { padding-inline: 0.2em; }

  /* The gloss on each legend label is what goes: the colour and the label
     already carry the meaning, and keeping it is what breaks 312px. */
  .legend dd { display: none; }
}

@media (min-width: 1800px) {
  .page { max-width: 1800px; margin-inline: auto; }
}

/* ------------------------------------------------------ reduced motion --
   Non-negotiable: no intro, no reveal, no rotation. main.js draws one
   settled frame and never starts a loop.                                  */

@media (prefers-reduced-motion: reduce) {
  .reveal { animation: none; }
  .cta, .cta .arrow { transition: none; }
}
