/* Ec(h)osystem: a dark cave that lights up where sound touches it.
   Built from the game's UI rules: off-white blue on pure black, thin
   contour lines, Dongle, and selection shown by inverting. Body text in
   Atkinson Hyperlegible Next (Braille Institute) for low vision.
   Every text colour meets WCAG AAA (7:1) on black. */

@font-face { font-family: "Echo Display"; src: url(/fonts/display.woff2) format("woff2"); font-weight: 700; font-display: swap; }
@font-face { font-family: "Echo Display"; src: url(/fonts/display-regular.woff2) format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "Echo Body"; src: url(/fonts/body.woff2) format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "Echo Body"; src: url(/fonts/body-bold.woff2) format("woff2"); font-weight: 700; font-display: swap; }

:root {
  --bg: #000;
  --ink: #cfd8e6;        /* 14.6:1 */
  --dim: #a3adbd;        /* 9.0:1 */
  --glow: #00e9c3;       /* 12.2:1, teal of the menu lights */
  --line: #262e3a;
  --panel: rgba(0, 0, 0, 0.74);
  --focus: #ffd34d;      /* a colour the cave never uses */
  --font-display: "Echo Display", sans-serif;
  --font-body: "Echo Body", Verdana, sans-serif;
  --track: 0;
  --word: 0;
  --leading: 1.65;
  color-scheme: dark;
}
:root[data-spacing="wide"] { --track: 0.12em; --word: 0.16em; --leading: 2; }
:root[data-contrast="high"] { --ink: #fff; --dim: #fff; --glow: #fff; --line: #fff; --panel: #000; }

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html { background: var(--bg); color: var(--ink); -webkit-text-size-adjust: 100%; scroll-padding: 5rem 0 8rem; }
body {
  margin: 0;
  font: 400 1.0625rem/var(--leading) var(--font-body);
  letter-spacing: var(--track);
  word-spacing: var(--word);
  background: var(--bg);
  overflow-x: hidden;
  /* Long German words must still fit a phone at 200% text. No automatic
     hyphenation: NVDA reads the inserted hyphens aloud ("lis-"). */
  overflow-wrap: anywhere;
}
.btn, .pill { max-width: 100%; text-align: center; }
p, li { max-width: 68ch; }
a { color: var(--ink); text-decoration-color: var(--glow); text-underline-offset: 0.22em; text-decoration-thickness: 2px; }
a:hover { color: var(--glow); }
strong { font-weight: 700; }
kbd { font: inherit; border: 1px solid var(--dim); border-radius: 4px; padding: 0 0.35em; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; border-radius: 4px; }

.skip {
  position: fixed !important; left: 1rem; top: -5rem; z-index: 100 !important;
  padding: 0.75rem 1rem; background: var(--focus); color: #000; font-weight: 700; border-radius: 6px;
}
.skip:focus { top: 1rem; }
.sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* Dongle is drawn small on its body; these sizes are its optical sizes. */
.display, h2, .studio, .btn, .pill {
  font-family: var(--font-display); font-weight: 700; line-height: 0.9; letter-spacing: 0.01em;
}

/* ---- cave -------------------------------------------------------------- */

#cave { position: fixed; inset: 0; width: 100vw; height: 100vh; z-index: 0; pointer-events: none; }
:root[data-contrast="high"] #cave { display: none; }
body > *:not(#cave):not(dialog):not(.skip) { position: relative; z-index: 1; }

/* ---- top bar ----------------------------------------------------------- */

.topbar {
  display: flex; justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap;
  max-width: 74rem; margin: 0 auto; padding: 1rem;
}
.studio { font-size: 2rem; color: var(--dim); }
.topbar nav { display: flex; align-items: center; gap: 1.25rem; flex-wrap: wrap; }

/* ---- buttons: outlined, inverted when chosen (as in the game menu) ------ */

.btn, .pill {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
  min-height: 48px; padding: 0.35rem 1.35rem 0.2rem;
  font-size: 1.9rem; color: var(--ink); text-decoration: none; cursor: pointer;
  border: 2px solid var(--ink); border-radius: 999px; background: var(--panel);
}
.btn svg, .pill svg { margin-top: -0.15rem; }
.btn:hover, .pill:hover, .btn:focus-visible, .pill:focus-visible,
.pill[aria-pressed="true"] { background: var(--ink); color: #000; }
.btn.primary { border-color: var(--glow); box-shadow: 0 0 24px rgba(0, 233, 195, 0.25); }
.btn.primary:hover, .btn.primary:focus-visible { background: var(--glow); border-color: var(--glow); }
.actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.75rem; }
.link { font: inherit; color: var(--ink); background: none; border: 0; padding: 0; text-decoration: underline; text-decoration-color: var(--glow); text-underline-offset: 0.22em; cursor: pointer; }

/* ---- hero: the title card ---------------------------------------------- */

.hero { min-height: 92vh; min-height: 92svh; display: grid; place-items: center; text-align: center; overflow: hidden; }
:root:not(.has-cave):not([data-contrast="high"]) .hero, :root.has-cave[data-motion="off"]:not([data-contrast="high"]) .hero {
  /* No script, or nothing moves: the screenshot shows dimly and stays put. */
  background: radial-gradient(ellipse at center, rgba(0,0,0,.55), #000 75%), url(/img/hero.jpg) 50% 50% / cover no-repeat;
}
:root[data-contrast="high"] .hero { background: none; }
.hero-inner { width: 100%; max-width: 74rem; padding: 1rem 1rem 3rem; display: grid; justify-items: center; }
.title-card { position: relative; width: min(64rem, 100%); aspect-ratio: 16 / 9; display: grid; place-items: center; margin-bottom: -2rem; }
/* The rings are decoration only, so they are a CSS background, not an
   element a screen reader could stop on. */
.rings, .title-card::before { content: ""; position: absolute; inset: 0; background: url(/img/rings.png) center / contain no-repeat; opacity: 0.9; }
@media (prefers-reduced-motion: no-preference) {
  :root.has-cave[data-motion="full"] .title-card::before { animation: breathe 9s ease-in-out infinite; }
  :root.has-cave[data-motion="calm"] .title-card::before { animation: breathe 18s ease-in-out infinite; }
}
@keyframes breathe { 50% { transform: scale(1.025); opacity: 0.75; } }
h1 { position: relative; margin: 0; width: 30%; }
h1 img { display: block; width: 100%; height: auto; }
.lede { font-size: clamp(1.15rem, 2.2vw, 1.4rem); line-height: 1.5; max-width: 34ch; margin: 0 auto; }
.hero .actions { justify-content: center; }

/* ---- content ----------------------------------------------------------- */

main { padding-bottom: 2rem; }
section { max-width: 46rem; margin: 0 auto; padding: 3rem 1rem; }
h2 { font-size: clamp(3rem, 6.5vw, 4.2rem); font-weight: 700; margin: 0 0 0.75rem; color: var(--ink); }
p { margin: 0 0 1rem; }
/* Reading areas sit on a soft pool of black, so the cave never shows
   through behind text, however bright an echo gets. */
main > section, .hero .lede, .hero .actions, .gallery figcaption {
  background: rgba(0, 0, 0, 0.88);
  box-shadow: 0 0 40px 28px rgba(0, 0, 0, 0.88);
  border-radius: 28px;
}
.hero .lede, .hero .actions { padding: 0.25rem 0.5rem; }
.gallery figcaption { padding: 0.4rem 0.2rem; box-shadow: 0 0 20px 12px rgba(0, 0, 0, 0.88); }
main > section + section, main > section + .gallery, .gallery + section { margin-top: 2rem; }

.by-ear {
  margin-top: 1rem; padding: 2rem 1.75rem 2.25rem;
  border: 1px solid var(--line); border-radius: 22px;
  background: #000; box-shadow: none;
}
.by-ear h2 { font-size: clamp(2.6rem, 5vw, 3.4rem); }

.steps { padding-left: 1.2rem; margin: 0 0 0.5rem; }
.steps li { margin-bottom: 0.4rem; }
.steps li::marker { color: var(--glow); }
.features { list-style: none; padding: 0; margin: 1.25rem 0; display: grid; gap: 0.9rem; }
.features li { padding-left: 2.1rem; position: relative; }
.features li::before {
  content: ""; position: absolute; left: 0; top: 0.3em; width: 1.25rem; height: 1.25rem;
  background: url(/img/ripple.png) center / contain no-repeat;
}
:root[data-contrast="high"] .features li::before { filter: brightness(2); }

.gallery {
  max-width: 74rem; margin: 0 auto; padding: 1rem;
  display: grid; gap: 1.25rem; grid-template-columns: repeat(auto-fit, minmax(min(19rem, 100%), 1fr));
}
.gallery figure { margin: 0; }
.gallery img, .gallery video {
  display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover;
  border-radius: 12px; background: #000; border: 1px solid var(--line);
}
figcaption { font-size: 0.95rem; color: var(--dim); margin-top: 0.6rem; }

footer {
  max-width: 46rem; margin: 0 auto; padding: 2rem 1rem 3rem;
  color: var(--dim); border-top: 1px solid var(--line);
}
footer a { color: var(--dim); }
footer nav { display: flex; gap: 1.5rem; flex-wrap: wrap; margin-top: 0.5rem; }

/* ---- dock and captions ------------------------------------------------- */

/* The controls are a solid bar along the bottom at every width. The page
   reserves room for it and scrolls focused elements clear of it, so it never
   hides text, links or focus, whatever the text size. */
.dock {
  position: fixed !important; left: 0; right: 0; bottom: 0; z-index: 5 !important;
  display: flex; gap: 0.6rem; align-items: center; justify-content: flex-end; flex-wrap: wrap;
  padding: 0.6rem 1rem calc(0.6rem + env(safe-area-inset-bottom));
  background: #000; border-top: 1px solid var(--line);
}
/* --dock-h is measured by app.js, so wrapping at large text sizes still fits. */
:root.has-cave body { padding-bottom: calc(var(--dock-h, 4.5rem) + 0.5rem); }
:root.has-cave { scroll-padding-bottom: calc(var(--dock-h, 4.5rem) + 2rem); }
.hero { min-height: calc(100svh - 9rem); }
.dock .pill { font-size: 1.6rem; }
/* The Snap button: a pill like the others, with the game's ripple as its
   icon, so any label length (German, 200% text) fits. */
.dock .snap { border-color: var(--glow); background: #000; font-size: 1.75rem; }
.dock .snap:hover, .dock .snap:focus-visible { background: var(--ink); border-color: var(--ink); color: #000; }
.snap::before, .btn[data-snap]::before {
  content: ""; width: 1.1em; height: 1.1em; margin: -0.1em 0.1em 0 -0.3em; flex: none;
  background: url(/img/ripple.png) center / contain no-repeat;
}
.dock .snap:hover::before, .dock .snap:focus-visible::before, .btn[data-snap]:hover::before, .btn[data-snap]:focus-visible::before { filter: invert(1); }
:root[data-contrast="high"] .dock .snap { border-color: #fff; }
:root:not([data-motion="off"]) .ping { animation: ping 0.6s ease-out; }
@keyframes ping { 40% { transform: scale(1.06); } }
:root:not(.has-cave) .dock, :root:not(.has-cave) [data-snap] { display: none; }

.captions {
  position: fixed !important; left: 1rem; bottom: calc(var(--dock-h, 4.5rem) + 0.75rem); z-index: 5 !important;
  display: flex; flex-direction: column; gap: 0.3rem; max-width: calc(100vw - 9rem); pointer-events: none;
}
.captions span {
  align-self: flex-start; padding: 0.2rem 0.65rem; border-radius: 6px;
  background: #000; color: #fff; font-size: 1rem; border: 1px solid #444;
}

/* ---- settings dialog --------------------------------------------------- */

dialog {
  width: min(36rem, calc(100vw - 2rem)); max-height: calc(100vh - 2rem); padding: 0;
  color: var(--ink); background: #05070a; border: 2px solid var(--ink); border-radius: 18px;
}
dialog::backdrop { background: rgba(0, 0, 0, 0.8); }
.panel { padding: 1.25rem 1.5rem 1.5rem; }
.panel-head { display: flex; justify-content: space-between; align-items: center; gap: 1rem; }
.panel-head h2 { margin: 0; font-size: 2.8rem; }
.panel-note, .panel-foot { color: var(--dim); font-size: 0.95rem; }
fieldset { border: 1px solid var(--line); border-radius: 12px; margin: 0 0 1rem; padding: 0.6rem 1rem 0.5rem; }
legend { font: 700 1.9rem/1 var(--font-display); padding: 0 0.4rem; }
fieldset label { display: flex; gap: 0.75rem; align-items: center; min-height: 44px; cursor: pointer; }
fieldset input[type="checkbox"], fieldset input[type="radio"] { width: 1.35rem; height: 1.35rem; accent-color: var(--glow); flex: none; }
.row { display: flex; align-items: center; gap: 1rem; min-height: 44px; flex-wrap: wrap; }
.row label { min-height: 0; }
select, input[type="range"] { font: inherit; accent-color: var(--glow); }
select { min-height: 44px; padding: 0 0.75rem; color: var(--ink); background: #000; border: 1px solid var(--dim); border-radius: 8px; }
input[type="range"] { width: 12rem; }

/* ---- info and legal pages ---------------------------------------------- */

.page { max-width: 46rem; margin: 0 auto; padding: 1rem 1rem 6rem; }
.page h1 { width: auto; font: 700 clamp(3.4rem, 8vw, 5rem)/0.9 var(--font-display); margin: 1.5rem 0 1rem; }
.page h2 { font-size: 2.6rem; margin-top: 2.25rem; }
.page li { margin-bottom: 0.5rem; }

/* ---- narrow screens ---------------------------------------------------- */

@media (max-width: 40rem) {
  .title-card { aspect-ratio: 16 / 9; width: 170vw; margin: 2rem calc((100% - 170vw) / 2) -1rem; }
  h1 { width: 32%; }
  .hero { min-height: 0; }
  .hero-inner { padding-bottom: 3rem; }
  .dock { justify-content: space-between; padding-left: 0.6rem; padding-right: 0.6rem; }
  .dock .pill { font-size: 1.5rem; min-height: 48px; }
  .dock .label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .dock .pill { padding: 0.3rem 0.9rem 0.15rem; }
  .dock .pill:not(.snap) { min-width: 52px; }
  .dock .snap { font-size: 1.5rem; }
  .captions { max-width: calc(100vw - 2rem); }
}

@media (forced-colors: active) {
  #cave, .title-card::before { display: none; }
  .btn, .pill { border: 2px solid ButtonText; }
}
@media print {
  #cave, .dock, .captions, .topbar nav, .skip, dialog, .title-card::before { display: none !important; }
  html, body { background: #fff; color: #000; }
  a { color: #000; }
  h1 img { filter: invert(1); }
}
