/* The quiet screen.
 *
 * One job: a Punggol scene, the resident's pet, and as close to nothing else as a page can get
 * and still be navigable. Every rule here is in service of *removing* chrome, so resist adding
 * a card, a panel or a second action to it later.
 *
 * This is the one surface in the site that does not follow the light/dark theme, and the reason
 * is in trap 5: a colour is themed by the property it sits in. Here the "surface" is a
 * photograph the theme knows nothing about, so a themeable neutral cannot be correct against it
 * — at night it would turn cream and sit on a bright sky. The chrome instead commits to a single
 * dark scrim with white on it, which measures the same in both themes: white on the scrim's
 * darkest point is well past 4.5:1, and the text also carries a shadow for the brightest frames.
 */
.ks-play {
  margin: 0;
  min-height: 100svh;
  overflow: hidden;
  background: #10171d;
  /* The pet is dragged around this page, and a drag that selects text feels broken. */
  -webkit-user-select: none;
  user-select: none;
}

.ks-play__scene {
  position: fixed;
  inset: 0;
  z-index: 0;
}

/* Two layers, crossfaded. The incoming one is decoded before it is faded up, so a slow
 * connection never shows a half-painted frame or a flash of the background colour. */
.ks-play__layer {
  position: absolute;
  inset: 0;
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
  opacity: 0;
  transition: opacity 2600ms ease-in-out;
  will-change: opacity;
}

.ks-play__layer[data-visible="true"] { opacity: 1; }

/* A whisper of movement over five minutes: the scene drifts a fraction of a percent so a still
 * photograph does not read as a frozen page. Nothing here is fast enough to notice directly. */
@media (prefers-reduced-motion: no-preference) {
  .ks-play__layer[data-visible="true"] { animation: ks-play-drift 300s linear both; }
}

@keyframes ks-play-drift {
  from { transform: scale(1.04) translate3d(0, 0, 0); }
  to { transform: scale(1.1) translate3d(-1.2%, -0.8%, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .ks-play__layer { transition-duration: 1ms; }
}

/* The scrim exists only so the two links stay readable over a bright sky. It covers the top
 * strip and fades out entirely, so it takes nothing away from the picture. */
.ks-play__chrome {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: clamp(14px, 2.6vw, 22px) clamp(14px, 3.4vw, 30px) clamp(34px, 6vw, 56px);
  background: linear-gradient(to bottom, rgba(9, 14, 18, .5), rgba(9, 14, 18, .28) 46%, rgba(9, 14, 18, 0));
  pointer-events: none;
}

/* The scrim is inert so the photograph underneath stays draggable and the pet stays
 * tappable through it. Every control the chrome actually holds has to take its own
 * clicks back. This said `a` alone until 28 August 2026, so Feed Your Pet - the one
 * <button> in the header - was hit-tested away by the backdrop layer and did nothing
 * at all: no note, no animation, no request. Name the controls, not one element type. */
.ks-play__chrome a,
.ks-play__chrome button { pointer-events: auto; }

/* Both links carry their own plate rather than trusting the scrim alone. The scrim is drawn
 * over a photograph nobody has measured, and its worst case is a white sky: white text needs an
 * effective overlay of about 0.60 to clear 4.5:1 there, which a fading gradient cannot promise
 * at the bottom of the row. The plate does, at any point of any picture. */
.ks-play__brand,
.ks-play__back {
  background: rgba(9, 14, 18, .62);
  border-radius: 999px;
  text-shadow: 0 1px 6px rgba(9, 14, 18, .7);
}

.ks-play__brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 5px 16px 5px 5px;
  color: #fff;
  text-decoration: none;
}

.ks-play__brand img {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  display: block;
}

.ks-play__brand strong {
  font: 800 17px/1 'Bricolage Grotesque', sans-serif;
  letter-spacing: -.01em;
}

.ks-play__back {
  margin-left: auto;
  color: #fff;
  font: 700 14px Cabin, sans-serif;
  text-decoration: none;
  padding: 8px 14px;
  border: 1px solid rgba(255, 255, 255, .5);
}

.ks-play__brand:hover,
.ks-play__back:hover { background: rgba(9, 14, 18, .78); }

.ks-play__chrome a:focus-visible,
.ks-play__hint:focus-visible {
  outline: 3px solid #fff;
  outline-offset: 3px;
  border-radius: 999px;
}

/* Said once, then gone. A permanent instruction line would be the second thing on a page whose
 * whole point is that there is only one. */
.ks-play__hint {
  position: fixed;
  left: 50%;
  bottom: clamp(18px, 4vw, 30px);
  z-index: 1;
  transform: translateX(-50%);
  margin: 0;
  max-width: min(88vw, 34ch);
  padding: 9px 16px;
  border-radius: 999px;
  background: rgba(9, 14, 18, .68);
  color: #fff;
  font: 400 14px/1.4 Literata, serif;
  text-align: center;
  text-wrap: balance;
  transition: opacity 1200ms ease;
}

.ks-play__hint[data-faded="true"] { opacity: 0; }

@media (max-width: 480px) {
  .ks-play__brand strong { display: none; }
  .ks-play__brand { padding: 5px }
}

/* The two controls, stacked.
 *
 * The owner asked for Feed Your Pet *below* Back to Pet Settings, so this is a column and not
 * the row the header used to be. It stays a two-control corner: this screen is still deliberately
 * almost empty, and the third thing on it had to be earned by a feature that gives the pet
 * something to do rather than by a link somewhere else. */
.ks-play__actions {
  margin-left: auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
}

.ks-play__back { margin-left: 0; }

/* Same plate as the links beside it, for the same measured reason: the scrim fades out and
 * cannot promise 4.5:1 over a white sky, and the plate can at any point of any picture. */
.ks-play__feed {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 7px 14px 7px 10px;
  border: 1px solid rgba(255, 255, 255, .5);
  border-radius: 999px;
  background: rgba(9, 14, 18, .62);
  color: #fff;
  font: 700 14px Cabin, sans-serif;
  text-shadow: 0 1px 6px rgba(9, 14, 18, .7);
  cursor: pointer;
}

.ks-play__feed img,
.ks-play__feed svg { display: block; }

.ks-play__feed:hover { background: rgba(9, 14, 18, .78); }

.ks-play__feed:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }

/* A full pet cannot be fed, and neither can one that has gone. The control says so by being
 * unavailable rather than by disappearing: a control that vanishes reads as a broken page. */
.ks-play__feed[disabled] { opacity: .55; cursor: default; }

/* What just happened — fed, bought, or out of points. It sits opposite the hint so the two
 * never overlap, and it says nothing until there is something to say. */
.ks-play__note {
  position: fixed;
  left: 50%;
  bottom: clamp(58px, 11vw, 76px);
  z-index: 1;
  transform: translateX(-50%);
  margin: 0;
  max-width: min(88vw, 36ch);
  padding: 9px 16px;
  border-radius: 999px;
  background: rgba(9, 14, 18, .78);
  color: #fff;
  font: 400 14px/1.4 Literata, serif;
  text-align: center;
  text-wrap: balance;
}

.ks-play__note[hidden] { display: none; }

@media (max-width: 480px) {
  .ks-play__feed span { font-size: 13px; }
}
