/* Sign-off: a sheet sent for approval, by link or by the code the app prints on it, and the answer
   coming back to the drawing. The words at top left; under them A-100 as printed paper at left and
   the app's two islands in a column beside it, the share card and the request. js/approval.js
   sizes the paper and the column to the room the words leave, moves the view on the paper and
   plays the presses. Nothing here paints a ground. */
.approval {
  /* The app's night inks for a thread the client is in (src/ui/styles/tokens.css, dark: --warning
     and --warning-text), the ones #talk tags "Client can see this" in, so the word reads as the
     same person across the two scenes. */
  --warn: #f97316; --warn-text: #fcd34d;
}
.approval-layout { position: absolute; inset: 0; display: flex; flex-direction: column; padding: clamp(40px, 7.5vh, 84px) 0 clamp(18px, 4vh, 40px); }
.approval-head { flex: none; }
.approval-head .say { margin-top: clamp(10px, 2vh, 20px); }
/* The table the paper and the islands stand on: no surface of its own, only the room left under the
   words, which the script lays the two out in. The islands stand on the paper's foot, beside the
   corner of the sheet the code is printed in, which is where the view goes. */
.approval-art { position: relative; flex: 1; min-height: 0; margin-top: clamp(18px, 3.4vh, 36px); display: flex; align-items: flex-end; gap: var(--gap, 40px); }
/* Right to left the words stand at the top right, so the paper stands under them there and the
   islands on its left; each still reads left to right, as the app shows it (css/lang.css). */
@media (min-width: 761px) {
  [dir="rtl"] .approval-art:not(.upright) { flex-direction: row-reverse; }
}

/* ── the sheet: paper on the dark ground, rounded like every object on the page, with the soft
   neutral shadow paper throws and nothing lighting it (the same paper as #sheets) ── */
.ap-sheet {
  position: relative; flex: none; width: var(--sw, 0px); height: var(--sh, 0px); border-radius: 14px; overflow: hidden;
  background: var(--paper);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.45), 0 18px 40px -14px rgba(0, 0, 0, 0.7);
  opacity: 0; transform: translateY(34px) scale(0.975); transform-origin: 50% 100%;
  transition: opacity 0.8s var(--ease), transform 1.1s var(--ease);
}
.ap-sheet.in { opacity: 1; transform: none; }
.ap-sheet svg { display: block; width: 100%; height: 100%; }
/* The ring round the code, drawn on by its dash in the sheet's own ink and weight, in millimetres,
   since a non-scaling stroke would measure the dash in screen pixels (as in #sheets). */
/* The browser's measure of a rounded rectangle runs a little over its stated length, so a dash of
   exactly the ring left a sliver open where the ring closes; the dash is a twentieth longer than the
   ring, and the gap after it twice the ring, so no sliver of the next dash shows either. */
.ap-ring { fill: none; stroke: #101826; stroke-width: 0.3; stroke-dasharray: 1.05 2; stroke-dashoffset: 1.05; transition: stroke-dashoffset 0.8s var(--ease); }
.ap-ring.on { stroke-dashoffset: 0; }

/* ── the islands: a stack beside the paper that grows up from its foot. The share card rises first
   and stays on the foot line, level with the code it goes with; the toast and then the request
   take turns in the slot over it, each standing on the card, so whatever is showing ends on the
   paper's foot and nothing floats over a gap kept for what comes later. When the client's answer
   folds away the request closes down onto the card. ── */
.ap-side { flex: none; width: var(--cw, 400px); display: flex; flex-direction: column-reverse; gap: 12px; --tint-text: color-mix(in oklab, var(--tint) 58%, #fff); }
.ap-slot { display: grid; min-height: var(--slot, 0px); }
.ap-slot > * { grid-area: 1 / 1; align-self: end; }
.ap-side .island { position: relative; opacity: 0; transform: translateY(22px) scale(0.98); transition: opacity 0.6s var(--ease), transform 0.8s var(--ease); }
.ap-side .island.on { opacity: 1; transform: none; }
.ap-ico { flex: none; fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; }
.ap-ico path { stroke-width: 1.2px; vector-effect: non-scaling-stroke; }

/* A button as the app draws one small: a quiet outline, or the ink one for the thing you came to do
   (black on paper, paper on black, the app's .btn-ink). Pressed, it goes down with a ring round
   it, the way the check's Fix goes down in #sheets. */
.ap-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; flex: none; height: 30px; padding: 0 12px;
  border-radius: 9px; font: 500 13px/1 var(--sans); color: var(--snow); white-space: nowrap;
  box-shadow: inset 0 0 0 1px var(--hair-2);
  transition: transform 0.22s var(--ease), box-shadow 0.22s, background 0.2s, color 0.2s;
}
.ap-btn.ink { background: var(--snow); color: var(--ground); box-shadow: none; }
.ap-btn.down { transform: scale(0.95); background: #2a2c30; box-shadow: 0 0 0 3px #1d1e21, 0 0 0 4.5px var(--snow); }
.ap-btn.ink.down { background: #c3c6cc; }

/* The share card: the app's menu body (src/ui/collab/CollabShare.tsx), its heading the words on the
   control that opens it. */
.ap-share { padding: 15px 16px 13px; border-radius: 16px; }
.ap-share-head { display: flex; align-items: center; gap: 9px; font: 600 14.5px/1.2 var(--sans); }
.ap-share-head .ap-ico { color: var(--snow-dim); }
.ap-link-row { display: flex; align-items: center; gap: 8px; margin-top: 12px; }
/* The address in the app's own face for it (collab.css .share-link: the interface's type, not a
   figure's), one line that ends in an ellipsis if the card is ever too narrow for it. A block, as
   an ellipsis is drawn only on a block's own line: as a flex box the text was clipped mid-word. */
.ap-link {
  flex: 1; min-width: 0; display: block; height: 30px; padding: 0 10px; border-radius: 8px;
  background: rgba(255, 255, 255, 0.05); font: 400 12.5px/30px var(--sans); color: var(--snow-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ap-copy .ap-ico { color: var(--snow-dim); }
.ap-copy span { min-width: 3.9em; text-align: left; }
.ap-fold { display: flex; align-items: center; gap: 6px; margin-top: 11px; font: 400 12.5px/1.2 var(--sans); color: var(--snow-faint); }
.ap-fold .ico { width: 12px; height: 12px; }

/* The app's echo after a copy: its sentence, on a small island of its own, out of the card. */
.ap-toast { padding: 11px 14px; border-radius: 13px; font: 400 13.5px/1.4 var(--sans); color: var(--snow-dim); text-wrap: balance; }
.ap-side .ap-toast { transform: translateY(8px); transition: opacity 0.4s var(--ease), transform 0.5s var(--ease); }

/* The request, as a row of the app's Requests list (src/ui/collab/CollabRequests.tsx): its mark,
   the title, the kind as a tag and the day, and whose court it is in; under it, the client's own
   answer, which the app offers only to the person the request waits on. */
.ap-request { border-radius: 16px; overflow: hidden; }
.ap-row { display: grid; grid-template-columns: auto 1fr; column-gap: 13px; padding: 15px 16px 14px; }
.ap-mark { display: grid; place-items: center; width: 32px; height: 32px; border-radius: 10px; background: rgba(255, 255, 255, 0.06); color: var(--snow-dim); }
.ap-body { min-width: 0; }
.ap-title { display: block; font: 600 15px/1.35 var(--sans); letter-spacing: -0.01em; color: var(--snow); transition: color 0.6s var(--ease); }
.ap-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; margin-top: 5px; font: 400 12.5px/1.2 var(--sans); color: var(--snow-faint); }
.ap-meta .fig { color: var(--snow-dim); }
/* A tag in the app's style for one (its .thread-tag): small capitals on a quiet chip. */
.ap-tag { display: inline-flex; align-items: center; padding: 3px 7px; border-radius: 6px; background: rgba(255, 255, 255, 0.07); color: var(--snow-dim); font: 600 10.5px/1 var(--sans); letter-spacing: 0.03em; text-transform: uppercase; font-style: normal; }
.ap-tag.client { color: var(--warn-text); background: color-mix(in srgb, var(--warn) 16%, transparent); }
/* Whose court it is in: the client's face, as the app's row sets it beside the line (CollabFace:
   the initials on the person's colour, lettered at 0.38 of the face in the app's white), and once
   he has answered, the line in his colour lifted until it reads as words on the dark island (his
   own amber is 3.5:1 there, under the 4.5 small type needs). */
.ap-state { display: flex; align-items: center; gap: 8px; margin-top: 10px; min-height: 24px; font: 500 13px/1.2 var(--sans); color: var(--snow); }
.ap-face { flex: none; display: inline-grid; place-items: center; width: 24px; height: 24px; border-radius: 50%; background: var(--tint); color: #fff; font: 600 9.1px/1 var(--sans); letter-spacing: 0.02em; }
.ap-state-words { transition: color 0.4s; }
.ap-reopen { margin-left: auto; height: 24px; padding: 0 9px; font-size: 12px; border-radius: 7px; opacity: 0; transition: opacity 0.4s 0.25s; }
.ap-request.done .ap-title { font-weight: 500; color: var(--snow-dim); }
.ap-request.done .ap-state-words { color: var(--tint-text); }
.ap-request.done .ap-reopen { opacity: 1; }

/* The client's answer folds shut once it is given, as a settled row leaves the app's list. */
.ap-answer { display: grid; grid-template-rows: 1fr; transition: grid-template-rows 0.55s var(--ease-io) 0.2s, opacity 0.4s 0.2s; }
.ap-answer > div { min-height: 0; overflow: hidden; }
.ap-request.done .ap-answer { grid-template-rows: 0fr; opacity: 0; }
.ap-answer-in { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 12px; margin: 0 16px; padding: 12px 0 14px; border-top: 1px solid var(--hair); }
.ap-client { display: flex; align-items: center; gap: 8px; font: 500 13px/1.2 var(--sans); color: var(--snow-dim); }
.ap-choices { display: flex; gap: 6px; margin-left: auto; }

/* An upright window, a tablet held tall (js/approval.js sets .upright where it lays the paper
   larger): the paper at the full width under the words, and the two islands side by side under
   it, the card and the request, top-aligned in a row whose height the script keeps. */
.approval-art.upright { flex-direction: column; align-items: flex-start; justify-content: flex-start; gap: 12px; }
.approval-art.upright .ap-side { flex-direction: row; align-items: flex-start; gap: 12px; }
.approval-art.upright .ap-side > * { flex: 1 1 0; min-width: 0; }
.approval-art.upright .ap-slot > * { align-self: start; }
.approval-art.upright .ap-request { min-height: var(--card, 0px); }
.approval-art.upright .ap-side .ap-toast { transform: translateY(-8px); }
.approval-art.upright .ap-side .island.on { transform: none; }

/* A short window: the words stay, a size down, and the islands close up. */
@media (max-height: 640px) and (min-width: 761px) {
  .approval-layout { padding-top: clamp(24px, 6vh, 40px); }
  .ap-share { padding: 11px 13px 10px; }
  .ap-link-row { margin-top: 9px; }
  .ap-fold { margin-top: 8px; }
  .ap-row { padding: 11px 13px 10px; column-gap: 11px; }
  .ap-mark { width: 28px; height: 28px; border-radius: 9px; }
  .ap-state { margin-top: 6px; }
  .ap-answer-in { margin: 0 13px; padding: 9px 0 11px; }
  .ap-side { gap: 9px; }
}
/* A phone: the words, the paper at the full width, and the islands under it, read in turn from the
   top, the card first and the request under it in a slot the script keeps its full height. */
@media (max-width: 760px) {
  .approval-layout { padding-top: clamp(56px, 9vh, 76px); }
  .approval-head .say { font-size: 19px; }
  .approval-art { flex-direction: column; align-items: stretch; justify-content: flex-start; gap: 12px; margin-top: 18px; }
  .ap-side { width: 100%; gap: 9px; flex-direction: column; }
  .ap-slot > * { align-self: start; }
  .ap-side .ap-toast { transform: translateY(-8px); }
  .ap-fold { display: none; }
  .ap-share { padding: 12px 13px 12px; }
  .ap-link-row { margin-top: 10px; }
  .ap-row { padding: 12px 13px 11px; column-gap: 11px; }
  .ap-mark { width: 28px; height: 28px; border-radius: 9px; }
  .ap-state { margin-top: 6px; }
  .ap-answer-in { margin: 0 13px; padding: 10px 0 12px; }
}
@media (prefers-reduced-motion: reduce) {
  .scene.approval { height: 100vh; height: 100svh; }
  .ap-sheet, .ap-side .island, .ap-btn, .ap-answer, .ap-title, .ap-state-words, .ap-reopen { transition: none; }
}
