/* Threads by Shade: one large soft pool of light on a pale page. The edges of the screen are a
   faint moss dusk, the pool is where everything happens, and the ending lets the dusk lift. */

:root {
  --dusk: color-mix(in srgb, var(--ak-accent-2) 42%, color-mix(in srgb, var(--ak-accent) 22%, transparent));
  --light: var(--ak-surface);
  --soft-green: color-mix(in srgb, var(--ak-accent) 12%, transparent);
  --slow: 700ms;
  --slower: 1200ms;
  --ease: cubic-bezier(0.33, 1, 0.68, 1);
  --ease-settle: cubic-bezier(0.34, 1.18, 0.64, 1);
  --gap: 12px;
}

* { box-sizing: border-box; }

html,
body {
  height: 100%;
  margin: 0;
}

body {
  overflow: hidden;
  background-color: var(--ak-bg);
  background-image: var(--ak-backdrop-layer, var(--ak-bg-art));
  background-size: cover;
  background-position: center;
  color: var(--ak-ink);
  font-family: var(--ak-font-body);
  -webkit-tap-highlight-color: transparent;
}

/* A faint dusk at the screen's edges, never behind the words; the house lights lift it at the end. */
.stage {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.stage::before,
.stage::after {
  content: "";
  position: absolute;
  inset: 0;
}

.stage::before {
  background: radial-gradient(ellipse 72% 68% at 50% 50%, transparent 45%, var(--dusk) 100%);
}

.stage::after {
  background: var(--soft-green);
  opacity: 0;
}

.lights-up .stage::before { opacity: 0; }
.lights-up .stage::after { opacity: 1; }

.play {
  position: fixed;
  inset: 0;
  z-index: 1;
  display: grid;
  grid-template-areas: "top" "board" "panel";
  grid-template-rows: auto minmax(0, 1fr) auto;
  gap: var(--gap);
  width: min(100%, 1100px);
  margin: 0 auto;
  padding:
    calc(var(--ac-status-h, 60px) + 8px)
    max(12px, env(safe-area-inset-right))
    max(12px, env(safe-area-inset-bottom))
    max(12px, env(safe-area-inset-left));
  touch-action: manipulation;
}

.play[hidden] { display: none; }

/* ---------- top: the small logo and the shelf of finished cards ---------- */

.top {
  grid-area: top;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--gap);
  min-height: 36px;
}

.logo {
  display: block;
  height: clamp(28px, 4.2dvh, 40px);
  width: auto;
  max-width: 40%;
  object-fit: contain;
  opacity: 0.9;
}

.shelf {
  display: flex;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.shelf li {
  position: relative;
  width: clamp(18px, 5dvw, 26px);
  aspect-ratio: 333 / 384;
  border-radius: 8px;
}

.shelf:not(:has(li:not(.is-empty))) { display: none; }
.shelf li.is-empty { visibility: hidden; }

/* ---------- a wound card: the painted card with this handful's shades wound on it ---------- */

.card {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
}

.card img {
  display: block;
  width: 100%;
  height: 100%;
}

.card .wound {
  position: absolute;
  left: 9%;
  right: 9%;
  top: 20%;
  bottom: 21%;
  border-radius: 6% / 4%;
}

/* ---------- the lit board ---------- */

.board {
  grid-area: board;
  position: relative;
  min-height: 0;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

/* The one soft shape: a pool of pale light that fades out with no edge at all. */
.board::before {
  content: "";
  position: absolute;
  inset: -9% -12%;
  z-index: -1;
  background: radial-gradient(closest-side, var(--light) 0%, var(--light) 74%, color-mix(in srgb, var(--light) 45%, transparent) 88%, transparent 100%);
  pointer-events: none;
}

/* The spot under a lifted thread brightens a little. */
.board::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at var(--lx, 50%) var(--ly, 50%), color-mix(in srgb, var(--ak-surface) 60%, #fff) 0%, transparent 30%);
  opacity: 0;
  pointer-events: none;
}

.board.is-lifting::after { opacity: 0.9; }

.board.is-resting { filter: saturate(0.8); opacity: 0.75; }

.linen {
  position: absolute;
  top: 0;
  left: 0;
  border-radius: 999px;
  background: url("art/linen-row.png") center / 100% 100% no-repeat;
  transform-origin: center;
  /* A faint strip under the light, not a loom: the threads on it carry the eye. */
  opacity: 0.5;
  filter: saturate(0.5) brightness(1.18);
  pointer-events: none;
}

.slot {
  position: absolute;
  top: 0;
  left: 0;
  border: 1.5px dashed color-mix(in srgb, var(--ak-ink-muted) 40%, transparent);
  border-radius: 999px;
  pointer-events: none;
}

.slot.is-next {
  border-color: var(--ak-accent);
  background: color-mix(in srgb, var(--ak-accent) 14%, transparent);
}

/* ---------- threads ---------- */

.thread {
  position: absolute;
  top: 0;
  left: 0;
  width: var(--L);
  height: var(--T);
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  transform-origin: center;
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
}

.thread.is-free { cursor: grab; }
.thread.is-dragging { cursor: grabbing; z-index: 20; }
.thread.is-held { z-index: 15; }
.thread:focus-visible { outline: 3px solid var(--ak-focus); outline-offset: 4px; border-radius: 999px; }

.body {
  position: absolute;
  inset: 0;
  isolation: isolate;
  filter: drop-shadow(0 0 1px color-mix(in srgb, var(--ak-ink) 85%, transparent)) drop-shadow(0 3px 4px color-mix(in srgb, var(--ak-ink) 22%, transparent));
}

.tint,
.sheen {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.tint {
  background: var(--shade);
  -webkit-mask: url("art/thread-strand.png") center / 100% 100% no-repeat;
  mask: url("art/thread-strand.png") center / 100% 100% no-repeat;
}

.sheen {
  mix-blend-mode: multiply;
  opacity: 0.7;
  pointer-events: none;
}

.band {
  position: absolute;
  left: 50.8%;
  top: 50%;
  width: 46%;
  height: 96%;
  translate: -50% -50%;
  overflow: visible;
  pointer-events: none;
}

.band .paper { fill: var(--ak-surface); stroke: color-mix(in srgb, var(--ak-ink-muted) 45%, transparent); stroke-width: 1.2; }
.band .stitch { stroke: var(--ak-ink); stroke-width: 3.6; stroke-linecap: round; }
/* A shade new to the player's book: a small brass bead, the same brass as the pins. */
.band .bead { fill: #C9A23F; stroke: #6E5520; stroke-width: 1.6; }

/* A pinned end: the painted end thread turned to lie the same way, tinted to its shade, and its
   own paper band and brass pin shown as painted. */
.turn {
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--T);
  height: var(--L);
  translate: -50% -50%;
  rotate: 90deg;
}

.is-pinned .tint {
  -webkit-mask-image: url("art/pinned-end.png");
  mask-image: url("art/pinned-end.png");
}

.is-pinned .sheen { filter: grayscale(1) brightness(1.45) contrast(0.9); }

.pinband {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  clip-path: inset(36% 0 37.5% 0);
  pointer-events: none;
}

.thread.is-glow .body {
  filter:
    drop-shadow(0 0 1px color-mix(in srgb, var(--ak-ink) 85%, transparent))
    drop-shadow(0 0 10px color-mix(in srgb, var(--ak-accent) 75%, transparent));
}

/* ---------- the guide: a ring, a stitched arrow ---------- */

.guide {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
  z-index: 12;
}

.guide .ring { fill: none; stroke: var(--ak-accent); stroke-width: 4; }
.guide .ring-soft { fill: none; stroke: color-mix(in srgb, var(--ak-accent) 35%, transparent); stroke-width: 12; }
.guide .arrow { fill: none; stroke: var(--ak-accent); stroke-width: 4; stroke-linecap: round; stroke-dasharray: 10 9; }
.guide .head { fill: var(--ak-accent); }

/* ---------- the finale: every card laid out under the house lights ---------- */

.finale {
  position: absolute;
  inset: 8%;
  display: flex;
  flex-wrap: wrap;
  align-content: center;
  justify-content: center;
  gap: clamp(10px, 3dvmin, 24px);
  pointer-events: none;
  z-index: 14;
}

.finale .card {
  width: clamp(64px, 18dvmin, 140px);
  height: auto;
  aspect-ratio: 333 / 384;
}

/* ---------- panel: one prompt, a hint and close ---------- */

.panel {
  grid-area: panel;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--gap);
}

.prompt {
  width: min(100%, 30ch);
  min-height: 2.9em;
  margin: 0;
  padding: 0 8px;
  color: var(--ak-ink);
  font-family: var(--ak-font-display);
  font-size: clamp(18px, 2.2dvh + 0.5dvw, 22px);
  font-weight: 500;
  line-height: 1.45;
  letter-spacing: 0.01em;
  text-align: center;
  text-transform: lowercase;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* The goal, quiet and always there: which way the row runs, and the stitch count. */
.goal {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  width: min(100%, 34ch);
  margin: 0;
  color: var(--ak-ink-muted);
  font-size: 18px;
  line-height: 1.35;
  text-align: left;
  text-transform: lowercase;
}

.goal-bar {
  flex: none;
  width: 44px;
  height: 12px;
  border-radius: 999px;
  background: linear-gradient(to right, #F4ECD4, #C4C99D, #97A572, #737A75, #435577, #2A2E62);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ak-ink) 30%, transparent);
}

.goal[data-mode="v"] .goal-bar {
  width: 12px;
  height: 40px;
  background: linear-gradient(to bottom, #F4ECD4, #C4C99D, #97A572, #737A75, #435577, #2A2E62);
}

.actions {
  display: flex;
  gap: var(--gap);
  justify-content: center;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  justify-content: center;
  min-width: 48px;
  min-height: 52px;
  padding: 0 24px;
  border: 0;
  border-radius: 999px;
  background: var(--ak-surface);
  color: var(--ak-ink);
  font-family: var(--ak-font-body);
  font-size: 18px;
  font-weight: 400;
  letter-spacing: 0.06em;
  text-transform: lowercase;
  cursor: pointer;
  touch-action: manipulation;
}

.pill.is-quiet {
  background: color-mix(in srgb, var(--ak-surface) 55%, transparent);
  color: var(--ak-ink-muted);
}

.pill svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; }
.pill:focus-visible { outline: 3px solid var(--ak-focus); outline-offset: 3px; }
.pill:active { background: var(--ak-choice-bg); }

@media (hover: hover) {
  .pill:hover { background: var(--ak-choice-bg); color: var(--ak-ink); }
}

.pill[hidden] { display: none; }

/* ---------- before play: one soft breathing circle, the title inside, the opening lines beneath ---------- */

.opening {
  position: fixed;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  /* Placed where start.js draws its own opening circle and lines, so one hands to the other
     without a second title showing through the fade. */
  gap: clamp(56px, 11vh, 92px);
  padding: clamp(40px, 8vh, 75px) 24px 24px;
  pointer-events: none;
}

.opening-circle {
  display: grid;
  place-items: center;
  width: min(80vw, 52vh, 370px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(closest-side, var(--light) 0%, var(--light) 78%, color-mix(in srgb, var(--light) 40%, transparent) 92%, transparent 100%);
}

.opening-circle img { width: min(54%, 169px); height: auto; }

.opening-lines {
  color: var(--ak-ink-muted);
  font-family: var(--ak-font-display);
  max-width: 288px;
  font-size: clamp(20px, 3.6vw, 30px);
  line-height: 1.35;
  text-align: center;
  text-transform: lowercase;
}

.opening-lines p { margin: 0 0 0.5em; }

.is-playing .opening { display: none; }
:root:not(.is-playing) .play { visibility: hidden; }

/* At the very end the words step aside: the cards under the rising light are the reason. */
.is-finale .panel { visibility: hidden; }

/* ---------- under an ending: the board steps away, so the circle stands alone ---------- */

.is-ending .play { opacity: 0; visibility: hidden; }

/* The ending's two choices on the pale page: the way back filled, the other plainly outlined. */
html body #activity-chrome-ending.site-insighfulness .ac-actions .ac-replay {
  background: var(--ak-btn-fill);
  color: var(--ak-btn-ink);
}

html body #activity-chrome-ending.site-insighfulness .ac-actions .ac-change {
  background: var(--ak-surface);
  color: var(--ak-ink);
  box-shadow: inset 0 0 0 1.5px var(--ak-choice-border);
}

html body #activity-chrome-ending.site-insighfulness .ac-work { max-width: 70%; }

/* The kind line about the player's shades is read, so it keeps the site's 18px floor. */
html body #activity-chrome-ending.site-insighfulness .ac-lines { font-size: 18px; line-height: 1.45; }

/* A phone on its side: a smaller circle, so it and its choices fit with no scrolling. */
@media (orientation: landscape) and (max-height: 520px) {
  /* A phone on its side: the circle as tall as the screen allows, its two choices beside it. */
  html body #activity-chrome-ending.site-insighfulness { padding: 12px 220px 12px 24px; }
  html body #activity-chrome-ending.site-insighfulness .ac-card { --ac-circle: min(84vmin, 420px); gap: 8px; }
  html body #activity-chrome-ending.site-insighfulness .ac-actions {
    top: 50%;
    left: calc(100% + 24px);
    flex-direction: column;
    align-items: stretch;
    translate: 0 -50%;
  }
}

/* ---------- sideways: the board on the left, everything else on the right ---------- */

@media (orientation: landscape) {
  /* The title sits in the free corner beside the status bar, above the board; the shelf of cards
     tops the side column; the board stretches across the rest of the width. */
  .play {
    grid-template-areas: "board shelf" "board panel";
    grid-template-columns: minmax(0, 1fr) min(30dvw, 300px);
    grid-template-rows: auto minmax(0, 1fr);
    gap: 10px 16px;
    width: min(100%, 1280px);
    padding-top: calc(var(--ac-status-h, 60px) + 4px);
  }

  .top { display: contents; }

  .logo {
    position: fixed;
    top: max(8px, env(safe-area-inset-top));
    left: max(12px, env(safe-area-inset-left));
    z-index: 2;
    /* Never taller than the status bar's row, so it never reaches the board below. */
    height: min(48px, calc(var(--ac-status-h, 60px) - 12px));
    max-width: 22dvw;
  }

  .shelf { grid-area: shelf; justify-content: center; }

  .panel { justify-content: center; gap: clamp(10px, 3dvh, 24px); }

  .actions { width: 100%; gap: 10px; }

  .actions .pill { flex: 1 1 0; padding: 0 12px; }

  .prompt { width: 100%; min-height: 0; font-size: clamp(18px, 1.5dvw + 1dvh, 23px); }

  .goal { width: 100%; }
}

/* ---------- motion: slow light, slow cloth ---------- */

@media (prefers-reduced-motion: no-preference) {
  :root:not(.ac-still) .stage::before,
  :root:not(.ac-still) .stage::after { transition: opacity 3200ms var(--ease); }

  :root:not(.ac-still) .board { transition: filter var(--slower) var(--ease), opacity var(--slower) var(--ease); }
  :root:not(.ac-still) .board::after { transition: opacity 900ms var(--ease); }
  :root:not(.ac-still) .play { transition: opacity 900ms var(--ease), visibility 0s linear 900ms; }
  :root:not(.ac-still):not(.is-ending) .play { transition: opacity 900ms var(--ease); }
  :root:not(.ac-still) .board::before { animation: pool 9000ms ease-in-out infinite alternate; }
  :root:not(.ac-still) .opening-circle { animation: pool 8000ms ease-in-out infinite alternate; }
  :root:not(.ac-still) .opening-lines p { animation: fadein 1800ms var(--ease) both; }
  :root:not(.ac-still) .opening-lines p:nth-child(2) { animation-delay: 900ms; }
  :root:not(.ac-still) .opening-lines p:nth-child(3) { animation-delay: 1800ms; }

  :root:not(.ac-still) .thread { transition: transform var(--slow) var(--ease), opacity var(--slower) var(--ease); }
  :root:not(.ac-still) .thread.is-dragging { transition: opacity var(--slower) var(--ease); }
  :root:not(.ac-still) .no-anim .thread { transition: none; }

  :root:not(.ac-still) .body { transition: transform var(--slow) var(--ease-settle), filter 900ms var(--ease); }
  :root:not(.ac-still) .is-lifted .body { transform: scale(1.08); }
  :root:not(.ac-still) .is-lifted .body { animation: sway 2400ms ease-in-out infinite alternate; }
  :root:not(.ac-still) .is-laid .body { animation: lay 900ms var(--ease-settle); }

  :root:not(.ac-still) .tangle-breath .thread.is-free:not(.is-lifted) .body { animation: drift 5200ms ease-in-out infinite alternate; animation-delay: calc(var(--i, 0) * -700ms); }

  :root:not(.ac-still) .slot { transition: opacity var(--slow) var(--ease), border-color 900ms var(--ease), background-color 900ms var(--ease); }
  :root:not(.ac-still) .slot.is-next { animation: glow 2400ms ease-in-out infinite alternate; }

  :root:not(.ac-still) .guide .ring,
  :root:not(.ac-still) .guide .ring-soft { animation: pulse 2000ms ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
  :root:not(.ac-still) .guide .arrow { animation: stitch 1800ms linear infinite; }

  :root:not(.ac-still) .is-breathing { animation: breathe 1800ms ease-in-out; }
  :root:not(.ac-still) .is-glowing .band .stitch { animation: stitchglow 1600ms ease-in-out both; animation-delay: calc(var(--i, 0) * 180ms); }

  :root:not(.ac-still) .thread.is-winding { transition: transform 1400ms var(--ease), opacity 1400ms var(--ease); }
  :root:not(.ac-still) .flying { transition: transform 1600ms var(--ease), opacity 900ms var(--ease); }

  :root:not(.ac-still) .prompt.is-new { animation: fadein 900ms var(--ease); }
  :root:not(.ac-still) .pill { transition: background-color 600ms var(--ease), color 600ms var(--ease), transform 600ms var(--ease-settle); }
  :root:not(.ac-still) .pill:active { transform: scale(0.96); }

  :root:not(.ac-still) .finale .card { animation: rise 1600ms var(--ease) both; animation-delay: calc(var(--i, 0) * 160ms); }
  :root:not(.ac-still) .shelf .card { animation: fadein 1200ms var(--ease) both; }
  :root:not(.ac-still) .board.is-entering .thread { animation: fadein 1400ms var(--ease) both; animation-delay: calc(var(--i, 0) * 90ms); }
}

/* With less motion, nothing slides: a moved thread fades out and in at its new place. */
.is-refade { animation: refade 700ms ease both; }
.board.is-entering .thread { animation: fadein 1200ms ease both; }

@keyframes pool {
  from { transform: scale(0.985); opacity: 0.92; }
  to { transform: scale(1.02); opacity: 1; }
}

@keyframes sway {
  from { transform: scale(1.08) rotate(-2deg); }
  to { transform: scale(1.08) rotate(2deg); }
}

@keyframes lay {
  0% { transform: scale(1.08); }
  55% { transform: scale(1.04, 0.92); }
  100% { transform: scale(1); }
}

@keyframes drift {
  from { transform: translateY(-1.5px) rotate(-0.6deg); }
  to { transform: translateY(1.5px) rotate(0.6deg); }
}

@keyframes glow {
  from { background-color: color-mix(in srgb, var(--ak-accent) 8%, transparent); }
  to { background-color: color-mix(in srgb, var(--ak-accent) 24%, transparent); }
}

@keyframes pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.55; transform: scale(1.06); }
}

@keyframes stitch {
  to { stroke-dashoffset: -38; }
}

@keyframes breathe {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.025); }
}

@keyframes stitchglow {
  0%, 100% { stroke: var(--ak-ink); }
  45% { stroke: var(--ak-accent); stroke-width: 4.2; }
}

@keyframes fadein {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes refade {
  0% { opacity: 0.15; }
  100% { opacity: 1; }
}

@keyframes rise {
  from { opacity: 0; transform: translateY(18px); }
  to { opacity: 1; transform: translateY(0); }
}
