/* The touch pad (F40): a handheld's shell around the game - a cross D-pad, four face
   buttons, Start, and a fullscreen chip. Drawn in the pack's colours (DESIGN.md) but in
   HTML, not on the canvas, so it can sit outside the 320x180 picture and never cover it
   (D25).

   Layout is a grid on #shell, set by the body class touch.js keeps in step with the
   screen shape:
     .pad-portrait  stage on top, hint under it, controls along the bottom
     .pad-landscape controls in their own gutters, stage in the middle
   Either way the stage is a grid area of its own, so a button can never land on the
   game - the picture shrinks to make room instead. */

:root {
  --ink: #47324b;
  --plum: #615679;
  --dusk: #81759b;
  --steel: #999ac4;
  --mist: #c3c6e9;
  --sand: #f3cdac;
  --cream: #fbe5c9;
  --gold: #ffb84c;
  --red: #dd674c;
  --teal: #7bd8c4;
  --purple: #a386ce;
  --shell: #241a2b;
  --shell-hi: #33253c;
  --well: #17111c;

  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);

  /* How fast a button answers. Short enough to feel instant, long enough to be seen. */
  --press: 70ms;
  --ease: cubic-bezier(0.2, 0.7, 0.3, 1);
}

/* ---- the pad only exists once touch.js turns it on ---- */

#pad { display: none; }
body.pad-on #pad { display: contents; }

/* Nothing on the pad scrolls, selects, long-press-menus or flashes a tap highlight:
   all four are browser habits that make a game control feel like a web page. */
#pad,
#pad * {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: none;
}

/* ---- grid ---- */

#shell { grid-template-columns: 1fr; grid-template-rows: 1fr; }

/* Upright the whole page is the body of the handheld, with the screen sunk into it:
   the first row is empty plastic above the screen, so the room a 16:9 picture cannot
   use reads as the machine rather than as a void. It collapses to nothing first when
   the window is short. */
body.pad-on.pad-portrait #shell {
  grid-template-columns: 1fr 1fr;
  grid-template-rows: minmax(0, 0.6fr) var(--stage-h, 1fr) minmax(0, 1fr) auto;
  background:
    radial-gradient(120% 44% at 50% 16%, rgba(195, 198, 233, 0.09), transparent 64%),
    linear-gradient(180deg, var(--shell-hi), var(--shell) 62%, #1e1626);
}
body.pad-on.pad-portrait #stage {
  grid-column: 1 / -1;
  grid-row: 2;
  margin: 0 12px;
  border-radius: 10px;
}
body.pad-on.pad-portrait .cluster-mid { grid-column: 1 / -1; grid-row: 3; }
body.pad-on.pad-portrait .cluster-left { grid-column: 1; grid-row: 4; }
body.pad-on.pad-portrait .cluster-right { grid-column: 2; grid-row: 4; }

/* The gutters carry the safe-area inset on top of the room the cluster needs. A notch
   or a rounded corner takes a strip off the side of the window that nothing may be drawn
   in, and the cluster is padded clear of it - so if the gutter were only as wide as the
   cluster, that padding would push the cluster out of its own column and onto the game. */
body.pad-on.pad-landscape #shell {
  grid-template-columns:
    calc(var(--gut) + var(--safe-l))
    1fr
    calc(var(--gut) + var(--safe-r));
  grid-template-rows: 1fr;
}
body.pad-on.pad-landscape #stage { grid-column: 2; grid-row: 1; }
body.pad-on.pad-landscape .cluster-left { grid-column: 1; grid-row: 1; }
body.pad-on.pad-landscape .cluster-right { grid-column: 3; grid-row: 1; }
/* Start and fullscreen ride along the top of the left gutter, away from both thumbs. */
body.pad-on.pad-landscape .cluster-mid {
  grid-column: 1;
  grid-row: 1;
  align-self: start;
  z-index: 2;
}

/* ---- the shell the controls sit in ---- */

.cluster {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  min-width: 0;
  background: linear-gradient(180deg, var(--shell-hi), var(--shell));
}
body.pad-on.pad-portrait .cluster-left,
body.pad-on.pad-portrait .cluster-right {
  padding: 12px 6px calc(20px + var(--safe-b));
  background: none;
}
body.pad-on.pad-portrait .cluster-left { padding-left: calc(8px + var(--safe-l)); }
body.pad-on.pad-portrait .cluster-right { padding-right: calc(8px + var(--safe-r)); }
/* Upright, this band is the face of the machine: too tall to leave blank, because a
   16:9 picture cannot fill a 9:19.5 window however it is scaled. Lit from the screen
   above, printed with the game's name and finished with a speaker grille, it reads as
   moulded plastic instead of as space left over. */
body.pad-on.pad-portrait .cluster-mid {
  flex-direction: column;
  justify-content: space-between;
  gap: 10px;
  padding: 14px 12px 4px;
  overflow: hidden;
  background: none;
}

.grille {
  position: absolute;
  right: 16px;
  bottom: 70px;
  width: 78px;
  height: 46px;
  transform: rotate(-30deg);
  opacity: 0.5;
  background-image: radial-gradient(rgba(23, 17, 28, 0.55) 1.6px, transparent 1.7px);
  background-size: 11px 11px;
  pointer-events: none;
}
body.pad-landscape .grille,
body.pad-tight .grille { display: none; }

body.pad-on.pad-landscape .cluster-left {
  padding: calc(8px + var(--safe-t)) 6px calc(10px + var(--safe-b)) calc(4px + var(--safe-l));
}
body.pad-on.pad-landscape .cluster-right {
  padding: calc(8px + var(--safe-t)) calc(4px + var(--safe-r)) calc(10px + var(--safe-b)) 6px;
}
body.pad-on.pad-landscape .cluster-mid {
  background: none;
  flex-direction: row;
  gap: 6px;
  padding: calc(12px + var(--safe-t)) 6px 0 calc(10px + var(--safe-l));
  justify-content: flex-start;
}
/* Sideways, the controls sit level with the middle of the picture rather than down in
   the corners: that is where a thumb sits when the device is held in two hands, and it
   keeps them off the bottom edge where a home bar or a browser chrome lives. */
body.pad-on.pad-landscape .cluster-left .dpad,
body.pad-on.pad-landscape .cluster-right .face { margin: auto 0; }

/* The picture comes in whole-number sizes, so a little of the stage is always bezel.
   Sunk and rimmed, it reads as the screen of the thing rather than as a gap. */
body.pad-on #stage {
  background: var(--well);
  box-shadow:
    inset 0 0 0 1px rgba(195, 198, 233, 0.1),
    inset 0 2px 8px rgba(0, 0, 0, 0.55),
    0 1px 0 rgba(195, 198, 233, 0.07);
}
body.pad-on canvas { margin: 0 auto; }

/* ---- the cross ---- */

/* Sized by --unit, but never wider than the room it has: if anything ever squeezes the
   gutter - a system inset bigger than we planned for, a browser with its own chrome -
   the controls shrink instead of spilling onto the picture. */
.dpad {
  position: relative;
  width: var(--unit);
  max-width: 100%;
  max-height: 100%;
  aspect-ratio: 1;
  flex: 0 1 auto;
}
.dpad-base {
  position: absolute;
  inset: 0;
  filter: drop-shadow(0 4px 0 rgba(0, 0, 0, 0.45));
}
.dpad-base::before,
.dpad-base::after {
  content: '';
  position: absolute;
  background: linear-gradient(180deg, #5c4f73, #3b2c46);
  border-radius: 16%;
}
.dpad-base::before { left: 0; right: 0; top: 34%; height: 32%; }
.dpad-base::after { top: 0; bottom: 0; left: 34%; width: 32%; }

.arm {
  position: absolute;
  border-radius: 16%;
  background: linear-gradient(180deg, var(--steel), var(--dusk));
  opacity: 0;
  transition: opacity var(--press) var(--ease);
  pointer-events: none;
}
.arm.up { left: 34%; width: 32%; top: 0; height: 42%; }
.arm.down { left: 34%; width: 32%; bottom: 0; height: 42%; }
.arm.left { top: 34%; height: 32%; left: 0; width: 42%; }
.arm.right { top: 34%; height: 32%; right: 0; width: 42%; }
.arm.on { opacity: 1; }

/* The hub reads as the middle of a moulded cross and shows the press as a dip. */
.dpad-hub {
  position: absolute;
  left: 36%;
  top: 36%;
  width: 28%;
  height: 28%;
  border-radius: 50%;
  background: radial-gradient(circle at 38% 32%, #6b5c85, #35283f);
  box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.18);
  transition: transform var(--press) var(--ease);
  pointer-events: none;
}
.dpad.held .dpad-hub { transform: scale(0.9); }

/* Arrow marks, so the cross reads as directions and not decoration. */
.arrow {
  position: absolute;
  width: 0;
  height: 0;
  opacity: 0.6;
  pointer-events: none;
}
.arrow.up {
  left: 50%; top: 9%;
  margin-left: -5px;
  border-left: 5px solid transparent; border-right: 5px solid transparent;
  border-bottom: 7px solid var(--mist);
}
.arrow.down {
  left: 50%; bottom: 9%;
  margin-left: -5px;
  border-left: 5px solid transparent; border-right: 5px solid transparent;
  border-top: 7px solid var(--mist);
}
.arrow.left {
  top: 50%; left: 9%;
  margin-top: -5px;
  border-top: 5px solid transparent; border-bottom: 5px solid transparent;
  border-right: 7px solid var(--mist);
}
.arrow.right {
  top: 50%; right: 9%;
  margin-top: -5px;
  border-top: 5px solid transparent; border-bottom: 5px solid transparent;
  border-left: 7px solid var(--mist);
}

/* ---- the four face buttons ---- */

.face {
  position: relative;
  width: var(--unit);
  max-width: 100%;
  max-height: 100%;
  aspect-ratio: 1;
  flex: 0 1 auto;
}
/* 38% across, centred 31% out from the middle of the cluster: adjacent buttons are
   then 43.8% apart with 38% of that taken by the buttons themselves, so there is a real
   gap between them the way there is on a controller. At 43%/28.5% they overlapped. */
.btn {
  position: absolute;
  width: 38%;
  height: 38%;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  font: 700 clamp(13px, 4.4vmin, 21px)/1 system-ui, sans-serif;
  letter-spacing: 0.04em;
  color: rgba(23, 17, 28, 0.82);
  background: var(--face-col);
  box-shadow:
    0 4px 0 var(--face-dark),
    0 5px 8px rgba(0, 0, 0, 0.42),
    inset 0 2px 3px rgba(255, 255, 255, 0.4);
  transition:
    transform var(--press) var(--ease),
    box-shadow var(--press) var(--ease),
    filter var(--press) var(--ease);
}
.btn.y { --face-col: var(--purple); --face-dark: #6d54a0; left: 31%; top: 0; }
.btn.x { --face-col: var(--teal); --face-dark: #4aa793; left: 0; top: 31%; }
.btn.a { --face-col: var(--gold); --face-dark: #c88720; right: 0; top: 31%; }
.btn.b { --face-col: var(--red); --face-dark: #a8422b; left: 31%; bottom: 0; }

.btn.on {
  transform: translateY(3px);
  filter: brightness(1.16);
  box-shadow:
    0 1px 0 var(--face-dark),
    0 1px 3px rgba(0, 0, 0, 0.5),
    inset 0 2px 5px rgba(0, 0, 0, 0.25);
}

/* What each button does is said once, in the band between the screen and the pad -
   a diamond has no room to caption four buttons without the words running into the
   buttons beside them. Sideways there is no band, so the letters speak for themselves
   and the in-game prompts name them ("press A to talk").  */
.legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px 14px;
  font: 600 11px/1 system-ui, sans-serif;
  letter-spacing: 0.04em;
  color: var(--mist);
}
.leg { display: inline-flex; align-items: center; gap: 5px; }
.leg i {
  display: grid;
  place-items: center;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: var(--c);
  color: rgba(23, 17, 28, 0.85);
  font: 700 10px/1 system-ui, sans-serif;
  font-style: normal;
}
.leg.a i { --c: var(--gold); }
.leg.b i { --c: var(--red); }
.leg.x i { --c: var(--teal); }
.leg.y i { --c: var(--purple); }
body.pad-landscape .legend,
body.pad-tight .legend { display: none; }

/* ---- Start and the fullscreen chip ---- */

.pills { display: flex; align-items: center; gap: 10px; }
body.pad-on.pad-portrait .pills { padding-bottom: 6px; }
/* Stacked sideways: a gutter is narrower than the two of them sitting side by side. */
body.pad-on.pad-landscape .pills { flex-direction: column; align-items: flex-start; gap: 7px; }

.pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  margin: 0;
  border: 0;
  padding: 0 14px;
  height: 30px;
  min-width: 30px;
  border-radius: 15px;
  background: linear-gradient(180deg, var(--dusk), #574b6e);
  color: var(--cream);
  font: 700 11px/1 system-ui, sans-serif;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  box-shadow: 0 3px 0 #3a2f4d, 0 4px 7px rgba(0, 0, 0, 0.4), inset 0 1px 2px rgba(255, 255, 255, 0.26);
  transform: rotate(-9deg);
  transition:
    transform var(--press) var(--ease),
    box-shadow var(--press) var(--ease),
    filter var(--press) var(--ease);
}
.pill.chip { padding: 0; width: 30px; font-size: 14px; letter-spacing: 0; transform: rotate(0deg); }
.pill.on {
  transform: rotate(-9deg) translateY(2px);
  filter: brightness(1.18);
  box-shadow: 0 1px 0 #3a2f4d, 0 1px 3px rgba(0, 0, 0, 0.45), inset 0 2px 4px rgba(0, 0, 0, 0.22);
}
.pill.chip.on { transform: translateY(2px); }

/* The name printed on the shell, the way a handheld has its own on the plastic below
   the screen. Upright there is more window than a 16:9 picture can use, and an empty
   band reads as a mistake where a moulded face reads as the machine. */
.brand {
  flex: 1;
  display: grid;
  place-items: center;
  min-height: 0;
  font: 700 clamp(13px, 4vw, 19px)/1 system-ui, sans-serif;
  letter-spacing: 0.42em;
  text-indent: 0.42em;
  color: rgba(195, 198, 233, 0.22);
}
body.pad-landscape .brand,
body.pad-tight .brand { display: none; }

.band-foot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: 100%;
}

/* ---- the rotate hint ---- */

.hint {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  max-width: 460px;
  box-sizing: border-box;
  padding: 8px 10px;
  border-radius: 10px;
  background: rgba(97, 86, 121, 0.34);
  border: 1px solid rgba(195, 198, 233, 0.2);
  color: var(--cream);
  font: 400 12px/1.35 system-ui, sans-serif;
}
body.pad-landscape .hint,
body.hint-done .hint { display: none; }

.hint b {
  display: block;
  color: var(--gold);
  font-size: 12.5px;
  letter-spacing: 0.02em;
}
.hint span { color: var(--mist); }
.hint-copy { min-width: 0; }

/* A phone turning on its side, drawn rather than written: it says the same thing in
   any language and costs no download. */
.hint-mark {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  color: var(--gold);
  animation: tip 2.6s var(--ease) infinite;
}
@keyframes tip {
  0%, 58%, 100% { transform: rotate(0deg); }
  72%, 90% { transform: rotate(-82deg); }
}
@media (prefers-reduced-motion: reduce) {
  .hint-mark { animation: none; }
}

.hint-x {
  flex: 0 0 auto;
  margin: 0;
  border: 0;
  padding: 0;
  width: 26px;
  height: 26px;
  border-radius: 13px;
  background: rgba(195, 198, 233, 0.14);
  color: var(--mist);
  font: 400 15px/1 system-ui, sans-serif;
  transition: filter var(--press) var(--ease), transform var(--press) var(--ease);
}
.hint-x:active { transform: scale(0.92); filter: brightness(1.3); }
