/* The home page's title, tagline and Start button fonts: Fredoka and Nunito,
   both under the SIL Open Font License (public/fonts/*-OFL.txt). They're kept
   here rather than loaded from Google Fonts, so the page doesn't wait on, or
   tell, another site. Until they load, the page uses its usual font. */






* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: #ccfbf1;
  color: #134e4a;
  font-family: system-ui, sans-serif;
  text-align: center;
  padding-top: 3rem;
}

.friends {
  display: flex;
  flex-wrap: wrap; /* on narrow screens, pals wrap onto a second row */
  justify-content: center;
  align-items: flex-end;
  gap: 0.5rem;
  padding: 0 1rem;
}

.pal {
  width: 120px;
}

/* On a phone, just the first six pals, so the title and Start button aren't
   pushed down past the first screen, a little smaller so they sit in two
   even rows of three. */
@media (max-width: 600px) {
  .friends > .pal {
    max-width: calc((100vw - 3.5rem) / 3);
  }

  .friends > .pal:nth-child(n + 7) {
    display: none;
  }
}

/* Tap a pal on the home page and she divides in two (game/split.js). The
   daughters can drift past the edge of her drawing while she's split. */
.splittable .pal {
  cursor: pointer;
  overflow: visible;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation; /* no double-tap zoom when tapping twice */
  user-select: none;
  -webkit-user-select: none;
}

.pal .cell {
  transform-box: fill-box;
  transform-origin: center;
}

.bob {
  animation: bob 2.4s ease-in-out infinite;
}

.squish {
  animation: squish 2s ease-in-out infinite 0.5s;
  transform-origin: bottom center;
}

@keyframes wobble {
  0%,
  100% {
    transform: rotate(-4deg);
  }

  50% {
    transform: rotate(4deg);
  }
}

@keyframes bob {
  0%,
  100% {
    transform: translateY(0);
  }

  50% {
    transform: translateY(-10px);
  }
}

@keyframes squish {
  0%,
  100% {
    transform: scale(1, 1);
  }

  50% {
    transform: scale(1.08, 0.92);
  }
}

/* Elia is a spirochete: she wiggles like a corkscrew. */
@keyframes slither {
  0%,
  100% {
    transform: skewX(-8deg);
  }

  50% {
    transform: skewX(8deg);
  }
}

.slither {
  animation: slither 1.6s ease-in-out infinite;
}

/* The game's name on the home page, big and round like a game logo. */
.logo {
  margin: 1.6rem 0 0.4rem;
  font-family: Fredoka, system-ui, sans-serif;
  font-size: clamp(3.2rem, 15vw, 5.2rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.01em;
}

/* What the game is, in a few words, under its name. */
.tagline {
  margin: 0 0 1.4rem;
  padding: 0 1rem;
  font-family: Nunito, system-ui, sans-serif;
  font-size: clamp(1.05rem, 4.6vw, 1.3rem);
  font-weight: 700;
  letter-spacing: 0.01em;
  color: #0f766e;
}

/* A sentence or two under the Start button saying what the game is, for
   new players (and search engines). */
.about {
  max-width: 34rem;
  margin: 2rem auto 0;
  padding: 0 1.25rem;
  line-height: 1.5;
  opacity: 0.85;
}

/* The link to FunGals, the sister game, under the description. */
.sister-game {
  margin: 0.75rem auto 0;
  padding: 0 1.25rem;
  opacity: 0.85;
}

.sister-game a {
  color: #0f766e;
  font-weight: 700;
}

.start-btn {
  margin-top: 1rem;
  padding: 0.8rem 2rem;
  font-family: Fredoka, system-ui, sans-serif;
  font-size: 1.3rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: white;
  background: #0f766e;
  border: none;
  border-radius: 999px;
  box-shadow: 0 4px 0 #134e4a;
  cursor: pointer;
  transition: background 0.2s ease, transform 0.15s ease, box-shadow 0.15s ease;
}

.start-btn:hover {
  background: #14b8a6;
}

.start-btn:active {
  transform: translateY(3px);
  box-shadow: 0 1px 0 #134e4a;
}

.start-btn:disabled {
  cursor: wait;
  opacity: 0.8;
}

/* The home page's second button, under Start: Who’s That Pal?
   (whos-that-pal.html). Outlined, so Start stays the main thing to press. */
.guess-link {
  display: inline-block;
  margin-top: 1rem;
  padding: 0.6rem 1.6rem;
  font-family: Fredoka, system-ui, sans-serif;
  font-size: 1.1rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: #0f766e;
  background: #f0fdfa;
  border: 2px solid #0f766e;
  border-radius: 999px;
  text-decoration: none;
  transition: background 0.2s ease;
}

.guess-link:hover {
  background: #ccfbf1;
}

.picker-page {
  min-height: 100vh;
  display: grid;
  place-items: center;
  /* Keep the card and the signature under it together in the middle, even
     on a page whose card is short (like choose-mode.html). */
  align-content: center;
  padding: 2rem 1rem;
}

.picker-shell {
  width: min(760px, 100%);
  background: rgba(255, 255, 255, 0.35);
  border: 2px solid rgba(19, 78, 74, 0.15);
  border-radius: 24px;
  padding: 2rem;
  box-shadow: 0 20px 40px rgba(19, 78, 74, 0.08);
}

/* The pal picker is wider than the other cards, to fit four pals across. */
.picker-wide {
  width: min(1000px, 100%);
  position: relative; /* for the microscope button in its corner */
}

/* Microscope mode (game/pal-picker.js): a button in the picker's corner that
   shows every pal as she'd look after a Gram stain, purple or pink. */
.scope-btn {
  position: absolute;
  top: 1.75rem;
  right: 1.75rem;
  display: flex;
  align-items: center;
  gap: 0.4em;
  padding: 0.45em 0.85em;
  border: 2px solid #99f6e4;
  border-radius: 999px;
  background: #f0fdfa;
  color: #0f766e;
  font: inherit;
  font-size: 0.9rem;
  font-weight: 700;
  cursor: pointer;
}

.scope-btn:hover {
  background: #ccfbf1;
}

.scope-btn[aria-pressed='true'] {
  background: #0f766e;
  border-color: #0f766e;
  color: #fff;
}

.scope-icon {
  font-size: 1.15rem;
  line-height: 1;
}

.scope-caption {
  margin: -0.5rem 0 1rem;
  text-align: center;
  font-size: 0.9rem;
  color: #475569;
}

.scope-caption b {
  white-space: nowrap;
}

.scope-caption .gram-positive {
  color: #6d28d9;
}

.scope-caption .gram-negative {
  color: #db2777;
}

/* Compare sizes (game/pal-picker.js): the same kind of button in the opposite
   corner, which shows the pals' sizes relative to each other. */
.scale-btn {
  position: absolute;
  top: 1.75rem;
  left: 1.75rem;
  display: flex;
  align-items: center;
  gap: 0.4em;
  padding: 0.45em 0.85em;
  border: 2px solid #99f6e4;
  border-radius: 999px;
  background: #f0fdfa;
  color: #0f766e;
  font: inherit;
  font-size: 0.9rem;
  font-weight: 700;
  cursor: pointer;
}

.scale-btn:hover {
  background: #ccfbf1;
}

.scale-btn[aria-pressed='true'] {
  background: #0f766e;
  border-color: #0f766e;
  color: #fff;
}

.scale-icon {
  font-size: 1.15rem;
  line-height: 1;
}

/* The two buttons sit in the picker's corners; on a phone they share a row. */
.picker-tools {
  display: contents;
}

.scale-caption {
  margin: -0.5rem 0 1rem;
  text-align: center;
  font-size: 0.9rem;
  color: #475569;
}

/* Each pal's picture shrinks and grows smoothly between full size and to
   scale. */
.pal-icon svg {
  transition: transform 0.5s ease;
}

/* Ari, the longest, spills past her picture's square into her tile's margin. */
.to-scale .pal-icon svg {
  overflow: visible;
}

.size-note {
  display: none;
}

.to-scale .size-note {
  display: block;
  margin: 0.15rem 0 0;
  font-size: 0.85rem;
  font-weight: 700;
  color: #0f766e;
}

/* On a phone or small tablet, where the corners are too close to the
   heading, the buttons sit side by side under it instead. */
@media (max-width: 760px) {
  .picker-tools {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.6rem;
    margin: -0.5rem auto 1rem;
  }

  .scope-btn,
  .scale-btn {
    position: static;
  }
}

/* Stained, each pal sits on a white slide. Her stain colors themselves are
   set on her drawing by game/stain.js; here they just fade in and out. */
.stained .pal-icon {
  background: radial-gradient(circle, #fff 0 58%, #f1f5f9 72%, #e2e8f0 100%);
  box-shadow: inset 0 0 0 2px #cbd5e1;
}

.pal-icon svg * {
  transition: fill 0.4s ease, stroke 0.4s ease;
}

.stain-note {
  display: none;
}

.stained .stain-note {
  display: block;
  font-size: 0.8rem;
  font-weight: 700;
  color: #db2777;
}

@media (prefers-reduced-motion: reduce) {
  .pal-icon svg,
  .pal-icon svg * {
    transition: none;
  }
}

/* A heading at the very top of the card sits on the card's own padding,
   without the browser's extra margin on top. */
.picker-shell > h1:first-child {
  margin-top: 0;
}

/* Four across on a computer (two rows of four), two on a tablet, one on a
   phone, where the Select buttons wouldn't fit side by side. */
/* Four cards across (two on a tablet, one on a phone), each the same
   width. Flex instead of grid so a page with fewer pals than a full row
   (like the second page, while it fills up) keeps them in the middle. */
.picker-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem;
  margin-top: 1.25rem;
}

.picker-grid[hidden] {
  display: none;
}

.picker-grid > .pal-card {
  flex: 0 0 calc((100% - 2.25rem) / 4);
  box-sizing: border-box;
  min-width: 0;
}

@media (max-width: 900px) {
  .picker-grid > .pal-card {
    flex-basis: calc((100% - 0.75rem) / 2);
  }
}

/* Back and More pals, under the cards. */
.picker-pager {
  display: flex;
  justify-content: center;
  gap: 0.75rem;
  margin-top: 1.25rem;
}

.picker-pager[hidden],
.pager-btn[hidden] {
  display: none;
}

.pager-btn {
  min-height: 44px;
  padding: 0.6rem 1.3rem;
  border: 2px solid #0f766e;
  border-radius: 999px;
  background: #f0fdfa;
  color: #0f766e;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}

.pager-btn:hover {
  background: #ccfbf1;
}

.pal-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  background: rgba(255, 255, 255, 0.5);
  border: 2px solid rgba(15, 118, 110, 0.2);
  border-radius: 18px;
  padding: 1rem;
}

/* Cards that are links, with no button: a pal on the picker
   (game/pal-picker.js) and a game on the mode page. The whole card is tapped,
   so it lifts a little and outlines itself in teal on hover, to show it can
   be. */
a.pal-card {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: border-color 0.15s ease, background 0.15s ease, transform 0.15s ease;
}

a.pal-card:hover {
  border-color: #0f766e;
  background: rgba(255, 255, 255, 0.85);
  transform: translateY(-2px);
}

a.pal-card:active {
  transform: translateY(0);
}

a.pal-card:focus-visible {
  outline: 3px solid #0f766e;
  outline-offset: 2px;
}

/* On the picker, a little more compact than elsewhere: less padding and a
   smaller picture, so more of the page fits on the screen. */
.picker-grid .pal-card {
  padding: 1.1rem 0.75rem 0.85rem;
}

.picker-grid .pal-icon {
  width: 96px;
  height: 96px;
  margin-bottom: 0.5rem;
}

.picker-grid .pal-icon svg {
  width: 80px;
  height: 80px;
}

/* Each pal's name, with her species right under it. */
.picker-grid .pal-card h2 {
  margin: 0.2rem 0 0.15rem;
  line-height: 1.2;
}

/* Her species, right under her name. Every card keeps room for two lines,
   so a long one that wraps (Streptococcus pneumoniae) doesn't make her card
   look different from the rest. */
.picker-grid .species {
  margin: 0;
  line-height: 1.3;
  min-height: 2.6em;
}

/* On a phone, two pals to a row instead of one, a little smaller, with
   less padding around the grid, so most of a page fits on the screen. */
@media (max-width: 520px) {
  .picker-shell:has(.picker-grid) {
    padding: 1.25rem 0.75rem;
  }

  .picker-grid {
    gap: 0.6rem;
    margin-top: 1rem;
  }

  .picker-grid > .pal-card {
    flex-basis: calc((100% - 0.6rem) / 2);
  }

  .picker-grid .pal-card {
    padding: 0.7rem 0.4rem 0.5rem;
  }

  .picker-grid .pal-icon {
    width: 72px;
    height: 72px;
    margin-bottom: 0.35rem;
  }

  .picker-grid .pal-icon svg {
    width: 60px;
    height: 60px;
  }

  .picker-grid .pal-card h2 {
    font-size: 1.2rem;
  }

  .picker-grid .species {
    font-size: 0.8rem;
  }
}

.pal-icon {
  width: 110px;
  height: 110px;
  margin: 0 auto 0.75rem;
  border-radius: 22px;
  display: grid;
  place-items: center;
  /* Each pal's own tile color (her `tile` in config.js), set by palTile. */
  background: var(--tile, rgba(255, 255, 255, 0.6));
  box-shadow: inset 0 0 0 2px rgba(19, 78, 74, 0.06);
}

.pal-icon svg {
  width: 90px;
  height: 90px;
  display: block;
}

/* On a tile she's small, so only the sparks at the tips of her nanowires
   show: the bursts along them would crowd the wires. */
.pal-icon .burst {
  display: none;
}

.pick-btn {
  margin-top: 0.75rem;
  padding: 0.7rem 1rem;
  border: none;
  border-radius: 999px;
  background: #0f766e;
  color: white;
  font-weight: 700;
  cursor: pointer;
  display: inline-block;
  text-decoration: none;
}

.pick-btn:hover {
  background: #14b8a6;
}

.back-link {
  display: inline-block;
  margin-top: 1.5rem;
  color: #0f766e;
  font-weight: 700;
  text-decoration: none;
}

.back-link:hover {
  text-decoration: underline;
}

.dish-shell {
  width: min(760px, 100%);
  /* Nothing on the game page needs selecting, and on an iPhone a finger
     that slips off the dish onto the words around it would otherwise bring
     up the text magnifier mid-game. */
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

/* The agar keeps itself square (below) and the glass rim wraps around it.
   Don't size the agar from the dish's height instead: Safari (so every
   browser on an iPhone) can ignore a percentage height when the parent's
   height only comes from aspect-ratio, which squashes the agar into an oval. */
.petri-dish {
  position: relative;
  width: min(600px, 100%);
  margin: 0 auto;
  padding: 18px;
  border-radius: 50%;
  /* A finger drags the pal from anywhere on the dish, rim included
     (game/touch.js): don't scroll or zoom the page, select text, or pop up
     the magnifier or long-press menu instead. */
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  /* glass rim */
  background: rgba(255, 255, 255, 0.55);
  border: 3px solid rgba(15, 118, 110, 0.35);
  box-shadow:
    0 18px 36px rgba(19, 78, 74, 0.15),
    inset 0 0 0 2px rgba(255, 255, 255, 0.8);
}

.agar {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  border-radius: 50%;
  display: grid;
  place-items: center;
  /* agar gel with a soft glass highlight */
  background:
    radial-gradient(circle at 32% 28%, rgba(255, 255, 255, 0.75), transparent 32%),
    radial-gradient(circle at 50% 50%, #fef9c3, #e7eeab);
  border: 2px solid rgba(180, 83, 9, 0.2);
  /* Touch and hold on the agar to steer (game/touch.js): don't scroll or zoom
     the page, select text, or pop up the long-press menu instead. */
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

/* Positioned by petri-dish.js; the pal's own idle animation stays on the SVG. */
/* The mode screen after picking a pal. */
.mode-shell h1 {
  margin: 0.75rem 0 0;
}

.mode-pal {
  display: flex;
  justify-content: center;
}

/* About her, under her picture on the mode screen: opens her profile
   (pal-profile.html). Shaped like the picker's Gram stain button. */
.about-btn {
  display: flex;
  align-items: center;
  gap: 0.4em;
  width: max-content;
  margin: 0.6rem auto 0;
  padding: 0.45em 0.95em;
  border: 2px solid #99f6e4;
  border-radius: 999px;
  background: #f0fdfa;
  color: #0f766e;
  font-size: 0.9rem;
  font-weight: 700;
  text-decoration: none;
}

.about-btn:hover {
  background: #ccfbf1;
}

.about-icon {
  width: 1.25em;
  height: 1.25em;
  border-radius: 50%;
  border: 2px solid currentColor;
  display: grid;
  place-items: center;
  font: italic 700 0.8em/1 Georgia, serif;
}

/* A pal's profile (game/pal-profile.js), like the box about an organism in
   a textbook. Read top to bottom, so it's left-aligned. */
.profile {
  display: grid;
  gap: 1.1rem;
  text-align: left;
}

.profile h2 {
  margin: 0.3rem 0 0;
  font-size: 1.25rem;
}

.profile-top {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 1.25rem;
  align-items: center;
}

.profile-top .pal-icon {
  width: 150px;
  height: 150px;
  margin: 0;
}

.profile-top .pal-icon svg {
  width: 124px;
  height: 124px;
}

.profile-name {
  margin: 0;
  font-size: 2.4rem;
  line-height: 1.05;
}

.profile-species {
  margin: 0.2rem 0 0;
  font-size: 1.1rem;
}

.profile-size {
  margin: 0.35rem 0 0;
  font-weight: 700;
  color: #0f766e;
}

.profile-stain {
  display: flex;
  gap: 0.9rem;
  align-items: center;
}

.profile-stain .pal-icon {
  width: 84px;
  height: 84px;
  margin: 0;
  flex: none;
  background: radial-gradient(circle, #fff 0 58%, #f1f5f9 72%, #e2e8f0 100%);
  box-shadow: inset 0 0 0 2px #cbd5e1;
}

.profile-stain .pal-icon svg {
  width: 68px;
  height: 68px;
}

.profile-stain p {
  margin: 0;
}

.profile-facts {
  margin: 0;
  padding-left: 1.2rem;
  display: grid;
  gap: 0.35rem;
  line-height: 1.4;
}

.profile-back {
  justify-self: center;
  margin-top: 0.5rem;
}

@media (max-width: 560px) {
  .profile-top {
    grid-template-columns: 1fr;
    justify-items: center;
    text-align: center;
  }
}

.mode-grid {
  display: grid;
  /* Two by two, on a phone too. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
  margin-top: 1.5rem;
}

.mode-card h2 {
  margin: 0.25rem 0 0.5rem;
}

.mode-card p {
  margin: 0;
  line-height: 1.45;
}

/* On a phone the two-by-two cards are narrow, so give the words more room:
   less padding, a closer gap, and slightly smaller text. */
@media (max-width: 600px) {
  .mode-grid {
    gap: 0.6rem;
  }

  .mode-shell .mode-card {
    padding: 0.75rem 0.6rem;
  }

  .mode-card h2 {
    font-size: 1.15rem;
  }

  .mode-card p {
    font-size: 0.85rem;
    line-height: 1.35;
  }
}

/* Picking rivals before a mixed culture race (game/choose-rivals.js): a
   tile for every other pal, tapped on and off, up to three. */
.rivals-status {
  margin: 0.5rem 0 0;
  font-weight: 700;
  color: #0f766e;
  min-height: 1.5em;
}

/* Six across (three on a phone), each the same width, with a short last row
   kept in the middle. */
.rivals-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem;
  margin-top: 1.25rem;
}

.rivals-grid > .rival-btn {
  flex: 0 0 calc((100% - 3.75rem) / 6);
  min-width: 0;
}

@media (max-width: 760px) {
  .rivals-grid {
    gap: 0.6rem;
  }

  .rivals-grid > .rival-btn {
    flex-basis: calc((100% - 1.2rem) / 3);
  }

  .rival-btn .pal-icon {
    width: 64px;
    height: 64px;
  }

  .rival-btn .pal-icon svg {
    width: 52px;
    height: 52px;
  }
}

.rival-btn {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  padding: 0.6rem 0.4rem 0.7rem;
  background: rgba(255, 255, 255, 0.5);
  border: 2px solid rgba(15, 118, 110, 0.2);
  border-radius: 18px;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.rival-btn .pal-icon {
  width: 76px;
  height: 76px;
  margin: 0;
  border-radius: 16px;
}

.rival-btn .pal-icon svg {
  width: 62px;
  height: 62px;
}

.rival-btn:hover:not(:disabled):not([aria-pressed='true']) {
  border-color: #14b8a6;
}

.rival-btn:focus-visible {
  outline: 3px solid #0f766e;
  outline-offset: 2px;
}

/* Picked: a thick teal border and a check in the corner. */
.rival-btn[aria-pressed='true'] {
  background: #f0fdfa;
  border: 3px solid #0f766e;
  padding: calc(0.6rem - 1px) calc(0.4rem - 1px) calc(0.7rem - 1px);
}

.rival-btn[aria-pressed='true']::after {
  content: '\2713';
  position: absolute;
  top: -0.55rem;
  right: -0.55rem;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
  background: #0f766e;
  color: white;
  font-size: 0.9rem;
  line-height: 1.6rem;
}

.rival-btn:disabled {
  opacity: 0.4;
  cursor: default;
}

.rivals-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 0.75rem;
  margin-top: 1.5rem;
}

.rivals-actions .pick-btn {
  margin-top: 0;
  min-height: 44px;
  padding: 0.6rem 1.4rem;
  font: inherit;
  font-weight: 700;
}

.rivals-actions .pick-btn:disabled {
  background: #94a3b8;
  cursor: default;
}

.rivals-actions .pager-btn {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}

/* Who’s That Pal? (game/whos-that-pal.js): a fact with "this pal" in place of
   her name, over a tile for every pal (the rival screen's tiles). */
.guess-shell {
  width: min(860px, 100%);
}

.guess-counter {
  margin: 0.25rem 0 0;
  font-size: 0.9rem;
  font-weight: 700;
  color: #0f766e;
  opacity: 0.75;
}

.guess-fact {
  max-width: 38rem;
  margin: 0.75rem auto 0;
  padding: 1rem 1.25rem;
  background: rgba(255, 255, 255, 0.7);
  border: 2px solid rgba(15, 118, 110, 0.2);
  border-radius: 18px;
  font-size: 1.15rem;
  line-height: 1.6;
}

/* Where her name goes: "this pal" in plain text, then her name, in her
   color, once she's found. */
.fact-blank.filled {
  font-weight: 700;
}

.guess-status {
  margin: 1rem 0 0;
  min-height: 1.5em;
  font-weight: 700;
  color: #0f766e;
}

/* Her species under her name on each tile, shortened: P. aeruginosa. It
   shrinks a little with the tile on a phone, and a long one
   (L. monocytogenes) wraps onto two lines if it still won't fit. */
.guess-btn {
  container-type: inline-size;
}

.guess-species {
  margin-top: -0.25rem;
  font-size: clamp(0.68rem, 11.5cqi, 0.8rem);
  font-weight: 400;
  color: #134e4a;
  line-height: 1.2;
}

/* The right pal: a thick teal border and a check, like a picked rival. */
.guess-btn.right {
  background: #f0fdfa;
  border: 3px solid #0f766e;
  padding: calc(0.6rem - 1px) calc(0.4rem - 1px) calc(0.7rem - 1px);
}

.guess-btn.right::after {
  content: '\2713';
  position: absolute;
  top: -0.55rem;
  right: -0.55rem;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
  background: #0f766e;
  color: white;
  font-size: 0.9rem;
  line-height: 1.6rem;
}

/* Keep room for Next fact, so the page doesn't jump when it shows up. */
.guess-shell .rivals-actions {
  min-height: 44px;
}

.next-fact[hidden] {
  display: none;
}

.pal-mover {
  grid-area: 1 / 1; /* stack in the dish center, even after dividing into two */
  width: 18%;
  position: relative;
  z-index: 1; /* swim over the nutrients */
  will-change: transform;
}

/* Nutrient flecks scattered on the agar; placed by petri-dish.js. */
.nutrient {
  position: absolute;
  width: 2.2%;
  aspect-ratio: 1;
  border-radius: 45% 55% 50% 40%;
  /* Each fleck gets a random --hue (set in game/nutrients.js), so the agar is
     sprinkled with every color of the rainbow. The faint dark ring keeps the
     yellow ones visible against the yellow agar. */
  background: hsl(var(--hue, 20) 85% 52%);
  box-shadow: 0 0 0 1px rgba(19, 78, 74, 0.25);
  opacity: 0.9;
  transform: translate(-50%, -50%);
  transition: transform 0.25s ease, opacity 0.25s ease;
}

.nutrient.small {
  width: 1.5%;
}

.nutrient.eaten {
  transform: translate(-50%, -50%) scale(0);
  opacity: 0;
}

.dish-pal {
  width: 100%;
  height: auto;
  display: block;
}

.dish-pal[hidden] {
  display: none;
}

.wobble {
  animation: wobble 3s ease-in-out infinite;
}

/* For anyone who'd rather not have motion, the pals stay still. */
@media (prefers-reduced-motion: reduce) {
  .bob,
  .squish,
  .slither,
  .wobble {
    animation: none;
  }
}

.species {
  font-size: 0.95rem;
}

/* The pal's name and species above the dish. */
.dish-title {
  margin-bottom: 1.25rem;
}

.dish-title .pal-name {
  margin: 0;
  font-size: 2rem;
}

.dish-title .species {
  margin: 0.15rem 0 0;
  font-size: 1.05rem;
}

.win-banner {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 3;
  width: min(320px, 85%);
  padding: 1.25rem 1.5rem 1.5rem;
  transform: translate(-50%, -50%);
  background: rgba(255, 255, 255, 0.92);
  border: 2px solid rgba(15, 118, 110, 0.25);
  border-radius: 20px;
  box-shadow: 0 16px 36px rgba(19, 78, 74, 0.2);
  animation: pop-in 0.35s ease-out;
}

@media (prefers-reduced-motion: reduce) {
  .win-banner {
    animation: none;
  }
}

.win-banner[hidden] {
  display: none;
}

.win-banner h2 {
  margin: 0 0 0.5rem;
}

.win-banner p {
  margin: 0;
}

/* The "Did you know?" fact about your pal when you win. */
.win-banner .fun-fact {
  margin-top: 0.75rem;
  padding: 0.55rem 0.75rem;
  border-radius: 12px;
  background: rgba(15, 118, 110, 0.08);
  font-size: 0.92rem;
  line-height: 1.4;
}

.win-banner .fun-fact[hidden] {
  display: none;
}

.win-banner .fun-fact strong {
  color: #0f766e;
}

@keyframes pop-in {
  from {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.85);
  }

  to {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
  }
}

.banner-buttons {
  margin-top: 1rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
}

.banner-buttons .pick-btn {
  margin-top: 0;
  font: inherit;
  font-weight: 700;
}

.banner-buttons .pick-btn[hidden] {
  display: none;
}

/* The other choices in the pop-up: outlined instead of filled. */
.start-over,
.back-to-modes {
  background: white;
  color: #0f766e;
  box-shadow: inset 0 0 0 2px #0f766e;
}

.start-over:hover,
.back-to-modes:hover {
  background: #ccfbf1;
}

/* The group the player steers stays on top, in full color with a soft halo;
   the offspring left behind are paler and a little washed out. */
.pal-mover.player {
  z-index: 2;
  filter:
    drop-shadow(0 0 2px #fff)
    drop-shadow(0 0 3px #fff)
    drop-shadow(0 0 7px rgba(15, 118, 110, 0.45));
}

/* Pearl's glow traces her whole capsule, a much bigger shape than a rod
   with thin flagella, so it gets a smaller, fainter teal ring to look like
   everyone else's. */
.pal-mover.player:has(> [data-pal="pearl"]:not([hidden])) {
  filter:
    drop-shadow(0 0 2px #fff)
    drop-shadow(0 0 3px #fff)
    drop-shadow(0 0 4px rgba(15, 118, 110, 0.28));
}

/* The rival's pal in mixed culture mode: a soft dark outline instead of the
   player's white glow, so you can tell who's who. */
.pal-mover.rival {
  z-index: 2;
  filter:
    drop-shadow(0 0 1.5px rgba(30, 41, 59, 0.55))
    drop-shadow(0 0 5px rgba(30, 41, 59, 0.25));
}

.pal-mover.offspring {
  opacity: 0.75;
  filter: saturate(0.45) brightness(1.08);
}

/* Elia's offspring are a touch paler still: her purple stays strong even
   washed out, so they stood out more than the others'. */
.pal-mover.offspring .dish-pal[data-pal="elia"] {
  opacity: 0.85;
  filter: saturate(0.8) brightness(1.05);
}

/* Only the player's pal has a face. */
.pal-mover.offspring .face {
  display: none;
}

/* Offspring sit still on the agar, without the idle wiggle. That also keeps
   a dish full of 64 cells smooth. */
.pal-mover.offspring .dish-pal {
  animation: none;
}

/* Petri Picnic (game/tumble.js): a tumble spins her on the spot, around her
   middle (Goldie's squish pivots from her bottom, which would swing her
   around in a loop instead). */
.pal-mover.tumbling .dish-pal {
  animation: tumble 0.35s linear;
  transform-origin: center;
}

/* Without motion, a tumble just turns her to face the new way. */
@media (prefers-reduced-motion: reduce) {
  .pal-mover.tumbling .dish-pal {
    animation: none;
  }
}

@keyframes tumble {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.cell-count {
  margin: 1rem 0 0;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.how-to-play {
  margin: 0.75rem 0 0;
  line-height: 1.6;
  color: #334155;
}

/* Arrow-key directions on a computer, touch directions on a phone or tablet.
   The media query picks from the device before any script runs (a finger is a
   "coarse" pointer); then game/touch.js switches them to match whatever the
   player actually uses, for devices with both. */
.for-touch {
  display: none;
}

@media (pointer: coarse) {
  .for-keys {
    display: none;
  }

  .for-touch {
    display: inline;
  }
}

html.input-touch .for-keys,
html.input-keys .for-touch {
  display: none;
}

html.input-touch .for-touch,
html.input-keys .for-keys {
  display: inline;
}

/* The antibiotic disk: a small white paper disk with the drug's code on it,
   like the disks used in the lab. Placed by game/antibiotic.js. */
.antibiotic {
  position: absolute;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #fff, #f1f5f9);
  border: 2px solid #cbd5e1;
  box-shadow: 0 2px 4px rgba(19, 78, 74, 0.2);
  color: #475569;
  font-size: clamp(8px, 1.3vw, 14px);
  font-weight: 800;
  letter-spacing: 0.02em;
}

/* The zone of inhibition around each disk: clear agar where the drug has
   soaked in and nothing can grow. Sized by game/antibiotic.js. */
.zone {
  position: absolute;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  /* Real zones are clear, slightly glassy agar with a soft, hazy edge where
     the growth thins out, not a crisp ring. Each zone also gets a slightly
     uneven shape (set in game/antibiotic.js). */
  border-radius: 50%;
  /* The disk covers the inner ~65%, so the visible ring is the outer third:
     clear agar, then a thin hazy rim right at the outside. The rim has to
     sit at the very edge, because that's where touching it ends the game
     (see touchesDisk in game/antibiotic.js); a rim that faded out early
     made the game end with a gap still showing. */
  background: radial-gradient(
    closest-side,
    rgba(255, 255, 252, 0.85) 0%,
    rgba(255, 255, 252, 0.8) 88%,
    rgba(255, 255, 248, 0.65) 93%,
    rgba(206, 192, 110, 0.4) 97%,
    rgba(206, 192, 110, 0.3) 99%,
    rgba(206, 192, 110, 0) 100%
  );
  filter: blur(0.5px);
  pointer-events: none;
}

/* Hover over a disk to see which antibiotic it is. */
.antibiotic::after {
  content: attr(data-name);
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%) translateY(3px);
  padding: 0.25rem 0.55rem;
  border-radius: 8px;
  background: #134e4a;
  color: white;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: normal;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.12s ease, transform 0.12s ease;
}

.antibiotic:hover {
  z-index: 4; /* above the pals, so the label isn't hidden behind them */
}

.antibiotic:hover::after {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* The player's pal after touching the antibiotic. */
.pal-mover.killed {
  filter: grayscale(1);
  opacity: 0.45;
  transition: filter 0.4s ease, opacity 0.4s ease;
}

/* Freeze her mid-wiggle rather than turning the animation off: switching it
   off snaps her back to her resting pose (up to 10px away for a bob), so she
   would look like she never touched the zone. */
.pal-mover.killed .dish-pal {
  animation-play-state: paused;
}

/* Jess's signature at the foot of every page. */
.signature {
  margin: 2rem 0 1.5rem;
  font-size: 0.85rem;
  letter-spacing: 0.04em;
  opacity: 0.6;
}

.picker-page .signature {
  margin: 1rem 0 0;
}

/* On the home page, push it down to the bottom of the screen instead of
   right under the start button. */
body:not(.picker-page) {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-height: 100vh;
}

body:not(.picker-page) .signature {
  margin-top: auto;
  padding-top: 2rem;
}

/* On a phone, give the dish as much of the screen as we can: less padding
   around the card and a thinner glass rim. */
@media (max-width: 600px) {
  .picker-page:has(.dish-shell) {
    padding: 0.75rem 0.5rem;
  }

  .dish-shell {
    padding: 1rem 0.5rem;
  }

  .dish-shell .petri-dish {
    padding: 8px;
  }
}

/* Short landscape screens: move the dish left at full screen height,
   with the name, cell count and instructions beside it, since dragging
   steers instead of scrolling. Reduce padding on other pages' cards. */
@media (orientation: landscape) and (max-height: 540px) {
  .picker-page {
    padding: 0.75rem 1rem;
  }

  .picker-shell {
    padding: 1.25rem 1.5rem;
  }

  .picker-page:has(.dish-shell) {
    padding: 0.5rem 1rem;
  }

  .dish-shell {
    width: min(1000px, 100%);
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    /* The words beside the dish stay together in the middle of its height. */
    grid-template-rows: 1fr auto auto auto auto 1fr;
    grid-template-areas:
      'dish .'
      'dish title'
      'dish count'
      'dish how'
      'dish back'
      'dish .';
    align-content: center;
    column-gap: 1.5rem;
    padding: 0.5rem 1rem 0.5rem 0.5rem;
  }

  .dish-shell .petri-dish {
    grid-area: dish;
    align-self: center;
    /* The screen's height, less the padding and borders around the dish.
       svh is the height with Safari's toolbars showing, so they never hide
       the bottom of the dish; vh is for browsers too old to know svh. */
    width: min(600px, calc(100vh - 2rem - 8px));
    width: min(600px, calc(100svh - 2rem - 8px));
    padding: 8px;
  }

  .dish-shell .dish-title {
    grid-area: title;
    margin-bottom: 0;
  }

  .dish-shell .dish-title .pal-name {
    font-size: 1.6rem;
  }

  .dish-shell .cell-count {
    grid-area: count;
    margin-top: 0.5rem;
  }

  .dish-shell .how-to-play {
    grid-area: how;
    font-size: 0.9rem;
    line-height: 1.45;
  }

  .dish-shell .back-link {
    grid-area: back;
    justify-self: center;
    margin-top: 0.75rem;
  }

  /* The pop-up when you win or lose can be taller than a dish this small:
     keep it inside the dish, and let it scroll if it has to. */
  .dish-shell .win-banner {
    max-height: 92%;
    overflow-y: auto;
    padding: 0.75rem 1rem 1rem;
  }

  .dish-shell .win-banner .fun-fact {
    margin-top: 0.5rem;
    font-size: 0.85rem;
  }
}

/* An offspring cell popping in an antibiotic zone (game/colony.js): a ring
   in the pal's color that bursts outward and fades. */
.pop {
  position: absolute;
  aspect-ratio: 1;
  border: 3px solid;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  animation: pop 0.35s ease-out forwards;
}

@keyframes pop {
  from {
    opacity: 0.9;
    transform: translate(-50%, -50%) scale(0.7);
  }

  to {
    opacity: 0;
    transform: translate(-50%, -50%) scale(1.8);
    border-width: 1px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .pop {
    animation-duration: 0.01s;
  }
}

/* "Growing the colony…": the small card that shows while the next screen
   loads (game/loading.js). It waits a moment before fading in, so a quick
   page change never flashes it. The see-through cover behind it keeps a
   second tap from starting a second trip. */
.loading-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  background: rgba(204, 251, 241, 0.55);
  animation: loading-in 0.2s ease-out 0.15s both;
}

.loading-overlay[hidden] {
  display: none;
}

/* On a page that's still being filled in, the cover is solid, so the half
   built page doesn't show through. If its script never gets to say it's
   done (an error, say), give up after a while rather than block the page
   forever. */
.loading-overlay.arriving {
  background: #ccfbf1;
  animation: loading-give-up 0s linear 8s forwards;
}

.loading-overlay.arriving .loading-card {
  animation: loading-in 0.2s ease-out 0.15s both;
}

.loading-card {
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.7rem 1.25rem;
  background: white;
  border: 2px solid rgba(15, 118, 110, 0.25);
  border-radius: 999px;
  box-shadow: 0 12px 28px rgba(19, 78, 74, 0.18);
  color: #134e4a;
  font-family: Fredoka, system-ui, sans-serif;
  font-weight: 600;
  font-size: 1.05rem;
}

/* A little cell pinching into two daughter cells, over and over. */
.loading-cells {
  position: relative;
  flex: none;
  width: 30px;
  height: 18px;
}

.loading-cells span {
  position: absolute;
  top: 2px;
  left: 8px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #14b8a6;
  animation: loading-split-left 0.9s ease-in-out infinite alternate;
}

.loading-cells span:last-child {
  background: #0f766e;
  animation-name: loading-split-right;
}

@keyframes loading-in {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

@keyframes loading-give-up {
  to {
    visibility: hidden;
  }
}

@keyframes loading-split-left {
  to {
    transform: translateX(-6px);
  }
}

@keyframes loading-split-right {
  to {
    transform: translateX(6px);
  }
}

/* No moving cells for anyone who'd rather not have motion: just the two
   daughters, side by side. */
@media (prefers-reduced-motion: reduce) {
  .loading-cells span {
    animation: none;
    transform: translateX(-6px);
  }

  .loading-cells span:last-child {
    transform: translateX(6px);
  }
}

/* Phage Attack (game/phage.js): bacteriophages hunting the colony, turned
   (--turn) so the tail leads. */
.phage {
  position: absolute;
  width: 3.3%;
  z-index: 3; /* over the cells they land on */
  pointer-events: none;
  transform: translate(-50%, -50%) rotate(var(--turn, 0deg));
  /* A thin light halo, so the dark phages stand out even over a cell. */
  filter: drop-shadow(0 0 1px rgba(255, 255, 255, 0.85));
}

.phage svg {
  display: block;
  width: 100%;
  height: auto;
}

/* A phage that landed: it has injected its DNA, so its empty coat fades. */
.phage.landed {
  animation: phage-land 0.5s ease-in forwards;
}

@keyframes phage-land {
  to {
    opacity: 0;
    transform: translate(-50%, -50%) rotate(var(--turn, 0deg)) scale(0.6);
  }
}

/* An infected cell, filling up with new phages before it bursts: it goes
   very dark, with a phage-purple glow, and throbs, so it's clear which
   cells are infected. (Not a hue shift: that
   flashes rainbow as it changes.) A rod is one cell, so the whole drawing
   does, with a filter; in a chain or cluster, just the infected cell, which
   game/coccus.js draws dark itself (Safari ignores filters inside an SVG). */
.pal-mover.offspring.infected .dish-pal {
  filter: grayscale(0.6) brightness(0.12) drop-shadow(0 0 3px #a855f7);
}

.pal-mover.offspring.infected .dish-pal,
.infected-cell {
  animation: infected 0.5s ease-in-out infinite alternate;
  transform-origin: center;
}

.infected-cell {
  transform-box: fill-box;
}

/* A rod is one cell, so drop the offspring's washed-out look too and let
   it go fully dark. */
.pal-mover.offspring.infected {
  opacity: 1;
  filter: none;
}

/* A chain or cluster with an infected cell: make it solid, so the infected
   cell isn't washed out by the offspring's see-through look. */
.pal-mover.offspring:has(.infected-cell) {
  opacity: 1;
}

/* Let the glow spill past the edge of the drawing instead of being cut off
   square. */
svg:has(.infected-cell) {
  overflow: visible;
}

@keyframes infected {
  from { transform: scale(1); }
  to { transform: scale(1.12); }
}

@media (prefers-reduced-motion: reduce) {
  .phage.landed {
    animation-duration: 0.01s;
  }

  /* Infected cells still go dark, but don't throb: the throb loops forever,
     so just speeding it up would make it flicker every frame. */
  .pal-mover.offspring.infected .dish-pal,
  .infected-cell {
    animation: none;
  }
}
