* { box-sizing: border-box; }

:root {
  --maxw: 1040px;

  /* Monochromatic: one slate-teal hue at a handful of values, plus white.
     Deliberately desaturated so the chrome never competes with — or echoes —
     the four operator colours in the animation itself. */
  --ground: #123236;      /* page background, the darkest value */
  --on-ground: #e8f1f2;   /* text on the ground */

  --ink: #123236;
  --muted: #5f7a7d;
  --faint: #7caeb3;

  --surface: #ffffff;
  --track: #ecf3f4;
  --border: #dbe7e8;
  --border-strong: #c4d8da;

  --accent: #3d8b93;      /* mid value: nav pill */
  --accent-600: #1e5b62;  /* dark value: primary button, hover text */
  --accent-050: #ecf3f4;
  --on-accent: #ffffff;

  --radius-lg: 22px;
  --radius-md: 14px;
  --radius-pill: 999px;

  --shadow-sm: 0 1px 2px rgba(18, 50, 54, 0.06);
  --shadow-md: 0 18px 44px -20px rgba(6, 26, 29, 0.45), 0 2px 8px rgba(18, 50, 54, 0.06);
  --shadow-accent: 0 10px 24px -8px rgba(18, 50, 54, 0.4);
}

html, body { margin: 0; }

body {
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  color: var(--on-ground);
  background: var(--ground);
  height: 100dvh;
  overflow: hidden;
  padding: clamp(10px, 2.5vw, 28px) 16px clamp(10px, 2vw, 24px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(10px, 2vw, 18px);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ---------- header ---------- */
header { width: 100%; max-width: var(--maxw); text-align: center; }

.eyebrow {
  margin: 0 0 6px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--faint);
}

h1 {
  font-size: clamp(23px, 4.6vw, 34px);
  line-height: 1.1;
  letter-spacing: -0.025em;
  margin: 0 0 clamp(10px, 1.8vw, 16px);
  font-weight: 700;
  color: var(--on-ground);
}

/* ---------- nav = dropdown (one row tall, to save vertical space) ---------- */
.nav {
  position: relative;
  display: flex;
  justify-content: center;
}
.navtrigger {
  font: inherit;
  font-size: 16px;
  font-weight: 600;
  padding: 10px 16px;
  min-width: min(420px, 100%);
  border-radius: var(--radius-pill);
  background: var(--accent);
  border: 1px solid transparent;
  box-shadow: var(--shadow-accent);
  color: var(--on-accent);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  text-align: center;
}
.navtrigger-label { line-height: 1.2; }
.navcaret { font-size: 18px; line-height: 1; opacity: 0.9; transition: transform 0.18s ease; }
.nav.open .navcaret { transform: rotate(180deg); }

.navmenu {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 20;
  min-width: min(420px, calc(100vw - 24px));
  max-height: min(60dvh, 420px);
  overflow-y: auto;
  padding: 6px;
  border-radius: var(--radius-md);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-md);
}
.nav.open .navmenu { display: block; }

.navbtn {
  font: inherit;
  font-size: 16px;
  font-weight: 600;
  width: 100%;
  padding: 10px 14px;
  border-radius: 10px;
  background: transparent;
  border: 0;
  color: var(--muted);
  cursor: pointer;
  text-align: left;
  transition: color 0.18s ease, background 0.18s ease;
}
.navbtn:hover { color: var(--ink); background: rgba(61, 139, 147, 0.12); }
.navbtn.active { color: var(--on-accent); background: var(--accent); }
.navbtn:focus-visible,
.navtrigger:focus-visible { outline: 3px solid rgba(61, 139, 147, 0.55); outline-offset: 2px; }

/* ---------- panel card ---------- */
main {
  width: 100%;
  max-width: var(--maxw);
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.panel {
  position: relative;
  flex: 1;
  min-height: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: clamp(12px, 2.4vw, 24px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(10px, 1.6vw, 16px);
}

/* ---------- help button + overlay ---------- */
/* Lives in the controls row rather than floating in the panel corner: the
   corner is the hardest spot to reach one-handed and it crowded the scene.
   Takes .btn's sizing wholesale — a narrower width here would fight .btn's
   horizontal padding (same specificity, and .btn wins on source order),
   collapsing the content box and shoving the glyph off-centre.
   Kept visually lighter than Restart — it's tertiary. */
.helpbtn { color: var(--muted); }
.helpbtn:hover { color: var(--on-accent); background: var(--accent); border-color: var(--accent); }

.helpoverlay {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(6, 26, 29, 0.55);
}
.helpoverlay[hidden] { display: none; }
.helpcard {
  position: relative;
  width: min(560px, 100%);
  max-height: 80dvh;
  overflow-y: auto;
  padding: clamp(20px, 3vw, 32px);
  background: var(--surface);
  color: var(--ink);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}
/* Right padding keeps the heading clear of the now-larger close button. */
.helpcard h2 { margin: 0 0 12px; padding-right: 40px; font-size: 1.1rem; }
.helpcard p { margin: 0 0 12px; font-size: 0.95rem; line-height: 1.55; color: var(--muted); }
.helpcard p:last-child { margin-bottom: 0; }
.helpcard strong { color: var(--ink); }
/* Sized to a proper touch target rather than the bare glyph's ~20px. */
.helpclose {
  position: absolute;
  top: 6px;
  right: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: none;
  color: var(--muted);
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
}
.helpclose:hover { color: var(--ink); }

/* ---------- stage ---------- */
.stage-wrap {
  flex: 1;
  min-height: 0;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
#stage {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  /* Set per-animation by app.js; the fallback matches the default scene. */
  aspect-ratio: var(--stage-aspect, 1000 / 952);
  background: transparent;
}

/* ---------- legend + footnote ---------- */
/* Out of the SVG deliberately: in there they scaled with the scene and landed
   around 9-13px on a phone. Here they hold their size whatever the scene does. */
.sceneinfo {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px 18px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.legend:empty { display: none; }
.legend li {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 14px;
  font-weight: 500;
  color: #475569;
}
/* Drawn as an inline SVG line in scene.js — see legendSwatch() for why a CSS
   dashed border wasn't good enough. */
.legend-swatch {
  flex: none;
  overflow: visible;
}

.footnote {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.4;
  color: #64748b;
  text-align: center;
  text-wrap: balance;
}
.footnote[hidden] { display: none; }

/* ---------- variant toggle = segmented pill ---------- */
/* Deliberately quieter than .btn-primary: this picks which variant to watch,
   it isn't the primary action. Grey selection, no accent fill. */
/* Animations with no variants render an empty container that would still cost a
   .panel gap — on a phone that's height taken for nothing. Same trick as .legend. */
.variants:empty { display: none; }
.variants {
  display: inline-flex;
  /* As a .panel flex child this shrinks below its own min-height and slices the
     labels in half — the scene, not the toggle, is what should absorb pressure. */
  flex: none;
  align-self: center;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  overflow: hidden;
}
.variantbtn {
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  padding: 6px 13px;
  min-height: 42px;   /* touch target — kept generous despite the small label */
  border: 0;
  border-left: 1px solid var(--border-strong);
  border-radius: 0;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  transition: color 0.18s ease, background 0.18s ease;
}
.variantbtn:first-child { border-left: 0; }
.variantbtn:hover { color: var(--ink); background: #f4f8f9; }
.variantbtn.active { color: var(--ink); background: var(--track); }
/* Inset, because the rounded container clips an outset ring on the end buttons. */
.variantbtn:focus-visible { outline: 3px solid rgba(61, 139, 147, 0.55); outline-offset: -3px; }

/* ---------- controls ---------- */
.controls { display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; }
.btn {
  font: inherit;
  font-size: 17px;
  font-weight: 600;
  padding: 9px 22px;
  min-height: 44px;
  /* Flex so the play/pause SVG centres in the box — as an inline child it sat on
     the text baseline instead, riding low. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: transform 0.06s ease, box-shadow 0.18s ease, background 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: 3px solid rgba(61, 139, 147, 0.55); outline-offset: 2px; }

/* Darkest value, a step below the nav pill's mid tone — with a single hue,
   emphasis has to come from value rather than from a different colour. */
.btn-primary {
  border: 0;
  background: var(--accent-600);
  color: var(--on-accent);
  box-shadow: var(--shadow-accent);
}
.btn-primary:hover { box-shadow: 0 14px 30px -8px rgba(61, 139, 147, 0.55); transform: translateY(-1px); }
.btn-primary:active { transform: translateY(1px); }

.btn-secondary {
  border: 1px solid var(--border-strong);
  background: #fff;
  color: var(--ink);
  box-shadow: var(--shadow-sm);
}
.btn-secondary:hover { background: var(--accent-050); border-color: #a8c9cd; color: var(--accent-600); }

/* ---- Credit ---- */
/* Sits in normal flow below the panel, but never claims space the panel needs:
   flex-shrinks to nothing and is simply clipped off-screen when there's no room. */
footer {
  width: 100%;
  max-width: var(--maxw);
  flex: 0 1 auto;
  min-height: 0;
}
/* The credit sits on the dark body background, not the white panel, so it uses
   the light --faint rather than the panel-side --muted. */
.credit {
  text-align: right;
  margin: 0;
  font-size: 12px;
  color: var(--faint);
}
.credit a {
  color: var(--faint);
  text-decoration: none;
}
.credit a:hover { color: var(--on-ground); }
.credit a { display: inline-flex; align-items: center; gap: 5px; }
.credit-sparkle {
  width: 1.15em;
  height: 1.15em;
  flex: none;
}

/* Credit link tap: brief shimmer + a puff of sparkles before navigating. */
.credit-poof {
  color: var(--faint) !important;
  animation: credit-poof 0.48s ease both;
}
@keyframes credit-poof {
  0%   { transform: none; }
  30%  { transform: scale(1.12); filter: drop-shadow(0 0 6px var(--faint)); }
  100% { transform: scale(0.96); opacity: 0.35; }
}
.credit-spark {
  position: fixed;
  z-index: 50;
  color: var(--faint);
  font-size: 12px;
  line-height: 1;
  pointer-events: none;
  transform: translate(-50%, -50%);
  animation: credit-spark 0.5s ease-out forwards;
}
@keyframes credit-spark {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.3); }
  25%  { opacity: 1; }
  100% { opacity: 0; transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(1.1) rotate(90deg); }
}

/* ---------- responsive ---------- */
@media (max-width: 520px) {
  body { padding: 10px 10px 12px; gap: 10px; }
  h1 { margin-bottom: 10px; }

  .nav { width: 100%; }
  .navtrigger { width: 100%; min-width: 0; font-size: 15px; }
  .navmenu { min-width: 0; width: 100%; }
  .navbtn { font-size: 15px; }

  /* Roomier gap than the shared clamp, which bottoms out at its 10px floor
     exactly where the scene, legend and toggle most need separating.
     The card takes the full height available and no more: the stage below
     resolves height: 100% against it, so it needs a definite height rather than
     the content-derived one `flex: 0 0 auto` would give it. */
  .panel { flex: 1 1 auto; min-height: 0; gap: 16px; }
  /* ...and let the leftover height pool below the panel instead of being split
     above and below it, which pushed the card away from the nav. */
  main { flex: 1 1 auto; min-height: 0; justify-content: flex-start; }
  /* The scene is the one thing in the card that can afford to give up height,
     so it's the only shrinkable child — everything below it (toggle, controls)
     is a fixed-size touch target that has to stay on screen. */
  .stage-wrap { flex: 1 1 auto; min-height: 0; }
  .sceneinfo, .variants, .controls { flex: 0 0 auto; }
  /* The scene fills the height left over after the chrome, rather than deriving
     it from the viewport width via aspect-ratio. On a narrow phone a near-square
     ratio makes the stage taller than the room actually available, which is what
     kept pushing the controls off-screen — and no dvh cap fixes that generally,
     since the right number differs per device and changes when the address bar
     hides. The SVG's default preserveAspectRatio letterboxes the drawing inside
     whatever box it gets, so the strategy stays centred and correctly shaped;
     the cost is unused margin at the sides on very short viewports. */
  #stage { aspect-ratio: auto; width: 100%; height: 100%; }

  /* On a ~480px phone a three-variant pill ("Edges" / "Edge & centre" / ...) is
     wider than the card, and `flex: none` meant it overflowed rather than fitting.
     Let it span the card and split the width evenly instead. */
  .variants { display: flex; width: 100%; align-self: stretch; }
  .variantbtn { flex: 1 1 0; padding: 6px 8px; min-width: 0; }

  /* Two full-size pills plus the help button also overflow one row; wrapping
     already happens, but the padding is what makes them too wide to pair up. */
  .controls { gap: 8px; }
  .btn { font-size: 16px; padding: 9px 16px; }
}

/* Short / landscape viewports: keep everything on one screen.
   Gated on orientation so none of this can reach a portrait phone — a landscape
   phone is short but wide, so the fix is to spend width instead of height:
   title and nav share one row, and the controls sit beside the scene rather
   than under it. Without this the near-square scene is starved by the short
   viewport and renders at a fraction of its usable size. */
@media (max-height: 560px) and (orientation: landscape) {
  body { padding: 8px 14px; gap: 8px; }

  /* Title and nav side by side: reclaims a whole row of height. */
  header { display: flex; align-items: center; gap: 14px; }
  h1 { font-size: 20px; margin: 0; flex: 0 0 auto; }
  .nav { flex: 1 1 auto; }
  .navtrigger { width: 100%; min-width: 0; padding: 8px 16px; }

  /* Scene takes the card's full height; the controls stack down its right.
     stage-wrap keeps width:100% and flex-grows — an auto width here would be
     circular against the SVG's own width:auto and collapse it to nothing. */
  .panel { flex-direction: row; align-items: center; gap: clamp(10px, 2vw, 20px); }
  .stage-wrap { flex: 1 1 auto; height: 100%; }
  .variants { flex: 0 0 auto; flex-direction: column; }
  .variantbtn { border-left: 0; border-top: 1px solid var(--border-strong); }
  .variantbtn:first-child { border-top: 0; }
  .controls { flex: 0 0 auto; flex-direction: column; flex-wrap: nowrap; }
}
