/* Phase 4 motion & streaming smoothness — loaded only when ?phase4=1 */

/* Arrival effect: the tail's newest block softly fades up as words arrive.
   No background flash (the ink tint read like a selection glitch — owner call).
   One animation on the persistent tail node, throttled by stream.js. */
.p4-tail.p4-arrive {
  animation: p4-arrive-fade 300ms ease-out;
}

@keyframes p4-arrive-fade {
  from {
    opacity: 0.5;
    transform: translateY(2px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .p4-tail.p4-arrive {
    animation: none !important;
  }
}

/* --------------------------------------------------------------------------
   Tables (§8.8)
   Horizontal scroll, edge fade, header row surface, 14px/10-12 padding,
   sticky first column when wider than screen, hide .swipehint.
   -------------------------------------------------------------------------- */
html.phase4 .swipehint {
  display: none;
}

html.phase4 .tbl-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
  margin: 10px 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-md, 12px);
  background: var(--surface);
  display: flex;
  position: relative;
  max-width: 100%;
}

html.phase4 .tbl-wrap table {
  border-collapse: collapse;
  width: 100%;
  min-width: 430px;
  font-size: 14px;
}

html.phase4 .tbl-wrap th,
html.phase4 .tbl-wrap td {
  padding: 10px 12px;
  font-size: 14px;
  line-height: 20px;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
}

html.phase4 .tbl-wrap thead th {
  background: var(--surface-2);
  color: var(--ink);
  font-weight: 600;
  font-size: 14px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}

html.phase4 .tbl-wrap tbody tr:last-child th,
html.phase4 .tbl-wrap tbody tr:last-child td {
  border-bottom: none;
}

/* Sticky first column when wider than the screen */
html.phase4 .tbl-wrap th:first-child,
html.phase4 .tbl-wrap td:first-child {
  position: sticky;
  left: 0;
  z-index: 2;
  background: var(--surface);
  box-shadow: 1px 0 0 var(--line);
}

html.phase4 .tbl-wrap thead th:first-child {
  z-index: 3;
  background: var(--surface-2);
}

/* Trailing edge fade */
html.phase4 .tbl-wrap::after {
  content: "";
  position: sticky;
  right: 0;
  flex: none;
  align-self: stretch;
  width: 32px;
  margin-left: -32px;
  pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--surface));
  transition: opacity 0.25s ease;
}

html.phase4 .tbl-wrap.scrolled::after {
  opacity: 0;
}

/* --------------------------------------------------------------------------
   Tool Detail Sheet Diff & Images (§8.6)
   -------------------------------------------------------------------------- */
html.phase4 .diff-line.diff-add {
  background-color: color-mix(in srgb, var(--ok, #2e6f40) 12%, transparent);
}

html.phase4 .diff-line.diff-del {
  background-color: color-mix(in srgb, var(--danger, #b42318) 12%, transparent);
}

html.phase4 .tool-sheet-images {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

html.phase4 .tool-sheet-img-wrap {
  width: 100%;
  border-radius: 8px;
  overflow: hidden;
  cursor: zoom-in;
  background: var(--code-bg, #1a1a1a);
  border: 1px solid var(--line);
}

html.phase4 .tool-sheet-img-wrap.zoomed {
  cursor: zoom-out;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

html.phase4 .tool-sheet-img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: 8px;
  transition: transform 0.2s ease;
}

html.phase4 .tool-sheet-img-wrap.zoomed .tool-sheet-img {
  width: auto;
  max-width: none;
  min-width: 100%;
  transform: scale(1.6);
  transform-origin: top left;
}

/* --------------------------------------------------------------------------
   Approvals / Needs-Input Sticky Amber Bar (§8.10)
   - 44px hit target, amber background, dark ink
   - Positioned above composer accounting for --composer-h
   - Feed padding and scroll-bot button adjusted when active
   -------------------------------------------------------------------------- */
html.phase4 .p4-needs-input {
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: calc(var(--composer-h, 60px) + 8px);
  min-height: 44px;
  height: 44px;
  border-radius: 14px;
  background: var(--warn, #d9a53c);
  color: #241f0c;
  font-family: system-ui, -apple-system, sans-serif;
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 14px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.14);
  cursor: pointer;
  z-index: 36;
  box-sizing: border-box;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  touch-action: pan-y;
  transition: transform 0.15s ease, opacity 0.15s ease;
}

html.phase4 .p4-needs-input[hidden] {
  display: none !important;
}

html.phase4 .p4-needs-input:active {
  transform: scale(0.985);
  opacity: 0.95;
}

html.phase4 .p4-needs-input-main {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  flex: 1 1 auto;
}

html.phase4 .p4-needs-input-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 20px;
  height: 20px;
}

html.phase4 .p4-needs-input-label {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-weight: 650;
}

html.phase4 .p4-needs-input-hint {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-left: 8px;
  opacity: 0.75;
}

/* Feed padding adjustment when needs-input bar is open so last message is never covered */
html.phase4:has(.p4-needs-input:not([hidden])) #feed,
html.phase4.has-needs-input #feed {
  padding-bottom: calc(var(--composer-h, 60px) + 68px);
}

/* Scroll to bottom button lifted above needs-input bar */
html.phase4:has(.p4-needs-input:not([hidden])) #btn-scroll-bot,
html.phase4.has-needs-input #btn-scroll-bot {
  bottom: calc(var(--bot-h, var(--composer-h, 60px)) + 60px);
}

/* Collapsed question chip in phase4 */
html.phase4 .question-chip.q-minimized,
html.phase4 .question-chip.minimized {
  display: none;
}

html.phase4 .question-chip .q-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}

html.phase4 .question-chip .q-minimize {
  margin-left: auto;
  font-family: system-ui, -apple-system, sans-serif;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted, #888);
  background: var(--surface-2, rgba(0, 0, 0, 0.05));
  border: 1px solid var(--line, rgba(0, 0, 0, 0.1));
  border-radius: 8px;
  padding: 4px 10px;
  cursor: pointer;
  min-height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.15s ease, color 0.15s ease;
}

html.phase4 .question-chip .q-minimize:hover,
html.phase4 .question-chip .q-minimize:active {
  background: var(--line, rgba(0, 0, 0, 0.12));
  color: var(--ink, #111);
}


/* --------------------------------------------------------------------------
   Phase 6 Slice B — the "alive" layer (planopus.md §6.5: E2, E3, E6, E7).
   Scoped html.phase5 only: default /v2/, ?phase3=1 and ?phase4=1 (no phase5)
   stay visually unchanged. Every loop is transform/opacity only (compositor);
   the two one-shot effects the plan names by hand (check draw 240ms,
   row flash 600ms) and the small background-position shimmer are the only
   exceptions. Each has a reduced-motion static fallback, and html.p6-paused
   (set on document.hidden) pauses the loops.
   -------------------------------------------------------------------------- */

/* --- E2 · thinking orb: 18px, 3 stacked pre-blurred radial gradients ------ */
html.phase5 .work-card.p6-thinking .work-glyph > svg {
  display: none;
}

html.phase5 .work-orb {
  display: none;
  position: relative;
  width: 18px;
  height: 18px;
  flex: none;
  border-radius: 50%;
  overflow: hidden;
}

html.phase5 .work-card.p6-thinking .work-orb {
  display: block;
}

html.phase5 .work-orb > i {
  position: absolute;
  inset: -16%;
  display: block;
  border-radius: 50%;
  transform: translateZ(0);
  will-change: transform;
}

/* amber */
html.phase5 .work-orb > i:nth-child(1) {
  background: radial-gradient(
    circle at 34% 30%,
    var(--accent) 0%,
    color-mix(in srgb, var(--accent) 52%, transparent) 36%,
    transparent 68%
  );
  animation: p6-orb-spin 6.5s linear infinite;
}

/* ochre */
html.phase5 .work-orb > i:nth-child(2) {
  background: radial-gradient(
    circle at 66% 62%,
    var(--ochre, #d08a2c) 0%,
    color-mix(in srgb, var(--ochre, #d08a2c) 45%, transparent) 38%,
    transparent 70%
  );
  animation: p6-orb-spin 4.6s linear reverse infinite;
  animation-delay: -1.7s;
}

/* sand */
html.phase5 .work-orb > i:nth-child(3) {
  background: radial-gradient(
    circle at 50% 50%,
    var(--sand, #e5c48f) 0%,
    color-mix(in srgb, var(--sand, #e5c48f) 40%, transparent) 42%,
    transparent 72%
  );
  animation: p6-orb-spin 8.4s linear infinite;
  animation-delay: -3.1s;
}

@keyframes p6-orb-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

/* While answer text is streaming the live cursor carries the motion, so the
   orb stands down: never more than two continuous animations at once (§6.2).
   Anchored on #feed so it holds whether the live text sits inside the same
   assistant block as the work card or in the next one. */
html.phase5 #feed:has(.live-text) .work-card.p6-thinking .work-orb {
  display: none;
}

/* --- E3 · shimmer label on "Thinking…" / "Running …" --------------------- */
html.phase5 .work-card[data-live="true"] .work-summary {
  background-image: linear-gradient(
    100deg,
    var(--ink-2) 0%,
    var(--ink) 28%,
    var(--accent) 48%,
    var(--ink) 68%,
    var(--ink-2) 100%
  );
  background-size: 220% 100%;
  background-repeat: no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: p6-shimmer 2.4s linear infinite;
}

@keyframes p6-shimmer {
  from {
    background-position: 130% 0;
  }
  to {
    background-position: -130% 0;
  }
}

/* --- E6 · step complete: check draws, row flashes ------------------------ */
html.phase5 .work-step.p6-just-done[data-st="ok"] {
  animation: p6-row-flash 600ms ease-out 1 both;
}

@keyframes p6-row-flash {
  from {
    background-color: var(--accent-soft);
  }
  to {
    background-color: transparent;
  }
}

html.phase5 .work-step.p6-just-done[data-st="ok"] .step-status svg {
  stroke-dasharray: 300;
  stroke-dashoffset: 0;
  animation: p6-check-draw 240ms ease-out 1 both;
}

@keyframes p6-check-draw {
  from {
    stroke-dashoffset: 300;
  }
  to {
    stroke-dashoffset: 0;
  }
}

/* --- E7 · live cursor: 6px amber dot at the end of the live block -------- */
html.phase5 .p4-tail[data-p4-block="open"]::after,
html.phase5 .live-text > :last-child:is(p, li, div, span, blockquote, pre, h1, h2, h3, h4, h5, h6)::after {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-left: 4px;
  border-radius: 50%;
  background: var(--accent);
  vertical-align: 0.05em;
  transform-origin: 50% 50%;
  animation: p6-cursor 1.2s ease-in-out infinite;
}

@keyframes p6-cursor {
  0%,
  100% {
    transform: scale(1);
    opacity: 0.95;
  }
  50% {
    transform: scale(1.45);
    opacity: 0.55;
  }
}

/* --- Paused while the app is not visible (§6.1) ------------------------- */
html.phase5.p6-paused .work-orb > i,
html.phase5.p6-paused .work-card[data-live="true"] .work-summary,
html.phase5.p6-paused .p4-tail[data-p4-block="open"]::after,
html.phase5.p6-paused .live-text > :last-child:is(p, li, div, span, blockquote, pre, h1, h2, h3, h4, h5, h6)::after {
  animation-play-state: paused;
}

/* --- Reduced motion: static fallbacks, no loops (§6.1) ------------------ */
@media (prefers-reduced-motion: reduce) {
  html.phase5 .work-orb > i,
  html.phase5 .work-card[data-live="true"] .work-summary,
  html.phase5 .work-step.p6-just-done[data-st="ok"],
  html.phase5 .work-step.p6-just-done[data-st="ok"] .step-status svg,
  html.phase5 .p4-tail[data-p4-block="open"]::after,
  html.phase5 .live-text > :last-child:is(p, li, div, span, blockquote, pre, h1, h2, h3, h4, h5, h6)::after {
    animation: none !important;
  }

  /* one steady amber dot instead of three orbiting gradients */
  html.phase5 .work-orb > i:nth-child(2),
  html.phase5 .work-orb > i:nth-child(3) {
    display: none;
  }

  html.phase5 .work-orb > i:nth-child(1) {
    inset: 0;
    opacity: 1;
    transform: none;
  }

  html.phase5 .work-card[data-live="true"] .work-summary {
    background-image: none;
    color: var(--ink);
    -webkit-text-fill-color: currentColor;
  }

  html.phase5 .work-step.p6-just-done[data-st="ok"] .step-status svg {
    stroke-dashoffset: 0;
  }

  html.phase5 .p4-tail[data-p4-block="open"]::after,
  html.phase5 .live-text > :last-child:is(p, li, div, span, blockquote, pre, h1, h2, h3, h4, h5, h6)::after {
    transform: none;
    opacity: 0.85;
  }
}

/* --------------------------------------------------------------------------
   Phase 6 Slice C — compact collapsed work card (planopus.md §8.5, §6.5).
   The live card used to stack the header (44px) over the redundant live line
   (same tool name + arg the header/expanded timeline already carry), which
   measured ~94px at 390px. Scoped html.phase5 so ?phase4=1 alone keeps its
   current card exactly as phone-checked: while collapsed the card is ONE 44px
   header row inside its 1px border (46px total) with 4px vertical margins. The
   live line is hidden with CSS only — its text stays in the DOM, and expanding
   still reveals the full timeline with every step, argument, duration and the
   Tool detail sheet. No effect (E2 orb, E3 shimmer, E6 step complete, E7
   cursor) is touched.
   -------------------------------------------------------------------------- */
/* Mirror phase4.css's own selectors (its #feed pairs beat a plain class rule):
   the collapsed card becomes one 44px header row inside a 1px border = 46px
   total, with 4px vertical margins (planopus.md §8.5: <=48px card, <=4px
   margin). The header carries the whole tap target, so the card padding goes
   to zero vertical. */
html.phase5 #feed .work-card.collapsed,
html.phase5 #feed > .work-card.collapsed,
html.phase5 .work-card.collapsed {
  padding: 0 10px !important;
  margin: 4px 0 !important;
}

html.phase5 #feed .work-card.collapsed[data-live="true"] .work-live-line,
html.phase5 .work-card.collapsed[data-live="true"] .work-live-line {
  display: none;
}
/* The collapsed trail needs a little room under the zero-padding phase5 card. */
html.phase5 .work-card.collapsed .work-trail:not(:empty) { padding-bottom: 4px; }
