/* The portal's stylesheet.
 *
 * Tokens transcribed from web/static/brand/visual-identity.json — the machine-readable sheet
 * is the source, and if these ever disagree the sheet wins (visual-identity.md §0). Named
 * after the tokens rather than after what they are used for, so a value can be traced back.
 *
 * Dark only, by decision: D6, and the mark may not sit on a light ground at all
 * (visual-identity.md §3 rule 5). There is deliberately no prefers-color-scheme block.
 */
:root {
  --void: #05060E; --space: #0B0E1D; --surface: #12162A; --raised: #1A1F38; --line: #262C4A;
  --starlight: #EAE7DE; --dim: #A9ADC2; --faint: #6D7290;
  --deep: #B35A1F; --core: #F09D3C; --hot: #FFD9A0; --lensed: #85B8FF;
  --stable: #4FD08C; --strain: #E8C357; --breach: #FF5D68;
  /* Saira and IBM Plex Mono are the two voices (visual-identity.md §5). Not loaded from a
   * font CDN: a public page should not hand a third party a request per visitor, and the
   * documented fallbacks are close enough until the files are self-hosted. */
  --display: Saira, Futura, "Avenir Next", "Century Gothic", system-ui, sans-serif;
  --data: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

body {
  margin: 0; background: var(--void); color: var(--starlight);
  font-family: var(--display); font-size: 16px; line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1, h2 { margin: 0; font-weight: 600; text-wrap: balance; }
p { margin: 0; }
a { color: var(--core); text-decoration: none; }
a:hover { color: var(--hot); }

.tiny { font-size: .82rem; line-height: 1.55; }
.dim { color: var(--dim); }
.faint { color: var(--faint); }
.hot { color: var(--hot); }
.stable { color: var(--stable); }
.strain { color: var(--strain); }
/* Every number the game computes is monospaced and tabular, so values tick without the
 * layout breathing (visual-identity.md §5). */
.mono { font-family: var(--data); font-variant-numeric: tabular-nums; }
.eyebrow {
  font-family: var(--data); font-size: .68rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--faint); margin-bottom: .4rem;
}
/* Wraps rather than squeezes: "Perihelion · Era 1" beside "not answering" does not fit a
 * card's width, and space-between alone broke the name mid-era. The state drops to its own
 * line instead, which reads as a label rather than as a layout bug. */
.rowline {
  display: flex; justify-content: space-between; gap: .25rem 1rem; flex-wrap: wrap;
}
.rowline > :last-child { white-space: nowrap; }

/* ---- chrome ---- */
.bar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 1rem clamp(1rem, 4vw, 3rem); border-bottom: 1px solid var(--line);
  flex-wrap: wrap; gap: .75rem;
}
.brand { display: flex; align-items: center; gap: .6rem; color: var(--starlight); }
.wordmark { font-weight: 700; letter-spacing: .18em; }
.bar nav { display: flex; align-items: center; gap: 1.2rem; font-size: .9rem; }
.bar form { margin: 0; }
button.link {
  background: none; border: 0; color: var(--core); font: inherit; cursor: pointer; padding: 0;
}
button.link:hover { color: var(--hot); }

.btn {
  display: inline-block; text-align: center; font: inherit; font-size: .9rem;
  letter-spacing: .04em; font-weight: 600; padding: .6rem 1.2rem; border-radius: 4px;
  border: 1px solid var(--line); color: var(--dim); cursor: pointer;
  /* Explicit, because this class was written for <a> and #366 put it on a <button>: a button
     inherits a light UA background, so the selector's submit came out looking like a filled
     primary action. The variants below set their own background after this. */
  background: transparent;
}
.btn.primary { background: var(--core); border-color: var(--core); color: #120A02; }
.btn.primary:hover { background: var(--hot); color: #120A02; }
.btn.quiet { border-color: var(--deep); color: var(--core); }
.btn.big { padding: .85rem 2rem; font-size: 1rem; }
.btn.provider { background: var(--starlight); border-color: var(--starlight); color: var(--void); width: 100%; }

/* ---- hero ---- */
.hero {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 1.4rem; padding: clamp(2.5rem, 7vw, 5rem) clamp(1rem, 8vw, 6rem);
  max-width: 60rem; margin: 0 auto;
}
.hero h1 { font-size: clamp(1.7rem, 4.5vw, 2.6rem); line-height: 1.15; max-width: 24ch; }
.hero .lede { color: var(--dim); max-width: 62ch; }
.hero .strip { font-size: .82rem; letter-spacing: .1em; color: var(--faint); }

/* The glow belongs to the embedding, not to the SVG: a glow sits on the surface behind the
 * mark, so the file cannot know it (visual-identity.md §6.5). The arc inside the file stills
 * itself under reduced motion; this stops too, for the same reader. */
.hero-glyph { animation: glyph-glow 4s ease-in-out infinite alternate; }
@keyframes glyph-glow {
  from { filter: drop-shadow(0 0 10px rgba(240, 157, 60, .30)); }
  to   { filter: drop-shadow(0 0 24px rgba(240, 157, 60, .60)); }
}
@media (prefers-reduced-motion: reduce) {
  .hero-glyph { animation: none; filter: drop-shadow(0 0 12px rgba(240, 157, 60, .35)); }
}

/* ---- cards and columns ---- */
.cards, .columns {
  display: grid; gap: 1.2rem; padding: 0 clamp(1rem, 4vw, 3rem) 2.5rem;
  max-width: 72rem; margin: 0 auto;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}
.card {
  background: var(--space); border: 1px solid var(--line); border-radius: 6px;
  padding: 1.1rem 1.2rem; display: flex; flex-direction: column; gap: .45rem;
}
/* The accretion gradient flowing toward hot, used as an ornament rather than as a progress
 * bar (visual-identity.md §6.4 owns the progress use). */
.column {
  border-top: 2px solid transparent;
  border-image: linear-gradient(90deg, var(--deep), var(--core), var(--hot)) 1;
  padding-top: .9rem; display: flex; flex-direction: column; gap: .5rem;
}

footer {
  border-top: 1px solid var(--line); padding: 1.5rem clamp(1rem, 4vw, 3rem);
  max-width: 72rem; margin: 0 auto;
}

/* ---- the sign-in dialog, opened by :target ----
 *
 * No JavaScript. The CTA is a link to #sign-in, this shows when it is the fragment, and the
 * close link goes back to #. A public page's one action must not depend on a script loading.
 */
.scrim {
  display: none; position: fixed; inset: 0; background: rgba(5, 6, 14, .72);
  align-items: center; justify-content: center; padding: 1rem; z-index: 10;
}
.scrim:target { display: flex; }
.modal {
  position: relative; width: min(23rem, 100%); background: var(--space);
  border: 1px solid var(--line); border-radius: 8px; padding: 2rem 1.8rem;
  display: flex; flex-direction: column; align-items: center; gap: 1.1rem;
  text-align: center; box-shadow: 0 24px 60px rgba(0, 0, 0, .65);
}
.modal .close {
  position: absolute; top: .5rem; right: .8rem; font-size: 1.4rem;
  color: var(--faint); line-height: 1;
}
.modal .note { border-top: 1px solid var(--raised); padding-top: 1rem; }

/* Focus has to stay visible (visual-identity.md §8). */
a:focus-visible, button:focus-visible {
  outline: 2px solid var(--core); outline-offset: 2px;
}

/* ---- the Metaverse ---- */
.lede-block { max-width: 72rem; margin: 0 auto; padding: 2rem clamp(1rem, 4vw, 3rem) .5rem; }
.tile.mine { border-color: var(--deep); }
.tile.dead { border-style: dashed; opacity: .8; }
.tile .facts { line-height: 1.7; }
.state {
  display: inline-flex; align-items: center; gap: .35rem; font-family: var(--data);
  font-size: .68rem; letter-spacing: .12em; text-transform: uppercase; font-weight: 600;
}
.state .dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
/* The state's colour is chosen in Rust and named here, so a card cannot claim a state the
 * portal did not decide (#364's "open and not answering"). */
.state.stable { color: var(--stable); }
.state.strain { color: var(--strain); }
.state.breach { color: var(--breach); }
.state.lensed { color: var(--lensed); }
.state.faint  { color: var(--faint); }
.btn.block { display: block; width: 100%; }
.btn.off { opacity: .55; cursor: default; }
.lensed { color: var(--lensed); }

.past {
  max-width: 72rem; margin: 0 auto; padding: 0 clamp(1rem, 4vw, 3rem) 2.5rem;
  border-top: 1px solid var(--line); padding-top: 1.5rem;
}
/* Wide content scrolls inside its own container rather than pushing the page sideways. */
.scroller { overflow-x: auto; }
.past table { width: 100%; border-collapse: collapse; min-width: 34rem; }
.past td { padding: .6rem .5rem; border-bottom: 1px solid var(--raised); vertical-align: top; }

/* ---- Surface 02: Standings (#366) -------------------------------------- */
.rowline.wrap { flex-wrap: wrap; gap: 1rem; align-items: flex-end; }
.rowline.wrap > :last-child { white-space: normal; }
.rowline.gap { gap: .5rem; align-items: center; }
.controls { display: flex; flex-direction: column; gap: .4rem; align-items: flex-end; }
.field {
  border: 1px solid var(--line); background: var(--surface); color: var(--dim);
  padding: .5rem .8rem; border-radius: 2px; font-size: .9rem;
}
.picker { display: flex; gap: .5rem; align-items: center; }
.picker select {
  border: 1px solid var(--line); background: var(--surface); color: var(--starlight);
  padding: .5rem .7rem; border-radius: 2px; font: inherit; font-size: .9rem;
}
/* A label the eye does not need and a screen reader does. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
.ladder { max-width: 72rem; margin: 0 auto; padding: .5rem clamp(1rem, 4vw, 3rem) 3rem; }
.ladder-table { width: 100%; border-collapse: collapse; min-width: 46rem; }
.ladder-table th {
  text-align: left; font-weight: 500; font-size: .78rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--faint); padding: 0 .5rem .5rem;
  border-bottom: 1px solid var(--line);
}
.ladder-table td { padding: .5rem; border-bottom: 1px solid var(--raised); }
.ladder-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.ladder-table .who { font-family: var(--display); font-weight: 600; color: var(--starlight); }
/* Kept on one line: the placeholder is bracketed by dashes and wrapping orphans the closing
   one, which reads as a rendering fault rather than as a withheld name. */
.ladder-table .who.withheld { font-weight: 400; color: var(--faint); font-style: italic; white-space: nowrap; }
.ladder-table tr.op .who { color: var(--hot); }
.chip {
  font-family: var(--data); font-size: .64rem; letter-spacing: .1em; vertical-align: middle;
  border: 1px solid var(--deep); color: var(--core); padding: .08rem .34rem; border-radius: 2px;
}
/* The "My rank" highlight, done by the browser: the jump is a fragment link and this is
   `:target`. No script on any public portal surface (#364). Both selectors, because the row
   should read as yours before you jump to it as well as after. */
.ladder-table tr.me td, .ladder-table tr:target td {
  background: color-mix(in srgb, var(--deep) 22%, transparent);
}
.ladder-table tr:target td { box-shadow: inset 0 0 0 1px var(--core); }
.footnote { max-width: 72rem; margin: 1rem auto 0; align-items: flex-start; }
.footnote p { max-width: 64ch; }
