@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("assets/fonts/ibm-plex-sans-latin-400-normal.woff2") format("woff2");
}

@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("assets/fonts/ibm-plex-sans-latin-600-normal.woff2") format("woff2");
}

@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("assets/fonts/ibm-plex-sans-latin-700-normal.woff2") format("woff2");
}

@font-face {
  font-family: "Press Start 2P";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("assets/fonts/press-start-2p-latin-400-normal.woff2") format("woff2");
}

/* Structure that every page shares. theme.css sets the colors, and the story sets them in
   game.css. Each look has a file that sets --radius, --dialog-radius and --dialog-width. */
:root {
  --pixel: "Press Start 2P", "Courier New", monospace;
  --sans: "IBM Plex Sans", Arial, sans-serif;
  /* The space beside the header, the main part and the footer, so their content lines up at 1120px
     or less. */
  --page-gutter: max(16px, calc((100vw - 1120px) / 2));
  /* The width of one frame of the tallest character in character-pictures.js at the base size of the
     characters, and how long a sprite strip shows each frame. A frame of Jack, 256 px, shows one pixel
     of the art on one pixel on screen. characters.js stops with an error when a loaded sprite of the
     tallest character has frames of another size. */
  --sprite-size: 256px;
  --sprite-frame-time: calc(1s / 12);
  /* The layers in front of the page, from back to front. */
  --layer-header: 2;
  --layer-jack-visit: var(--layer-header);
  --layer-trap: calc(var(--layer-header) + 1);
  --layer-way-out: calc(var(--layer-trap) + 1);
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  min-height: 100vh;
  font: 400 16px/1.5 var(--sans);
  background: var(--bg);
  color: var(--text);
}
/* The glow of theme.css does not move while the page scrolls, so it lights the top of the window on
   a long page as on a short one. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background: var(--page-glow);
  pointer-events: none;
}

h1, h2, h3, p { margin: 0; }

[hidden] { display: none !important; }
dialog:not([open]) { display: none; }

.muted { color: var(--muted); }

button:focus-visible, a:focus-visible, input:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
}

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px;
}

.btn {
  display: inline-block;
  text-decoration: none;
  cursor: pointer;
}

.actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }

/* A sprite of characters.js shows one frame of its file. Each place sets a width of --sprite-size
   times or divided by a power of two, so every pixel of the art of the tallest character covers the
   same number of pixels on screen. A standing figure scales the frames of every other character by
   his height. Each frame is square, so the full height of the picture shows one frame. A strip shows its
   frames one after another while the system allows motion. A strip with a rest frame shows that frame
   and plays its frames only where a look starts it, once. */
.character-sprite { width: var(--sprite-size); aspect-ratio: 1; overflow: hidden; }
.character-sprite img {
  display: block;
  width: auto;
  max-width: none;
  height: 100%;
  image-rendering: pixelated;
}
@media (prefers-reduced-motion: no-preference) {
  .character-sprite-strip:not(.character-sprite-once) img { animation: sprite-frames calc(var(--frames) * var(--sprite-frame-time)) steps(var(--frames)) infinite; }
}
.character-sprite-once img { transform: translateX(calc(-100% * var(--rest-frame) / var(--frames))); }
@keyframes sprite-frames { from { transform: none; } to { transform: translateX(-100%); } }

/* A character standing beside others, as wide as --width times --frame-scale, so each stands at his
   height. It covers only the width of its figure in a row, between --figure-left and --figure-right
   percent of the picture, and stands with the bottom edge of its figure, --figure-bottom percent down
   the picture, on the bottom of the row, so the empty edges of a sprite frame do not open a gap and
   every character stands on one floor. */
.standing-figure {
  --frame-width: calc(var(--width) * var(--frame-scale));
  margin-inline: calc(var(--figure-left) * var(--frame-width) / -100) calc((100 - var(--figure-right)) * var(--frame-width) / -100);
  margin-bottom: calc((100 - var(--figure-bottom)) * var(--frame-width) / -100);
}
.standing-figure .character { width: var(--frame-width); }

/* The pixel sprites of Shelly and Jack are drawn for a dark background, and parts of their edge, such
   as the white tail of Jack, are as light as the light theme. So in the light theme they get a dark
   outline on every page. */
:root[data-theme="light"] .character {
  filter: drop-shadow(1px 0 0 var(--text)) drop-shadow(-1px 0 0 var(--text))
    drop-shadow(0 1px 0 var(--text)) drop-shadow(0 -1px 0 var(--text));
}

/* Read by screen readers and not shown. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* --- The header, the same on both websites and the legal pages, and the footer of every page --- */

/* The header sets its own font, so it has the same height on every page. */
.nav {
  position: sticky;
  top: 0;
  z-index: var(--layer-header);
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px var(--page-gutter);
  background: color-mix(in oklab, var(--bg) 88%, transparent);
  border-bottom: 1px solid var(--line);
  backdrop-filter: blur(8px);
  font: 400 15px/1.4 var(--sans);
}
/* site-header.js sets .scrolled while the page is scrolled down. */
.nav.scrolled { box-shadow: 0 4px 12px var(--shadow); }
.logo {
  font: 700 20px/1 var(--sans);
  color: var(--text);
  text-decoration: none;
}
.nav-links { display: flex; gap: 20px; }
.nav-links a { color: var(--text-2); text-decoration: none; }
.nav-links a:hover { color: var(--text); }
.icon-button {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  background: transparent;
  color: var(--text);
  cursor: pointer;
}
.menu-button { display: none; }
.settings-button { margin-left: auto; }

/* One column for each group of links, and the copyright below them. Leaves room at the bottom for
   the traps that open along the bottom edge. The footer sets its fonts, so it looks the same on every
   page. */
.site-footer {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, max-content));
  gap: 24px 48px;
  padding: 40px var(--page-gutter) 120px;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font: 400 14px/1.5 var(--sans);
}
.site-footer h2 { margin-bottom: 8px; color: var(--text); font: 600 14px/1.5 var(--sans); }
.site-footer ul { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; }
.site-footer a { color: inherit; text-decoration: none; }
.site-footer a:hover { color: var(--text); text-decoration: underline; }
.copyright { grid-column: 1 / -1; }

/* --- Layout of both websites --- */

main { padding: 0 var(--page-gutter); }

.section {
  display: grid;
  gap: 16px;
  padding: 56px 0;
  scroll-margin-top: var(--header-height);
}

/* --- Traps --- */

/* A trap is a dialog opened with show(). Each kind below places it on the page. */
.trap {
  position: fixed;
  inset: auto;
  z-index: var(--layer-trap);
  width: auto;
  margin: 0;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 16px 48px var(--shadow);
  animation: slide-up 0.35s ease-out both;
}
@keyframes slide-up { from { transform: translateY(24px); opacity: 0; } }

.trap-close {
  margin-left: auto;
  background: none;
  border: 0;
  color: var(--muted);
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
}
.trap-quiet {
  background: none;
  border: 0;
  color: var(--muted);
  font: 400 14px/1.4 var(--sans);
  text-decoration: underline;
  cursor: pointer;
  padding: 8px 0;
}
.trap-bait {
  background: var(--jack-purple);
  color: var(--on-jack);
  border: 0;
  border-radius: 8px;
  padding: 14px 24px;
  font: 700 16px/1 var(--sans);
  cursor: pointer;
}
.trap-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 20px; }

.trap-cookies {
  left: 16px;
  right: 16px;
  bottom: 16px;
  max-width: 720px;
  margin: 0 auto;
  padding: 20px;
  display: grid;
  gap: 12px;
}
.file-chip {
  justify-self: start;
  font: 600 14px/1 var(--sans);
  color: var(--text-2);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 8px 10px;
}

.trap-promo {
  top: 76px;
  left: 16px;
  right: 16px;
  max-width: 560px;
  margin: 0 auto;
  padding: 18px;
  display: flex;
  align-items: flex-start;
  gap: 12px;
}
.trap-promo > div { display: grid; gap: 8px; }
.promo-link {
  justify-self: start;
  background: none;
  border: 0;
  padding: 0;
  font: 600 16px/1.4 var(--sans);
  color: var(--accent);
  text-decoration: underline;
  cursor: pointer;
}

.trap-notice {
  top: 76px;
  right: 16px;
  width: min(400px, calc(100vw - 32px));
  padding: 18px;
  display: grid;
  gap: 12px;
}
.notice-head { display: flex; align-items: flex-start; gap: 8px; }

.trap-form {
  right: 16px;
  bottom: 16px;
  width: min(380px, calc(100vw - 32px));
  max-height: calc(100dvh - 32px);
  overflow-y: auto;
  padding: 18px;
  display: grid;
  gap: 12px;
}
.form-step { display: grid; gap: 12px; }
.survey-question { font-weight: 600; }
.survey-answers { display: grid; gap: 8px; }
.survey-answer {
  font: 600 16px/1.4 var(--sans);
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  padding: 10px 12px;
  text-align: left;
  cursor: pointer;
}

.trap-qr {
  left: 16px;
  bottom: 16px;
  width: min(280px, calc(100vw - 32px));
  padding: 18px;
  display: grid;
  gap: 10px;
  justify-items: center;
  text-align: center;
}
.trap-qr .trap-close { position: absolute; top: 8px; right: 8px; }
.qr-button {
  display: grid;
  gap: 8px;
  justify-items: center;
  background: none;
  border: 0;
  font: 600 14px/1.4 var(--sans);
  cursor: pointer;
}
.qr {
  width: 160px;
  height: 160px;
  padding: 12px;
  background: var(--qr-paper);
  border-radius: 8px;
  image-rendering: pixelated;
}
.qr-caption { font: 600 14px/1.4 var(--sans); color: var(--muted); }

.trap-chat {
  right: 16px;
  bottom: 16px;
  width: min(360px, calc(100vw - 32px));
  padding: 16px;
  display: grid;
  gap: 12px;
}
.chat-head { display: flex; align-items: center; gap: 10px; }
.chat-avatar {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--chat-avatar);
  color: var(--on-chat-avatar);
  font: 700 14px/1 var(--sans);
}
.chat-name { font-weight: 600; }
.chat-status { font-size: 13px; color: var(--success); }
.chat-messages { display: grid; gap: 8px; min-height: 64px; }
.chat-bubble {
  justify-self: start;
  max-width: 90%;
  border-radius: 12px 12px 12px 4px;
  padding: 10px 12px;
  animation: slide-up 0.25s ease-out both;
}
.chat-input { display: flex; gap: 8px; }
.chat-input input { flex: 1; min-width: 0; }

/* --- Dialogs: the sign-in trap, result cards and settings --- */

.trap-login, .result, .settings {
  display: grid;
  width: min(var(--dialog-width), calc(100vw - 32px));
  max-height: calc(100dvh - 32px);
  padding: 24px;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--dialog-radius);
}
.trap-login { gap: 14px; }
.trap-login h2, .result h2, .settings h2 { font: 700 20px/1.3 var(--sans); }
.login-head { display: flex; align-items: center; }
.login-form { display: grid; gap: 14px; }
.login-form label { display: grid; gap: 6px; font-weight: 600; }
.login-form input, .chat-input input {
  font: 16px/1.4 var(--sans);
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  padding: 10px 12px;
}

.caught { --tone: var(--danger); }
.spotted { --tone: var(--success); }
.flags { margin: 0; padding-left: 20px; display: grid; gap: 6px; }
.result > .btn { justify-self: start; }

.settings { width: min(360px, calc(100vw - 32px)); }
.settings form { justify-self: start; }
.setting {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 16px;
  font-weight: 600;
}
.setting input {
  appearance: none;
  position: relative;
  width: 44px;
  height: 24px;
  margin: 0;
  border: 1px solid var(--line-strong);
  border-radius: 12px;
  background: var(--bg);
  cursor: pointer;
}
.setting input::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--muted);
  transition: transform 0.15s;
}
.setting input:checked { background: var(--accent); border-color: var(--accent); }
.setting input:checked::after { transform: translateX(20px); }
.segmented {
  display: flex;
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
}
.segmented > * {
  padding: 4px 10px;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-decoration: none;
  cursor: pointer;
}
.segmented > * + * { border-left: 1px solid var(--line); }
.segmented :is([aria-pressed="true"], [aria-current]) { background: var(--accent); color: var(--on-accent); }

/* --- Phone --- */

/* home.css and the stylesheet of each website size the homepage and the headings for phones, below
   the values for wide screens. On a phone the links show below the header while the menu button is
   pressed. */
@media (max-width: 760px) {
  .site-header .menu-button { display: grid; order: 1; }
  .nav-links {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    gap: 0;
    padding: 4px var(--page-gutter) 12px;
    background: var(--bg);
    border-bottom: 1px solid var(--line);
  }
  .nav-links a { padding: 12px 0; }
  .menu-button[aria-expanded="true"] ~ .nav-links { display: flex; }
}

@media (prefers-reduced-motion: no-preference) {
  .nav { transition: box-shadow 0.3s; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .trap, .chat-bubble { animation: none; }
  .setting input::after { transition: none; }
}
