/* toasty.games
   The page is a toaster: paper above a line, a block of enamel below it,
   and the word sitting in the slot. Two colours, nothing else. */

/* Fonts are hosted here rather than on Google Fonts, so pages make no requests
   to Google (which would pass visitors' IP addresses on). Both are under the
   SIL Open Font License; see assets/fonts/. */

/* Bagel Fat One, latin */
@font-face {
  font-family: "Bagel Fat One";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/bagel-fat-one-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Bagel Fat One, latin-ext */
@font-face {
  font-family: "Bagel Fat One";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/bagel-fat-one-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Schibsted Grotesk, latin */
@font-face {
  font-family: "Schibsted Grotesk";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("../fonts/schibsted-grotesk-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Schibsted Grotesk, latin-ext */
@font-face {
  font-family: "Schibsted Grotesk";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("../fonts/schibsted-grotesk-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}


:root {
  --paper: #EEEFF3;
  --enamel: #2F2BE0;

  --font-display: "Bagel Fat One", system-ui, sans-serif;
  --font-text: "Schibsted Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;

  --ui: 0.9375rem;   /* 15px: links, labels */
  --read: 1.0625rem; /* 17px: anything you read */

  --gutter: 16px;
  --block: clamp(170px, 32dvh, 340px); /* height of the toaster */
  color-scheme: light;
}

@media (min-width: 720px) {
  :root { --gutter: 32px; }
}

*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--enamel);
  font-family: var(--font-text);
  font-size: var(--read);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-underline-offset: 0.2em; text-decoration-thickness: 1px; }
a:hover { text-decoration-thickness: 2px; }

:focus-visible {
  outline: 2px solid var(--enamel);
  outline-offset: 4px;
  border-radius: 2px;
}

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* Front page */

.home {
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

.toaster {
  display: grid;
  grid-template-rows: 1fr var(--block);
  height: 100%;
  /* The thud when the word lands: the whole toaster is knocked down a little */
  transform: translateY(var(--thud, 0px));
}

/* The paper above the line. Its bottom edge is the slot: anything below it is
   inside the toaster and hidden. */
.stage {
  position: relative;
  overflow: hidden;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  touch-action: none;
  cursor: grab;
}

.stage.is-pressed { cursor: grabbing; }

.toast {
  position: absolute;
  left: var(--gutter);
  bottom: 0;
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  /* The word is 3.08 times as wide as its font size, so 10.8vw makes it a
     third of the screen. Tablets get a bit more (110px), and it is never
     taller than about half the paper. */
  font-size: min(max(10.8vw, 110px), calc((100dvh - var(--block)) * 0.5));
  line-height: 1;
  letter-spacing: -0.01em;
  white-space: nowrap;
  color: var(--enamel);
  /* toaster.js moves and turns the word about its centre of mass (--ox, --oy) */
  transform: translate3d(var(--toast-x, 0px), var(--toast-y, 120%), 0) rotate(var(--toast-r, 0deg));
  transform-origin: var(--ox, 50%) var(--oy, 60%);
  will-change: transform;
  pointer-events: none;
}

/* Squash and stretch, anchored near the baseline so it squashes onto the slot */
.toast-inner {
  display: inline-block;
  transform: scale(var(--sx, 1), var(--sy, 1));
  transform-origin: 50% 82%;
}

/* Phones: let the word take most of the width */
@media (max-width: 599px) {
  .toast { font-size: min(25vw, calc((100dvh - var(--block)) * 0.5)); }
}

/* The toaster itself */
.block {
  position: relative;
  background: var(--enamel);
  color: var(--paper);
}

.block :focus-visible { outline-color: var(--paper); }

.links {
  position: absolute;
  left: var(--gutter);
  bottom: calc(var(--gutter) + env(safe-area-inset-bottom));
  display: flex;
  gap: 1.5rem;
  font-size: var(--ui);
  line-height: 1.4;
}

.link {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0.25rem 0;
  cursor: pointer;
  text-decoration: none;
}

.link:hover {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.25em;
}

/* The lever: a track on the right of the block with a knob that travels down */
.lever {
  position: absolute;
  right: calc(var(--gutter) - 12px);
  top: 22%;
  width: 48px;
  height: 52%;
  padding: 0;
  background: none;
  border: 0;
  cursor: grab;
  touch-action: none;
  -webkit-touch-callout: none;
  user-select: none;
}

.lever::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 2px;
  margin-left: -1px;
  background: color-mix(in srgb, var(--paper) 45%, transparent);
  border-radius: 1px;
}

.lever-knob {
  position: absolute;
  left: 50%;
  top: 0;
  width: 30px;
  height: 14px;
  margin-left: -15px;
  background: var(--paper);
  border-radius: 7px;
  transform: translateY(calc(var(--lever, 0) * (var(--track, 120px) - 14px)));
}

/* Contact: a slip of paper that rises out of the slot */
.slip-dialog {
  position: fixed;
  inset: 0 0 var(--block) 0;
  width: auto;
  height: auto;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  /* clip, not hidden: focusing a card must not scroll its hidden bottom into view */
  overflow: clip;
  color: var(--enamel);
}

.slip-dialog::backdrop { background: transparent; }

/* The bottom of the slip sits inside the toaster, so when it pops past its
   resting place you see it lift clear of the slot */
.slip {
  position: absolute;
  left: var(--gutter);
  bottom: -18px;
  width: min(25rem, calc(100vw - 2 * var(--gutter)));
  max-height: calc(100% - var(--gutter) + 18px);
  overflow: auto;
  padding: 1.5rem 1.5rem calc(1.75rem + 18px);
  background: var(--paper);
  border: 2px solid var(--enamel);
  border-radius: 14px;
}

.slip-close {
  position: absolute;
  top: 1rem;
  right: 1.25rem;
  font: inherit;
  font-size: var(--ui);
  color: var(--enamel);
  background: none;
  border: 0;
  padding: 0.25rem 0;
  cursor: pointer;
}
.slip-close:hover { text-decoration: underline; text-decoration-thickness: 2px; }

.form { display: grid; gap: 1.25rem; }

.field-row { display: grid; gap: 0.25rem; }

.field-row label { font-size: var(--ui); }

.field-row input,
.field-row textarea {
  width: 100%;
  font: inherit;
  color: var(--enamel);
  background: transparent;
  border: 0;
  border-bottom: 1.5px solid var(--enamel);
  border-radius: 0;
  padding: 0.4rem 0;
}

.field-row textarea { min-height: 6.5rem; resize: vertical; }

.field-row input:focus,
.field-row textarea:focus {
  outline: none;
  box-shadow: 0 1.5px 0 var(--enamel);
}

.field-row [aria-invalid="true"]:not(:focus) { border-bottom-style: double; border-bottom-width: 4px; }

.field-error {
  margin: 0;
  font-size: var(--ui);
  font-weight: 600;
}
.field-error:empty { display: none; }

.honeypot { display: none; }

.button {
  justify-self: start;
  display: inline-block;
  font: inherit;
  font-size: var(--ui);
  font-weight: 600;
  color: var(--paper);
  background: var(--enamel);
  border: 2px solid var(--enamel);
  border-radius: 999px;
  padding: 0.55rem 1.2rem;
  cursor: pointer;
  text-decoration: none;
  transition: background-color 150ms ease-out, color 150ms ease-out;
}

.button:hover {
  color: var(--enamel);
  background: transparent;
}

.button:disabled { cursor: progress; opacity: 0.7; }

.form-status { margin: 0; font-size: var(--ui); }
.form-status:empty { display: none; }
.form-status.is-error { font-weight: 600; }

.slip-meta {
  margin: 1.5rem 0 0;
  padding-top: 1rem;
  border-top: 1px solid color-mix(in srgb, var(--enamel) 30%, transparent);
  font-size: var(--ui);
}

.sent p { margin: 0; }

/* Games: a card per game, standing in the slot like slices of toast. They
   line up from the left, and when there are more than fit, the row scrolls
   sideways. */
.cards {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -18px;
  display: flex;
  gap: 12px;
  margin: 0;
  /* Room above the cards for the overshoot and the hover lift, which the
     scrolling row would otherwise cut off */
  padding: 2rem var(--gutter) 0;
  list-style: none;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}

.card-slot { flex: none; display: flex; }

.card {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  width: 12.5rem;
  padding: 1.25rem 1.25rem calc(1.5rem + 18px);
  background: var(--paper);
  border: 2px solid var(--enamel);
  border-radius: 14px;
  text-decoration: none;
  transition: transform 160ms ease-out;
}

.card:focus-visible { border-radius: 14px; transform: translateY(-6px); }

@media (hover: hover) {
  .card:hover { transform: translateY(-6px); }
}

.card-icon {
  display: block;
  width: clamp(56px, 14dvh, 96px);
  height: auto;
  aspect-ratio: 1;
  border-radius: 22%; /* the iOS icon corner */
  background: var(--enamel);
}

.card-title {
  font-family: var(--font-display);
  font-size: 1.375rem;
  line-height: 1.05;
}

/* Game pages: paper, one column, enamel ink */

.page-top { padding: var(--gutter); }

.page-top a {
  font-family: var(--font-display);
  font-size: 1.5rem;
  line-height: 1;
  text-decoration: none;
}

.page {
  max-width: calc(36rem + 2 * var(--gutter));
  padding: clamp(3rem, 12vh, 7rem) var(--gutter) 6rem;
}

.game-icon {
  display: block;
  width: 96px;
  height: 96px;
  margin-bottom: 1.5rem;
  border-radius: 22px; /* the iOS icon corner, about 22% of the width */
  background: var(--enamel);
  object-fit: cover;
}

.page h1 {
  margin: 0 0 0.5rem;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.4rem, 7vw, 3.75rem);
  line-height: 1;
}

.page .lead { margin: 0 0 1.5rem; max-width: 40ch; }

.page section { margin-top: 4.5rem; }

.page h2 {
  margin: 0 0 0.75rem;
  font-size: var(--ui);
  font-weight: 600;
}

.page h3 {
  margin: 1.75rem 0 0.25rem;
  font-size: var(--read);
  font-weight: 600;
}

.page p { margin: 0 0 1rem; max-width: 60ch; }

.template-note {
  padding: 0.75rem 1rem;
  border: 1.5px dashed var(--enamel);
  border-radius: 8px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}
