:root {
  --primary: #0f5c8c;
  --primary-dark: #0b4568;
  --bg: #f4f7fa;
  --card: #ffffff;
  --text: #1e2a33;
  --muted: #66788a;
  --border: #dde4ea;
  --danger: #c0392b;
  --success: #1e8e5a;
  --radius: 10px;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; background: var(--bg); color: var(--text); height: 100%; }
body { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; }

/* ---- Left-hand navigation panel (replaces the old top bar) ---- */
:root { --side-w: 240px; }
.app-header { display: none; }                         /* nothing shown until signed in */
body.has-sidebar { padding-left: var(--side-w); }
body.has-sidebar .app-header {
  display: flex; flex-direction: column;
  position: fixed; top: 0; left: 0; bottom: 0; width: var(--side-w); z-index: 900;
  background: var(--primary-dark); color: #fff; overflow-y: auto; padding: 0.9rem 0.6rem;
}
.side-brand { font-weight: 700; font-size: 1.05rem; display: flex; align-items: center; gap: 0.55rem; padding: 0.2rem 0.5rem 0.9rem; border-bottom: 1px solid rgba(255,255,255,0.15); margin-bottom: 0.6rem; }
.brand-icon { width: 28px; height: 28px; border-radius: 7px; object-fit: cover; }
.side-nav, .side-project-nav { display: flex; flex-direction: column; gap: 2px; }
.side-project-nav { margin-top: 0.8rem; padding-top: 0.6rem; border-top: 1px solid rgba(255,255,255,0.15); }
.side-project-nav[hidden], .notif-dropdown[hidden], .notif-badge[hidden] { display: none; }
.side-label { font-size: 0.68rem; letter-spacing: 0.08em; text-transform: uppercase; color: #9fc3dc; padding: 0.3rem 0.6rem; }
.side-project-no { font-size: 0.8rem; color: #dceeff; padding: 0 0.6rem 0.4rem; word-break: break-all; }
.side-grow { flex: 1; }
.side-link {
  display: flex; align-items: center; gap: 0.6rem; width: 100%; text-align: left;
  color: #dceeff; text-decoration: none; background: none; border: none; font: inherit; font-size: 0.92rem;
  padding: 0.5rem 0.6rem; border-radius: 7px; cursor: pointer; position: relative;
}
.side-link:hover { background: rgba(255,255,255,0.13); color: #fff; }
.side-link.active { background: rgba(255,255,255,0.22); color: #fff; font-weight: 600; }
.side-icon { width: 1.3rem; text-align: center; flex: none; }
.side-tab { padding-left: 0.9rem; font-size: 0.88rem; }
.side-footer { margin-top: auto; position: sticky; bottom: -0.9rem; background: var(--primary-dark); padding: 0.8rem 0 0.9rem; z-index: 2; border-top: 1px solid rgba(255,255,255,0.15); display: flex; flex-direction: column; gap: 2px; }
.side-user { font-size: 0.85rem; padding: 0.2rem 0.6rem 0.5rem; display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; }
.dept-badge { background: rgba(255,255,255,0.2); padding: 0.15rem 0.5rem; border-radius: 999px; font-size: 0.72rem; }
.link-btn { background: none; border: none; color: #dceeff; text-decoration: underline; cursor: pointer; font: inherit; }
.side-link .notif-badge { position: static; margin-left: auto; }

/* Back button + narrow form panel */
.back-btn { margin-bottom: 0.75rem; font-weight: 600; background: var(--card); border: 1px solid var(--primary); color: var(--primary-dark); padding: 0.5rem 1rem; }
.back-btn:hover { background: #e6f1f8; }
.narrow-panel { max-width: 460px; }

/* Phone / small window: the panel becomes a slide-in drawer */
.side-toggle, .side-backdrop { display: none; }
@media (max-width: 900px) {
  body.has-sidebar { padding-left: 0; }
  body.has-sidebar .app-header { transform: translateX(-100%); transition: transform 0.2s ease; box-shadow: none; }
  body.has-sidebar.side-open .app-header { transform: translateX(0); box-shadow: 4px 0 18px rgba(0,0,0,0.3); }
  body.has-sidebar .side-toggle {
    display: block; position: fixed; top: 0.6rem; left: 0.6rem; z-index: 880; width: 40px; height: 40px;
    background: var(--primary-dark); color: #fff; border: none; border-radius: 8px; font-size: 1.3rem; cursor: pointer;
  }
  body.has-sidebar.side-open .side-backdrop { display: block; position: fixed; inset: 0; background: rgba(0,0,0,0.4); z-index: 890; }
  body.has-sidebar .app-root { padding-top: 3.6rem; }
}

.app-root { flex: 1; padding: 1.25rem; max-width: 1200px; margin: 0 auto; width: 100%; }
/* The centered, 1200px-capped column above is right for normal signed-in screens (keeps
   table/form line lengths readable), but on a pre-auth screen it was quietly fighting the
   login card's own right-alignment: .login-screen's "flex-end" was pushing against THIS
   box's edge, not the actual browser window edge - so on any window wider than 1200px the
   card stalled short of where the background image (sized against the real viewport,
   unaffected by .app-root) actually ends, and the two ended up overlapping. Removed here
   so the card can reach the real edge, matching the image underneath it. */
body.login-page .app-root { max-width: none; padding: 0; margin: 0; }

.loading, .empty-state { text-align: center; color: var(--muted); padding: 3rem 1rem; }
.error-panel { background: #fdecea; color: var(--danger); border: 1px solid #f5c6cb; padding: 1rem; border-radius: var(--radius); }

/* Login */
/* Applied to <body> only while a pre-auth screen (login/forgot/reset password) is showing -
   removed again the moment any signed-in screen renders (see renderHeader in app.js).
   login-bg.jpg is a TALL, portrait image (940x1672) - a full poster with its own top
   banner ("Plan | Track | Deliver"), centered logo/laptop/icon composition, and a footer
   band ("Project Management System"). "background-size: cover" (the previous approach)
   scales a portrait image up until it fills a typically-wider-than-tall browser window
   completely, which necessarily crops its top and bottom clean off - the banner and
   footer never showed at all on a normal desktop window, only the vertical middle slice
   did. "contain" instead guarantees the WHOLE image is always visible, letterboxed
   left/right on a wide window rather than cropped top/bottom - every detail in the
   picture stays on screen, however the window is shaped. The gradient in the second
   background layer approximates the picture's own pale-cyan-to-blue vertical tone so
   the letterboxed strips either side blend with it rather than reading as a mismatched
   plain color; it shows only where the image itself doesn't reach.
   Deliberately "scroll", not "fixed": background-attachment: fixed is unreliable on mobile
   browsers (notably iOS Safari, which mostly just doesn't support it). */
body.login-page {
  background:
    url('../images/login-bg.jpg') center center / contain no-repeat scroll,
    linear-gradient(180deg, #eaf9fb 0%, #eaf9fb 78%, #1668a3 100%);
  min-height: 100vh;
  min-height: 100dvh; /* modern mobile browsers: excludes the address bar, so this never leaves a gap as it shows/hides */
}
/* app-header is emptied (innerHTML = '') on every pre-auth screen, but .app-header's own
   padding still rendered as a bare colored strip across the top of the background image -
   collapse it entirely so the background truly fills the page edge-to-edge. */
body.login-page #app-header { display: none; }
/* With the whole image now visible (see body.login-page above), a wide/short window
   leaves genuinely empty letterboxed space to the image's left and right - the login
   card sits in that empty space on the right, instead of overlapping the picture at all.
   The image's OWN ratio (940/1672 = ~0.562) is the point where "contain" STARTS to
   letterbox left/right instead of top/bottom, but it is not a safe point to push the
   card into that space: right at that threshold the letterboxed strip is 0px wide, and
   it stays too narrow for a 360px card on plenty of ordinary desktop windows above it too
   - a 4:3 1024x768 window (aspect 1.333) already clears 940/1672 easily, yet only leaves
   ~296px of letterbox on either side, so a card pushed in there overlapped the artwork
   instead of sitting beside it. 8/5 (1.6) is chosen instead as the threshold: it's about
   where a typical desktop/laptop window's letterbox first grows wide enough to clear a
   360px card plus a comfortable margin (confirmed at 1366x768, 1440x900 and 1920x1080),
   while still excluding narrower windows like 1024x768 or a portrait/phone shape, where
   the card instead stays centered over the image - not empty space, but with the frosted
   glass treatment the image still shows through it rather than being hidden. */
.login-screen {
  display: flex; align-items: center; justify-content: center;
  min-height: 90vh;
  min-height: 90dvh;
  padding: 1.25rem;
}
@media (min-aspect-ratio: 8/5) {
  .login-screen {
    justify-content: flex-start;
    /* Not a flat vw fraction: this is the image's own actual rendered right edge (half the
       viewport width, plus half the image's contain-scaled width, since "contain" sizes a
       height-constrained image to 100vh * (940/1672) here) plus a fixed 2rem gap - so the
       card always starts just clear of the artwork itself, at any window size, rather than
       an arbitrary fraction of the window that happens to work at some sizes and overlap at
       others. */
    padding: 2rem clamp(1.5rem, 3vw, 3rem) 2rem calc(50vw + (50vh * 940 / 1672) + 2rem);
  }
}
.login-card {
  /* Frosted glass, not a flat white card: tinted just enough to keep text readable, with
     the background image showing softly through the blur behind it, so the card reads as
     part of the same picture instead of a box pasted on top of it. */
  background: rgba(255,255,255,0.82);
  backdrop-filter: blur(16px) saturate(160%);
  -webkit-backdrop-filter: blur(16px) saturate(160%);
  border: 1px solid rgba(255,255,255,0.65);
  padding: 2rem;
  border-radius: var(--radius);
  box-shadow: 0 8px 40px rgba(15,40,60,0.18);
  width: 100%;
  max-width: 360px;
}
/* Browsers with no backdrop-filter support get a near-solid card instead of a
   half-transparent one over a sharp (un-blurred) photo, which would be much harder to
   read than either the old flat card or the blurred version above. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .login-card { background: rgba(255,255,255,0.95); }
}
.login-logo { display: block; max-width: 160px; max-height: 64px; margin: 0 auto 1rem; }
.login-card h1 { font-size: 1.3rem; margin: 0 0 0.25rem; color: var(--primary-dark); text-align: center; }
.login-card .subtitle { color: var(--muted); margin: 0 0 1.25rem; font-size: 0.9rem; }
.login-card label { display: block; font-size: 0.85rem; margin: 0.75rem 0 0.25rem; color: var(--muted); }
.login-card input { width: 100%; padding: 0.6rem 0.7rem; border: 1px solid var(--border); border-radius: 8px; font-size: 1rem; }
/* One-time login code: 4 separate empty boxes (see app.js's otpBoxesHtml/bindOtpBoxes)
   instead of a single 4-character field, so each box is unmistakably empty until typed
   into rather than reading like it already holds a value. */
.otp-boxes { display: flex; gap: 0.6rem; justify-content: center; }
.otp-digit {
  width: 3rem !important; height: 3.25rem; padding: 0 !important; text-align: center;
  font-size: 1.5rem; font-weight: 600; letter-spacing: 0;
}
.otp-digit:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px rgba(15,92,140,0.15); }
.form-error { color: var(--danger); font-size: 0.85rem; margin-top: 0.6rem; min-height: 1.2em; }
.form-success { color: var(--success); font-size: 0.85rem; margin-top: 0.6rem; }
.checkbox-row { margin-top: 0.75rem; font-size: 0.85rem; color: var(--muted); }
.checkbox-row label { display: flex; align-items: center; gap: 0.4rem; margin: 0; }
.checkbox-row input[type=checkbox] { width: auto; }
.form-links { display: flex; justify-content: space-between; gap: 0.75rem; margin-top: 0.9rem; font-size: 0.85rem; flex-wrap: wrap; }
.form-links a { color: var(--primary); text-decoration: none; }
.form-links a:hover { text-decoration: underline; }

/* Buttons */
.btn { display: inline-block; padding: 0.55rem 1rem; border-radius: 8px; border: 1px solid var(--border); background: #fff; color: var(--text); cursor: pointer; font-size: 0.9rem; text-decoration: none; }
.btn:hover { border-color: var(--primary); }
.btn.primary { background: var(--primary); border-color: var(--primary); color: #fff; }
.btn.primary:hover { background: var(--primary-dark); }
.btn.danger { background: #fdecea; border-color: #f5c6cb; color: var(--danger); }
.btn.full { width: 100%; margin-top: 1rem; }

/* Toolbar / dashboard */
.toolbar { display: flex; gap: 0.6rem; flex-wrap: wrap; margin-bottom: 1rem; align-items: center; }
.toolbar .search { flex: 1; min-width: 200px; padding: 0.55rem 0.75rem; border: 1px solid var(--border); border-radius: 8px; }
.toolbar select { padding: 0.55rem 0.6rem; border: 1px solid var(--border); border-radius: 8px; background: #fff; }

.data-table { width: 100%; border-collapse: collapse; background: var(--card); border-radius: var(--radius); overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.05); }
.data-table th, .data-table td { padding: 0.65rem 0.8rem; border-bottom: 1px solid var(--border); text-align: left; font-size: 0.9rem; }
.data-table th { background: #eef3f7; color: var(--muted); font-weight: 600; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.03em; }
.data-table tbody tr.row-link { cursor: pointer; }
.data-table tbody tr.row-link:hover { background: #f5f9fc; }
.table-footer { color: var(--muted); font-size: 0.8rem; padding: 0.5rem 0.2rem; }
.table-scroll { overflow-x: auto; }

/* Freeze panes (FormRenderer.enableFreezePanes, called after any .data-table's rows are
   in the DOM): the header row stays visible while scrolling down and the first couple of
   columns stay visible while scrolling right, the same "frozen rows/columns" behaviour as
   a spreadsheet - useful once a table has more rows or columns than fit on screen at once.
   .freeze-scroll (added to the .table-scroll wrapper, not the table) is what actually
   bounds the table's height so there's something for the header to stay pinned within;
   the table itself switches to border-collapse: separate because sticky positioning and
   collapsed borders don't reliably render together across browsers - every cell already
   carries its own border-bottom, so nothing is visually lost by the switch. Rounded
   corners/shadow move from the table onto the wrapper, since the table's own overflow now
   has to stay visible for sticky to work at all. */
.table-scroll.freeze-scroll { overflow: auto; max-height: 65vh; border-radius: var(--radius); box-shadow: 0 1px 3px rgba(0,0,0,0.05); }
.data-table.freeze-panes { border-collapse: separate; border-spacing: 0; overflow: visible; border-radius: 0; box-shadow: none; }
.data-table.freeze-panes thead th { position: sticky; top: 0; z-index: 2; box-shadow: 0 1px 0 var(--border); }
.data-table.freeze-panes .frozen-col { position: sticky; z-index: 1; }
.data-table.freeze-panes tbody .frozen-col { background: var(--card); }
.data-table.freeze-panes thead .frozen-col { z-index: 3; }
.data-table.freeze-panes tbody tr.row-link:hover .frozen-col { background: #f5f9fc; }
.data-table.freeze-panes .frozen-col-last { box-shadow: 2px 0 4px -2px rgba(0,0,0,0.18); }
.data-table.freeze-panes thead th.frozen-col-last { box-shadow: 0 1px 0 var(--border), 2px 0 4px -2px rgba(0,0,0,0.18); }
.status-pill { background: #e6f4ea; color: var(--success); padding: 0.15rem 0.6rem; border-radius: 999px; font-size: 0.78rem; }
.status-pill.overdue { background: #fdecea; color: var(--danger); }
.status-pill.closed { background: #eef3f7; color: var(--muted); }

.progress-cell { display: flex; align-items: center; gap: 0.5rem; min-width: 110px; }
.progress-track { flex: 1; height: 8px; background: #e5e7eb; border-radius: 999px; overflow: hidden; }
.progress-fill { height: 100%; background: var(--primary); border-radius: 999px; transition: width 0.3s ease; }
.progress-pct { font-size: 0.75rem; color: var(--muted); white-space: nowrap; }

/* Panels / tabs */
.panel { background: var(--card); border-radius: var(--radius); padding: 1.25rem; box-shadow: 0 1px 3px rgba(0,0,0,0.05); }
.panel-inset { background: #f8fafc; border: 1px dashed var(--border); border-radius: var(--radius); padding: 1rem; margin-top: 0.75rem; }

.subsection-heading { margin: 1.25rem 0 0.5rem; font-size: 1rem; color: var(--primary-dark); }
.subsection-heading:first-child { margin-top: 0; }
.tab-subsection + .subsection-heading { border-top: 1px solid var(--border); padding-top: 1rem; }

.project-header { display: flex; justify-content: space-between; align-items: flex-start; flex-wrap: wrap; gap: 0.75rem; margin-bottom: 1rem; }
.project-header h2 { margin: 0; }
.muted { color: var(--muted); font-size: 0.9rem; }
.header-actions { display: flex; gap: 0.5rem; }
.view-only-note { margin-top: 0.75rem; font-style: italic; }

/* Forms */
.field-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 1rem; }
.field-wrap label { display: block; font-size: 0.82rem; color: var(--muted); margin-bottom: 0.3rem; }
.field-wrap .req { color: var(--danger); }
.f-input { width: 100%; padding: 0.5rem 0.65rem; border: 1px solid var(--border); border-radius: 8px; font-size: 0.92rem; background: #fff; }
.f-input:disabled, .f-input[readonly] { background: #f1f4f7; color: var(--muted); }
.f-input.computed { background: #eef7f1; color: var(--success); font-weight: 600; }
textarea.f-input { resize: vertical; min-height: 2.4em; }
.prefixed, .suffixed { display: flex; align-items: center; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; background: #fff; }
.prefixed span, .suffixed span { padding: 0 0.5rem; color: var(--muted); background: #eef3f7; align-self: stretch; display: flex; align-items: center; }
.prefixed input, .suffixed input { border: none; flex: 1; padding: 0.5rem 0.65rem; }
.multiselect { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.chip { display: inline-flex; align-items: center; gap: 0.3rem; background: #eef3f7; padding: 0.3rem 0.6rem; border-radius: 999px; font-size: 0.82rem; cursor: pointer; }
.help { font-size: 0.75rem; color: var(--muted); margin-top: 0.3rem; }
.redacted { padding: 0.5rem 0.65rem; border: 1px dashed var(--border); border-radius: 8px; color: var(--muted); font-size: 0.85rem; background: #f8fafc; }
.field-wrap.hidden { display: none; }
.form-actions { margin-top: 1rem; display: flex; gap: 0.5rem; }
.row-actions { white-space: nowrap; }
.icon-btn { background: none; border: none; cursor: pointer; font-size: 1rem; padding: 0.2rem 0.35rem; }
.icon-btn:hover { background: #eef3f7; border-radius: 6px; }

/* Admin matrix */
table.matrix th, table.matrix td { white-space: nowrap; }
.role-name { font-weight: 600; }
.option-list { list-style: none; padding: 0; margin: 0 0 1rem; display: flex; flex-wrap: wrap; gap: 0.4rem; }
.option-list li { background: #eef3f7; padding: 0.3rem 0.5rem; border-radius: 8px; font-size: 0.85rem; }

.tabs { display: flex; gap: 0.3rem; overflow-x: auto; margin-bottom: 0.75rem; padding-bottom: 2px; }
.tab-btn { background: none; border: none; padding: 0.55rem 0.9rem; cursor: pointer; color: var(--muted); border-bottom: 3px solid transparent; white-space: nowrap; font-size: 0.9rem; }
.tab-btn.active { color: var(--primary-dark); border-bottom-color: var(--primary); font-weight: 600; }

/* Notification bell */
.notif-badge {
  background: var(--danger); color: #fff;
  font-size: 0.65rem; font-weight: 700; border-radius: 999px; padding: 0.1rem 0.4rem; line-height: 1.2;
}
.notif-dropdown {
  position: fixed; left: calc(var(--side-w) + 8px); bottom: 1rem; width: 340px; max-height: 70vh; overflow-y: auto;
  background: var(--card); color: var(--text); border-radius: var(--radius); box-shadow: 0 8px 28px rgba(0,0,0,0.25);
  z-index: 1000;
}
.notif-empty { padding: 1rem; color: var(--muted); font-size: 0.85rem; text-align: center; }
.notif-item { padding: 0.7rem 0.9rem; border-bottom: 1px solid var(--border); cursor: pointer; font-size: 0.85rem; }
.notif-item:last-child { border-bottom: none; }
.notif-item:hover { background: #f5f9fc; }
.notif-item.unread { background: #eef7fd; font-weight: 600; }
.notif-item.unread:hover { background: #e2f1fb; }
.notif-message { margin-bottom: 0.2rem; }
.notif-time { color: var(--muted); font-size: 0.75rem; font-weight: 400; }

/* Analytics dashboard */
.stat-row { display: flex; flex-wrap: wrap; gap: 0.9rem; margin-bottom: 1.25rem; }
.stat-tile { background: var(--card); border-radius: var(--radius); padding: 1rem 1.4rem; box-shadow: 0 1px 3px rgba(0,0,0,0.05); min-width: 160px; flex: 1; }
.stat-value { font-size: 1.5rem; font-weight: 700; color: var(--primary-dark); }
.stat-label { color: var(--muted); font-size: 0.82rem; margin-top: 0.2rem; }
.pill-row { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.bar-row { display: grid; grid-template-columns: 180px 1fr 120px; align-items: center; gap: 0.75rem; margin-bottom: 0.6rem; }
.bar-label { font-size: 0.85rem; }
.bar-track { background: #eef3f7; border-radius: 999px; height: 10px; overflow: hidden; }
.bar-fill { background: var(--primary); height: 100%; border-radius: 999px; }
.bar-value { font-size: 0.85rem; text-align: right; color: var(--muted); }
@media (max-width: 640px) {
  .bar-row { grid-template-columns: 1fr; gap: 0.25rem; }
  .bar-value { text-align: left; }
}

/* Toasts */
.toast-box { position: fixed; bottom: 1rem; right: 1rem; display: flex; flex-direction: column; gap: 0.5rem; z-index: 999; }
.toast { background: #333; color: #fff; padding: 0.6rem 1rem; border-radius: 8px; opacity: 0; transform: translateY(10px); transition: all 0.25s ease; font-size: 0.88rem; max-width: 320px; box-shadow: 0 4px 12px rgba(0,0,0,0.2); }
.toast.show { opacity: 1; transform: translateY(0); }
.toast.error { background: var(--danger); }

@media (max-width: 640px) {
  .app-root { padding: 0.75rem; }
  .field-grid { grid-template-columns: 1fr; }
  .project-header { flex-direction: column; }
  .notif-dropdown { left: 0.6rem; right: 0.6rem; width: auto; bottom: 0.6rem; }
}

/* Project Communication */
.comm-project { max-width: 520px; }
.comm-layout { display: grid; grid-template-columns: minmax(280px, 380px) 1fr; gap: 1rem; align-items: start; margin-top: 1rem; }
.comm-layout .panel { margin-bottom: 1rem; }
.comm-layout h3 { margin: 0 0 0.6rem; font-size: 1rem; }
.comm-thread-item { padding: 0.6rem 0.7rem; border: 1px solid var(--border); border-radius: 8px; margin-bottom: 0.5rem; cursor: pointer; background: var(--card); }
.comm-thread-item:hover { background: #f5f9fc; }
.comm-thread-item.active { border-color: var(--primary); background: #eaf4fb; }
.comm-thread-item.unread { border-left: 4px solid var(--primary); }
.comm-thread-top { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; }
.comm-thread-last { font-size: 0.85rem; color: var(--text); margin-top: 0.2rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.comm-thread-time { font-size: 0.75rem; color: var(--muted); margin-top: 0.2rem; }
.comm-thread-head { border-bottom: 1px solid var(--border); padding-bottom: 0.6rem; margin-bottom: 0.8rem; }
.comm-messages { max-height: 55vh; overflow-y: auto; display: flex; flex-direction: column; gap: 0.6rem; padding: 0.2rem; margin-bottom: 0.8rem; }
.comm-msg { max-width: 85%; padding: 0.55rem 0.75rem; border-radius: 10px; background: #eef3f7; align-self: flex-start; }
.comm-msg.mine { align-self: flex-end; background: #dcefe6; }
.comm-msg-meta { font-size: 0.78rem; color: var(--muted); margin-bottom: 0.2rem; }
.comm-msg-text { white-space: pre-wrap; word-break: break-word; font-size: 0.92rem; }
.comm-msg-time { font-size: 0.72rem; color: var(--muted); margin-top: 0.25rem; text-align: right; }
.comm-tag { background: #fff; border: 1px solid var(--border); border-radius: 999px; padding: 0 0.4rem; font-size: 0.68rem; margin-left: 0.3rem; }
.comm-reply textarea { width: 100%; }
#comm-text { width: 100%; }
.side-comm { margin-top: 0.4rem; border-top: 1px solid rgba(255,255,255,0.15); border-radius: 0 0 7px 7px; padding-top: 0.6rem; }
@media (max-width: 900px) { .comm-layout { grid-template-columns: 1fr; } }
.comm-layout textarea.f-input, .comm-reply textarea.f-input { font-family: inherit; font-size: 0.92rem; resize: vertical; }

.side-build { font-size: 0.68rem; color: #7fa8c4; padding: 0.3rem 0.6rem 0; }
.build-warning { position: sticky; top: 0; z-index: 2000; background: #c0392b; color: #fff; padding: 0.7rem 1rem; font-size: 0.9rem; text-align: center; }
