/* The card viewer and the bi-fold card pages. Pages are laid out at the design size
   (--card-w × --card-h); viewer.js scales the whole card to fit the screen. */

/* ---------- Viewer layer ---------- */
.viewer {
  position: fixed; inset: 0; z-index: 60;
  display: flex; flex-direction: column;
  touch-action: none; user-select: none; -webkit-user-select: none;
}
.viewer__scrim { position: absolute; inset: 0; background: var(--c-overlay); opacity: 0; }
.viewer__bar {
  position: relative; z-index: 2;
  display: flex; align-items: center; gap: var(--s-2);
  padding: max(var(--s-2), env(safe-area-inset-top)) max(var(--s-3), env(safe-area-inset-right)) var(--s-2) max(var(--s-3), env(safe-area-inset-left));
  min-height: var(--header-h);
  background: var(--g, var(--c-primary)); /* its own header: covers the app header completely */
  color: var(--g-ink, var(--c-on-primary));
  box-shadow: var(--shadow-1);
}
.viewer__bar > .viewer__group { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.viewer__bar > .btn, .viewer__bar > .viewer__no { flex: none; }
@media (max-width: 600px) { .viewer__bar > .viewer__group { display: none; } }
/* Phones: squeeze the buttons so the bar never pushes the page wider than the screen. */
@media (max-width: 520px) {
  .viewer__bar { gap: var(--s-1); padding-left: max(var(--s-2), env(safe-area-inset-left)); padding-right: max(var(--s-2), env(safe-area-inset-right)); }
  .viewer__bar > .btn { min-width: var(--tap-xs); min-height: var(--tap-xs); }
  .viewer__bar > .viewer__no { display: none; }
}
.viewer__bar .btn { background: var(--c-veil); color: var(--c-ink); }
.viewer__bar .btn--read.is-speaking { background: var(--c-accent); }
.viewer__group, .viewer__no { font-weight: var(--fw-bold); }
.viewer__group .bi { flex-direction: row; gap: 0.4em; }
.viewer__stage { position: relative; flex: 1; min-height: 0; overflow: hidden; }
.viewer__zoomer { position: absolute; inset: 0; }
/* 3D only while the card moves (viewer.js adds .is-3d); at rest everything is flat. */
.viewer__stage.is-3d { perspective: 1800px; }
.viewer__stage.is-3d .viewer__zoomer, .viewer__stage.is-3d .card-pos { transform-style: preserve-3d; }
.viewer__hint {
  position: relative; z-index: 2; min-height: var(--tap);
  padding: var(--s-2) var(--s-4) max(var(--s-4), env(safe-area-inset-bottom));
  color: var(--c-on-primary); font-weight: var(--fw-semi); text-align: center;
}
.viewer__hint .bi { align-items: center; }

/* ---------- 3D card ---------- */
/* .card-pos places the card (left/top at rest, a transform while moving); .card3d is laid
   out at design size and enlarged with CSS zoom, so it renders at real size. */
.card-pos { position: absolute; left: 0; top: 0; transform-origin: 0 0; }
.card3d {
  position: relative;
  width: var(--card-w); height: var(--card-h);
  transform-style: preserve-3d;
}
.flipper, .base, .leaf { position: absolute; transform-style: preserve-3d; }
.flipper, .base, .leaf { inset: 0; }
.flipper { transform-origin: 50% 50%; }
.leaf { transform-origin: 0 50%; }
.face {
  position: absolute; inset: 0; overflow: hidden;
  border-radius: var(--r-sm); background: var(--c-paper); box-shadow: var(--shadow-2);
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
}
.face--y { transform: rotateY(180deg); }
.face--x { transform: rotateX(180deg); }
/* While turned over, only the back of the card should show. */
.card3d.is-flipped .leaf { visibility: hidden; }

/* At rest: no 3D. Only the faces you can see are shown, flat and untransformed. */
.card3d.is-rest, .card3d.is-rest .flipper, .card3d.is-rest .base, .card3d.is-rest .leaf { transform-style: flat; }
.card3d.is-rest .face { transform: none; backface-visibility: visible; -webkit-backface-visibility: visible; visibility: hidden; }
.card3d.is-rest[data-pose="front"] .leaf > .face--front,
.card3d.is-rest[data-pose="open"] .leaf > .face--back,
.card3d.is-rest[data-pose="open"] .base > .face--front,
.card3d.is-rest[data-pose="back"] .base > .face--back { visibility: visible; }
/* Open: the cover lies flat to the left of the spine, inside facing up. */
.card3d.is-rest[data-pose="open"] .leaf { inset: 0 100% 0 -100%; }

.grab {
  position: absolute; right: 0; top: 50%;
  display: grid; place-items: center; width: var(--size-dot); height: calc(var(--size-dot) * 2.2);
  border-radius: var(--r-sm) 0 0 var(--r-sm);
  background: var(--c-accent); color: var(--c-on-accent);
  font-size: var(--fs-lg); font-weight: var(--fw-bold);
  box-shadow: var(--shadow-1);
  transform: translateY(-50%);
  animation: nudge 1.6s ease-in-out infinite;
  pointer-events: none;
}
.card3d.is-open .grab { visibility: hidden; }

/* ---------- Card pages ---------- */
.cpage {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; gap: var(--s-2);
  padding: var(--s-3);
  background: var(--c-paper); color: var(--c-ink);
  border: var(--bw-tile) solid var(--g, var(--c-line)); border-radius: inherit;
  font-size: var(--card-fs); line-height: 1.3;
}
.cpage__blank { margin: auto; font-size: var(--emoji-xxl); opacity: 0.12; }
.cpage__heading {
  display: flex; align-items: center; gap: var(--s-2);
  padding-bottom: var(--s-1); border-bottom: var(--bw-thin) solid var(--c-paper-line);
  font-size: var(--card-fs-title);
}
.cpage__heading .bi, .bi--inline { flex-direction: row; flex-wrap: wrap; column-gap: 0.4em; align-items: baseline; }
.cpage .badge { min-height: 0; padding: var(--s-hair) var(--s-2) var(--s-hair) var(--s-hair); font-size: var(--card-fs-sm); }
.cpage .badge .bi { flex-direction: row; }
.cpage .badge__code { width: var(--callout-dot); height: var(--callout-dot); font-size: var(--card-fs-sm); }

/* Cover */
.cpage--cover { padding: 0; gap: 0; }
.cover__top {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--s-1) var(--s-3);
  background: var(--g); color: var(--g-ink); font-weight: var(--fw-bold);
}
.chip--group { display: inline-flex; align-items: center; gap: var(--s-1); padding: 0; background: none; color: inherit; font-size: var(--card-fs-sm); }
.chip--group .bi { flex-direction: row; gap: 0.4em; }
.cover__no { font-size: var(--card-fs-sm); }
.cover__photo { position: relative; flex: 1 1 auto; min-height: 0; background: var(--c-bg-deep); }
.cover__photo .pic { position: absolute; inset: 0; object-fit: cover; }
.cover__credit {
  position: absolute; left: var(--s-2); bottom: var(--s-2);
  width: var(--size-dot); height: var(--size-dot); border: 0; border-radius: 50%;
  background: var(--c-veil); font-size: var(--card-fs-sm); cursor: pointer;
}
.cover__names { padding: var(--s-2) var(--s-3) 0; }
.cover__name { font-size: var(--card-fs-name); line-height: 1.05; }
.bi--cover > .t-zh { font-size: 0.8em !important; }
.cover__sci { font-style: italic; color: var(--c-ink-soft); font-size: var(--card-fs-sm); }
.cover__bottom { display: flex; gap: var(--s-3); align-items: flex-end; padding: var(--s-2) var(--s-3) var(--s-3); }
.cover__facts { flex: 1; margin: 0; padding-left: 1.2em; display: grid; gap: var(--s-1); font-size: var(--card-fs-sm); }
.cover__side { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: var(--s-1); width: calc(var(--card-w) * 0.32); }
.cover__side .map { width: 100%; }
.cover__badges { display: flex; flex-direction: column; align-items: flex-end; gap: var(--s-1); }
.cover__badges:empty, .back__badges:empty { display: none; } /* e.g. a plant with no IUCN status */

/* Map: inline SVG (land from assets/world.svg), zoomed by its viewBox. */
.map { position: relative; width: 100%; aspect-ratio: 360 / 142; overflow: hidden; border-radius: var(--r-sm); background: var(--c-map-sea); }
.map__svg { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }
.map__land { fill: var(--c-map-land); }
.map__range {
  fill: var(--g, var(--c-map-spot)); fill-opacity: 0.45;
  stroke: var(--g-edge, var(--c-map-spot)); stroke-width: 1.2; stroke-linejoin: round;
}
.map__dots { position: absolute; inset: 0; pointer-events: none; }
.map__spot {
  position: absolute; width: var(--spot); height: var(--spot);
  margin: calc(var(--spot) / -2) 0 0 calc(var(--spot) / -2);
  border-radius: 50%; background: var(--c-map-spot);
  box-shadow: 0 0 0 var(--bw-thin) var(--c-surface);
}
/* Zoomed-in maps: a little world in the corner, with a filled marker where the range is. */
.map__inset {
  position: absolute; right: var(--s-1); bottom: var(--s-1);
  width: 34%; aspect-ratio: 360 / 142; overflow: hidden;
  border-radius: var(--s-1); background: var(--c-map-sea);
  box-shadow: 0 0 0 var(--bw-thin) var(--c-surface), var(--shadow-1);
}
.map__marker {
  position: absolute; width: var(--map-marker); height: var(--map-marker);
  margin: calc(var(--map-marker) / -2) 0 0 calc(var(--map-marker) / -2);
  border-radius: 50%; background: var(--g, var(--c-map-spot));
  box-shadow: 0 0 0 var(--bw-thin) var(--c-surface);
}

/* Profile: a clean photo; picking a feature shows it through a magnifier (magnifier.js). */
.profile__pic { position: relative; flex: none; border-radius: var(--r-sm); overflow: hidden; background: var(--c-bg-deep); cursor: pointer; }
.profile__pic .pic { position: static; height: auto; }
.loupe { position: absolute; inset: 0; pointer-events: none; }
.loupe__wire { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.loupe__wire line {
  stroke: var(--c-surface); stroke-width: var(--bw-thin); stroke-linecap: round;
  stroke-dasharray: 1; stroke-dashoffset: 0;
  filter: drop-shadow(0 0 1px var(--c-shade-strong));
}
.loupe__ring, .loupe__lens { position: absolute; aspect-ratio: 1; border-radius: 50%; transform-origin: 50% 50%; }
.loupe__ring {
  border: var(--bw-thin) solid var(--c-surface);
  box-shadow: 0 0 0 1px var(--c-shade-strong), inset 0 0 0 1px var(--c-shade-strong);
}
.loupe__lens {
  overflow: hidden; background: var(--c-surface);
  border: var(--bw-thick) solid var(--c-surface);
  box-shadow: var(--shadow-3);
}
.loupe__img { position: absolute; max-width: none; height: auto; }
.callouts { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-hair); font-size: var(--card-fs-sm); }
.callouts__item {
  display: grid; grid-template-columns: var(--hotspot) 1fr; gap: var(--s-2); align-items: center;
  width: 100%; padding: var(--s-hair); border: 0; border-radius: var(--r-sm);
  background: none; color: inherit; font: inherit; text-align: left; cursor: pointer;
}
.callouts__no {
  display: grid; place-items: center; width: var(--hotspot); height: var(--hotspot); border-radius: 50%;
  background: var(--c-callout); color: var(--c-callout-ink); font-weight: var(--fw-bold);
}
.callouts__item .bi, .cycle li .bi { flex-direction: row; flex-wrap: wrap; column-gap: 0.5em; }
.callouts li.is-lit .callouts__item { background: var(--c-callout-soft); font-weight: var(--fw-semi); }
.profile__tax { display: flex; flex-wrap: wrap; gap: var(--s-1) var(--s-3); margin-top: auto; color: var(--c-ink-soft); font-size: var(--card-fs-sm); }

/* Inside right page: statistics you can tap, and the comparison they drive. */
.cpage--inside { gap: var(--s-2); }
.csection { display: flex; flex-direction: column; gap: var(--s-1); }
.stat {
  display: grid; grid-template-columns: auto auto 1fr; gap: var(--s-2); align-items: baseline;
  padding: var(--s-1); border-bottom: var(--bw-thin) dashed var(--c-paper-line);
}
.stat--pick {
  grid-template-columns: auto auto 1fr auto;
  width: 100%; border-radius: var(--r-sm);
  background: none; color: inherit; font: inherit; text-align: left; cursor: pointer;
  border-top: 0; border-left: 0; border-right: 0;
}
.stat--pick.is-on { background: var(--c-callout-soft); }
.stat__label { font-weight: var(--fw-bold); }
.stat__label .bi { flex-direction: row; flex-wrap: wrap; column-gap: 0.3em; }
.stat__value { text-align: right; font-size: var(--card-fs-sm); }
.stat__note { display: block; color: var(--c-ink-soft); font-size: var(--card-fs-sm); }
.stat__go { color: var(--g); font-weight: var(--fw-bold); }
.stat__hint { color: var(--c-ink-soft); font-size: var(--card-fs-sm); }
.stat__hint .bi { flex-direction: row; flex-wrap: wrap; column-gap: 0.4em; }

.cmp { display: flex; flex-direction: column; gap: var(--s-2); }
.cmp__caption { text-align: center; font-size: var(--card-fs-sm); font-weight: var(--fw-semi); }
.cmp__caption .bi { align-items: center; }
.cmp__sub { color: var(--c-ink-soft); font-weight: normal; }
.cmp__num { display: block; color: var(--c-ink-soft); font-weight: normal; }
.cmp__emoji { font-size: var(--fs-lg); line-height: 1; }

/* length: silhouettes on the ground */
.cmp-len {
  position: relative; height: var(--compare-h);
  display: flex; align-items: flex-end; justify-content: center; gap: var(--s-4);
  margin-bottom: calc(var(--card-fs) * 3.2);
  border-bottom: var(--bw-mid) solid var(--c-ink-faint);
}
.cmp-len__item { position: relative; margin: 0; display: flex; align-items: flex-end; }
.cmp-len__img { display: block; height: auto; transform-origin: 50% 100%; }
.cmp-len__item figcaption {
  position: absolute; top: calc(100% + var(--s-1)); left: 50%; transform: translateX(-50%);
  white-space: nowrap; text-align: center; font-size: var(--card-fs-sm); font-weight: var(--fw-semi);
}
.cmp-len__item figcaption .bi { align-items: center; }

/* weight: a balance scale */
.cmp-wt { position: relative; height: var(--compare-h); --tilt: 0deg; --drop: 0; --arm: calc(var(--card-w) * 0.27); }
.cmp-wt::after {
  content: ""; position: absolute; left: 50%; bottom: 0; width: calc(var(--arm) * 0.6); height: var(--s-2);
  transform: translateX(-50%); border-radius: var(--r-sm); background: var(--c-ink-soft);
}
.cmp-wt__post {
  position: absolute; left: 50%; bottom: 0; top: 22%; width: var(--s-2);
  transform: translateX(-50%); border-radius: var(--r-sm); background: var(--c-ink-soft);
}
.cmp-wt__beam {
  position: absolute; top: 22%; left: calc(50% - var(--arm)); width: calc(var(--arm) * 2); height: var(--s-1);
  border-radius: var(--r-sm); background: var(--c-ink-soft);
  transform: rotate(var(--tilt)); transition: transform var(--t-med) ease-out;
}
.cmp-wt__pan {
  position: absolute; top: 22%; height: 66%; width: calc(var(--arm) * 1.05);
  transition: transform var(--t-med) ease-out;
}
.cmp-wt__pan--left { left: calc(50% - var(--arm)); transform: translate(-50%, calc(var(--drop) * var(--arm) * -1)); }
.cmp-wt__pan--right { left: calc(50% + var(--arm)); transform: translate(-50%, calc(var(--drop) * var(--arm))); }
.cmp-wt__pan::before { content: ""; position: absolute; left: 50%; top: 0; bottom: var(--s-2); width: var(--bw-thin); background: var(--c-ink-faint); }
.cmp-wt__pan::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: var(--s-2);
  border-radius: 0 0 var(--r-md) var(--r-md); background: var(--g);
}
.cmp-wt__stack {
  position: absolute; left: 0; right: 0; bottom: var(--s-2); max-height: 100%;
  display: flex; flex-wrap: wrap-reverse; justify-content: center; align-items: flex-end; gap: var(--s-hair);
}
.cmp-wt__icon { display: block; height: var(--cmp-icon); width: auto; }
.cmp-wt__stack .cmp__animal { height: calc(var(--cmp-icon) * 0.7); }
.cmp-wt__stack.is-many .cmp-wt__icon { height: var(--cmp-icon-sm); }
.cmp-wt__count {
  position: absolute; left: 50%; top: 0; transform: translate(-50%, -50%);
  padding: 0 var(--s-2); border-radius: var(--r-pill);
  background: var(--c-accent); color: var(--c-on-accent); font-weight: var(--fw-bold); font-size: var(--card-fs-sm);
  white-space: nowrap;
}

/* lifespan: birthday timelines */
.cmp-life { display: grid; gap: var(--s-4); padding: var(--s-4) 0 var(--s-1); }
.cmp-life__row { display: grid; grid-template-columns: 30% 1fr auto; gap: var(--s-2); align-items: center; font-size: var(--card-fs-sm); }
.cmp-life__who .bi { line-height: 1.15; }
.cmp-life__track { position: relative; height: var(--life-bar); border-radius: var(--r-pill); background: var(--c-paper-line); }
.cmp-life__fill { position: absolute; left: 0; top: 0; bottom: 0; width: 0; border-radius: var(--r-pill); background: var(--g); }
.cmp-life__row--you .cmp-life__fill { background: var(--c-accent); }
.cmp-life__candles { position: absolute; inset: 0; pointer-events: none; }
.cmp-life__candle { position: absolute; bottom: 70%; transform: translateX(-50%); font-size: var(--card-fs-sm); line-height: 1; }
.cmp-life__cake { position: absolute; top: 50%; margin-top: calc(var(--card-fs) * -0.7); transform: translateX(-50%); font-size: var(--card-fs-title); line-height: 1; }
.cmp-life__row .cmp__num { min-width: 2.2em; text-align: right; font-weight: var(--fw-bold); color: var(--c-ink); }

/* diet: a plate */
.cmp-diet { display: grid; place-items: center; padding: var(--s-1) 0; }
.cmp-diet__plate {
  position: relative; width: var(--plate); aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(circle, var(--c-surface) 55%, var(--c-paper-line) 56% 63%, var(--c-surface) 64%);
  box-shadow: var(--shadow-1);
}
.cmp-diet__food { position: absolute; transform: translate(-50%, -50%); font-size: var(--card-fs-name); line-height: 1; }

/* Back */
.cycle { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-2); counter-reset: step; font-size: var(--card-fs-sm); }
.cycle li { counter-increment: step; position: relative; display: grid; grid-template-columns: var(--callout-dot) 1fr; gap: var(--s-2); align-items: start; }
.cycle li::before {
  content: counter(step); display: grid; place-items: center;
  width: var(--callout-dot); height: var(--callout-dot); border-radius: 50%;
  background: var(--g); color: var(--g-ink); font-weight: var(--fw-bold);
}
.back__habitat { font-size: var(--card-fs-sm); }
.back__badges { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: auto; }

.card-credits { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-2); font-size: var(--fs-xs); }
.card-credits a { word-break: break-word; }
.card-credits .bi { display: inline-flex; flex-direction: row; gap: 0.3em; }

@keyframes nudge { 0%, 100% { transform: translate(0, -50%); } 50% { transform: translate(calc(var(--s-2) * -1), -50%); } }

/* You / Animal: what the creature is compared with. */
.cview { display: flex; flex-direction: column; gap: var(--s-2); }
.cmp-toggle { display: flex; gap: var(--s-1); padding: var(--s-hair); border-radius: var(--r-pill); background: var(--c-paper-line); align-self: flex-start; }
.cmp-toggle__btn {
  display: inline-flex; align-items: center; gap: var(--s-1);
  padding: var(--s-1) var(--s-3); border: 0; border-radius: var(--r-pill); background: none;
  font: inherit; font-size: var(--card-fs-sm); font-weight: var(--fw-bold); color: var(--c-ink-soft); cursor: pointer;
}
.cmp-toggle__btn .bi { flex-direction: row; gap: 0.3em; }
.cmp-toggle__btn[aria-checked="true"] { background: var(--g); color: var(--g-ink); }

/* Animal: two lookalikes side by side at scale, and how to tell them apart. */
.cmp-look__pick { display: flex; flex-wrap: wrap; gap: var(--s-1); }
.cmp-look__chip {
  padding: var(--s-hair) var(--s-2); border: var(--bw-thin) solid var(--c-paper-line); border-radius: var(--r-pill);
  background: none; font: inherit; font-size: var(--card-fs-sm); cursor: pointer;
}
.cmp-look__chip .bi { flex-direction: row; gap: 0.3em; }
.cmp-look__chip[aria-checked="true"] { border-color: var(--g); background: var(--c-callout-soft); font-weight: var(--fw-bold); }
.cmp-look__group { font-size: var(--card-fs-sm); color: var(--c-ink-soft); font-weight: var(--fw-semi); }
.cmp-look__group .bi { display: inline-flex; flex-direction: row; gap: 0.3em; }
/* Two columns on one ground line; names and sizes underneath. */
.cmp-look__ground { position: relative; display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-3); }
.cmp-look__ground::after {
  content: ""; position: absolute; left: 0; right: 0; top: var(--compare-look-h);
  border-top: var(--bw-mid) solid var(--c-ink-faint);
}
.cmp-look__item {
  margin: 0; display: grid; grid-template-rows: var(--compare-look-h) auto; justify-items: center; align-items: end;
  color: inherit; text-decoration: none;
}
/* A standalone lookalike is a button: tap it to see its photo. */
button.cmp-look__item { padding: 0; border: 0; background: none; font: inherit; cursor: pointer; }
.cmp-look__cam { font-size: var(--card-fs-sm); }
.cmp-look__caption { padding-top: var(--s-2); text-align: center; font-size: var(--card-fs-sm); font-weight: var(--fw-semi); align-self: start; }
.cmp-look__caption .bi { align-items: center; }
/* Sizes and the "not yet" note on one line each, in both languages. */
.cmp-look__item .cmp__num .bi { flex-direction: row; flex-wrap: wrap; justify-content: center; column-gap: 0.4em; }
.cmp-look__pic { display: block; height: auto; transform-origin: 50% 100%; }
/* No silhouette yet: a neutral outline at the right size; dark when not collected yet. */
.cmp-look__box {
  aspect-ratio: 4 / 3; display: grid; place-items: center; border-radius: var(--r-md);
  border: var(--bw-mid) dashed var(--c-ink-faint); background: var(--c-paper); color: var(--c-ink-faint);
  font-weight: var(--fw-bold); font-size: var(--card-fs-title);
}
.cmp-look__box.is-locked { filter: none; opacity: 1; border-style: solid; border-color: var(--c-locked); background: var(--c-locked); color: var(--c-locked-ink); }
/* Not collected yet: a dark silhouette. */
.cmp-look__pic.is-locked { filter: brightness(0); opacity: 0.55; }
.cmp-look__name { display: inline-flex; align-items: center; gap: var(--s-1); }
.cmp-look__q {
  display: grid; place-items: center; width: var(--callout-dot); height: var(--callout-dot); border-radius: 50%; flex: none;
  background: var(--g); color: var(--g-ink); font-weight: var(--fw-bold);
}
.cmp-look__diff { font-size: var(--card-fs-sm); }
.cmp-look__title { font-weight: var(--fw-bold); margin-bottom: var(--s-hair); }
.cmp-look__diff ul { margin: 0; padding-left: 1.2em; display: grid; gap: var(--s-hair); }
.cmp-look__diff .bi { gap: 0; }
