* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background: var(--color-background, #f5f7fa);
  color: #1c2530;
}

a { color: var(--color-primary, #0b3d66); }

h1 { font-size: 1.6rem; margin-bottom: 0.25rem; }
h2 { font-size: 1.15rem; margin-top: 0; margin-bottom: 1.1rem; }
.subtitle { color: #5b6b7c; margin-top: 0; margin-bottom: 1.5rem; }
.muted { color: #7a8896; }
.muted-card { background: #eef2f6; }

/* Topbar */
.topbar {
  background: var(--color-primary, #0b3d66);
  color: #fff;
}
/* The logo/brand and the account menu use justify-content:space-between,
   but that only pushes them to the edges of THIS box -- it was capped at
   960px and centered, so on any screen wider than that there was empty
   topbar color on both sides and the two ends looked bunched toward the
   middle instead of actually sitting at opposite ends of the window
   (Dan, 08/08). No max-width now -- it fills the full topbar, so
   space-between actually reaches the real left/right edges. */
.topbar-inner {
  padding: 0.9rem 1.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.brand { display: flex; align-items: baseline; gap: 0.6rem; }
.brand-link { display: contents; text-decoration: none; }
.topbar .brand-link:hover .brand-wordmark { opacity: 0.9; }
.brand.centered { justify-content: center; margin-bottom: 0.5rem; }
.brand-logo { height: 40px; }
.brand-logo.large { height: 100px; }
/* AGI's logo wordmark is drawn in a medium blue close to the topbar's own
   brand-blue background (#007ebf, see src/config.js) — the two blend
   together and the logo nearly disappears there (Dan, 08/08 screenshot).
   Only the small topbar variant needs this — the "large" logo on the
   login/reset-password cards already sits on a white card background, so
   scoping to ".topbar .brand-logo" leaves that one untouched. */
.topbar .brand-logo {
  background: #fff;
  padding: 4px 10px;
  border-radius: 6px;
}
.brand-wordmark { font-weight: 700; font-size: 1.2rem; letter-spacing: 0.03em; }
.brand-wordmark.large { font-size: 1.8rem; font-weight: 800; letter-spacing: 0.02em; text-transform: uppercase; color: var(--color-primary, #0f2d47); }
.brand-sub { font-size: 0.85rem; opacity: 0.85; }
.topbar .link-button { color: rgba(255, 255, 255, 0.85); }
.topbar .link-button:hover { color: #fff; }

/* Groups the Calcusign button (Project Engineers only) with the profile
   menu on the right side of the topbar, so justify-content:space-between
   on .topbar-inner still only splits it into two groups -- brand on the
   left, everything else together on the right (views/layout.js). */
.topbar-right { display: flex; align-items: center; gap: 0.75rem; }

/* "Open Calcusign" button for subscribed Project Engineers, or the same
   button locked for unsubscribed ones (views/layout.js's
   renderCalcusignButton) -- Tom's idea, 08/08: sell individual Calcusign
   seats through AGI's own portal, with the locked state as the upsell.
   Styled to look like actual candy (Dan, 08/08: "enticing... like candy
   that you want to lick") -- glossy highlight, saturated gradient, soft
   pulsing glow -- deliberately NOT matching the rest of the app's flat,
   utilitarian buttons, since the whole point is to stand out as a treat
   instead of blending in as just another nav link. #5d0e07 (Dan, 08/08:
   sampled directly from the real Murdoch Engineering site -- the logo
   file's own red, #991b1e, ran noticeably brighter/more orange than the
   site's actual brand red) is a FLAT fill here, not a gradient -- Dan,
   08/08: "why cant the button be that colar the exact read that I
   shared" -- an earlier version faded a brighter red into this color, so
   the button itself never actually read as an exact match. The glossy
   shine (see ::before below) still gives it the candy look on top of the
   flat color. Text is white (#fff). */
.calcusign-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.45rem 1.05rem;
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 800;
  letter-spacing: 0.01em;
  text-decoration: none;
  white-space: nowrap;
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.55);
  background: #5d0e07;
  box-shadow:
    0 2px 0 rgba(61, 9, 4, 0.9),
    0 5px 12px rgba(93, 14, 7, 0.55),
    inset 0 1px 1px rgba(255, 255, 255, 0.5);
  text-shadow: 0 1px 2px rgba(50, 6, 2, 0.5);
  transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease;
  animation: calcusign-glow 2.4s ease-in-out infinite;
}
/* The "wet shine" that reads as a hard-candy shell rather than a flat
   button -- a rounded translucent bar near the top of the pill. Its own
   border-radius keeps it looking like a highlight without needing
   overflow:hidden on the parent (which would clip the outer box-shadow
   above). */
.calcusign-btn::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 10%;
  right: 10%;
  height: 38%;
  border-radius: 999px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0));
  pointer-events: none;
}
.calcusign-btn:hover {
  transform: translateY(-1px) scale(1.05);
  filter: brightness(1.05);
  box-shadow:
    0 3px 0 rgba(61, 9, 4, 0.9),
    0 7px 16px rgba(93, 14, 7, 0.65),
    inset 0 1px 1px rgba(255, 255, 255, 0.6);
}
@keyframes calcusign-glow {
  0%, 100% {
    box-shadow:
      0 2px 0 rgba(61, 9, 4, 0.9),
      0 5px 12px rgba(93, 14, 7, 0.55),
      inset 0 1px 1px rgba(255, 255, 255, 0.5);
  }
  50% {
    box-shadow:
      0 2px 0 rgba(61, 9, 4, 0.9),
      0 6px 18px rgba(212, 64, 43, 0.85),
      inset 0 1px 1px rgba(255, 255, 255, 0.5);
  }
}
/* Locked state -- 08/13 update (Dan): used to be a faded/washed version of
   the site red (#a97874) so it read as "greyed out." Dan asked for the
   SAME exact #5d0e07 in both states -- so this no longer overrides
   background/box-shadow/text-shadow at all, it inherits .calcusign-btn's
   flat fill and shine untouched. "Locked" is now signalled by: the small
   padlock badge pinned to the icon corner (.calcusign-lock-badge below,
   rendered only in the locked markup -- views/layout.js), cursor:
   not-allowed, and turning off the pulsing glow/hover-lift so it visibly
   doesn't behave like a live button. */
.calcusign-btn-locked {
  cursor: not-allowed;
  animation: none;
}
.calcusign-btn-locked:hover {
  transform: none;
  filter: none;
  box-shadow:
    0 2px 0 rgba(61, 9, 4, 0.9),
    0 5px 12px rgba(93, 14, 7, 0.55),
    inset 0 1px 1px rgba(255, 255, 255, 0.5);
}

/* "Cs" wordmark chip (views/layout.js's CALCUSIGN_ICON_SVG) replacing the
   old candy/lock emoji -- shape and lettering modeled on calcusign.com's
   own favicon/apple-touch-icon (a rounded-square chip with a bold "Cs"),
   rendered in white-on-translucent-white since the real favicon's dark
   red chip would disappear sitting on this button's own dark red fill.
   calcusign-icon-wrap is the positioning context for the small lock
   badge below. */
.calcusign-icon-wrap {
  position: relative;
  display: inline-flex;
  line-height: 0;
}
.calcusign-icon { display: block; }
/* Small padlock pinned to the bottom-right corner of the Cs chip, only
   rendered for the locked state -- see comment on .calcusign-btn-locked
   above for why this replaced a second background color as the "this one
   is locked" signal. */
.calcusign-lock-badge {
  position: absolute;
  right: -4px;
  bottom: -4px;
  display: block;
}

/* Profile dropdown, top-right of every logged-in page (views/layout.js) */
.profile-menu { position: relative; }
.profile-trigger {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 999px;
  color: #fff;
  font: inherit;
  font-size: 0.88rem;
  padding: 0.4rem 0.8rem;
  cursor: pointer;
}
.profile-trigger:hover { background: rgba(255, 255, 255, 0.14); }
.profile-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--color-accent, #f2a71b);
  color: #1c2530;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  flex-shrink: 0;
}
.profile-name { max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.profile-caret { font-size: 0.7rem; opacity: 0.7; margin-left: 0.1rem; }
.profile-dropdown {
  display: none;
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(15, 35, 55, 0.18);
  min-width: 160px;
  padding: 0.4rem;
  z-index: 20;
}
.profile-dropdown.open { display: block; }
.profile-dropdown-header { padding: 0.3rem 0.65rem 0.6rem; margin-bottom: 0.3rem; border-bottom: 1px solid #eef2f6; }
.profile-dropdown-name { font-weight: 600; font-size: 0.9rem; color: #1c2530; }
.profile-dropdown-role { font-size: 0.78rem; color: #7a8896; margin-top: 0.1rem; }
.profile-dropdown a,
.profile-dropdown .link-button {
  display: block;
  width: 100%;
  text-align: left;
  padding: 0.5rem 0.65rem;
  border-radius: 5px;
  color: #1c2530;
  text-decoration: none;
  font-size: 0.88rem;
}
.profile-dropdown a:hover,
.profile-dropdown .link-button:hover {
  background: #eef2f6;
  text-decoration: none;
}
.profile-dropdown .link-button.danger { color: #b3261e; }

/* Pages */
.page {
  max-width: 760px;
  margin: 0 auto;
  padding: 2rem 1.5rem 4rem;
}

.centered-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
}

.auth-card {
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 6px 24px rgba(15, 35, 55, 0.08);
  padding: 2.5rem;
  max-width: 380px;
  width: 100%;
  text-align: center;
}

.card {
  background: #fff;
  border-radius: 10px;
  box-shadow: 0 2px 10px rgba(15, 35, 55, 0.06);
  padding: 1.5rem 1.75rem;
  margin-bottom: 1.5rem;
}

/* Forms */
.stacked-form { display: flex; flex-direction: column; gap: 1.4rem; text-align: left; }
.stacked-form label { display: flex; flex-direction: column; gap: 0.35rem; font-size: 0.9rem; font-weight: 600; color: #33414f; }
.stacked-form input, .stacked-form textarea, .stacked-form select {
  font: inherit;
  padding: 0.6rem 0.7rem;
  border: 1px solid #cbd5e0;
  border-radius: 6px;
  font-weight: 400;
}
.stacked-form input:focus, .stacked-form textarea:focus, .stacked-form select:focus {
  outline: none;
  border-color: var(--color-primary, #0b3d66);
  box-shadow: 0 0 0 3px rgba(11, 61, 102, 0.12);
}
.inline-form { display: inline; }

/* Stacks "Remove access" above the reset-password form in a table cell's
   actions column, instead of letting them wrap onto a second line
   unpredictably when the column runs out of horizontal space (got worse
   once the Type dropdown column was added next to it — Dan, 08/08
   screenshot, they were colliding/overlapping the row above). Scoped to
   this wrapper specifically rather than changing .inline-form/.reset-form
   themselves, since those are also reused inline elsewhere (e.g. the
   urgent-toggle button sitting next to a project name).
*/
.table-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.4rem;
}
.reset-form {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin-left: 0.75rem;
}
.table-actions .reset-form {
  margin-left: 0;
}
.reset-form input {
  font: inherit;
  font-size: 0.82rem;
  padding: 0.3rem 0.45rem;
  border: 1px solid #cbd5e0;
  border-radius: 4px;
  width: 130px;
}
.reset-form input:focus {
  outline: none;
  border-color: var(--color-primary, #0b3d66);
  box-shadow: 0 0 0 3px rgba(11, 61, 102, 0.12);
}

.btn {
  font: inherit;
  font-weight: 600;
  border: none;
  border-radius: 6px;
  padding: 0.65rem 1.1rem;
  cursor: pointer;
}
.btn-primary { background: var(--color-primary, #0b3d66); color: #fff; }
.btn-primary:hover { background: var(--color-primary-dark, #082b47); }
.btn-block { width: 100%; }

.link-button {
  background: none;
  border: none;
  color: var(--color-primary, #0b3d66);
  text-decoration: underline;
  cursor: pointer;
  font: inherit;
  padding: 0;
}
.link-button.danger { color: #b3261e; }

/* Alerts */
.alert { padding: 0.75rem 1rem; border-radius: 6px; margin-bottom: 1rem; font-size: 0.9rem; text-align: left; }
.alert-error { background: #fdecea; color: #a12820; }
.alert-success { background: #e8f5e9; color: #1e6b2c; }

/* Urgent badge — small attention-grabbing pill shown next to a project
   name on both the PM dashboard and admin submissions table (see
   views/dashboard.js and views/admin.js's urgentBadge()). Reuses the same
   red tone as .alert-error so "urgent" reads as the same level of
   attention as an error banner would, at a glance. */
.badge-urgent {
  display: inline-block;
  background: #fdecea;
  color: #a12820;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  padding: 0.15rem 0.45rem;
  border-radius: 999px;
  vertical-align: middle;
  margin-right: 0.3rem;
}

/* Table */
.table { width: 100%; border-collapse: collapse; font-size: 0.92rem; }
/* A bit more vertical breathing room than before (was 0.55rem) -- rows
   with multi-line cell content (e.g. the PM table's stacked Remove
   access / Reset password actions, see .table-actions above) were
   sitting right up against the row divider above them (Dan, 08/08
   screenshot). */
.table th, .table td { text-align: left; padding: 0.8rem 0.5rem; border-bottom: 1px solid #e7ecf1; }
.table th { color: #5b6b7c; font-weight: 600; font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.03em; }
/* Clips a single-line cell to a fixed width with an ellipsis instead of
   letting it force the whole table wider (Site address was the single
   biggest column in the admin submissions table -- up to 300px+ for a
   full street address -- and was the main reason the table still needed
   horizontal scroll to reach the last couple columns, Dan 08/11). Kept
   single-line (not wrapped) since multi-line wrapping broke row
   alignment before (see the 08/08 "Fix site-address wrapping" fix) --
   the full text is still one hover away via the cell's title=. */
.cell-clip { display: inline-block; max-width: 190px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }

/* Brief highlight on a History row whose status/Project # just changed via
   the dashboard's live-update polling (see views/dashboard.js's
   pollDashboardSubmissions) -- without this, a row updating itself while
   you're looking at it is easy to miss entirely, especially on a subtle
   change like "Pending" -> a real Project #. Fades back to normal on its
   own; only fires on rows the poll actually changed, never on every row
   every 20s. */
@keyframes row-updated-flash {
  0% { background-color: rgba(11, 61, 102, 0.1); }
  100% { background-color: transparent; }
}
.table tbody tr.row-updated { animation: row-updated-flash 2s ease-out; }
@media (prefers-reduced-motion: reduce) {
  .table tbody tr.row-updated { animation: none; }
}

.footnote { font-size: 0.82rem; color: #7a8896; margin-top: 1.5rem; }

/* Inline save confirmation next to the notifications checkbox — replaces a
   full page reload, see views/admin.js's saveNotifyPreference(). */
.save-status { font-size: 0.82rem; color: #7a8896; }
.save-status-ok { color: #1e6b2c; }
.save-status-error { color: #a12820; }

/* Submit / History tabs on the PM dashboard (views/dashboard.js) — swap
   which panel shows with no page reload, so each gets the full page to
   itself instead of stacking and competing for space. */
.tabs {
  display: flex;
  gap: 1.5rem;
  margin-bottom: 1.5rem;
  border-bottom: 1px solid #dde4ea;
}
.tab-button {
  background: none;
  border: none;
  border-bottom: 3px solid transparent;
  margin-bottom: -1px;
  padding: 0.7rem 0.1rem;
  font: inherit;
  font-weight: 600;
  font-size: 0.98rem;
  color: #7a8896;
  cursor: pointer;
}
.tab-button:hover { color: #33414f; }
.tab-button.active { color: var(--color-primary, #0b3d66); border-bottom-color: var(--color-accent, #f2a71b); }
.tab-count {
  display: inline-block;
  margin-left: 0.4rem;
  font-size: 0.78rem;
  font-weight: 600;
  color: #7a8896;
  background: #eef2f6;
  border-radius: 999px;
  padding: 0.1rem 0.5rem;
}
.tab-button.active .tab-count { color: var(--color-primary, #0b3d66); background: rgba(11, 61, 102, 0.1); }
.tab-panel { display: none; }
.tab-panel.active { display: block; }

/* Pizza-tracker status — compact 4-stage bar for table rows. Segments
   fill in left-to-right on load (staggered via the --seg-index custom
   property set per-segment in dashboard.js/admin.js), and whichever stage
   is currently active gets a slow pulsing glow so it reads as "still
   moving" rather than a static bar — same idea as a shipping tracker. */
.status-track { display: flex; gap: 5px; width: 130px; }
.status-seg { flex: 1; height: 12px; border-radius: 6px; background: #e2e8f0; }
.status-seg.done {
  background: #1e6b2c;
  transform-origin: left;
  animation: status-seg-fill 0.45s ease-out both;
  animation-delay: calc(var(--seg-index, 0) * 0.1s);
}
.status-seg.current {
  background: #f2a71b;
  box-shadow: 0 0 0 4px rgba(242, 167, 27, 0.25);
  transform-origin: left;
  /* Pulses a few times on load to draw the eye to "this is the current
     stage," then settles into a static ring — deliberately NOT an
     infinite loop. A submission can sit at one stage for hours or days
     waiting on a human at Murdoch; an endless pulse would visually claim
     ongoing real-time activity that isn't actually happening. */
  animation:
    status-seg-fill 0.45s ease-out both,
    status-seg-pulse 1.4s ease-in-out 3;
  animation-delay: calc(var(--seg-index, 0) * 0.1s), 0.6s;
}
@keyframes status-seg-fill {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}
@keyframes status-seg-pulse {
  0%, 100% { box-shadow: 0 0 0 4px rgba(242, 167, 27, 0.25); }
  50% { box-shadow: 0 0 0 10px rgba(242, 167, 27, 0.1); }
}
.status-label { font-size: 0.86rem; color: #5b6b7c; margin-top: 6px; white-space: nowrap; }
.status-engineer { font-size: 0.78rem; color: #8494a6; margin-top: 2px; white-space: nowrap; font-style: italic; }
.status-label-complete {
  color: #1e6b2c;
  font-weight: 600;
  display: inline-block;
  animation: status-label-pop 0.4s ease-out both;
  animation-delay: calc(3 * 0.1s);
}
@keyframes status-label-pop {
  0% { transform: scale(0.8); opacity: 0; }
  70% { transform: scale(1.1); opacity: 1; }
  100% { transform: scale(1); }
}
.status-sub { font-size: 0.78rem; color: #a7b3bf; margin-top: 2px; white-space: nowrap; }

@media (prefers-reduced-motion: reduce) {
  .status-seg.done,
  .status-seg.current,
  .status-label-complete {
    animation: none !important;
  }
}

/* Login page wrapper — stacks card + powered-by footer in a column */
.login-wrapper { display: flex; flex-direction: column; align-items: center; gap: 1.25rem; width: 100%; max-width: 380px; }
.powered-by { display: flex; align-items: center; gap: 0.45rem; margin: 0; font-size: 0.75rem; color: #8d2a24; }
.murdoch-logo { height: 28px; opacity: 0.9; }
code { background: #eef2f6; padding: 0.1rem 0.35rem; border-radius: 4px; font-size: 0.85em; }

/* Filter bar above the submissions tables (search box + Status/Type/etc.
   dropdowns) -- lets a PM or admin narrow the list by more than just free
   text (Dan, 08/08). Flex-wrap so it doesn't force horizontal scroll on
   narrow screens the way the table itself does. */
.filter-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem; margin-bottom: 0.75rem; }
.filter-bar .search-input { font: inherit; padding: 0.55rem 0.7rem; border: 1px solid #cbd5e0; border-radius: 6px; }
.filter-bar select { font: inherit; padding: 0.5rem 0.6rem; border: 1px solid #cbd5e0; border-radius: 6px; background: #fff; }
.filter-bar label { font-size: 0.88rem; color: #33414f; display: flex; align-items: center; gap: 0.35rem; }
.filter-bar select:focus, .filter-bar .search-input:focus {
  outline: none;
  border-color: var(--color-primary, #0b3d66);
  box-shadow: 0 0 0 3px rgba(11, 61, 102, 0.12);
}

/* Wider page container for admin -- the "All submissions" table has 12
   columns and genuinely doesn't fit in the standard 760px .page width
   without forcing a horizontal scrollbar on every normal-sized screen,
   which read as broken/annoying rather than intentional (Dan, 08/08
   screenshot). Scoped to a modifier class rather than widening .page
   itself, since narrower pages (login, submit form, account settings)
   are more readable staying narrow -- only admin's page opts in. */
.page-wide { max-width: 1500px; }
/* Keeps the Team tab's "Add project manager"/"Add admin" forms at a
   comfortable reading width even though the page itself is now wide --
   otherwise a single "Full name" input would stretch nearly the full
   1500px, which looks broken in the other direction. */
.form-narrow { max-width: 480px; }

/* Dashboard (PM/PE view, see views/dashboard.js) needs BOTH: the Submit
   tab's form reads best narrow (Dan, 08/11 -- widening it left a dead gap
   next to the capped-width fields, and stretching the fields full-width
   looked broken too), while the History tab's table has too many columns
   for the narrow 760px .page and was getting cut off (Dan, 08/11
   screenshot). Rather than pick one width for the whole page, size .page
   itself off of which tab-panel is currently .active -- showTab() in this
   page's own <script> already toggles that class, so this just piggybacks
   on state that's already there instead of adding more JS. Only take
   effect when paired with .page (the plain modifier class alone does
   nothing) so this stays scoped to the dashboard's own <main>. */
main.page.page-wide-on-history:has(.tab-panel[data-tab="history"].active) {
  max-width: 1500px;
}

/* Help widget (views/layout.js's renderHelpWidget) -- fixed bottom-right on
   every logged-in page, same corner convention as most chat/help widgets
   so it reads as familiar rather than needing explanation itself. z-index
   30 keeps it above the profile dropdown (20) and everything else on the
   page, since it needs to float over whatever's underneath regardless of
   which page it's on.

   08/12 redesign (Dan: "seems like text just thrown in... more
   professional"): the old panel was one flat list of Q&As under a plain
   text header. This pass groups topics into labeled sections, gives the
   header an icon + subtitle so it reads as a real support panel rather
   than a dropped-in FAQ, and swaps the old dense stage-explainer paragraph
   for a scannable dot-list that echoes the pizza-tracker bar itself. */
.help-widget {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  z-index: 30;
}
.help-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.65rem 1.1rem;
  border-radius: 999px;
  border: none;
  background: var(--color-primary, #0b3d66);
  color: #fff;
  font-size: 0.88rem;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 0 4px 16px rgba(15, 35, 55, 0.25);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.help-toggle:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 20px rgba(15, 35, 55, 0.3);
}
/* Panel opens UPWARD from the toggle button (bottom: 100%, not top), since
   the toggle sits at the very bottom of the viewport -- opening downward
   would push most of the panel off-screen. */
.help-panel {
  display: none;
  position: absolute;
  right: 0;
  bottom: calc(100% + 0.6rem);
  width: 378px;
  max-width: calc(100vw - 2.5rem);
  max-height: 74vh;
  background: #fff;
  border-radius: 14px;
  border: 1px solid #e9edf2;
  box-shadow: 0 16px 40px rgba(15, 35, 55, 0.22);
}
.help-panel.open {
  display: flex;
  flex-direction: column;
  animation: help-panel-in 0.16s ease-out both;
}
@keyframes help-panel-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}
.help-panel-header {
  display: flex;
  align-items: flex-start;
  gap: 0.65rem;
  padding: 1rem 1.1rem 0.9rem;
  background: linear-gradient(165deg, var(--color-primary, #0b3d66), var(--color-primary-dark, #082b47));
  border-radius: 14px 14px 0 0;
  flex-shrink: 0;
}
.help-panel-header-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.1rem;
  height: 2.1rem;
  flex-shrink: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.16);
  font-size: 1rem;
}
.help-panel-title {
  font-weight: 700;
  font-size: 0.98rem;
  color: #fff;
  line-height: 1.3;
}
.help-panel-subtitle {
  margin-top: 0.15rem;
  font-size: 0.78rem;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.78);
  line-height: 1.3;
}
.help-panel-body {
  padding: 0.3rem 0.5rem;
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}
.help-section + .help-section {
  margin-top: 0.35rem;
  padding-top: 0.5rem;
  border-top: 1px solid #eef2f6;
}
.help-section-label {
  padding: 0.55rem 0.6rem 0.15rem;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #8593a3;
}
/* 08/12, second pass same day (Dan: "I almost feel like a help chat would
   be nicer with these as prompts") -- the questions themselves now read as
   tappable chat "prompts" (a permanent tinted chip, not just plain text
   that highlights on hover), and the revealed answer reads as an incoming
   reply bubble underneath it, echoing a real chat thread instead of a
   plain accordion list. Both keep an asymmetric border-radius (one corner
   less round) so prompt->reply visually reads as a connected exchange
   rather than two unrelated boxes. */
.help-item-q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  width: 100%;
  text-align: left;
  background: #f2f5f8;
  border: 1px solid transparent;
  padding: 0.6rem 0.75rem;
  font-size: 0.86rem;
  font-weight: 600;
  color: #1c2530;
  cursor: pointer;
  border-radius: 14px 14px 14px 4px;
  margin: 0.2rem 0;
  transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.help-item-q:hover { background: #e9eef3; }
.help-item-q-active {
  background: rgba(11, 61, 102, 0.08);
  border-color: rgba(11, 61, 102, 0.18);
  color: var(--color-primary, #0b3d66);
}
.help-item-q-active:hover { background: rgba(11, 61, 102, 0.11); }
.help-item-caret { font-size: 0.7rem; opacity: 0.6; transition: transform 0.15s ease; flex-shrink: 0; }
.help-item-q[aria-expanded="true"] .help-item-caret { transform: rotate(180deg); }
.help-item-a {
  display: none;
  margin: -0.05rem 0.4rem 0.5rem 0.6rem;
  padding: 0.65rem 0.8rem;
  background: #f8fafc;
  border: 1px solid #eef2f6;
  border-radius: 4px 14px 14px 14px;
  font-size: 0.84rem;
  line-height: 1.5;
  color: #4a5a68;
}
.help-item-a.open {
  display: block;
  animation: help-item-in 0.12s ease-out both;
}
@keyframes help-item-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
.help-item-a p { margin: 0 0 0.6rem; }
.help-item-a p:last-child { margin-bottom: 0; }
/* Stage explainer -- reuses the pizza tracker's own visual language (a dot
   per stage) instead of a paragraph, so a PM recognizes it as the same bar
   they see in their table rather than a second unrelated explanation. */
.help-stage-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}
.help-stage-list li {
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
}
.help-stage-list li strong {
  display: block;
  font-size: 0.84rem;
  color: #1c2530;
  font-weight: 700;
}
.help-stage-dot {
  flex-shrink: 0;
  margin-top: 0.3rem;
  width: 9px;
  height: 9px;
  border-radius: 999px;
  background: var(--color-primary, #0b3d66);
  opacity: 0.55;
}
.help-stage-dot-complete {
  background: var(--color-accent, #f2a71b);
  opacity: 1;
  box-shadow: 0 0 0 3px rgba(242, 167, 27, 0.18);
}
/* "Still stuck?" contact fallback (08/12, same day as the chat-prompt
   redesign above) -- replaces the old static ".help-panel-footer" note
   ("reach out directly") with an actual escape hatch: two category
   prompts that open a small composer and send a real email via this
   app's own SMTP client (src/mail.js's sendHelpRequest), routed by
   category to either Dan directly or Murdoch's existing project inbox.
   No mailto: link (silently fails without a default mail client
   configured) and no third-party chat widget (see the comment above
   renderHelpWidget in views/layout.js for why). */
.help-contact-options { display: flex; flex-direction: column; gap: 0.35rem; padding: 0 0.6rem 0.3rem; }
.help-prompt-chip {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  text-align: left;
  background: #eef2f6;
  border: 1px solid #e3e8ee;
  border-radius: 999px;
  padding: 0.55rem 0.9rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: #33414f;
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease;
}
.help-prompt-chip:hover { background: #e3e9ef; border-color: #d3dce4; }
.help-contact-form { padding: 0.2rem 0.6rem 0.4rem; }
.help-contact-form-title {
  font-size: 0.82rem;
  font-weight: 700;
  color: #1c2530;
  margin-bottom: 0.45rem;
}
.help-contact-textarea {
  width: 100%;
  resize: vertical;
  font: inherit;
  font-size: 0.85rem;
  line-height: 1.4;
  color: #1c2530;
  border: 1px solid #cbd5e0;
  border-radius: 10px;
  padding: 0.6rem 0.7rem;
  box-sizing: border-box;
}
.help-contact-textarea:focus {
  outline: none;
  border-color: var(--color-primary, #0b3d66);
  box-shadow: 0 0 0 3px rgba(11, 61, 102, 0.12);
}
.help-contact-form-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.75rem;
  margin-top: 0.5rem;
}
.help-contact-form-actions .btn { padding: 0.45rem 0.95rem; font-size: 0.82rem; }
.help-contact-status { font-size: 0.78rem; color: #7a8896; margin-top: 0.4rem; text-align: right; }
.help-contact-status-error { color: #b3261e; }
.help-contact-sent {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  background: #eaf6ec;
  border: 1px solid #cfead3;
  border-radius: 10px;
  padding: 0.65rem 0.8rem;
  font-size: 0.84rem;
  color: #1e6b2c;
}
.help-contact-sent .link-button { margin-left: auto; font-size: 0.78rem; }

/* Trash-can delete button on the admin submissions table (Tom, 08/12) --
   plain .link-button.danger's underline (see that rule above) looks odd
   under an icon glyph rather than text, so this drops it and bumps the
   icon's size slightly for a comfortable click target. */
.delete-submission-btn { text-decoration: none; font-size: 1.05rem; line-height: 1; }
.delete-submission-btn:hover { opacity: 0.75; }
