/* CodeChat — front end styles. Namespaced under .codechat-root so themes don't fight it. */



.codechat-root {
	--cc-accent: #3b5bdb;
	--cc-bg: #f7f6f3;
	--cc-panel: #fffefc;
	--cc-line: #e6e3dd;
	--cc-ink: #2b2a27;
	--cc-quiet: #7c7972;
	--cc-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	height: auto;
	max-height: var(--cc-max, min(82vh, 960px));
	min-height: var(--cc-min, min(62vh, 560px));
	max-width: 900px;
	margin: 0 auto;
	background: var(--cc-bg);
	color: var(--cc-ink);
	font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
	font-size: 15px;
	line-height: 1.5;
	-webkit-text-size-adjust: 100%;
	text-size-adjust: 100%;
	border: 1px solid var(--cc-line);
	border-radius: 14px;
	overflow: hidden;
	-webkit-font-smoothing: antialiased;
}
.codechat-root *, .codechat-root *::before, .codechat-root *::after { box-sizing: border-box; }
.codechat-root.cc-centered { align-items: center; justify-content: center; }
.cc-boot { margin: auto; color: var(--cc-quiet); font-family: var(--cc-mono); font-size: 12px; }

.cc-shell { display: flex; flex-direction: column; flex: 1; min-height: 0; padding: 0 22px; }

/* gate */
.cc-gate { display: flex; flex-direction: column; align-items: center; gap: 26px; padding: 40px 22px; width: 100%; }
.cc-gate-head { display: flex; flex-direction: column; gap: 8px; align-items: center; text-align: center; }
.cc-eyebrow { font-family: var(--cc-mono); font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--cc-quiet); }
.cc-gate-title { margin: 0; font-size: 30px; font-weight: 600; letter-spacing: -.02em; }
.cc-gate-sub { margin: 0; max-width: 340px; color: #5c5a55; font-size: 15px; }
.cc-card { display: flex; flex-direction: column; gap: 10px; width: 100%; max-width: 400px; padding: 22px; background: var(--cc-panel); border: 1px solid var(--cc-line); border-radius: 14px; box-shadow: 0 8px 24px rgba(0,0,0,.04); }
.cc-label { font-family: var(--cc-mono); font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: var(--cc-quiet); }
.cc-input { width: 100%; padding: 12px 14px; font: inherit; font-size: max(16px, 1rem); color: var(--cc-ink); background: #fff; border: 1px solid #d9d5ce; border-radius: 9px; outline: none; }
.cc-input:focus { border-color: var(--cc-accent); box-shadow: 0 0 0 3px rgba(59,91,219,.14); }
.cc-input-code { font-family: var(--cc-mono); font-size: 20px; letter-spacing: .08em; text-transform: uppercase; }
.cc-error { padding: 9px 11px; font-size: 13px; color: #8c2f1c; background: #fbeae6; border-radius: 7px; }

.cc-btn { padding: 12px 16px; font: inherit; font-size: 15px; font-weight: 500; color: #fff; background: var(--cc-accent); border: none; border-radius: 9px; cursor: pointer; }
.cc-btn:disabled { opacity: .6; cursor: default; }
.cc-btn-dark { background: #2b2a27; }
.cc-btn-dark:hover { background: #46443f; }
.cc-btn-sm { padding: 7px 12px; font: inherit; font-size: 13px; color: #3a3833; background: #fff; border: 1px solid var(--cc-line); border-radius: 7px; cursor: pointer; }
.cc-btn-sm:hover { border-color: #b9b4ab; }

/* header */
.cc-head { display: flex; align-items: center; gap: 12px; padding: 16px 2px 14px; border-bottom: 1px solid var(--cc-line); }
.cc-head-left { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.cc-room-name { font-size: 17px; font-weight: 600; letter-spacing: -.01em; }
.cc-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-family: var(--cc-mono); font-size: 10.5px; color: var(--cc-quiet); }
.cc-sep { color: #cdc9c1; }
.cc-sync { display: inline-flex; align-items: center; gap: 5px; }
.cc-dot { width: 6px; height: 6px; border-radius: 50%; background: #2f855a; }
.cc-chip { display: inline-flex; align-items: center; height: 30px; padding: 0 11px; font-family: var(--cc-mono); font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase; color: #55524c; background: #fff; border: 1px solid var(--cc-line); border-radius: 7px; cursor: pointer; }
.cc-chip:hover { border-color: #b9b4ab; }
.cc-chip-quiet { background: transparent; border-color: transparent; color: var(--cc-quiet); }
/* Both header chips centre on the meta line ("synced just now"), not on the
   two-line name+meta block, so they read as part of that row. */
.cc-head > .cc-chip,
.cc-leave { align-self: flex-end; transform: translateY(7px); }

.cc-modbar { display: flex; flex-wrap: wrap; align-items: center; gap: 9px; margin-top: 14px; padding: 13px; background: var(--cc-panel); border: 1px solid var(--cc-line); border-radius: 11px; }

/* stream */
/* flex: 0 1 auto — takes only the room the messages need, scrolls once it hits
   the container's max-height, so the composer stays under the last message. */

/* Bottom-aligned via margin-top:auto on the first child, NOT justify-content:
   flex-end — flex-end pushes overflow past the scroll container's start edge,
   where it can't be scrolled back to, so older messages become unreachable. */
.cc-list { flex: 0 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 18px; overflow-y: auto; overscroll-behavior: contain; overflow-anchor: none; scrollbar-width: thin; scrollbar-color: #14130f transparent; padding: 22px 16px 18px 2px; }
/* With no messages the empty-state copy sits above the composer. Once messages
   arrive that element is hidden, so the first actual row—not the hidden empty
   node—must take the auto margin. */
.cc-list > :first-child { margin-top: auto; }
.cc-list.cc-has-messages > .cc-empty + .cc-row { margin-top: auto; }

.cc-list::-webkit-scrollbar { width: 3px; }
.cc-list::-webkit-scrollbar-thumb { background: #14130f; border-radius: 3px; }
.cc-empty { display: flex; flex-direction: column; gap: 4px; padding: 2px 0 6px; color: var(--cc-quiet); }
.cc-empty-1 { font-size: 14px; }
.cc-welcome { display: flex; align-items: center; justify-content: flex-end; gap: 12px; font-family: var(--cc-mono); font-size: 12px; font-style: italic; text-align: right; color: var(--cc-quiet); }
.cc-welcome-timer { flex: none; color: #a09c94; }
.cc-empty-2 { font-family: var(--cc-mono); font-size: 11px; }

.cc-row { display: flex; animation: cc-in .18s ease-out; }
.cc-row.cc-grouped { margin-top: -12px; }
.cc-row.cc-grouped .cc-byline { display: none; }

/* The moderator's own posts sit on the opposite side, so who is answering is
   legible before a word is read. Everyone in the room sees this, not just them. */
.cc-row.cc-mod-post { justify-content: flex-end; }
.cc-row.cc-mod-post > .cc-body { flex: 0 1 auto; max-width: 86%; align-items: flex-end; }
.cc-row.cc-mod-post .cc-text { text-align: right; }
.cc-row.cc-mod-post .cc-byline { justify-content: flex-end; }
@keyframes cc-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.cc-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
/* Centred rather than baseline-aligned: the row mixes a pill, Latin text, Hangul
   and monospace digits, and only centring lines all four up. */
.cc-byline { display: flex; align-items: center; gap: 8px; flex-wrap: wrap-reverse; }
/* The name must never be the thing that gives: on narrow screens a squeezed
   Hangul name breaks one glyph per line, so it stays intrinsic and the verdict
   buttons wrap to their own line instead. */
.cc-author { font-size: 13px; font-weight: 600; letter-spacing: .01em; flex: 0 0 auto; min-width: max-content; white-space: nowrap; word-break: keep-all; overflow-wrap: normal; }
/* Quiet by design: it should read as a credential, not a decoration. Height and
   line-height are fixed so the pill centres on the name whatever script the name
   is written in — Hangul and Latin sit on different baselines. */
.cc-badge { flex: none; align-self: center; display: inline-flex; align-items: center; height: 17px; padding: 0 6px; font-family: var(--cc-mono); font-size: 9px; line-height: 1; letter-spacing: .14em; text-transform: uppercase; color: #3ad9f7; background: #070b10; border: 1px solid #3ad9f7; border-radius: 5px; }
.cc-time { font-family: var(--cc-mono); font-size: 10.5px; color: #8e8b84; }
.cc-del { padding: 1px 6px; font-family: var(--cc-mono); font-size: 10.5px; color: #a09c94; background: transparent; border: none; border-radius: 5px; cursor: pointer; }
.cc-del:hover { color: #8c2f1c; background: #fbeae6; }
.cc-del[disabled] { opacity: .55; cursor: default; }
.cc-del-armed { color: #8c2f1c; background: #fbeae6; }
.cc-text { max-width: 62ch; font-size: 15px; line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere; text-wrap: pretty; }

/* Moderator verdicts. The tint sits on the body rather than the row so it hugs
   the message instead of the full transcript width. */
.cc-row.cc-v-ok > .cc-body,
.cc-row.cc-v-part > .cc-body,
.cc-row.cc-v-bad > .cc-body {
	padding: 10px 13px;
	border-radius: 11px;
	/* Hug the message: the tint should end where the text does, not run the
	   full transcript width. */
	flex: 0 1 auto;
	align-self: flex-start;
	width: fit-content;
	max-width: 100%;
}
/* The ruling is a quiet aside outside the box: beside it when the row has room,
   otherwise under its bottom corner (see placeVerdictMark). */
.cc-row.cc-vrow { flex-wrap: wrap; align-items: flex-end; }
.cc-vmark { flex: 0 0 auto; margin: 0 0 2px 10px; opacity: .72; font-family: var(--cc-mono); font-style: italic; font-size: 11.5px; letter-spacing: .02em; line-height: 1.3; white-space: nowrap; }
.cc-vmark-below { flex-basis: 100%; max-width: 100%; margin: 3px 0 0; text-align: right; }
/* A moderator's own post hangs right, so its label belongs on the left of the box. */
.cc-row.cc-mod-post .cc-vmark { order: -1; margin: 0 10px 2px 0; }
.cc-row.cc-mod-post .cc-vmark-below { order: 0; margin: 3px 0 0; }
.cc-vmark-ok { color: #2f6b45; }
.cc-vmark-part { color: #7a6420; }
.cc-vmark-bad { color: #8d3b34; }

.cc-row.cc-mod-post.cc-v-ok > .cc-body,
.cc-row.cc-mod-post.cc-v-part > .cc-body,
.cc-row.cc-mod-post.cc-v-bad > .cc-body { align-self: flex-end; }
.cc-row.cc-v-ok > .cc-body { background: #f1f7f0; box-shadow: inset 0 0 0 1px #cfe1cc; }
.cc-row.cc-v-part > .cc-body { background: #fbf6e8; box-shadow: inset 0 0 0 1px #e6dbb8; }
.cc-row.cc-v-bad > .cc-body { background: #fbf1f0; box-shadow: inset 0 0 0 1px #e7d0cd; }
.cc-vbtns { display: inline-flex; gap: 3px; margin-left: auto; align-self: center; }
.cc-vbtn { flex: none; width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center; font-size: 11px; line-height: 1; color: #8a867e; background: #fff; border: 1px solid var(--cc-line); border-radius: 8px; cursor: pointer; }
.cc-vbtn:hover { border-color: #b9b4ab; }
.cc-vbtn[disabled] { opacity: .5; cursor: default; }
.cc-vbtn-ok.cc-vbtn-on { color: #fff; background: #5f8f57; border-color: #5f8f57; }
.cc-vbtn-part.cc-vbtn-on { color: #fff; background: #c19a3e; border-color: #c19a3e; }
.cc-vbtn-bad.cc-vbtn-on { color: #fff; background: #b0605a; border-color: #b0605a; }

/* A quote reads as a quote: an indent and a rule, not a card. */
.cc-quote { display: flex; flex-direction: row; align-items: center; gap: 9px; width: fit-content; max-width: 46ch; padding: 4px 0 4px 10px; text-align: left; background: transparent; border: none; border-left: 2px solid #d5d1c9; cursor: pointer; }
.cc-quote:hover { border-left-color: var(--cc-accent); }
.cc-quote-col { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cc-quote-mic { flex: none; display: flex; align-items: center; color: #c0392b; }
.cc-quote-who { font-family: var(--cc-mono); font-size: 13px; font-weight: 700; line-height: 1.4; color: var(--cc-quiet); }
.cc-quote-line { font-size: 13px; line-height: 1.4; color: #6b6862; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
@keyframes cc-flash { 0%, 100% { background: transparent; } 25% { background: rgba(59,91,219,.10); } }
.cc-row.cc-flash { animation: cc-flash 1s ease-out; border-radius: 11px; }

.cc-replybar { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 8px; padding: 8px 10px; background: #f2f0ec; border: 1px solid var(--cc-line); border-radius: 10px; }
.cc-replybar-text { flex: 1; min-width: 0; display: flex; flex-direction: row; align-items: center; gap: 9px; }
.cc-replybar-x { flex: none; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; font-size: 12px; color: var(--cc-quiet); background: transparent; border: none; border-radius: 7px; cursor: pointer; }
.cc-replybar-x:hover { color: var(--cc-ink); background: #e6e3dd; }
@media (max-width: 640px) {
	.cc-vbtn { width: 30px; height: 30px; }
}

/* audio */
.cc-audio-wrap { display: flex; flex-direction: column; gap: 6px; max-width: 460px; }
.cc-audio { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; padding: 10px 14px 10px 10px; background: var(--cc-panel); border: 1px solid var(--cc-line); border-radius: 11px; }

/* The memo drops onto its own line inside the clip's box — a note kept with the
   recording rather than a message of its own. */
.cc-memo { flex: 0 0 100%; margin-top: 2px; padding-top: 7px; font-family: var(--cc-mono); font-size: 11px; line-height: 1.5; color: #6b6862; border-top: 1px solid var(--cc-line); overflow-wrap: anywhere; }
.cc-memo-edit { display: block; width: 100%; min-height: 0; font: inherit; font-family: var(--cc-mono); font-size: 11px; color: var(--cc-ink); background: transparent; border: none; border-top: 1px solid var(--cc-line); border-radius: 0; outline: none; resize: none; overflow: hidden; }
.cc-memo-edit::placeholder { color: #b0aca4; }
.cc-memo-edit:focus { border-top-color: var(--cc-accent); }
.cc-play { flex: none; width: 34px; height: 34px; display: flex; align-items: center; justify-content: center; font-size: 12px; color: #fff; background: #2b2a27; border: none; border-radius: 50%; cursor: pointer; }
.cc-play:hover { background: #46443f; }
.cc-play:disabled { background: #b9b4ab; cursor: default; }
.cc-wave { flex: 1; min-width: 0; display: flex; align-items: center; gap: 2px; height: 28px; cursor: pointer; }
.cc-bar { flex: 1; border-radius: 2px; background: #d5d1c9; transition: background .12s linear; }
.cc-bar-on { background: var(--cc-accent); }
.cc-audio-clock { flex: none; min-width: 34px; text-align: right; font-family: var(--cc-mono); font-size: 11px; color: #6b6862; }
.cc-expiry { padding-left: 4px; font-family: var(--cc-mono); font-size: 10.5px; color: var(--cc-quiet); }
.cc-expiry-soon { color: #8c2f1c; }
.cc-tomb { display: flex; align-items: center; max-width: 460px; padding: 10px 14px; font-family: var(--cc-mono); font-size: 11px; color: var(--cc-quiet); border: 1px dashed #d9d5ce; border-radius: 11px; }

/* composer */
.cc-composer { padding: 0 0 20px; }
.cc-bar-row { display: flex; align-items: flex-end; gap: 8px; padding: 8px 8px 8px 14px; background: var(--cc-panel); border: 1px solid var(--cc-line); border-radius: 12px; }
/* max() guards against a host theme shrinking the root font size: anything under
   16px makes mobile browsers magnify the page on focus. */
.cc-msg { flex: 1; min-width: 0; padding: 9px 0; font: inherit; font-size: max(16px, 1rem); line-height: 1.45; color: var(--cc-ink); background: transparent; border: none; outline: none; resize: none; overflow-y: auto; max-height: 132px; scrollbar-width: none; -ms-overflow-style: none; }
/* Chrome on Android paints a standing scrollbar thumb inside the composer, which
   reads as a stray grey rule beside the placeholder. Scrolling still works. */
.cc-msg::-webkit-scrollbar { width: 0; height: 0; }
/* The composer row aligns to flex-end so the textarea grows downward — which
   left this label sitting on the row's baseline, below the round button beside
   it. Give it the button's height and center inside that, so it stays optically
   centred on the button no matter how tall the textarea gets. */
.cc-reclabel { flex: none; align-self: flex-end; height: 38px; display: flex; align-items: center; font-family: var(--cc-mono); font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: #b3402a; user-select: none; }
.cc-rec { flex: none; width: 38px; height: 38px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 15px; color: #b3402a; background: #fff; border: 1px solid var(--cc-line); cursor: pointer; }
.cc-rec:hover { border-color: #ddab9e; background: #fdf3f0; }
.cc-send { height: 38px; padding: 0 16px; font-size: 14px; }
.cc-note-hidden { display: none; }
.cc-note { display: flex; justify-content: space-between; gap: 12px; padding: 7px 4px 0; font-family: var(--cc-mono); font-size: 10px; color: #8e8b84; }
.cc-locked { margin-bottom: 8px; padding: 10px; text-align: center; font-family: var(--cc-mono); font-size: 11px; color: var(--cc-quiet); background: #f2f0ec; border: 1px solid var(--cc-line); border-radius: 10px; }
/* Frozen, not emptied: the draft stays legible so it is obviously still there. */
.cc-msg-frozen { color: #9a968e; background: #f4f2ee; }

.cc-recbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 12px; padding: 12px 14px; background: #fdf3f0; border: 1px solid #eccdc3; border-radius: 12px; }
.cc-recinfo { flex: 1 1 200px; min-width: 0; display: flex; align-items: center; gap: 10px; }
.cc-recactions { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; }
.cc-recdot { width: 9px; height: 9px; border-radius: 50%; background: #c0392b; animation: cc-pulse 1.1s ease-in-out infinite; }
@keyframes cc-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
.cc-recclock { font-family: var(--cc-mono); font-size: 13px; color: #8c3a25; white-space: nowrap; }
.cc-recclock-warn { color: #b7472a; }
.cc-recdot-quiet { background: #c9bfae; }
.cc-meter { flex: 1 1 0; min-width: 0; display: flex; align-items: flex-end; justify-content: flex-end; gap: 2px; height: 24px; overflow: hidden; }
.cc-mbar { flex: 1 1 0; min-width: 0; max-width: 3px; border-radius: 2px; background: #c0392b; transition: height .07s linear; }
.cc-meter-quiet .cc-mbar { background: #d8cfc2; }
.cc-spacer { flex: 1; }
.cc-btn-rec { background: #b7472a; }

/*
 * The sheet — the whole mobile layout.
 *
 * Fixed to the visual viewport. iOS moves that viewport upward as it reveals a
 * focused field, so merely subtracting the keyboard from `bottom` clips the
 * sheet's top (and its existing messages). --cc-vv-top and --cc-vv-height keep
 * the whole sheet in the viewport Safari is actually showing.
 */
.codechat-root.cc-sheet {
	position: fixed;
	top: var(--cc-vv-top, 0px);
	left: 0;
	right: 0;
	bottom: auto;
	width: auto;
	max-width: none;
	height: var(--cc-vv-height, 100dvh);
	min-height: 0;
	max-height: none;
	margin: 0;
	border: none;
	border-radius: 0;
	/* Opaque: it covers the page, and a theme may have made the resting state
	   transparent. */
	background: var(--cc-bg);
	z-index: 99999;
	overflow: hidden;
	/* Keyboards on iOS overlay the sheet during the first frames of their
	   animation; containing paint stops the transcript bleeding past the edge. */
	contain: paint;
}
/* Undo the negative page-edge margin: full-bleed already. */
.codechat-root.cc-sheet .cc-shell { height: 100%; min-height: 0; padding-inline: 16px; }
/* Basis 0, not auto: with the keyboard up and a multi-line message there may be
   almost no height to go round, and the transcript is what yields. */
.codechat-root.cc-sheet .cc-list { flex: 1 1 0; }
/* The field's ceiling has to be a share of what is actually visible, not a fixed
   132px — otherwise a four-line message plus the keyboard pushes the send button
   off the bottom of the sheet. */
.codechat-root.cc-sheet .cc-msg { max-height: min(132px, calc(var(--cc-vv-height, 100dvh) * 0.3)); }
/* Home-indicator gap, only where there is one. */
.codechat-root.cc-sheet .cc-composer { padding-bottom: max(12px, env(safe-area-inset-bottom)); }
.codechat-root.cc-sheet .cc-head { padding-top: max(14px, env(safe-area-inset-top)); }

/*
 * Phones, sheet closed: an ordinary block in the page with its own scroller. No
 * measured height — a fraction of the small viewport is stable regardless of what
 * the page puts above it, and the sheet is what handles the keyboard.
 */
@media (max-width: 900px) {
	.codechat-root {
		height: 70svh;
		min-height: 0;
		max-height: none;
		overflow: hidden;
	}
	.cc-list {
		flex: 1 1 auto;
		min-height: 0;
		overflow-y: auto;
		overscroll-behavior: contain;
		padding-bottom: 12px;
	}
	.cc-composer { position: static; padding-top: 8px; }
}

@media (max-width: 640px) {
	/* Reclaim width: tighter internal padding, and lean a little past the
	   theme's content padding without going full-bleed. */
	.codechat-root { margin-inline: -6px; border-radius: 10px; }
	/* No height floor on phones: the room should be exactly as tall as its
	   content. A vh-based minimum leaves dead space under the composer, and with
	   the keyboard open iOS still reports the full viewport height, so that gap
	   grows instead of shrinking. */
	.cc-shell { padding: 0 14px; }
	.cc-list { padding: 16px 14px 12px 0; gap: 15px; }
	.cc-composer { padding-bottom: 12px; }
	.cc-head { padding: 16px 2px 12px; }
	.cc-bar-row { padding: 7px 7px 7px 12px; }
	.cc-gate { padding: 28px 12px; }
	.cc-note { flex-direction: column; gap: 3px; }
	.cc-rec { width: 44px; height: 44px; }
	.cc-reclabel { height: 44px; }
	.cc-send { min-height: 44px; }
	/* Keep the meter beside the timer, but move it away from the screen edge so
	   the recording row feels balanced on narrow phones. */
	.cc-recinfo { flex: 1 1 100%; }
	.cc-meter { transform: translateX(-32px); }
	.cc-recactions { flex: 1 1 100%; }
	.cc-recactions button { flex: 1; min-height: 44px; justify-content: center; }
	.cc-recclock { white-space: normal; }
	.cc-play { width: 44px; height: 44px; }
}

/*
 * Desktop: the room sticks inside the page rather than scrolling away.
 *
 * A room in normal page flow means two nested scroll containers, and the outer
 * one decides whether you can see the inner one's composer. Scroll the page so
 * the room's top meets the viewport top and the composer — the last thing in the
 * room — sits below the fold, with nothing on screen to suggest it exists. People
 * scrolled the transcript looking for it.
 *
 * Sticky pins the room once it reaches the top of the viewport, and the height is
 * capped to what the viewport can actually show, so the composer is on screen
 * whenever the room is. Where the room's own container is no taller than the room,
 * sticky is inert and this changes nothing.
 *
 * These rules live at the end of the file on purpose: they override the base
 * .codechat-root block above, and a media query adds no specificity of its own.
 */
@media (min-width: 901px) {
	.codechat-root:not(.cc-sheet) {
		--cc-stick-top: 14px;
		position: sticky;
		top: var(--cc-stick-top);
		max-height: min(
			var(--cc-max, min(82vh, 960px)),
			calc(100dvh - var(--cc-stick-top) - 14px)
		);
	}
	/* The admin bar is fixed over the top of the viewport, so it has to come out of
	   both the offset and the height. */
	body.admin-bar .codechat-root:not(.cc-sheet) { --cc-stick-top: 46px; }

	/*
	 * A drawn frame, desktop only: one box, three bands, the middle one scrolls.
	 *
	 * The frame is drawn on .cc-shell, not on .codechat-root. The root carries a
	 * border of its own in the base styles, but a host theme can and does win
	 * against it — a block theme's layout rules reach the shortcode's own wrapper,
	 * and when they strip its box the header and composer rules were left hanging
	 * in space with no sides to meet. The shell is the plugin's own element,
	 * untouched by the theme, and it is exactly the box that holds the three bands.
	 */
	.codechat-root:not(.cc-sheet) { --cc-frame: #14130f; }
	.codechat-root:not(.cc-sheet) .cc-shell {
		border: 1px solid var(--cc-frame);
		border-radius: 12px;
		/* The panel colour moves with the frame, so the box reads as one surface
		   against whatever the theme puts behind it. */
		background: var(--cc-bg);
		/* Clips the two internal rules to the frame's rounded corners. */
		overflow: hidden;
	}
	.codechat-root:not(.cc-sheet) .cc-head { border-bottom: 1px solid var(--cc-frame); }
	/* The composer's own rule, so the scrolling band is bounded on both sides. */
	.codechat-root:not(.cc-sheet) .cc-composer {
		border-top: 1px solid var(--cc-frame);
		margin-top: 0;
		padding-top: 14px;
	}
	/*
	 * The shell's side padding would inset the two rules and leave the frame
	 * looking unfinished at the corners, so they reach out to it and pad back in.
	 * The list keeps the padding, so text still clears the frame.
	 */
	.codechat-root:not(.cc-sheet) .cc-head,
	.codechat-root:not(.cc-sheet) .cc-composer {
		margin-inline: -22px;
		padding-inline: 22px;
	}
	/* Nothing may sit outside the frame now that the frame is the shell. */
	.codechat-root:not(.cc-sheet) { border-width: 0; background: transparent; }
}
