/* Phase. Fonts are the homepage's, self-hosted (SIL Open Font License, see /fonts/OFL-*.txt). */
@font-face { font-family: "Inter Tight"; font-style: normal; font-weight: 400 500; font-display: swap;
  src: url("../fonts/inter-tight-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Inter Tight"; font-style: normal; font-weight: 400 500; font-display: swap;
  src: url("../fonts/inter-tight-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("../fonts/jetbrains-mono-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("../fonts/jetbrains-mono-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }

/* Phase: space, always dark. */
:root {
  --bg: #05060b; --ink: #ecE9f4; --soft: #b9b7c9; --dim: #9a98ad; --accent: #ffb074;
  --sans: "Inter Tight", ui-sans-serif, system-ui, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, Menlo, monospace;
  color-scheme: dark;
}
* { box-sizing: border-box; }
html, body { height: 100%; }
body { margin: 0; background: var(--bg); color: var(--ink); font: 400 15px/1.55 var(--sans); -webkit-font-smoothing: antialiased; overflow: hidden; }
a { color: inherit; }
:focus-visible { outline: 1px solid var(--accent); outline-offset: 3px; }

#sky, #phase { position: fixed; inset: 0; display: block; }
#phase { touch-action: none; }
#phase:focus-visible { outline: none; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; margin: -1px; }

/* The words: a quiet type scale on the sky. Sans for reading, mono only for small labels; owner 2026-10-03: "should
   have a better ui and typography". */
/* The words scroll when an open section is taller than the window (padding leaves room for the panels' edges). */
.head { position: fixed; top: 22px; left: calc(max(clamp(16px, 4vw, 44px), env(safe-area-inset-left)) - 14px); width: min(24rem + 28px, calc(100vw - 4px)); padding: 0 14px 24px;
  max-height: calc(100vh - 44px); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, 0.14) transparent;
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 24px), transparent); mask-image: linear-gradient(to bottom, #000 calc(100% - 24px), transparent);
  z-index: 2; pointer-events: none; }
.head:has(details[open]) { pointer-events: auto; }
.head a, .head summary { pointer-events: auto; }
.back { display: inline-block; padding: 4px 0; font: 11px/1 var(--mono); letter-spacing: 0.04em; color: var(--dim); text-decoration: none; transition: color 0.3s; }
.back:hover { color: var(--ink); }
h1 { font: 500 26px/1.1 var(--sans); letter-spacing: -0.02em; margin: 16px 0 10px; }
h1 .no { font: 400 10px/1 var(--mono); letter-spacing: 0.1em; color: var(--accent); opacity: 0.75; vertical-align: 0.95em; margin-left: 4px; }
.intro { margin: 0; color: var(--soft); font-size: 14.5px; line-height: 1.6; text-wrap: pretty; }
details { margin-top: 12px; color: var(--dim); font-size: 13px; line-height: 1.55; border-radius: 12px; transition: background-color 0.4s, border-color 0.4s; border: 1px solid transparent; margin-inline: -14px; padding: 0 14px; }
details + details { margin-top: 2px; }
details[open] { pointer-events: auto; background: rgba(9, 10, 18, 0.66); border-color: rgba(255, 255, 255, 0.07); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px); padding-bottom: 12px; }
summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 10px; min-height: 32px; font: 10.5px/1 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--dim); transition: color 0.3s; }
summary:hover, details[open] summary { color: var(--ink); }
summary::-webkit-details-marker { display: none; }
summary::after { content: ""; flex: 1; height: 1px; background: linear-gradient(90deg, rgba(255, 255, 255, 0.1), transparent); }
dl { margin: 4px 0 0; }
dt { color: var(--ink); font-weight: 500; margin-top: 10px; }
dd { margin: 1px 0 0; text-wrap: pretty; }
kbd { font: 10.5px/1 var(--mono); color: var(--ink); padding: 2px 5px 1px; border: 1px solid rgba(255, 255, 255, 0.16); border-bottom-width: 2px; border-radius: 4px; background: rgba(255, 255, 255, 0.04); }
/* Once the visitor starts playing (or comes back), the words fold away to one line: owner 2026-10-03, "text always
   there is also not clean". */
#more { display: none; pointer-events: auto; margin: 0; padding: 8px 0; font: 10.5px/1 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--dim); background: none; border: 0; cursor: pointer; }
#more::before { content: "+ " / ""; }
#more:hover { color: var(--ink); }
.folded #more { display: block; animation: rise 0.7s 0.25s cubic-bezier(0.2, 0.7, 0.2, 1) backwards; }
/* Folding: the words close upwards (rows 1fr -> 0fr) and fade; opening reverses it. */
#about { display: grid; grid-template-rows: 1fr; transition: grid-template-rows 0.8s cubic-bezier(0.3, 0.7, 0.2, 1), opacity 0.6s, visibility 0s; }
#about > .inner { min-height: 0; overflow: hidden; margin-inline: -14px; padding-inline: 14px; }   /* room for the open panels' edges */
.folded #about { grid-template-rows: 0fr; opacity: 0; visibility: hidden; transition: grid-template-rows 0.8s cubic-bezier(0.3, 0.7, 0.2, 1), opacity 0.45s, visibility 0s 0.8s; }
/* Sections open with their height eased where the browser can (::details-content), instantly elsewhere. */
:root { interpolate-size: allow-keywords; }
details::details-content { block-size: 0; overflow: hidden; opacity: 0; transition: block-size 0.5s cubic-bezier(0.3, 0.7, 0.2, 1), opacity 0.4s, content-visibility 0.5s allow-discrete; }
details[open]::details-content { block-size: auto; opacity: 1; }
/* Arrival: the sky fades up out of black, then the words rise in one after another. */
@keyframes rise { from { opacity: 0; transform: translateY(6px); } }
@keyframes dawn { from { opacity: 0; } }
#sky { animation: dawn 1.6s ease-out backwards; }
#phase { animation: dawn 2.2s 0.2s ease-out backwards; }
.head > :not(#about), #about .inner > * { animation: rise 0.9s cubic-bezier(0.2, 0.7, 0.2, 1) backwards; }
.head > .back { animation-delay: 0.2s; } .head > h1 { animation-delay: 0.35s; }
#about .inner > .intro { animation-delay: 0.55s; } #about .inner > details:nth-of-type(1) { animation-delay: 0.75s; }
#about .inner > details:nth-of-type(2) { animation-delay: 0.85s; }
.controls, #caption { animation: dawn 1.2s 1.1s backwards; }
@media (prefers-reduced-motion: reduce) {
  .head > :not(#about), #about .inner > *, .folded #more { animation-name: dawn; }
  #about, .folded #about, details::details-content { transition-property: opacity, visibility; }
}
summary::before { content: "+" / ""; display: inline-block; width: 8px; font-size: 13px; transition: transform 0.4s cubic-bezier(0.3, 0.7, 0.2, 1); }
details[open] summary::before { transform: rotate(45deg); }
ol { list-style: none; counter-reset: idea; margin: 6px 0 0; padding: 0; }
ol li { counter-increment: idea; position: relative; padding-left: 28px; margin-top: 10px; text-wrap: pretty; }
ol li::before { content: counter(idea, decimal-leading-zero); position: absolute; left: 0; top: 0.3em; font: 10px/1.2 var(--mono); color: var(--accent); opacity: 0.7; }
ol b { display: block; color: var(--ink); font-weight: 500; }

.controls { position: fixed; top: 14px; right: max(clamp(16px, 4vw, 40px), env(safe-area-inset-right)); z-index: 2; display: flex; gap: 18px; }
.controls button { margin: -10px -8px; padding: 14px 8px; min-width: 44px; font: 12px/1 var(--mono); color: var(--dim); background: none; border: 0; cursor: pointer; }
.controls button:hover, .controls button:focus-visible { color: var(--ink); }
.controls button[hidden] { display: none; }
#listen { color: var(--accent); }
/* The invitation to listen, in the quiet middle of the rings (placed by app.js). */
#invite { position: fixed; z-index: 2; transform: translate(-50%, -50%); margin: 0; padding: 14px 10px; border: 0;
  background: none; cursor: pointer; font: 13px/1.4 var(--mono); color: var(--accent); text-align: center;
  animation: breathe 3.2s ease-in-out 6; }   /* breathes a while, then rests (an endless animation costs CPU) */
#invite { transform: translate(-50%, 0); padding: 10px; text-shadow: 0 0 12px #000, 0 0 4px #000; }
#invite[hidden] { display: none; }
@keyframes breathe { 50% { opacity: 0.75; } }
@media (prefers-reduced-motion: reduce) { #invite { animation: none; } }

#caption { position: fixed; left: 0; right: 0; bottom: 14px; margin: 0; text-align: center; z-index: 2; pointer-events: none;
  font: 12px/1 var(--mono); color: var(--dim); letter-spacing: 0.02em; }
#caption b { color: var(--accent); font-weight: 400; }
#caption .spark { color: var(--dim); opacity: 0.8; margin-left: 4px; }
#caption .spark svg { width: 48px; height: 10px; margin-right: 5px; vertical-align: -1px; fill: currentColor; opacity: 0.6; }
#caption .spark .lit { fill: var(--accent); }
#caption .spark .none { opacity: 0.4; }
#hint { position: fixed; left: 50%; transform: translateX(-50%); bottom: 72px; margin: 0; z-index: 2; pointer-events: none;
  font: 12px/1 var(--mono); color: var(--dim); transition: opacity 1.2s; white-space: nowrap; }
#hint.gone { opacity: 0; }
noscript p { position: fixed; inset: 40% 16px auto; text-align: center; color: var(--dim); }

/* A calm screen: after a while without input, everything but the sky fades (app.js toggles .calm). */
.head, .controls, #caption, #hint, #invite { transition: opacity 2.5s; }
body.calm .head, body.calm .controls, body.calm #caption, body.calm #hint { opacity: 0; }
body.calm #invite { opacity: 0.8; }
#caption { bottom: calc(14px + env(safe-area-inset-bottom)); }

@media (max-width: 640px) {
  .head { top: auto; bottom: calc(44px + env(safe-area-inset-bottom)); max-height: 46vh; overflow-y: auto; overscroll-behavior: contain; }
  .head:has(details[open]) { pointer-events: auto; }
  #caption .spark { display: none; }   /* no room for it beside the counts on a phone */
  /* The fade mask would hide the back link (fixed at the top, outside the head's box) and dim the last line. */
  .head { -webkit-mask-image: none; mask-image: none; }
  .head:not(:has(details[open])) { max-height: none; }
  /* On a phone the words sit over the orbits: a soft dark scrim behind them keeps them readable. */
  .head { padding: 28px 16px 4px; left: 0; margin: 0; width: 100vw; background: linear-gradient(to bottom, transparent, rgba(5, 6, 11, 0.82) 26px); }
  .folded .head { background: none; }
  h1 { font-size: 22px; }
  .back { position: fixed; top: 18px; left: 16px; }
  h1 { margin-top: 0; }
  #hint { bottom: auto; top: 46px; }
}
