:root {
  --bg: #ffffff;
  --ink: #000000;
  --border: #ededed;
  --input-border: #aaaaaa;
  --muted: #666666;
  --title: #696969;
  /* The grid's lines: faint across the page, darker round the centre column's box. */
  --line: #f4f4f4;
  --frame: #cccccc;
  --window-text: #aaaaaa;
  --window-glow: #4747474a;
  --font: system-ui, sans-serif;
}

/* The title's script face, served from this site (see fonts/ballet-OFL.txt). Only the
   Latin subset: the title is fixed text. */
@font-face {
  font-family: "Ballet";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/ballet-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;
}

* {
  box-sizing: border-box;
}

html {
  height: 100%;
  /* The page scrolls as usual. Setting this, rather than leaving it visible, stops the body's
     overflow being passed up to the page, so it clips the body itself (see below). */
  overflow: auto;
}

/* The page, as in the Paper design: a grid of three columns and five rows, with the title,
   the ball and the question box stacked in the middle column and centred on the page.
   The outer rows and columns are empty and take up what is left. The lines between the
   cells are drawn by the cells themselves: each one draws its top edge across the whole
   page, and the middle column's sides run the full height. */
body {
  min-height: 100%;
  margin: 0;
  display: grid;
  grid-template-columns: 1fr 420px 1fr;
  grid-template-rows: 1fr 63px 346px 118px 1fr;
  /* The lines run out 100vw past their cells; none of that should make the page scroll. */
  overflow-x: clip;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
}

/* The middle column's sides, above the title and below the question box. The cells
   draw them darker where they are. */
body::before {
  content: "";
  grid-area: 1 / 2 / -1 / 3;
  border-inline: 1px solid var(--line);
  z-index: -1;
}

/* A cell's top edge, run out to both sides of the page behind it. */
.site-header::before,
.ball-cell::before,
.ask-cell::before,
.ask-cell::after {
  content: "";
  position: absolute;
  top: -1px;
  left: -100vw;
  right: -100vw;
  border-top: 1px solid var(--line);
  z-index: -1;
}

/* The bottom of the question box is the top of the row below it. */
.ask-cell::after {
  top: auto;
  bottom: -1px;
}

/* The three cells of the middle column: the box they draw together is the darker line. */
.site-header,
.ball-cell,
.ask-cell {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  border: solid var(--frame);
  border-width: 0 1px;
}

.site-header {
  grid-area: 2 / 2;
  flex-direction: column;
  padding: 16px 36px;
  border-top-width: 1px;
}

.site-title {
  margin: 0;
  color: var(--title);
  font: 400 24px/30px "Ballet", system-ui, sans-serif;
  white-space: nowrap;
}

/* Questions from other visitors, drifting behind everything else. */
.background {
  position: fixed;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.blurb {
  position: absolute;
  max-width: 260px;
  padding: 8px;
  border: 1px dashed var(--border);
  border-radius: 9999px;
  color: var(--window-text);
  font-family: var(--font);
  line-height: 1.25;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  opacity: 0;
}

/* The ball and the question box are cells of the page's grid. */
.stage {
  display: contents;
}

.ball-cell {
  grid-area: 3 / 2;
  padding: 36px;
  border-top: 1px solid var(--line);
}

/* The ball */
.ball {
  position: relative;
  flex-shrink: 0;
  width: 273px;
  height: 273px;
  border-radius: 50%;
  background: var(--ink);
  overflow: clip;
  /* Drag to rotate: keep the browser from scrolling, zooming or selecting instead. */
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  /* A click pushes the ball back into the page: it shrinks a little (the individual
     `scale` property, so it combines with the shake's `transform`) and comes back. This is
     the way back: it eases in and out, starting slowly, speeding up, and slowing again as it
     reaches full size. */
  scale: 1;
  transition: scale 600ms ease-in-out;
}

.ball.is-pushed {
  scale: 0.9;
  /* The way in: quick, and easing out as it reaches its deepest point. The duration is how
     long that takes; ball-rotate.js reads it, so the push is held until the ball has got
     there whatever it is set to. */
  transition-duration: 100ms;
  transition-timing-function: cubic-bezier(0.2, 0.8, 0.2, 1);
}

.ball.is-dragging {
  cursor: grabbing;
}

/* Both faces are centred on the ball. The front is at rest facing the viewer; the
   back is on the far side and hidden until the ball is rotated (see ball-rotate.js). */
.window {
  position: absolute;
  /* 149px wide, in the middle of the ball whatever its size. */
  top: calc(50% - 74.5px);
  left: calc(50% - 74.5px);
  width: 149px;
  height: 149px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  overflow: clip;
  will-change: transform;
}

.window-front {
  background: var(--ink);
  border: 1px solid var(--ink);
  box-shadow: var(--window-glow) 0 2px 112px 58px inset;
}

.window-back {
  background: var(--bg);
  opacity: 0;
}

.model {
  margin: 0;
  color: var(--ink);
  font-family: ui-monospace, "SFMono-Regular", "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
  font-size: 14px;
  line-height: 18px;
}

.answer {
  margin: 0;
  max-width: 100px;
  color: var(--window-text);
  font-size: 14px;
  line-height: 18px;
  text-align: center;
  text-wrap: balance;
  transition: opacity 0.4s ease;
}

.ball.thinking .answer {
  animation: pulse 1s ease-in-out infinite;
}

.ball.shaking {
  animation: shake 0.6s cubic-bezier(0.36, 0.07, 0.19, 0.97);
}

/* With the 3D ball, the sphere is drawn in a canvas that replaces the flat
   circle. The canvas and the window are inside .ball, so they shake with it. */
.ball-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.ball.is-3d {
  background: transparent;
}

/* With the 3D model, both faces are drawn on the sphere. The answer stays in the page
   for screen readers (and the model reads it), but is not drawn twice. */
.ball.is-3d .window-front {
  top: 0;
  left: 0;
  width: 1px;
  height: 1px;
  border: 0;
  background: none;
  box-shadow: none;
  clip-path: inset(50%);
}

.ball.is-3d .window-back {
  display: none;
}

@keyframes shake {
  10%, 90% { transform: translate(-2px, 1px) rotate(-1deg); }
  20%, 80% { transform: translate(4px, -2px) rotate(2deg); }
  30%, 50%, 70% { transform: translate(-7px, 3px) rotate(-3deg); }
  40%, 60% { transform: translate(7px, -3px) rotate(3deg); }
}

@keyframes pulse {
  50% { opacity: 0.25; }
}

/* The question input */
.ask-cell {
  grid-area: 4 / 2;
  padding: 36px;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--frame);
}

.ask {
  display: flex;
  align-items: center;
  width: 100%;
  /* 12 + 18 + 12 + the 1px borders is the design's 44px. The text needs the 18px: at
     14px a line is about 17px tall, and any less cuts the tails off g, y, p, q and j. */
  padding: 12px;
  background: var(--bg);
  border: 1px solid var(--input-border);
  border-radius: 6px;
  overflow: clip;
}

.ask:focus-within {
  border-color: var(--ink);
}

.ask input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--ink);
  padding: 0;
  font: inherit;
  font-size: 14px;
  line-height: 18px;
  height: 18px;
}

.ask input::placeholder {
  color: var(--muted);
}

.ask button {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 15px;
  height: 15px;
  margin-left: 8px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
}

.ask button:disabled {
  opacity: 0.3;
  cursor: default;
}

.ask button:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
  border-radius: 4px;
}

.ask-wrap {
  position: relative;
  width: 100%;
}

.error {
  position: absolute;
  top: calc(100% + 12px);
  left: 0;
  margin: 0;
  color: var(--muted);
  font-size: 14px;
  line-height: 18px;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* The phone design: the same grid with a smaller ball and 16px at the sides of the cells. The
   middle column is as wide as the title (about 300px), and the empty columns take the rest,
   so the box has a strip of the page's lines on either side of it. The title's row grows
   if the title has to wrap on a very narrow phone. */
@media (max-width: 600px) {
  body {
    grid-template-columns: 1fr minmax(0, max-content) 1fr;
    grid-template-rows: 1fr minmax(63px, auto) 252px 118px 1fr;
  }

  .site-header {
    padding: 16px;
  }

  .ball-cell,
  .ask-cell {
    padding: 36px 16px;
  }

  .site-title {
    text-align: center;
    text-wrap: balance;
    white-space: normal;
  }

  .ball {
    width: 179px;
    height: 179px;
  }
}

@media (prefers-reduced-motion: reduce) {
  /* No pushing in and out for people who ask for less motion. */
  .ball,
  .ball.is-pushed {
    transition: none;
  }

  .ball.is-pushed {
    scale: 1;
  }

  .ball.shaking,
  .ball.thinking .answer {
    animation: none;
  }
}
