/* layout: one fixed rounded stage like todeulb.works; the well in the middle, the glass blob-meter (a
   tall pill) on its left, the next piece, the held piece and the menu's blob on its right, the brand
   and the scoreboard as big text at the far left */
@font-face {
  font-family: 'TeX Gyre Heros';
  src: url('fonts/texgyreheros-bold.otf') format('opentype');
  font-weight: 700;
  font-style: normal;
  font-display: block;
}

:root {
  --stage: #e0dcd9;
  --ink: #1f2326;
  --frame: #161616;
  --accent: hsl(194 100% 51.4%);
  --accent-pressed: hsl(18 100% 50%);
  --theme-fade: 450ms ease;
  --font: 'TeX Gyre Heros', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --stage: #161616; --ink: #e0dcd9; --frame: #e0dcd9; color-scheme: dark; }
}

:root[data-theme="dark"] { --stage: #161616; --ink: #e0dcd9; --frame: #e0dcd9; color-scheme: dark; }

/* the game's own toggle (and the flood's flip) wins over the viewer's theme */
:root:root[data-game-theme="light"] { --stage: #e0dcd9; --ink: #1f2326; --frame: #161616; color-scheme: light; }
:root:root[data-game-theme="dark"] { --stage: #161616; --ink: #e0dcd9; --frame: #e0dcd9; color-scheme: dark; }

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

html, body { height: 100%; overflow: hidden; }

body {
  background: var(--frame);
  color: var(--ink);
  font-family: var(--font);
  font-weight: 700;
  text-transform: lowercase;
  letter-spacing: -0.07em;
  -webkit-font-smoothing: antialiased;
  transition: background-color var(--theme-fade), color var(--theme-fade);
}

button {
  background: none;
  border: none;
  font: inherit;
  letter-spacing: -0.07em;
  text-transform: lowercase;
  color: inherit;
  cursor: pointer;
}

.stage {
  position: fixed;
  inset: clamp(10px, 1.6vw, 24px);
  background: var(--stage);
  border-radius: 31px;
  overflow: hidden;
  clip-path: inset(0 round 31px);
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  transition: background-color var(--theme-fade);
}

/* (hidden until it has drawn its first picture: a blank canvas would flash for a frame; the stage's
   own color shows meanwhile) */
.stage-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  visibility: hidden;
}

.stage.gl-ready .stage-canvas { visibility: visible; }

/* the menu's blob is drawn by the canvas; this is its tap target and its label */
.menu-blob {
  position: absolute;
  z-index: 4;
  border-radius: 50%;
  font-size: 1.05rem;
  line-height: 1;
}

.menu-blob span {
  position: absolute;
  right: calc(100% + 0.35em);
  top: 50%;
  transform: translateY(-50%);
  pointer-events: none;
}

/* the menu: its glass is drawn by the canvas under these words, and it grows out of the blob's corner */
.panel {
  position: absolute;
  z-index: 4;
  width: min(290px, calc(100% - 32px));
  padding: 1.1rem 1.3rem 1.25rem;
  transform-origin: top right;
}

.panel[hidden] { display: none; }

.panel ul { list-style: none; }

.menu-item {
  padding: 0;
  text-align: left;
  font-size: 2rem;
  line-height: 0.92;
  transition: transform 150ms cubic-bezier(0.2, 0.8, 0.2, 1), color 150ms ease;
}

.menu-item:hover { transform: translateY(-1px); }
/* the items come in one after the other, like the site's "trabalhos" list (--i: their place in line) */
.panel li, .panel-keys {
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity 180ms ease, transform 180ms ease;
}

.stage.menu-open .panel li, .stage.menu-open .panel-keys {
  opacity: 1;
  transform: none;
  transition: opacity 260ms ease, transform 260ms cubic-bezier(0.2, 0.8, 0.2, 1);
  transition-delay: calc(var(--i, 0) * 25ms + 60ms);
}

.stage.menu-open .panel-keys { opacity: 0.55; }

.menu-item:focus-visible, .menu-blob:focus-visible, .hold:focus-visible {
  outline: none;
  color: var(--accent);
}

.panel-keys { margin-top: 1rem; font-size: 0.95rem; line-height: 1.12; white-space: pre-line; }

/* the held piece's panel is drawn by the canvas; this is its mark and its tap target */
.hold {
  position: absolute;
  z-index: 2;
  text-align: left;
  display: flex;
  align-items: flex-start;
  padding: 0.55em 0.75em;
  font-size: 1.05rem;
  line-height: 1;
  border-radius: 26px;
}

/* the marks over the waiting piece and the held one: plain symbols, drawn here so that they look the
   same everywhere (as characters, some phones turn them into colored emoji) */
.hold svg, .tag svg {
  display: block;
  width: 1.5em;
  height: 1.5em;
  fill: currentColor;
}

/* (the next piece's mark) */
.tag {
  position: absolute;
  z-index: 2;
  font-size: 1.05rem;
  line-height: 1;
  pointer-events: none;
}

/* the keys, under the menu's blob: they leave after the first two pieces (the menu has them too) */
.hints {
  position: absolute;
  z-index: 2;
  font-size: 1rem;
  line-height: 1.12;
  opacity: 0.55;
  white-space: pre-line;
  pointer-events: none;
  transition: opacity 900ms ease;
}

.hints.faded { opacity: 0; }

.message {
  position: absolute;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  text-align: center;
  pointer-events: none;
}

.message[hidden] { display: none; }

.message strong { font-size: 2.6rem; line-height: 0.85; font-weight: 700; }

/* the final score, counting up */
.message-number { font-size: 3.6rem; line-height: 0.85; }

.message-number:empty, .message-keys:empty { display: none; }

.message span { font-size: 1.15rem; line-height: 1.05; max-width: 12em; }

.message-keys { margin-top: 0.6rem; font-size: 1rem; line-height: 1.12; opacity: 0.6; white-space: pre-line; }

/* "+800": rises from where the points were made */
.pop {
  position: absolute;
  z-index: 3;
  font-size: 1.5rem;
  line-height: 1;
  white-space: nowrap;
  pointer-events: none;
  transform: translate(-50%, -50%);
  animation: pop-rise 900ms cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
}

@keyframes pop-rise {
  0% { opacity: 0; transform: translate(-50%, -20%) scale(0.6); }
  18% { opacity: 1; transform: translate(-50%, -70%) scale(1.1); }
  100% { opacity: 0; transform: translate(-50%, -190%) scale(1); }
}

/* an ink chain's running total: it stays put while it counts, then rises like the others */
.pop.counting { animation: none; font-size: 2rem; }

@keyframes pop-fade {
  0%, 70% { opacity: 1; }
  100% { opacity: 0; }
}

/* what's written on the panels (the well, the held piece): they have the opposite of the stage's
   color, so their words take the stage's */
.hold, .message, .pop {
  color: var(--stage);
  transition: color var(--theme-fade);
}

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

/* the brand's square (top left, desktop) is drawn by the canvas; this is its tap target: it switches the theme */
.brand { position: absolute; z-index: 2; }
.brand[hidden] { display: none; }
.brand:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.stage:not(.compact) .phone-only { display: none; }

/* The cursor: the site's own (its js/cursor.js, built into the game by build.ps1, and these rules,
   copied from its styles.css). A dot that lags behind the mouse; over the stage it fades out and
   the canvas draws the big drop instead (body.droplet-active). Only where there's a mouse (class
   set by the script); the system cursor is hidden the site's way. */
.blob-cursor, .blob-cursor * {
  cursor: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=') 0 0, none !important;
}
.custom-cursor {
  position: fixed;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  pointer-events: none;
  z-index: 2147483647;
  visibility: hidden;
  will-change: transform;
}
.custom-cursor svg { display: block; overflow: visible; }
.custom-cursor line { stroke: var(--accent); stroke-linecap: round; transition: stroke 114ms ease; }
.custom-cursor circle { fill: var(--accent); transition: fill 114ms ease; }
.custom-cursor.clicked line { stroke: var(--accent-pressed); }
.custom-cursor.clicked circle { fill: var(--accent-pressed); }
body.droplet-active .custom-cursor { opacity: 0; }

/* the page opening (stepIntro(), the class is taken off when it's their turn): the words wait
   unseen while the canvas grows the panels and blobs in, then fade in, one just after the other */
.tag, .hold svg, .menu-blob span { transition: opacity 400ms ease; }
.stage .message { transition: opacity 400ms ease 60ms, color var(--theme-fade); }
.hold svg { transition-delay: 40ms; }
.menu-blob span { transition-delay: 120ms; }
.stage.intro .tag, .stage.intro .hold svg, .stage.intro .menu-blob span, .stage.intro .message, .stage.intro .hints { opacity: 0; }

.stage.menu-open .hints { opacity: 0; transition-duration: 200ms; }
.stage.menu-up .panel { transform-origin: bottom right; }

/* phone / portrait (class set by the script, the site's isCompact rule): blob-meter, next piece and
   held piece in a strip above the well; the scoreboard and the menu's blob in a strip below it */
.stage.compact .panel-keys { display: none; }
.stage.compact .menu-item { font-size: calc(1.7rem * var(--menu-fit, 1)); white-space: nowrap; }
.stage.compact .menu-blob { font-size: 0.8rem; }
/* (a phone's top row is slim: small marks, the held piece's inside its little panel at the left) */
.stage.compact .hold, .stage.compact .tag { font-size: 0.5rem; }
.stage.compact .hold { border-radius: 999px; padding: 0; align-items: center; }
.stage.compact .hold svg { margin-left: calc(7px + 0.9em); }
.stage.compact .hints { display: none; }
/* where the game can't run (state.js): only the message, in the ink, on the plain stage */
.stage.unsupported > :not(.message) { display: none; }
.stage.unsupported .message { color: var(--ink); pointer-events: auto; }
.stage.unsupported .message-keys a { color: inherit; pointer-events: auto; }
.stage.unsupported .message-keys a:hover { color: var(--accent); }
.stage.compact .message strong { font-size: 2rem; }
.stage.compact .message-number { font-size: 2.6rem; }
.stage.compact .message-keys { font-size: 0.85rem; }

.stage.compact .pop { font-size: 1.15rem; }

/* ?erro: the saved error log (main.js), plain, over everything, to copy or screenshot */
.error-log {
  position: fixed; inset: 16px; z-index: 1000;
  display: flex; flex-direction: column; gap: 12px;
  padding: 16px; border-radius: 16px;
  background: var(--stage); color: var(--ink); box-shadow: 0 0 0 2px var(--ink);
  cursor: auto;
}
.error-log pre {
  flex: 1; margin: 0; overflow: auto;
  font: 12px/1.45 ui-monospace, Menlo, Consolas, monospace;
  white-space: pre-wrap; word-break: break-word; user-select: text;
  text-transform: none; letter-spacing: normal; /* (an error's words as they are: case matters there) */
}
.error-log div { display: flex; gap: 16px; }
.error-log button { font: 700 1rem var(--font); color: inherit; background: none; border: 0; padding: 4px 0; cursor: pointer; }
.error-log button:hover { color: var(--accent); }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
  .pop { animation-name: pop-fade; }
}
