/* 七巧板 — the tangram at /tangram/.
   The sheet is one square of paper with a figure printed on it in ink and the
   seven cut pieces waiting below. A placed piece is the same paper as the
   others, so a finished figure reads as one sheet with cut lines through it
   rather than as seven coloured tiles. Colour does no work here that geometry
   can do: ink, paper and one cinnabar seal. */

.tangram-page {
  /* the toy follows the system theme; declare it so the shared chrome does too */
  color-scheme: light dark;
  min-height: 100vh;
  background-color: var(--paper);
  background-image:
    repeating-linear-gradient(0deg, transparent 0 5px, color-mix(in srgb, var(--ink) 1.2%, transparent) 5px 6px),
    repeating-linear-gradient(90deg, transparent 0 104px, color-mix(in srgb, var(--ink) 1.8%, transparent) 104px 105px);
}

.tg-shell {
  display: grid;
  gap: clamp(var(--space-5), 4vw, var(--space-7));
  width: var(--qb-content-width);
  margin-inline: auto;
  /* The shared back control is fixed at the top left of every child route, so
     the first line of the page starts below it at every width rather than
     under it on the widths where the gutter happens to be narrow. */
  padding-block: var(--qb-chrome-clear-block) clamp(var(--space-7), 9vw, var(--space-8));
}

.tg-head { max-width: 34rem; }

.tg-head h1 {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-3);
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 5vw, 3.6rem);
  font-weight: 630;
  line-height: 1;
  letter-spacing: -.04em;
}

.tg-head h1 span {
  font-family: var(--font-cjk);
  font-weight: 700;
  letter-spacing: .1em;
}

.tg-head h1 small {
  font-size: clamp(.95rem, 1.6vw, 1.15rem);
  font-weight: 500;
  letter-spacing: -.01em;
  color: var(--ink-mute);
}

.tg-lede {
  margin: var(--space-4) 0 0;
  max-width: 30rem;
  font-size: clamp(1rem, 1.5vw, 1.15rem);
  line-height: 1.6;
  color: var(--ink-soft);
}

.tg-play {
  display: grid;
  gap: var(--space-4);
  justify-items: start;
  max-width: 36rem;
}

.tg-figure {
  margin: 0;
  font-family: var(--font-mono);
  font-size: .82rem;
  letter-spacing: .08em;
  text-transform: lowercase;
  color: var(--ink-mute);
}

.tg-figure b {
  margin-right: var(--space-2);
  color: var(--ink);
  font-weight: 700;
}

/* — the sheet — */
.tg-board {
  display: block;
  width: 100%;
  height: auto;
  background: var(--paper-raised);
  border: var(--line-thin) solid var(--line-dark);
  border-radius: 3px;
  box-shadow: 0 18px 40px rgba(34, 42, 34, .14), 0 2px 6px rgba(34, 42, 34, .1);
}

.tg-rule {
  stroke: var(--line-dark);
  stroke-width: .04;
  stroke-dasharray: .3 .34;
}

.tg-outline { fill: var(--ink); }

.tg-ghost {
  fill: none;
  stroke: var(--celadon);
  stroke-width: .1;
  stroke-dasharray: .34 .28;
  stroke-linejoin: round;
  visibility: hidden;
}

.is-showing .tg-ghost { visibility: visible; }

/* Only the pieces swallow touch gestures: `touch-action: none` on the whole
   board would stop a phone reader scrolling past a sheet that fills the
   screen. */
.tg-piece { cursor: grab; outline: none; touch-action: none; }
.tg-piece.is-held { cursor: grabbing; }

.tg-piece__face {
  /* One step off the sheet, so a piece reads as cut paper lying on paper in
     the tray and still lightens the figure when it lands on the ink. */
  fill: var(--paper-deep);
  stroke: var(--ink);
  stroke-width: .07;
  stroke-linejoin: round;
  pointer-events: none;
}

/* The hit shape is the piece grown by a transparent stroke: a small triangle
   is 36px wide on a phone, and a bare fill would be a 36px target with a
   17px waist. `pointer-events: all` counts the stroke whatever its paint. */
.tg-piece__hit {
  fill: none;
  stroke: transparent;
  stroke-width: .8;
  stroke-linejoin: round;
  pointer-events: all;
}

.tg-piece:focus-visible .tg-piece__face {
  stroke: var(--cinnabar);
  stroke-width: .22;
}

.tg-piece.is-held .tg-piece__face {
  stroke-width: .14;
  filter: drop-shadow(0 .18px .3px rgba(34, 42, 34, .45));
}

/* — the seal — */
.tg-seal { visibility: hidden; }
.tg-seal.is-stamped { visibility: visible; }
.tg-seal__frame { fill: none; stroke: var(--cinnabar); stroke-width: .26; }
.tg-seal__mark { fill: var(--cinnabar); }

/* — controls — */
.tg-controls {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.tg-button {
  min-height: 44px;
  padding: 0 var(--space-3);
  background: var(--paper-raised);
  color: var(--ink);
  border: var(--line-thin) solid var(--line-dark);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: .82rem;
  letter-spacing: .06em;
  text-transform: lowercase;
  cursor: pointer;
}

.tg-button:hover { border-color: var(--ink-mute); }
.tg-button[aria-pressed="true"] { background: var(--ink); color: var(--paper); border-color: var(--ink); }

.tg-status {
  margin: 0;
  min-height: 2.6em;
  max-width: 32rem;
  font-size: .92rem;
  line-height: 1.4;
  color: var(--ink-soft);
}

.tg-keys {
  margin: 0;
  max-width: 32rem;
  font-size: .85rem;
  line-height: 1.5;
  color: var(--ink-mute);
}

.tg-keys b {
  font-family: var(--font-mono);
  font-weight: 700;
  color: var(--ink-soft);
}

/* The docked listener parks over the bottom-right corner at this width
   (`business-chrome.css`, `max-width: 44rem`), and the control row is what sits
   there on a phone. It gives back the same inches plate.css does. */
@media (max-width: 44rem) {
  .tg-controls { padding-right: max(0px, calc(5.33rem - var(--qb-page-gutter))); }
}

@media (min-width: 64rem) {
  .tg-shell {
    grid-template-columns: minmax(18rem, 24rem) minmax(0, 34rem);
    align-items: start;
    justify-content: center;
    column-gap: clamp(var(--space-7), 6vw, var(--space-8));
  }

  .tg-head { padding-top: var(--space-5); }
}

@media (prefers-color-scheme: dark) {
  .tangram-page {
    --paper: #17201a;
    --paper-raised: #222a22;
    --paper-deep: #111712;
    --ink: #e8ede4;
    --ink-soft: #cdd7ce;
    --ink-mute: #b8c4ba;
    --line: #36433a;
    --line-dark: #536357;
    --cinnabar: #e25c50;
    --cinnabar-deep: #ee6a58;
    --celadon: #a9bfad;
    --celadon-deep: #a9bfad;
  }

  .tg-board {
    box-shadow: 0 18px 40px rgba(0, 0, 0, .38), 0 2px 6px rgba(0, 0, 0, .26);
  }

  .tg-piece.is-held .tg-piece__face { filter: drop-shadow(0 .18px .3px rgba(0, 0, 0, .6)); }
}

/* Motion is the settling and the arrival, never the rule: a snapped piece
   still snaps under reduced motion, it simply arrives without the travel. */
@media (prefers-reduced-motion: no-preference) {
  .tg-piece.is-settling { transition: transform 200ms var(--ease-out); }

  .tg-outline.is-arriving { animation: tg-arrive 540ms var(--ease-out) both; }

  .tg-seal.is-stamped .tg-seal__ink { animation: tg-stamp 420ms var(--ease-out) both; }

  @keyframes tg-arrive {
    from { opacity: 0; transform: translateX(-1.4px); }
    to { opacity: 1; transform: translateX(0); }
  }

  @keyframes tg-stamp {
    from { opacity: 0; transform: scale(1.3) rotate(-4deg); }
    60% { opacity: 1; }
    to { opacity: 1; transform: scale(1) rotate(0); }
  }
}

.tg-seal__ink { transform-box: fill-box; transform-origin: center; }
