/* Taam — client.css: the client's path up to the last swipe (landing, invite, the deck).
   Builds on base.css (tokens, .card, .stamp, .btn, .dim …). The result screen has its own rules in report.css.

   CLASSES
   -------
   Landing   .landing  .landing__hero  .landing__resume  .landing__how  .how  .how__row  .landing__foot
             .pstack (the static three-card stack)  .pstack__card--1/--2/--3  .pstack__stamp
   Invite    .invite  .gkey (gesture key)  .gkey__row--right/--left/--up  .invite__cta (sticks to the bottom)
   Deck      .deck  .deck__top  .deck__undo  .prog (progress dimension line)  .deck__band
             .deck__stage  .deck__stack  .deck__sheet--2/--3 (blank sheets under the top card)
             .deck__card (moved by the finger)  > .deck__card-in (canned animations)  .deck__stamp--like/--dislike/--love
             .coach (first-card overlay)  .deck__msg (done / offline / catalog states)
             .deck__actions  .act  .act--like/--love/--dislike  .act__circle  .act__label  .act__key

   Gestures are PHYSICAL (ux.md 3.4): everything about the card, the stamps, the coach, the gesture key and
   the action bar uses left / right / translateX on purpose. Everything else is logical, like the rest of the app. */

/* ---------- landing (2.1) ---------- */

.landing { display: flex; flex-direction: column; gap: var(--s-6); }
.landing__resume { display: flex; flex-direction: column; gap: var(--s-3); align-items: flex-start; max-width: 560px; }
.landing__resume .row { width: 100%; }
.landing__text { display: flex; flex-direction: column; gap: var(--s-4); min-width: 0; }
.landing__text .t-label { color: var(--c-graphite); }
.landing__lead { max-width: 46ch; }
.landing__meta { color: var(--c-pencil); }
.landing__form { display: flex; flex-direction: column; gap: var(--s-4); margin-block-start: var(--s-2); max-width: 420px; }
.landing__visual { display: flex; justify-content: center; }
@media (min-width: 600px) {
  /* The stack comes first in the document (it leads on a phone) but sits in the end columns here. */
  .landing__hero > * { grid-row: 1; }
  .landing__hero { align-items: center; }
  .landing__form .btn { align-self: flex-start; min-width: 200px; }
}

/* Three cards, not interactive: the same faces as the deck, the top one caught mid-like. */
.pstack {
  position: relative;
  width: min(100%, 320px, calc((46vh - 76px) * 0.8));
  min-width: 150px;
  margin-block: var(--s-2) var(--s-5);
}
.pstack__card { transform-origin: 50% 100%; }
.pstack__card--1 { position: relative; transform: rotate(4deg); }
.pstack__card--2, .pstack__card--3 { position: absolute; inset: 0; }
.pstack__card--2 { transform: translateY(8px) scale(.96); }
.pstack__card--3 { transform: translateY(16px) scale(.92); }
.pstack__stamp { position: absolute; top: 16px; left: 16px; transform: rotate(-12deg); }
@media (max-width: 359.98px) { .pstack__stamp { font-size: 1.125rem; padding: 4px 10px; } }

.landing__how { display: flex; flex-direction: column; gap: var(--s-4); }
.how { display: grid; gap: var(--s-5); }
.how__row { display: flex; flex-direction: column; gap: var(--s-1); min-width: 0; }
.how__row .sec-head { margin-block-end: var(--s-1); }
.how__row p { color: var(--c-graphite); max-width: 46ch; }
@media (min-width: 1100px) { .how { grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: var(--s-6); } }

.landing__foot {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s-2) var(--s-4);
  padding-block-start: var(--s-4); border-block-start: 1px solid var(--c-rule);
  color: var(--c-pencil);
}
.landing__foot .link { min-height: 44px; display: inline-flex; align-items: center; font-size: 0.875rem; }

/* ---------- invite (2.2) ---------- */

.invite { display: flex; flex-direction: column; gap: var(--s-4); max-width: 560px; }
.invite__hello { color: var(--c-graphite); }
.invite__project { color: var(--c-graphite); }
.invite__tips { display: flex; flex-direction: column; gap: var(--s-2); color: var(--c-graphite); }
.invite__privacy { color: var(--c-pencil); }

/* The gesture key. Laid out physically: the right arrow sits at the right edge, the left arrow at the left. */
.gkey {
  --surface: var(--c-sheet);
  direction: ltr;
  display: grid; gap: 2px;
  padding: var(--s-2) var(--s-3);
  background: var(--c-sheet); border: 1px solid var(--c-rule); border-radius: var(--r-1);
}
/* The rows wrap, so at a large text size the stamp and the words stay inside the key (6.1). */
.gkey__row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-1) var(--s-3); min-height: 48px; }
.gkey__row + .gkey__row { border-top: 1px solid var(--c-rule); }
.gkey__row--right { justify-content: flex-end; }
.gkey__row--left { justify-content: flex-start; }
.gkey__row--up { justify-content: center; }
.gkey__text { direction: rtl; min-width: 0; font: 500 1rem/1.5rem var(--font-text); }
.gkey__row .icon { color: var(--c-ink); }
.gkey__row .stamp { flex: none; }
.gkey__row--right .stamp { transform: rotate(-4deg); }
.gkey__row--left .stamp { transform: rotate(4deg); }
.gkey__row--up .stamp { transform: rotate(-2deg); }
@media (max-width: 359.98px) { .gkey__text { font-size: 0.875rem; } .gkey__row { gap: var(--s-2); } }

/* The start button stays in reach when the page is taller than the screen; the board fades in behind it. */
.invite__cta {
  position: sticky; bottom: 0; z-index: 2;
  display: flex; flex-direction: column; align-items: stretch; gap: var(--s-1);
  margin-inline: calc(-1 * var(--gutter)); padding: var(--s-5) var(--gutter) calc(var(--s-3) + env(safe-area-inset-bottom));
  background: linear-gradient(to top, var(--c-board) 0, var(--c-board) calc(100% - 28px), rgba(230, 233, 232, 0) 100%);
}
@media (min-width: 600px) {
  .invite__cta { align-items: flex-start; }
  .invite__cta .btn--primary { min-width: 240px; }
}

/* ---------- the deck (2.3, section 3) ---------- */

.deck {
  flex: 1 1 auto; min-height: 0; height: 100%;
  display: flex; flex-direction: column;
  overflow: hidden; overscroll-behavior: none;
  /* Nothing on this screen scrolls: a drag that starts beside the card must not pan or refresh the page (iOS). */
  touch-action: none;
  -webkit-user-select: none; user-select: none;
}

/* Heights here are minimums: at a large text size (6.1) the bar grows with its text instead of cutting it. */
.deck__top {
  flex: none; min-height: var(--hdr-h);
  display: flex; align-items: center; gap: var(--s-2);
  padding-inline: 6px;
  margin-block-start: env(safe-area-inset-top);
}
.deck__undo {
  flex: none; display: inline-flex; align-items: center; gap: 6px;
  min-height: 44px; padding-inline: var(--s-2);
  border-radius: var(--r-2); color: var(--c-ink);
  font: 500 0.875rem/1.25rem var(--font-text); white-space: nowrap;
  transition: opacity var(--t-2) var(--ease-std);
}
@media (hover: hover) and (pointer: fine) { .deck__undo:hover:not(:disabled) { background: var(--c-vellum); } }
.deck__undo:disabled { opacity: .35; }
/* In rem, so a phone at a large text size gets the icon-only button too (360px at the default size). */
@media (max-width: 22.49rem) {
  .deck__undo { width: 44px; justify-content: center; padding: 0; }
  .deck__undo span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}

/* Progress (5.8.4): a dimension line that is being drawn. It fills in reading order, from the right. */
.prog { flex: 1 1 auto; min-width: 0; min-height: 34px; display: flex; flex-direction: column; gap: 4px; padding-inline: var(--s-1); }
.prog__line { position: relative; height: 12px; }
.prog__line::before {
  content: ""; position: absolute; inset-inline: 0; top: 50%; height: 1px; margin-top: -0.5px;
  background: var(--c-rule-strong);
}
.prog__end, .prog__q, .prog__fill::after { position: absolute; top: 50%; }
.prog__end { width: 1.5px; height: 9px; margin-top: -4.5px; background: var(--c-rule-strong); transform: rotate(45deg); }
.prog__end--s { inset-inline-start: 0; }
.prog__end--e { inset-inline-end: 0; }
.prog__q { width: 1px; height: 5px; margin-top: -2.5px; background: var(--c-rule-strong); }
.prog__fill {
  position: absolute; inset-inline-start: 0; top: 50%; height: 3px; margin-top: -1.5px;
  background: var(--c-ink);
  transition: width var(--t-3) var(--ease-out);
}
.prog__fill::after {
  content: ""; inset-inline-end: -1px; width: 1.5px; height: 9px; margin-top: -4.5px;
  background: var(--c-ink); transform: rotate(45deg);
}
.prog__phase {
  min-height: 1.125rem; color: var(--c-pencil);
  font: 400 0.8125rem/1.125rem var(--font-label); letter-spacing: 0.02em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  animation: fade-in var(--t-2) var(--ease-std) both;
}

/* In-person session: whose turn it is. */
.deck__band { flex: none; min-height: 28px; padding-block: 3px; font-size: 0.8125rem; line-height: 1.125rem; }

.deck__stage {
  flex: 1 1 auto; min-height: 0; position: relative;
  display: flex; align-items: center; justify-content: center;
  padding: 8px 16px;
}
/* --card-w is measured by the screen: min(100vw - 32px, 460px, (stage height - 64px) * 0.8). */
.deck__stack {
  position: relative; flex: none;
  width: var(--card-w, 280px);
  height: calc(var(--card-w, 280px) * 1.25 + 42px);      /* 4:5 photo + 40px label strip + the card's border */
}
.deck__sheet, .deck__card { position: absolute; inset: 0; transform-origin: 50% 100%; }

/* What lies under the top card is blank paper: the deck is adaptive, so the next photo is not known yet. */
.deck__sheet { z-index: 1; }
.deck__sheet--2 { transform: translate3d(0, 8px, 0) scale(.96); will-change: transform; }
.deck__sheet--3 { z-index: 0; transform: translate3d(0, 16px, 0) scale(.92); }
.deck__sheet--2.is-promote { animation: deck-sheet-up 220ms var(--ease-out) backwards; }
.deck__sheet--3.is-promote { animation: fade-in 140ms var(--ease-std) backwards; }
.deck__sheet--2.is-drop { animation: deck-sheet-drop 260ms var(--ease-out) backwards; }
@keyframes deck-sheet-up { from { transform: translate3d(0, 16px, 0) scale(.92); } }
@keyframes deck-sheet-drop { from { transform: translate3d(0, 0, 0) scale(1); } }

.deck__card {
  z-index: 2;
  touch-action: none; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
  will-change: transform; cursor: grab;
}
.deck__card:active { cursor: grabbing; }
.deck__card.is-out { z-index: 3; pointer-events: none; }
.deck__card-in { height: 100%; transform-origin: 50% 100%; }
.deck__card-in > .card { height: 100%; }
.deck__card .card__photo { aspect-ratio: auto; flex: 1 1 auto; min-height: 0; }
.deck__card img { pointer-events: none; }

/* A new top card grows out of the second position; --from-* continue where the drag left the sheet. */
.deck__card-in.is-promote { animation: deck-promote 220ms var(--ease-out) backwards; }
@keyframes deck-promote { from { transform: translate3d(0, var(--from-y, 8px), 0) scale(var(--from-s, .96)); } }
/* Undo: the card comes back from the side it left. */
.deck__card-in.is-undo-like { animation: deck-undo-like var(--t-4) var(--ease-out) backwards; }
.deck__card-in.is-undo-dislike { animation: deck-undo-dislike var(--t-4) var(--ease-out) backwards; }
.deck__card-in.is-undo-love { animation: deck-undo-love var(--t-4) var(--ease-out) backwards; }
@keyframes deck-undo-like { from { transform: translate3d(120vw, 0, 0) rotate(18deg); } }
@keyframes deck-undo-dislike { from { transform: translate3d(-120vw, 0, 0) rotate(-18deg); } }
@keyframes deck-undo-love { from { transform: translate3d(0, -110vh, 0); } }
/* Idle hint on the first card: one rock to the right, one to the left. */
.deck__card-in.is-rock { animation: deck-rock 900ms var(--ease-std); }
@keyframes deck-rock {
  0%, 100% { transform: none; }
  28% { transform: translate3d(14px, 0, 0) rotate(2deg); }
  68% { transform: translate3d(-14px, 0, 0) rotate(-2deg); }
}

/* Stamps (3.5). Opacity and scale are driven by the drag, straight on the element. */
.deck__stamp { position: absolute; z-index: 2; opacity: 0; }
.deck__stamp--like { top: 20px; left: 20px; transform: rotate(-12deg) scale(.9); }
.deck__stamp--dislike { top: 20px; right: 20px; transform: rotate(12deg) scale(.9); }
.deck__stamp--love { bottom: 64px; left: 50%; transform: translateX(-50%) rotate(-4deg) scale(.9); }

.deck__loading {
  position: absolute; inset: 0; z-index: 1;
  display: flex; align-items: center; justify-content: center;
  color: var(--c-pencil); font: 400 0.8125rem/1.125rem var(--font-label); letter-spacing: 0.02em;
}

/* Coach overlay (3.12). It never takes the pointer: a drag that starts on it goes straight to the card. */
.coach {
  position: absolute; inset: 0; z-index: 3;
  direction: ltr; pointer-events: none;
  background: var(--c-scrim-text); color: var(--c-sheet);
  font: 600 0.9375rem/1.25rem var(--font-text);
  animation: fade-in var(--t-2) var(--ease-std) both;
}
.coach__dir { position: absolute; display: flex; flex-direction: column; gap: 6px; max-width: 46%; }
.coach__dir span, .coach__foot { direction: rtl; }
.coach__dir--up { top: 16px; left: 0; right: 0; max-width: none; align-items: center; text-align: center; }
.coach__dir--right { right: 14px; top: 40%; align-items: flex-end; text-align: right; }
.coach__dir--left { left: 14px; top: 40%; align-items: flex-start; text-align: left; }
.coach__foot {
  position: absolute; left: 0; right: 0; bottom: 16px; padding-inline: var(--s-4);
  display: flex; flex-direction: column; align-items: center; gap: var(--s-3); text-align: center;
  font-weight: 400;
}
.coach__cta { pointer-events: auto; min-width: 120px; }
.coach__cta:focus-visible { outline-color: var(--c-trace); }

/* Done, offline and catalog-error states take the place of the stack. */
.deck__msg {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: min(380px, calc(100% - 48px));
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--s-3);
}
.deck__msg p { color: var(--c-graphite); }
.deck__msg .dim { align-self: stretch; --draw-ms: 700ms; }
.deck__msg .btn { margin-block-start: var(--s-2); }

/* Action bar (3.4, 5.8.3). An LTR grid with explicit columns: dislike left, love centre, like right,
   while the DOM order stays like, love, dislike so focus moves in reading order. */
.deck__actions {
  flex: none; min-height: calc(124px + env(safe-area-inset-bottom)); padding: 10px 0 env(safe-area-inset-bottom);
  direction: ltr;
  display: grid; grid-template-columns: repeat(3, 72px); column-gap: 20px;      /* 28px between the 64px circles */
  justify-content: center; align-items: start;
}
.act {
  direction: rtl; grid-row: 1;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  min-height: 88px; padding: 0; border-radius: var(--r-2);
  color: var(--c-graphite);
  transition: opacity var(--t-2) var(--ease-std);
}
.act--dislike { grid-column: 1; }
.act--love { grid-column: 2; padding-top: 4px; }
.act--like { grid-column: 3; }
.act__circle {
  width: 64px; height: 64px; flex: none; border-radius: var(--r-round);
  display: inline-flex; align-items: center; justify-content: center;
  transition: transform var(--t-1) var(--ease-std), box-shadow var(--t-1) var(--ease-std);
}
.act--dislike .act__circle { background: var(--c-sheet); border: 1.5px solid var(--c-graphite); color: var(--c-graphite); }
.act--dislike .icon { width: 26px; height: 26px; }
.act--love .act__circle { width: 56px; height: 56px; background: var(--c-trace); border: 1.5px solid var(--c-ink); color: var(--c-ink); }
.act--love .icon { width: 24px; height: 24px; }
.act--like .act__circle { background: var(--c-blue); color: var(--c-sheet); }
.act--like .icon { width: 28px; height: 28px; }
/* The label wraps inside its 72px column rather than run into its neighbours at a large text size. */
.act__label {
  display: inline-flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 2px 6px;
  max-width: 100%; text-align: center;
  font: 400 0.8125rem/1.125rem var(--font-label); letter-spacing: 0.02em;
}
.act__key {
  display: inline-flex; align-items: center; gap: 2px; padding: 0 4px; min-height: 18px;
  border: 1px solid var(--c-rule-strong); border-radius: var(--r-1); color: var(--c-pencil);
  font-size: 0.75rem;
}
.act__key .icon { width: 12px; height: 12px; }
/* Desk: the keycap goes under the label, so three labels still fit under circles 28px apart. */
@media (min-width: 1100px) { .act__label { flex-direction: column; gap: 3px; } .act { gap: 4px; } }
@media (hover: hover) and (pointer: fine) { .act:hover:not(:disabled) .act__circle { transform: translateY(-1px); } }
.act:active:not(:disabled) .act__circle { transform: scale(.94); }
.act:disabled { opacity: .4; }
.act:focus-visible { outline: none; }
.act:focus-visible .act__circle { outline: 2px solid var(--c-blue); outline-offset: 3px; }
.act--like:focus-visible .act__circle { outline-color: var(--c-ink); }

/* While a card is dragged (3.6): the button of that direction is armed past the threshold, the others step back. */
.deck__actions[data-dir="like"] .act:not(.act--like),
.deck__actions[data-dir="love"] .act:not(.act--love),
.deck__actions[data-dir="dislike"] .act:not(.act--dislike) { opacity: .5; }
.deck__actions[data-armed="like"] .act--like .act__circle { transform: scale(1.08); box-shadow: 0 0 0 3px var(--c-blue-wash); }
.deck__actions[data-armed="love"] .act--love .act__circle { transform: scale(1.08); box-shadow: 0 0 0 3px var(--c-trace-wash); }
.deck__actions[data-armed="dislike"] .act--dislike .act__circle { transform: scale(1.08); box-shadow: 0 0 0 3px var(--c-rule); }

@media (max-width: 359.98px) {
  .deck__actions { grid-template-columns: repeat(3, 64px); column-gap: 12px; }      /* 20px between the circles */
  .act__circle { width: 56px; height: 56px; }
  .act--love .act__circle { width: 48px; height: 48px; }
}
/* Landscape phone: smaller circles, labels kept for screen readers only; the zones stay as they are. */
@media (max-height: 480px) {
  .act__circle, .act--love .act__circle { width: 48px; height: 48px; }
  .act--love { padding-top: 0; }
  .act { min-height: 48px; }
  .act__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .deck__actions { align-items: center; }
}

/* Reduced motion (3.3): nothing flies or springs; a leaving card fades while the next one fades in. */
@media (prefers-reduced-motion: reduce) {
  .deck .deck__card-in.is-promote,
  .deck .deck__card-in[class*="is-undo-"] { animation-name: fade-in; animation-duration: 120ms !important; }
  .deck .deck__sheet.is-promote, .deck .deck__sheet.is-drop, .deck .deck__card-in.is-rock { animation: none; }
}
