/* The town (scenes/town.html, scenes/town.js): the World's mini town at dusk, drawn in depth layers.
   Everything is scoped to .sc-town. The scene is a window onto a 2000 x 1080 world: --cx, --cy, --cw and
   --ch pick the part you see at each width, so a phone gets a closer, recomposed view (the tower, Cloud
   Café and one house, bigger) instead of the whole street shrunk. Teammates, clouds, the car and bushes
   are placed in world units (--x, --y, --w; --xs and --ys on phones). The markup is the finished still;
   town.js adds .is-live (it moves things) and .is-on (it is playing). */

.sc-town {
  --cx: 200;
  --cy: 200;
  --cw: 1600;
  --ch: 800;
  --wk: 90; /* a teammate's width, in world units */
  --tn-rad: 26px;
  position: relative;
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  aspect-ratio: 2 / 1;
  border-radius: var(--tn-rad);
  box-shadow: 0 50px 100px -40px rgba(233, 255, 59, 0.25);
}

.sc-town .tn-view {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: var(--tn-rad);
  clip-path: inset(0 round var(--tn-rad));
  isolation: isolate;
  transform: translateZ(0);
  background: #18235a;
  -webkit-user-select: none;
  user-select: none;
}
.sc-town .tn-view::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 10;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
  pointer-events: none;
}

/* Each layer is the whole world, placed so the camera's part fills the scene. */
.sc-town .tn-layer {
  position: absolute;
  left: calc(var(--cx) / var(--cw) * -100%);
  top: calc(var(--cy) / var(--ch) * -100%);
  width: calc(2000 / var(--cw) * 100%);
  height: calc(1080 / var(--ch) * 100%);
  pointer-events: none;
}
.sc-town .tn-art {
  position: absolute;
  left: 0;
  top: 0;
  display: block;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
.sc-town .tn-sign,
.sc-town .tn-awning {
  font-family: Geist, system-ui, sans-serif;
  font-weight: 800;
}

/* Tower windows (lit = someone at work) and house windows (lit = they are home). */
.sc-town .tn-w { transition: opacity 0.45s ease; }
.sc-town .tn-w.is-off { opacity: 0; }
.sc-town .tn-hw { opacity: 0; transition: opacity 0.6s ease; }
.sc-town .tn-hw.is-on { opacity: 1; }

/* Clouds, in the brand's cloud shape. */
.sc-town .tn-cloud {
  position: absolute;
  left: calc(var(--x) * 0.05%);
  top: calc(var(--y) / 10.8 * 1%);
  width: calc(var(--w) * 0.05%);
}
.sc-town .tn-cloud svg { display: block; width: 100%; height: auto; }
.sc-town .tn-cloud.is-high { fill: #c3c6ee; opacity: 0.2; }
.sc-town .tn-cloud.is-low { fill: #f6b8a0; opacity: 0.34; }

/* The teammates. Their feet sit on the point (--x, --ly); lane 0 is the back of the pavement. */
.sc-town .tn-walker {
  --ly: 884;
  --ls: 1;
  position: absolute;
  z-index: 2;
  left: calc(var(--x) * 0.05%);
  top: calc(var(--ly) / 10.8 * 1%);
  width: calc(var(--wk) * 0.05%);
  transform-origin: 50% 100%;
  transform: translate(-50%, -100%) scale(var(--ls));
}
.sc-town .tn-walker[data-lane="0"] { --ly: 856; --ls: 0.92; z-index: 1; }
.sc-town .tn-walker[data-who="cloudy"] { width: calc(var(--wk) * 1.25 * 0.05%); }
.sc-town .tn-walker.is-talk { z-index: 3; }
.sc-town .tn-ava {
  position: relative;
  display: block;
  width: 100%;
  height: auto;
  transform-origin: 50% 100%;
}
.sc-town .tn-shadow {
  position: absolute;
  left: 20%;
  right: 20%;
  bottom: -5%;
  height: 16%;
  border-radius: 50%;
  background: rgba(10, 10, 10, 0.4);
}

/* A speech bubble: what they are doing right now. It pops in with a little spring. */
.sc-town .tn-say {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 8px);
  z-index: 1;
  padding: 6px 10px 7px;
  border-radius: 10px;
  background: #fff;
  color: #0a0a0a;
  font: 600 13px/16px Geist, system-ui, sans-serif;
  letter-spacing: -0.01em;
  white-space: nowrap;
  box-shadow: 0 0 0 1px rgba(10, 10, 10, 0.14), 0 10px 22px -10px rgba(0, 0, 0, 0.6);
  transform-origin: 50% 100%;
  transform: translate(calc(-50% + var(--sh, 0px)), 6px) scale(0.5);
  opacity: 0;
  transition: transform 0.25s ease, opacity 0.2s ease;
  pointer-events: none;
}
.sc-town .tn-say.is-on {
  opacity: 1;
  transform: translate(calc(-50% + var(--sh, 0px)), 0) scale(1);
  transition: transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.2s ease;
}
.sc-town .tn-say::after {
  content: "";
  position: absolute;
  left: calc(50% - var(--sh, 0px));
  top: 100%;
  width: 9px;
  height: 9px;
  margin: -5px 0 0 -4.5px;
  border-radius: 2px;
  background: #fff;
  transform: rotate(45deg);
}

/* A mood you can read from across the street, with a tiny burst of confetti. */
.sc-town .tn-mood {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 6px);
  z-index: 1;
  padding: 4px 7px;
  border-radius: 6px;
  background: var(--lime, #e9ff3b);
  color: #0a0a0a;
  font: 600 10px/12px "Geist Mono", ui-monospace, monospace;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  box-shadow: 0 0 0 1.5px #0a0a0a, 0 8px 18px -8px rgba(0, 0, 0, 0.6);
  transform-origin: 50% 100%;
  transform: translateX(-50%);
}
.sc-town .tn-cf {
  position: absolute;
  left: 50%;
  top: 40%;
  width: 5px;
  height: 8px;
  border-radius: 1px;
  background: var(--c);
  transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) rotate(var(--rot));
}

/* The car, parked at the far kerb in the still (facing left). */
.sc-town .tn-car {
  position: absolute;
  z-index: 1;
  left: calc(var(--x) * 0.05%);
  top: calc(var(--y) / 10.8 * 1%);
  width: 7%;
  transform: translate(-50%, -100%) scaleX(-1);
}
.sc-town .tn-car svg { display: block; width: 100%; height: auto; overflow: visible; }

/* Bushes on the near pavement: the closest layer. */
.sc-town .tn-bush {
  position: absolute;
  left: calc(var(--x) * 0.05%);
  top: calc(var(--y) / 10.8 * 1%);
  width: calc(var(--w) * 0.05%);
}
.sc-town .tn-bush svg { display: block; width: 100%; height: auto; }
.sc-town .tn-bush[data-show="phone"] { display: none; }

/* Pause / play (shown by town.js). */
.sc-town .tn-toggle {
  position: absolute;
  right: 12px;
  top: 12px;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: rgba(10, 10, 10, 0.55);
  color: #fff;
  cursor: pointer;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  transition: background 0.15s ease;
}
.sc-town .tn-toggle[hidden] { display: none; }
.sc-town .tn-toggle:hover { background: rgba(10, 10, 10, 0.8); }
.sc-town .tn-toggle:focus-visible { outline: 2px solid var(--lime, #e9ff3b); outline-offset: 2px; }
.sc-town .tn-toggle svg { display: block; fill: currentColor; }
.sc-town .tn-toggle .tn-i-play,
.sc-town .tn-toggle.is-paused .tn-i-pause { display: none; }
.sc-town .tn-toggle.is-paused .tn-i-play { display: block; margin-left: 2px; }

/* Live: town.js moves things with transforms (left/top go to 0). */
.sc-town.is-live .tn-walker,
.sc-town.is-live .tn-car,
.sc-town.is-live .tn-cloud {
  left: 0;
  top: 0;
  transform-origin: 0 0;
  will-change: transform;
}
.sc-town.is-live .tn-layer { will-change: transform; }
.sc-town.is-live .tn-cf { opacity: 0; }
.sc-town.is-live .tn-walker.is-walk .tn-ava { animation: tn-walk 0.72s infinite; animation-delay: var(--d, 0s); }
.sc-town.is-live .tn-walker:not(.is-walk) .tn-ava { animation: tn-idle 2.6s ease-in-out infinite; animation-delay: var(--d, 0s); }
/* Celebrating: a hop, the badge pops and the confetti bursts, all on one 3.6 s beat while standing. */
.sc-town.is-live .tn-walker.is-mood:not(.is-walk) .tn-ava { animation: tn-hop 3.6s linear infinite; animation-delay: 0s; }
.sc-town.is-live .tn-walker.is-mood:not(.is-walk) .tn-mood { animation: tn-pop 3.6s ease-out infinite; }
.sc-town.is-live .tn-walker.is-mood:not(.is-walk) .tn-cf { animation: tn-burst 3.6s cubic-bezier(0.2, 0.7, 0.3, 1) infinite; }
/* Off screen, tab hidden or paused: everything holds still. */
.sc-town:not(.is-on) * { animation-play-state: paused !important; }

@keyframes tn-walk {
  0%, 100% { transform: translateY(0) rotate(-3deg); animation-timing-function: cubic-bezier(0.25, 0.6, 0.45, 1); }
  25% { transform: translateY(-11%) rotate(0deg); animation-timing-function: cubic-bezier(0.55, 0, 0.75, 0.4); }
  50% { transform: translateY(0) rotate(3deg); animation-timing-function: cubic-bezier(0.25, 0.6, 0.45, 1); }
  75% { transform: translateY(-11%) rotate(0deg); animation-timing-function: cubic-bezier(0.55, 0, 0.75, 0.4); }
}
@keyframes tn-idle {
  0%, 100% { transform: scale(1, 1); }
  50% { transform: scale(1.03, 0.96); }
}
@keyframes tn-hop {
  0% { transform: translateY(0) scale(1, 1); }
  5% { transform: translateY(0) scale(1.08, 0.9); animation-timing-function: cubic-bezier(0.2, 0.7, 0.4, 1); }
  14% { transform: translateY(-30%) scale(0.96, 1.06); animation-timing-function: cubic-bezier(0.6, 0, 0.8, 0.4); }
  22% { transform: translateY(0) scale(1.07, 0.92); }
  28%, 100% { transform: translateY(0) scale(1, 1); }
}
@keyframes tn-pop {
  0%, 10% { transform: translateX(-50%) scale(1); }
  15% { transform: translateX(-50%) scale(1.16); }
  24%, 100% { transform: translateX(-50%) scale(1); }
}
@keyframes tn-burst {
  0%, 10% { transform: translate(-50%, -50%) rotate(0deg) scale(0.2); opacity: 0; }
  13% { opacity: 1; }
  32% { transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) rotate(var(--rot)) scale(1); opacity: 1; }
  54% { transform: translate(calc(-50% + var(--dx) * 1.2), calc(-50% + var(--dy) + 18px)) rotate(calc(var(--rot) * 1.8)) scale(0.8); opacity: 0; }
  100% { transform: translate(-50%, -50%) rotate(0deg) scale(0.2); opacity: 0; }
}

/* Tablet, wide: a little closer, the far houses and the park's end drop out. */
@media (max-width: 1179.98px) {
  .sc-town { --cx: 330; --cw: 1300; --wk: 96; aspect-ratio: 13 / 8; }
}

/* Tablet, narrow: closer again, nearly square. */
@media (max-width: 899.98px) {
  .sc-town { --cx: 500; --cw: 960; --wk: 100; --tn-rad: 22px; aspect-ratio: 6 / 5; }
}

/* Phones: a portrait view of the tower, Cloud Café and Sunshine's house; bigger teammates and their own spots. */
@media (max-width: 640px) {
  .sc-town { --cx: 672; --cy: 250; --cw: 600; --ch: 750; --wk: 112; --tn-rad: 18px; aspect-ratio: 4 / 5; }
  .sc-town .tn-walker,
  .sc-town .tn-car { left: calc(var(--xs, var(--x)) * 0.05%); }
  .sc-town .tn-cloud { left: calc(var(--xs, var(--x)) * 0.05%); top: calc(var(--ys, var(--y)) / 10.8 * 1%); }
  .sc-town .tn-say { padding: 5px 9px 6px; font-size: 12px; line-height: 15px; }
  .sc-town .tn-bush[data-show="wide"] { display: none; }
  .sc-town .tn-bush[data-show="phone"] { display: block; }
  .sc-town .tn-toggle { right: 8px; top: 8px; }
}

@media (hover: none) {
  .sc-town .tn-toggle:hover { background: rgba(10, 10, 10, 0.55); }
}

/* Reduced motion: the still (town.js does not start it unless you press Play). */
@media (prefers-reduced-motion: reduce) {
  .sc-town .tn-say,
  .sc-town .tn-say.is-on,
  .sc-town .tn-w,
  .sc-town .tn-hw,
  .sc-town .tn-toggle { transition: none; }
}
