/* 조판대 — the live analysis board. Five stations are bands on one sheet, separated by hairlines,
   each with a margin gutter carrying a folio, a bare Tabler mark and a state word. No card, no
   radius, no shadow, no avatar. Heights are fixed for the whole run and text is clipped inside its
   own column, so new content can never arrive below the fold. Existing tokens only; light and dark
   follow premier.css. Nothing here sets a min-width. */

/* ── tokens: scoped to the board, never to :root ─────────────────────────── */
.theater{
  --th-margin:color-mix(in srgb,var(--p-surface-2) 55%,var(--p-surface));
  --th-rule:var(--p-line);
  --th-rule-fine:color-mix(in srgb,var(--studio-grid) 62%,transparent);
  /* the wet end of the ink take carries the newest text for the whole run, so it stays above 4.5:1
     against the sheet. The blur, not the alpha, is what reads as wet. */
  --th-ink-wet:color-mix(in srgb,var(--p-text) 65%,transparent);
  --th-blank:color-mix(in srgb,var(--p-text) 9%,transparent);
  --th-blank-strong:color-mix(in srgb,var(--p-text) 15%,transparent);
  --th-bench:var(--p-surface);
  /* 윤은 막대보다 한 단 옅다(라이트) — 빛이 지나가면 그 자리가 지면에 가까워진다.
     두 굵기의 막대가 같은 세기로 반짝이도록 값을 따로 푼다: 모두 ΔL* ≈ 4.7 이다. */
  --th-sheen:color-mix(in srgb,var(--p-text) 3%,transparent);
  --th-sheen-strong:color-mix(in srgb,var(--p-text) 9%,transparent);
  /* 활자는 이 스타일시트가 따로 정하지 않는다: premier.css 의 M3 역할을 그대로 쓴다.
     이전에는 여기에만 다섯 단이 따로 있었고, 그것이 사이트 전체가 46가지 크기로
     흩어진 방식의 축소판이었다. 남는 것은 한글 본문의 행간 하나뿐이다. */
  --th-lead:1.72;
  /* `ch` is a Latin unit: at 13px it is ~7px, so 42ch held only ~22 Korean characters per line and
     left a third of every column blank. The measure is set for the script the board actually sets. */
  --th-measure:min(100%,64ch);
  --th-gutter:72px;
  --th-pitch:calc(13px * var(--th-lead));
  display:flex;flex-direction:column;min-height:0;background:var(--p-surface);animation:none;
}
[data-theme=dark] .theater{
  --th-margin:color-mix(in srgb,var(--p-surface-2) 70%,var(--p-surface));
  --th-ink-wet:color-mix(in srgb,var(--p-text) 55%,transparent);
  --th-sheen:color-mix(in srgb,var(--p-text) 14%,transparent);
  --th-sheen-strong:color-mix(in srgb,var(--p-text) 20%,transparent);
  --th-bench:color-mix(in srgb,var(--p-text) 7%,var(--p-surface));
}
/* 시스템 설정만으로 어두운 경우에도 같은 값이어야 한다: premier.css 가 토큰을 바꾸는 조건과 맞춘다. */
@media(prefers-color-scheme:dark){
  :root:not([data-theme=light]) .theater{
    --th-margin:color-mix(in srgb,var(--p-surface-2) 70%,var(--p-surface));
    --th-ink-wet:color-mix(in srgb,var(--p-text) 55%,transparent);
    --th-sheen:color-mix(in srgb,var(--p-text) 14%,transparent);
    --th-sheen-strong:color-mix(in srgb,var(--p-text) 20%,transparent);
    --th-bench:color-mix(in srgb,var(--p-text) 7%,var(--p-surface));
  }
}

/* ── the shell around the board: the focus header is untouched ───────────── */
.theater .focus-actions{align-items:center;gap:12px}
.theater .focus-actions .discovery-status{font-size:11px;white-space:nowrap}
.theater .focus-actions .text-button{font-size:11px}
.theater-draft-note{flex:0 0 auto;margin:0;padding:7px 28px;font:var(--md-label-s);color:var(--studio-hold)}
.theater-margin{flex:0 0 auto;display:flex;align-items:center;padding:8px 28px;border-top:1px solid var(--th-rule)}
.theater-margin p{margin:0;font:var(--md-label-s);color:var(--p-muted)}

/* ── the board ───────────────────────────────────────────────────────────── */
.theater-board{position:relative;flex:1 1 auto;min-height:0;display:flex;flex-direction:column;padding-inline:28px;background:var(--p-surface)}
.theater-station{position:relative;min-width:0;min-height:0}
.theater-station+.theater-station{border-top:1px solid var(--th-rule)}

/* ── 조판대 ───────────────────────────────────────────────────────────────
   작성 중인 칸은 지면에서 들어 올려 조판대에 올린다: 그늘이 지고, 좌우로 더 넓어지고,
   글자가 커진다. 완료되면 그늘과 여백을 반납하며 제 줄에 납작하게 앉는다 — 한 칸씩
   눌러 찍어 지면이 차오르는 것이 보이도록. 위치를 절대배치로 옮기지 않고 같은 흐름
   안에서 커졌다 작아지므로, 옆 칸들이 밀려나며 '자리를 내준다'는 것도 함께 읽힌다. */
.theater-station{transition:background-color 560ms var(--pm-ease),box-shadow 560ms var(--pm-ease),
  margin 560ms var(--pm-ease),padding 560ms var(--pm-ease),opacity 560ms var(--pm-ease)}
.theater-station[data-state=active]{
  z-index:2;border-radius:var(--md-shape-l);background:var(--th-bench);
  margin-inline:-16px;padding-inline:16px;
  box-shadow:0 22px 48px -24px color-mix(in srgb,var(--p-text) 45%,transparent),
             0 0 0 1px color-mix(in srgb,var(--p-accent) 26%,transparent)}
.theater-station[data-state=active]+.theater-station,
.theater-station:has(+.theater-station[data-state=active]){border-top-color:transparent}
/* 조판대 위에서는 글이 한 단 커진다: 지금 읽으라고 올려둔 것이기 때문이다. */
.theater-station[data-state=active] :is(.theater-live,.theater-text p){font-size:16px}
.theater-station[data-state=active] .theater-station-title{font-size:14px}
/* 이미 앉은 칸은 물러난다. 지워지지는 않는다 — 방금 무엇이 지나갔는지 읽을 수 있어야 한다. */
.theater-station[data-state=done]{opacity:.78}
.theater-station[data-state=done]:hover,.theater-station[data-state=done]:focus-within{opacity:1}
.theater-board.is-resolved .theater-station[data-state=done]{opacity:1}

/* ── the head rule row ───────────────────────────────────────────────────── */
.theater-station-head{position:relative;display:flex;align-items:center;gap:10px;min-height:26px;padding:2px 0;overflow:hidden;border-bottom:1px solid var(--th-rule);transition:border-color var(--pm-shift) var(--pm-ease)}
.theater-folio{flex:0 0 auto;font:600 11px/1 var(--p-mono);letter-spacing:.08em;font-variant-numeric:tabular-nums;color:var(--p-muted);transition:color 240ms var(--pm-ease)}
.theater-station-title{margin:0;font:var(--md-title-s);letter-spacing:-.01em;color:var(--p-text)}
.theater-station-state{margin-left:auto;font:var(--md-label-s);letter-spacing:.12em;color:var(--p-muted);white-space:nowrap}
.theater-station[data-state=active] .theater-folio{color:var(--p-accent);animation:theater-folio 260ms var(--pm-ease) both}
/* 작성 중 is the one thing a member looks for across the room, so the active band carries it in more
   than a 10px word at the far right: the head rule takes the accent and the gutter is tinted with it. */
.theater-station[data-state=active] .theater-station-state{color:var(--p-accent);font-size:12px;font-weight:700;letter-spacing:.1em}
.theater-station[data-state=active] .theater-station-head{border-bottom-color:color-mix(in srgb,var(--p-accent) 60%,var(--th-rule))}
.theater-station[data-state=active] .theater-gutter{background:color-mix(in srgb,var(--p-accent) 8%,var(--th-margin))}
.theater-station[data-state=failed] .theater-folio,
.theater-station[data-state=failed] .theater-station-state{color:var(--studio-negative)}
.theater-station[data-state=failed] .theater-station-head{border-bottom-color:var(--studio-negative)}
@keyframes theater-folio{from{opacity:0;transform:translateY(3px)}to{opacity:1;transform:none}}

/* 판면 스윕: a band of accent travelling the head rule. The only motion legible from across the room. */
.theater-sweep{position:absolute;left:0;right:0;bottom:0;height:2px;overflow:hidden;pointer-events:none}
.theater-sweep::after{content:'';position:absolute;inset:0;transform:translateX(-100%);
  background:linear-gradient(90deg,transparent 0,transparent 40%,color-mix(in srgb,var(--p-accent) 22%,transparent) 50%,transparent 60%,transparent 100%)}
.theater-station[data-state=active] .theater-sweep::after{will-change:transform;animation:theater-sweep 2400ms linear infinite}
@keyframes theater-sweep{from{transform:translateX(-100%)}to{transform:translateX(100%)}}

/* ── the margin gutter ───────────────────────────────────────────────────── */
.theater-gutter{display:flex;flex-direction:column;align-items:flex-start;justify-content:center;gap:5px;padding:8px 12px 8px 0;background:var(--th-margin);color:var(--p-muted);transition:background-color 560ms var(--pm-ease)}
.theater-station-mark .p-icon{width:20px;height:20px}
.theater-gutter-check .p-icon{width:14px;height:14px;color:var(--studio-positive)}
.theater-gutter-state{font:var(--md-label-s);letter-spacing:.06em}
.theater-station[data-state=active] .theater-gutter,.theater-station[data-state=done] .theater-gutter{color:var(--p-text)}
.theater-station[data-state=failed] .theater-gutter{color:var(--studio-negative)}
.theater-gutter-rule{display:block;background:var(--th-rule)}

/* ── one role column ─────────────────────────────────────────────────────── */
.theater-field{min-width:0;min-height:0;padding-top:12px}
.theater-col{display:flex;flex-direction:column;min-width:0;min-height:0}
.theater-col-head{display:flex;align-items:center;gap:8px;min-height:26px}
.theater-col-mark{display:inline-flex;color:var(--p-muted)}
.theater-col-mark .p-icon{width:16px;height:16px}
.theater .theater-col-head .studio-section-kicker{margin:0;font:var(--md-title-s);letter-spacing:-.005em;text-transform:none;color:var(--p-muted);transition:color 520ms var(--pm-ease)}
.theater-col:is([data-status=running],[data-status=streaming],[data-status=retrying],[data-status=completed]) .theater-col-head .studio-section-kicker{color:var(--p-text)}
.theater-col[data-tone=positive] .theater-col-mark{color:var(--studio-positive)}
.theater-col[data-tone=negative] .theater-col-mark{color:var(--studio-negative)}
.theater-col[data-tone=hold] .theater-col-mark{color:var(--studio-hold)}
/* mostly Korean — '작성 중', '응답을 받지 못했습니다' — and no face in the mono stack carries Hangul. */
.theater-col-count{margin-left:auto;font:var(--md-label-s);font-variant-numeric:tabular-nums;color:var(--p-muted);white-space:nowrap}
/* the Korean for the English protocol token the prompt demanded: 저평가 의견, 비중 축소 … */
.theater .theater-col-head .stance.theater-col-chip{flex:0 0 auto;gap:5px;padding:1px 7px;border-radius:var(--md-shape-xs);font:var(--md-label-s);letter-spacing:0}
.theater .theater-col-head .stance.theater-col-chip::before{width:6px;height:6px}
.theater-col[data-status=failed] .theater-col-count{color:var(--studio-negative)}
/* 컬럼 점화: the rule draws itself down, briefly in accent, as the column starts taking ink. */
.theater-col-rule{display:block;height:1px;margin-top:6px;background:var(--th-rule-fine);transform:scaleY(0);transform-origin:top;transition:transform 520ms var(--pm-ease)}
.theater-col:is([data-status=completed],[data-status=failed]) .theater-col-rule{transform:scaleY(1)}
.theater-col:is([data-status=running],[data-status=streaming],[data-status=retrying]) .theater-col-rule{transform:scaleY(1);animation:theater-ignite 820ms var(--pm-ease) both}
@keyframes theater-ignite{0%,63%{background-color:var(--p-accent)}100%{background-color:var(--th-rule-fine)}}

/* the clipped, masked text box: bottom-anchored while writing, top-anchored once settled */
/* The fades are capped in PROPORTION as well as in pixels: a fixed 14px/28px pair swallowed a 28px
   body whole, so the shortest bands showed nothing but gradient. The top fade is one line high, so a
   partial line disappears instead of leaving its glyph tops behind. */
.theater-col-body{position:relative;flex:1 1 auto;min-height:0;display:flex;flex-direction:column;justify-content:flex-end;gap:12px;overflow:hidden;padding-top:10px;
  --th-fade-top:min(var(--th-pitch),16%);--th-fade-bottom:min(22px,16%);
  -webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 var(--th-fade-top),#000 calc(100% - var(--th-fade-bottom)),transparent 100%);
  mask-image:linear-gradient(to bottom,transparent 0,#000 var(--th-fade-top),#000 calc(100% - var(--th-fade-bottom)),transparent 100%)}
.theater-col-body[data-anchor=top]{justify-content:flex-start;
  -webkit-mask-image:linear-gradient(to bottom,#000 calc(100% - var(--th-fade-bottom)),transparent 100%);
  mask-image:linear-gradient(to bottom,#000 calc(100% - var(--th-fade-bottom)),transparent 100%)}

/* ── the type itself ─────────────────────────────────────────────────────── */
.theater-live,.theater-text p,.theater-station-copy{margin:0;font:400 14px/var(--th-lead) var(--p-font);color:var(--p-text);word-break:keep-all;overflow-wrap:anywhere;text-wrap:pretty;max-width:var(--th-measure)}
.theater-live{white-space:pre-wrap}
/* 문단 사이는 행간보다 넓어야 문단으로 읽힌다. 8px 은 행간(≈25px)보다 좁아 두 문단이
   한 덩어리로 붙었다. 한 행 높이의 절반 남짓을 준다. */
.theater-text{display:grid;gap:14px;max-width:var(--th-measure)}
.theater-station-copy{color:var(--p-muted)}
.theater-note{margin:4px 0 0;font:var(--md-label-s);color:var(--studio-hold)}
.theater-wait{margin:0;padding:10px 0 0;font:var(--md-body-s);color:var(--p-muted);text-align:center}

/* 잉크 스밈: the newest characters arrive wet and dry off over 420ms. The dry head is patched in
   place by mount(); the wet tail carries the gradient. currentColor cannot be used inside the
   gradient — the span's own colour is transparent for background-clip:text — so the ink token is named. */
/* The resting state is DRY. patch() adds .is-wet on the frame the tail grows and drops it on the
   next, so the computed filter really changes and the 420ms decay really runs. Holding the blur as
   the resting value — which is what an inline style of the same value did — transitioned nothing. */
.theater-live-tail{
  background-image:linear-gradient(90deg,var(--p-text) 0 calc(100% - 5ch),var(--th-ink-wet) 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
  -webkit-box-decoration-break:clone;box-decoration-break:clone;
  transition:filter 420ms var(--pm-ease)}
.theater-live-tail.is-wet{filter:blur(.4px);transition:none}
@supports not ((background-clip:text) or (-webkit-background-clip:text)){.theater-live-tail{color:currentColor;background:none}}
@media (forced-colors:active){.theater-live-tail{color:CanvasText;background:none;filter:none}}

/* 조판 괘선: the composing rule breathes, it does not blink. */
.theater-caret{display:inline-block;width:2px;height:1.15em;margin-left:2px;vertical-align:-.15em;background:var(--p-accent);border-radius:1px;opacity:1;animation:theater-nib 620ms steps(1,end) infinite alternate}
/* steps(1), not a glide: a nib that eases in and out reads as a pulse beside the text. A write
   point has to be somewhere definite on every frame, so it is either down or lifted. */
@keyframes theater-nib{from{opacity:1;transform:scaleY(1)}to{opacity:.25;transform:scaleY(.9)}}

/* 스켈레톤: the waiting band shows the shape of what is coming. Bars sit at the body's own pitch and
   at the body's own measure, so when the text arrives it lands where the skeleton stood — nothing
   jumps. */
.theater-skeleton{display:flex;flex-direction:column;gap:calc(var(--th-pitch) - 10px);padding-top:8px;max-width:var(--th-measure)}
.theater-skeleton i{display:block;height:10px;border-radius:var(--md-shape-xs);
  background-image:linear-gradient(90deg,var(--th-blank) 25%,var(--th-sheen) 37%,var(--th-blank) 63%);
  background-size:400% 100%;background-position:100% 50%;
  animation:theater-sheen 1500ms ease infinite}
.theater-skeleton i[data-bar=head]{height:12px;border-radius:var(--md-shape-xs);margin-bottom:4px;
  background-image:linear-gradient(90deg,var(--th-blank-strong) 25%,var(--th-sheen-strong) 37%,var(--th-blank-strong) 63%)}
.theater-skeleton i[data-bar=chip]{height:20px;border-radius:var(--md-shape-xs);margin-bottom:6px;
  background-image:linear-gradient(90deg,var(--th-blank-strong) 25%,var(--th-sheen-strong) 37%,var(--th-blank-strong) 63%)}
/* 자료 수집 칸의 스켈레톤은 채워진 값과 같은 높이를 차지해야 한다: 넷 중 하나만 늦게 와도
   줄이 어긋나 보이면 안 된다. 부모가 이미 gap 을 주므로 여기서 padding 을 더하지 않는다. */
.theater-skeleton[data-shape=fact]{gap:0;padding-top:0}
.theater-skeleton[data-shape=fact] i{height:calc(13px * 1.55)}

/* 막대의 길이가 곧 앞으로 올 문단의 모양이다: 제목 한 줄, 꽉 찬 줄들, 그리고 짧게 끝나는 마지막 줄. */
.theater-skeleton[data-shape=prose] i:nth-child(1){width:62%}
.theater-skeleton[data-shape=prose] i:nth-child(2){width:100%}
.theater-skeleton[data-shape=prose] i:nth-child(3){width:92%}
.theater-skeleton[data-shape=prose] i:nth-child(4){width:74%}
.theater-skeleton[data-shape=prose] i:nth-child(5){width:46%}
.theater-skeleton[data-shape=fact] i:nth-child(1){width:78%}
.theater-skeleton[data-shape=verdict] i:nth-child(1){width:34%}
.theater-skeleton[data-shape=verdict] i:nth-child(2){width:100%}
.theater-skeleton[data-shape=verdict] i:nth-child(3){width:68%}
/* 윤: the sheen belongs to each bar, not to a band laid over the group — an overlay tints the gaps
   too, which is what made one wide stripe cross the whole column. It is a lighter shade of the bar
   itself, never the brand colour: a skeleton is absent content, and colour would claim it is not. */
@keyframes theater-sheen{from{background-position:100% 50%}to{background-position:0 50%}}

/* 지우고 다시 쓰기: a retry is a re-judgment, and the board should say so. The superseded draft is
   lifted right-to-left under a mask while its ink drains, and the new attempt types in beneath it —
   so the member sees the page cleared and set again, not one string swapped for another. The ghost
   is aria-hidden and removed by its own timer; the live text underneath is the real one throughout. */
.theater-col-body{position:relative}
.theater-erase{
  position:absolute;inset:0;pointer-events:none;overflow:hidden;
  animation:theater-lift 560ms var(--pm-ease) forwards}
.theater-erase>*{margin:0}
@keyframes theater-lift{
  from{opacity:1;filter:none;-webkit-mask-image:linear-gradient(270deg,#000 0 100%);mask-image:linear-gradient(270deg,#000 0 100%)}
  to{opacity:0;filter:grayscale(1);-webkit-mask-image:linear-gradient(270deg,transparent 0 100%);mask-image:linear-gradient(270deg,transparent 0 100%)}}

/* ── 01 자료 수집 ────────────────────────────────────────────────────────── */
.theater-facts{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));align-content:center;min-width:0}
.theater-fact{display:flex;flex-direction:column;gap:6px;min-width:0;padding:0 18px;border-left:1px solid var(--th-rule-fine)}
.theater-fact:first-child{border-left:0;padding-left:0}
.theater-fact-label{display:flex;align-items:center;gap:6px;font:var(--md-label-s);letter-spacing:.08em;color:var(--p-muted)}
.theater-fact-mark{display:inline-flex}
.theater-fact-mark .p-icon{width:16px;height:16px}
.theater-fact-text{font:var(--md-body-s);color:var(--p-text);word-break:keep-all;overflow-wrap:anywhere}
.theater-fact[data-state=failed] .theater-fact-text{color:var(--studio-negative)}
.theater-fact:is([data-state=none],[data-state=not_applicable]) .theater-fact-text{color:var(--p-muted)}
.theater-fact .theater-skeleton{max-width:100%}

/* ── 03 상승·하락 관점 ──────────────────────────────────────────────────── */
.theater-pair{position:relative;display:grid;grid-template-columns:minmax(0,1fr) 34px minmax(0,1fr);grid-template-rows:minmax(0,1fr);min-width:0;min-height:0;overflow:hidden}
.theater-vs{position:relative;align-self:center;justify-self:center;padding:6px 3px;font:500 16px/1 var(--p-display);color:var(--p-muted)}
/* the column rule runs the full band, broken open where the `vs` mark sits */
.theater-vs::before{content:'';position:absolute;left:50%;top:-999px;bottom:calc(100% + 5px);width:1px;background:var(--th-rule)}
.theater-vs::after{content:'';position:absolute;left:50%;top:calc(100% + 5px);bottom:-999px;width:1px;background:var(--th-rule)}
.theater-pair>.theater-col:last-of-type{padding-left:22px}
.theater-pair>.theater-col:first-of-type{padding-right:22px}

/* ── the apparatus column (04 / 05) and apparatus row (01 / 03) ──────────── */
.theater-apparatus{display:flex;flex-direction:column;gap:6px;min-width:0;overflow:hidden}
.theater-apparatus-kicker{font:var(--md-label-s);letter-spacing:.12em;color:var(--p-muted)}
.theater-review{display:flex;align-items:flex-start;gap:6px;margin:0;font:var(--md-label-s);color:var(--p-muted);overflow-wrap:anywhere}
.theater-review-mark{display:inline-flex;flex:0 0 auto;padding-top:2px;color:var(--p-muted)}
.theater-review-mark .p-icon{width:13px;height:13px}
.theater-review[data-done=true] .theater-review-mark{color:var(--studio-positive)}
.theater-verdict-meta,.theater-saving{margin:0;font:var(--md-label-s);color:var(--p-muted)}

/* ── 05 의장 결론 ───────────────────────────────────────────────────────── */
.theater-verdict{display:grid;gap:10px;justify-items:start;min-width:0}
/* 자간 조판: the stance sets itself once, then a hairline is drawn under it. Never loops. */
.theater-stance{position:relative;display:inline-block;padding-bottom:7px}
.theater-stance .stance{padding:0;gap:9px;font:500 36px/1 var(--p-display);letter-spacing:-.03em;animation:theater-kern 620ms var(--pm-ease) both;transition:font-size 560ms var(--pm-ease)}
.theater-stance .stance::before{width:9px;height:9px}
.theater-stance::after{content:'';position:absolute;left:0;right:0;bottom:0;height:1px;background:var(--th-rule);transform:scaleX(0);transform-origin:left;animation:theater-underline 480ms var(--pm-ease) 200ms both}
@keyframes theater-kern{from{letter-spacing:.14em;opacity:0}to{letter-spacing:-.03em;opacity:1}}
@keyframes theater-underline{to{transform:scaleX(1)}}
.theater-thesis{margin:0;max-width:58ch;font:var(--md-title-m);letter-spacing:-.2px;color:var(--p-text);word-break:keep-all;overflow-wrap:anywhere;text-wrap:pretty;transition:font-size 560ms var(--pm-ease),max-width 560ms var(--pm-ease)}

/* ── failure: the station where it stopped keeps its exact height ────────── */
/* One row, not a stack: the band that stopped keeps its height, and a 100px stack would push the
   retry button — the only recovery on screen — below a clip the board never scrolls. */
.theater-failure{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px;padding:2px 0 8px}
.theater-failure-title{flex:0 0 auto;display:flex;align-items:center;gap:6px;margin:0;font:var(--md-title-s);color:var(--studio-negative)}
.theater-failure-mark{display:inline-flex}
.theater-failure-mark .p-icon{width:16px;height:16px}
.theater-failure p{margin:0;font:400 13px/1.6 var(--p-font);color:var(--p-text);overflow-wrap:anywhere}
.theater-failure-message{flex:1 1 280px;min-width:0}
.theater-failure .p-button{flex:0 0 auto;min-height:32px;padding:5px 12px;font-size:12px}

/* ── the follow button: armed only where the page itself scrolls ─────────── */
.theater-follow{position:sticky;bottom:12px;align-self:center;margin-top:12px;padding:7px 12px;border-radius:var(--md-shape-xl);background:var(--md-card-bg);box-shadow:var(--md-elev-2);font-size:11px;border:var(--md-card-border)}

/* ── 정판 / imposition: the one class that rewrites the five band heights ── */
.theater-board.is-resolved .theater-gutter{background:var(--p-surface-2)}
.theater-board.is-resolved .theater-sweep,.theater-board.is-resolved .theater-caret{display:none}
.theater-board.is-resolved .theater-stance .stance{font-size:44px}
.theater-board.is-resolved .theater-thesis{font-size:18px;line-height:1.75;max-width:72ch}

/* ── the library tile, unchanged ─────────────────────────────────────────── */
.theater-tile .stock-name small{color:var(--p-accent)}
.theater-tile .theater-tile-meta{display:inline-flex;margin-top:12px;font-size:11px}
#research-focus.is-handoff{opacity:.85;transition:opacity .4s var(--pm-ease,ease)}
:is(.premier-motion-reduced,.premier-motion-paused) #research-focus.is-handoff{transition:none}

/* ════════════════════════════════════════════════════════════════════════
   THE SHEET. Only where compact desk locks the shell to the viewport height
   does the board have a definite height to divide, so only there do the five
   stations take fixed flex proportions and stop the page from scrolling.
   Everywhere else the board is a document-flow list (see §11 below).
   ════════════════════════════════════════════════════════════════════════ */
@media (min-width:1050px) and (min-height:650px){
  .compact-desk[data-studio-view=research] .theater-board{overflow:hidden}
  .compact-desk[data-studio-view=research] .theater-station{
    display:grid;grid-template-columns:var(--th-gutter) 1px minmax(0,1fr);grid-template-rows:auto minmax(0,1fr);overflow:hidden;
    transition:flex-grow 560ms var(--pm-ease),flex-basis 560ms var(--pm-ease)}
  .compact-desk[data-studio-view=research] .theater-station-head{grid-column:1/-1}
  /* Every pixel of fixed overhead is paid four times over, so the field sits close to its head rule. */
  .compact-desk[data-studio-view=research] .theater-field{padding-top:10px;padding-right:0}
  /* RUNNING — 88 fixed for 01, four proportional bands below it, Σfr = 6.5. */
  .compact-desk[data-studio-view=research] .theater-station[data-station=collect]{flex:0 0 88px}
  .compact-desk[data-studio-view=research] .theater-station[data-station=analysis]{flex:1.9 1 0}
  .compact-desk[data-studio-view=research] .theater-station[data-station=debate]{flex:1.8 1 0}
  .compact-desk[data-studio-view=research] .theater-station[data-station=risk]{flex:1.45 1 0}
  .compact-desk[data-studio-view=research] .theater-station[data-station=chair]{flex:1.35 1 0}
  /* The band being written is always the tallest one: a fixed share left 04 and 05 showing a sliver
     of the opinion they were in the middle of writing, which is the one a member is watching. */
  .compact-desk[data-studio-view=research] .theater-station[data-state=active]:not([data-station=collect]){flex-grow:2.55}
  /* The interrupted band takes what its failure block and its finished columns need — no more, and
     never so little that the retry button is clipped out of a board that does not scroll. */
  .compact-desk[data-studio-view=research] .theater-station[data-state=failed]{flex:0 0 164px}
  /* the text field: how each band divides its width */
  .compact-desk[data-studio-view=research] .theater-station[data-station=analysis] .theater-field{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));grid-template-rows:minmax(0,1fr)}
  .compact-desk[data-studio-view=research] .theater-station[data-station=analysis] .theater-col+.theater-col{padding-left:22px;border-left:1px solid var(--th-rule)}
  .compact-desk[data-studio-view=research] .theater-station[data-station=analysis] .theater-col{padding-right:22px}
  .compact-desk[data-studio-view=research] .theater-station[data-station=debate] .theater-field{display:grid;grid-template-rows:minmax(0,1fr) auto}
  .compact-desk[data-studio-view=research] .theater-station[data-station=collect] .theater-field{display:grid;grid-template-rows:minmax(0,1fr) auto;padding-top:0}
  /* 04 gives its whole width to the one opinion it holds: its verdict chip rides in the column head,
     so no 320px apparatus column is reserved for lines that never arrive. Only 05 keeps one. */
  .compact-desk[data-studio-view=research] .theater-station[data-station=risk] .theater-field{display:grid;grid-template-rows:minmax(0,1fr) auto}
  .compact-desk[data-studio-view=research] .theater-station[data-station=chair] .theater-field{display:grid;grid-template-columns:minmax(0,1fr) 300px;grid-template-rows:minmax(0,1fr);column-gap:22px}
  .compact-desk[data-studio-view=research] .theater-station[data-station=chair] .theater-apparatus{padding-left:22px;border-left:1px solid var(--th-rule)}
  .compact-desk[data-studio-view=research] .theater-station:is([data-station=risk],[data-station=chair]) .theater-col{--th-measure:min(100%,86ch)}
  /* a review line sits in the band it checks (02 sources, 04 committee): a row across the foot of the band */
  .compact-desk[data-studio-view=research] .theater-station:is([data-station=analysis],[data-station=risk]) .theater-apparatus{grid-column:1/-1;flex-direction:row;align-items:center;gap:12px;padding-top:4px;border-top:1px solid var(--th-rule-fine)}
  .compact-desk[data-studio-view=research] .theater-station:is([data-station=analysis],[data-station=risk]) .theater-review{font-size:11px;line-height:1.5}
  /* the failure block and the wait line always span the whole field */
  .compact-desk[data-studio-view=research] .theater-failure,
  .compact-desk[data-studio-view=research] .theater-wait{grid-column:1/-1}
  .compact-desk[data-studio-view=research] .theater-wait{padding-top:6px}
  .compact-desk[data-studio-view=research] .theater-station[data-state=upcoming]:has(.theater-wait) .theater-skeleton{display:none}
  /* the interrupted band gives its first row to the one-line failure block and keeps the rest for the
     columns that DID finish — a completed 상승 관점 must not vanish because its opposite failed */
  .compact-desk[data-studio-view=research] .theater-station[data-state=failed] .theater-field{grid-template-rows:auto minmax(0,1fr) auto}
  /* the board never overflows here, so the follow button can never be needed */
  .compact-desk[data-studio-view=research] .theater-follow{display:none!important}

  /* ── 정판 / imposition: 01–04 compact to one head line, 05 takes the sheet ── */
  .compact-desk[data-studio-view=research] .theater-board.is-resolved .theater-station:not([data-station=chair]){flex:0 0 62px}
  .compact-desk[data-studio-view=research] .theater-board.is-resolved .theater-station[data-station=chair]{flex:1 1 0}
  .compact-desk[data-studio-view=research] .theater-board.is-resolved .theater-station:not([data-station=chair]) .theater-col-body,
  .compact-desk[data-studio-view=research] .theater-board.is-resolved .theater-station:not([data-station=chair]) .theater-col-rule,
  .compact-desk[data-studio-view=research] .theater-board.is-resolved .theater-station:not([data-station=chair]) .theater-wait{display:none}
  .compact-desk[data-studio-view=research] .theater-board.is-resolved .theater-station:not([data-station=chair]) :is(.theater-apparatus-kicker,.theater-review){display:none}
  /* A compacted gutter is one glyph in a 31px row: the stacked mark, check and state word overflowed
     upward into the head and painted over the 01…05 folio that anchors the whole board. */
  .compact-desk[data-studio-view=research] .theater-board.is-resolved .theater-station:not([data-station=chair]) .theater-gutter{flex-direction:row;align-items:center;gap:6px;padding:0 12px 0 0;background:var(--p-surface-2)}
  .compact-desk[data-studio-view=research] .theater-board.is-resolved .theater-station:not([data-station=chair]) .theater-gutter-state{display:none}
  .compact-desk[data-studio-view=research] .theater-board.is-resolved .theater-station:not([data-station=chair]) .theater-station-mark .p-icon{width:16px;height:16px}
  .compact-desk[data-studio-view=research] .theater-board.is-resolved .theater-station[data-station=chair] .theater-gutter{background:var(--p-surface-2)}
  /* the conclusion sits in the middle of the sheet it was given, rather than at the top of it with
     150px of blank paper underneath — the band is the whole point of the resolve */
  .compact-desk[data-studio-view=research] .theater-board.is-resolved .theater-station[data-station=chair] .theater-col-body{justify-content:center}
  .compact-desk[data-studio-view=research] .theater-board.is-resolved .theater-station[data-station=chair] .theater-apparatus{justify-content:center}
  /* 03 compacts like the others: the vs track and the mark between the two sides collapse, so the
     two column heads sit on one line instead of being sliced to a 7px strip of glyph tops. */
  .compact-desk[data-studio-view=research] .theater-board.is-resolved .theater-pair{grid-template-columns:minmax(0,1fr) minmax(0,1fr);overflow:visible}
  .compact-desk[data-studio-view=research] .theater-board.is-resolved .theater-vs{display:none}
  .compact-desk[data-studio-view=research] .theater-board.is-resolved .theater-pair>.theater-col:first-of-type{padding-right:22px}
  .compact-desk[data-studio-view=research] .theater-board.is-resolved .theater-pair>.theater-col:last-of-type{padding-left:22px;border-left:1px solid var(--th-rule)}
  /* 01 compacts to four labelled facts on one line */
  .compact-desk[data-studio-view=research] .theater-board.is-resolved .theater-station[data-station=collect] .theater-fact{flex-direction:row;align-items:baseline;gap:8px}
  .compact-desk[data-studio-view=research] .theater-board.is-resolved .theater-station[data-station=collect] .theater-fact-text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
}

/* ════════════════════════════════════════════════════════════════════════
   §11 NARROW / SHORT — a stated fallback: the board becomes a document-flow
   list, the page scrolls and the follow button re-arms by itself.
   ════════════════════════════════════════════════════════════════════════ */
@media (max-width:900px),(max-height:640px){
  .theater-board{padding-inline:18px}
  .theater-col-body{max-height:168px}
  .theater-col+.theater-col{margin-top:18px;padding-top:18px;border-top:1px solid var(--th-rule-fine)}
  .theater-apparatus{margin-top:14px;padding-top:10px;border-top:1px solid var(--th-rule-fine);border-left:0}
  .theater-facts{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
  .theater-fact{padding:0;border-left:0}
  .theater-pair{display:block;overflow:visible}
  .theater-vs{display:block;width:100%;margin:14px 0;text-align:center}
  .theater-vs::before,.theater-vs::after{display:none}
  .theater-station{padding-bottom:16px}
  /* stacked, the gutter sits directly under a head that already prints the same word, so the margin
     annotation keeps its mark and drops the repeat. The markup keeps it; only the screen does not. */
  .theater-gutter{flex-direction:row;align-items:center;gap:8px;padding:8px 10px;margin-top:8px;background:transparent}
  .theater-gutter-state{display:none}
  .theater-gutter-rule{display:none}
  .theater-board.is-resolved .theater-station{max-height:none}
  .theater-failure .p-button{margin-left:0}
}
@media (max-width:390px){
  .theater{--th-gutter:0}
  .theater-board{padding-inline:14px}
  .theater-draft-note,.theater-margin{padding-inline:14px}
  .theater-station-head{gap:8px;padding-inline:0}
  .theater-gutter{gap:6px;padding:6px 0 0;margin-top:0}
  .theater-station-mark .p-icon{width:16px;height:16px}
  .theater-col-body{max-height:150px}
  .theater-facts{display:block}
  .theater-fact+.theater-fact{margin-top:8px}
  .theater-live,.theater-text p,.theater-station-copy{font-size:13px;--th-lead:1.8}
  .theater-stance .stance{font-size:28px}
  .theater .focus-actions{flex-wrap:wrap;justify-content:flex-end}
}

/* ════════════════════════════════════════════════════════════════════════
   Reduced motion. The STRUCTURE is byte-identical in both modes — five
   stations, fixed heights, clamped columns, the same rules and margins.
   Only the arrival changes: everything is simply already there.
   ════════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion:reduce){
  #research-focus.is-handoff{transition:none}
  .theater :is(.theater-sweep,.theater-caret,.theater-col-rule,.theater-live-tail,.theater-stance,.theater-stance .stance,.theater-folio,.theater-station,.theater-station-head,.theater-thesis,.theater-gutter,.theater-col-head .studio-section-kicker,.theater-skeleton i,.theater-erase),
  .theater .discovery-status.scanning::before,
  .theater-tile .discovery-status.scanning::before{animation:none!important;transition:none!important}
  .theater .theater-col-rule{transform:scaleY(1)}
  .theater .theater-sweep{opacity:0}
  .theater .theater-live-tail,.theater .theater-live-tail.is-wet{filter:none!important}
  .theater .theater-stance::after{transform:scaleX(1)}
  .theater .theater-skeleton i{background-image:none;background-color:var(--th-blank)}
  .theater .theater-station{transition:none!important}
  .theater .theater-erase{display:none}
}
:is(.premier-motion-reduced,.premier-motion-paused) .theater :is(.theater-sweep,.theater-caret,.theater-col-rule,.theater-live-tail,.theater-stance,.theater-stance .stance,.theater-folio,.theater-station,.theater-station-head,.theater-thesis,.theater-gutter,.theater-col-head .studio-section-kicker,.theater-skeleton i,.theater-erase),
:is(.premier-motion-reduced,.premier-motion-paused) .theater .discovery-status.scanning::before,
:is(.premier-motion-reduced,.premier-motion-paused) .theater-tile .discovery-status.scanning::before{animation:none!important;transition:none!important}
:is(.premier-motion-reduced,.premier-motion-paused) .theater .theater-col-rule{transform:scaleY(1)}
:is(.premier-motion-reduced,.premier-motion-paused) .theater .theater-sweep{opacity:0}
:is(.premier-motion-reduced,.premier-motion-paused) .theater .theater-live-tail,
:is(.premier-motion-reduced,.premier-motion-paused) .theater .theater-live-tail.is-wet{filter:none!important}
:is(.premier-motion-reduced,.premier-motion-paused) .theater .theater-stance::after{transform:scaleX(1)}
:is(.premier-motion-reduced,.premier-motion-paused) .theater .theater-skeleton i{background-image:none;background-color:var(--th-blank)}
:is(.premier-motion-reduced,.premier-motion-paused) .theater .theater-station{transition:none!important}
  .theater .theater-station{transition:none!important}
:is(.premier-motion-reduced,.premier-motion-paused) .theater .theater-erase{display:none}
