/* ============================================================
   Managertools — design system
   Tokens first, then base, then components. The /styleguide route renders every
   component below against these tokens, so it is the place to check a change.
   ============================================================ */

:root {
  /* Neutrals — cool slate rather than pure grey */
  --ink-900: #0E1320;
  --ink-700: #28324A;
  --ink-500: #5A6678;
  --ink-300: #93A0B4;
  --line: #E5E9F0;
  --paper: #F7F8FA;
  --surface: #FFFFFF;

  /* Accents — reserved for actions and status, never for decoration */
  --accent: #2F5FD0;
  --accent-ink: #23479C;
  --positive: #1B7F4A;
  --negative: #C0392B;

  --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --radius: 8px;
  --e1: 0 1px 2px rgba(14, 19, 32, 0.08);
  --e2: 0 4px 12px rgba(14, 19, 32, 0.10);

  /* The one breakpoint. Also hard-coded in the @media rules below, because CSS custom
     properties cannot be used in a media query. Keep the two in step, and keep both in step with
     ApplicationSystemTestCase::BREAKPOINT. */
  --breakpoint: 768px;
}

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font-body);
  background: var(--paper);
  color: var(--ink-900);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); }

.container {
  max-width: 1100px;
  margin: 0 auto;
  padding: 1.5rem 1rem 3rem;
}

/* ---------- Navbar ----------
   The markup this styles is depended on by the system suite: below the breakpoint .navbar-menu is
   hidden until the navbar Stimulus controller opens it, which is what click_nav_link drives. */
.navbar {
  background: var(--surface);
  box-shadow: var(--e1);
  position: sticky;
  top: 0;
  z-index: 100;
}

.navbar-inner {
  max-width: 1100px;
  margin: 0 auto;
  padding: 0 1rem;
  display: flex;
  align-items: center;
  height: 56px;
  gap: 2rem;
}

.navbar-brand {
  font-weight: 700;
  font-size: 1.1rem;
  color: var(--ink-900);
  text-decoration: none;
}

.navbar-menu { display: contents; }
.navbar-links { display: flex; gap: 0.25rem; }

/* min-width: 0 on both, so the signed-in email is what gives way when the links outgrow the bar
   just above the breakpoint, rather than the page scrolling sideways. With the fourth link
   (Projects) the bar overflowed a 780px viewport by 7px; a longer address would by more. */
.navbar-right {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-left: auto;
  min-width: 0;
}

.navbar-user {
  color: var(--ink-500);
  font-size: 0.85rem;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.navbar-link {
  color: var(--ink-700);
  text-decoration: none;
  padding: 0.5rem 0.75rem;
  border-radius: 6px;
  font-size: 0.9rem;
}

.navbar-link:hover { background: var(--paper); }
.navbar-link.active { color: var(--accent); font-weight: 600; }

.navbar-toggle {
  display: none;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0.5rem;
  margin-left: auto;
}

.navbar-toggle-icon,
.navbar-toggle-icon::before,
.navbar-toggle-icon::after {
  display: block;
  width: 22px;
  height: 2px;
  background: var(--ink-900);
}

.navbar-toggle-icon { position: relative; }

.navbar-toggle-icon::before,
.navbar-toggle-icon::after {
  content: "";
  position: absolute;
  left: 0;
}

.navbar-toggle-icon::before { top: -6px; }
.navbar-toggle-icon::after { top: 6px; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-block;
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 0.5rem 0.9rem;
  font: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
}

.btn-primary { background: var(--accent); color: #fff; }
.btn-primary:hover { background: var(--accent-ink); }
.btn-secondary { background: var(--surface); color: var(--ink-700); border-color: var(--line); }
.btn-secondary:hover { background: var(--paper); }
.btn-danger { background: var(--negative); color: #fff; }

/* ---------- Page header and cards ---------- */
.page-header {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1.5rem;
}

.page-header h1 { margin: 0; font-size: 1.5rem; }
.page-header-actions { margin-left: auto; display: flex; gap: 0.5rem; }
/* The title gives up width, the actions do not: without these, a long title squeezed three buttons
   until "Copy share link" broke over three lines and stretched its neighbours to 69px (measured at
   780px). Below the breakpoint the actions wrap under the title instead — see the @media block. */
.page-header-actions { flex-shrink: 0; }

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--e1);
  padding: 1.25rem;
  margin-bottom: 1rem;
}

.card-title { margin: 0 0 0.75rem; font-size: 1.05rem; }

/* ---------- Forms ---------- */
.form-group { margin-bottom: 1rem; }
.form-label { display: block; font-size: 0.85rem; font-weight: 600; margin-bottom: 0.25rem; }

.form-input {
  width: 100%;
  max-width: 26rem;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  font: inherit;
  background: var(--surface);
}

.form-input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
/* The search field of Ui::SelectFilter sits directly above the select it narrows. */
.select-filter-query { display: block; margin-bottom: 0.35rem; }
.form-hint { display: block; color: var(--ink-500); font-size: 0.8rem; margin-top: 0.25rem; }
/* A radio and its label on one line, with room for a thumb between them at any width. */
.form-radio { display: flex; align-items: center; gap: 0.5rem; padding: 0.15rem 0; }
.form-error { display: block; color: var(--negative); font-size: 0.8rem; margin-top: 0.25rem; }
.form-actions { display: flex; gap: 0.5rem; margin-top: 1.25rem; }

.form-errors {
  border: 1px solid var(--negative);
  border-radius: var(--radius);
  padding: 0.75rem 1rem;
  margin-bottom: 1rem;
}

.form-errors h3 { margin: 0 0 0.5rem; font-size: 0.95rem; color: var(--negative); }

/* ---------- Data table ---------- */
/* One grid for the whole table: the header, the body and every row are subgrids of it, so they all
   share its tracks. Each used to be a grid of its own, and a 1fr track — minmax(auto, 1fr) — sized
   to that row's own content, so a column's cells drifted off their header (measured on the action
   item index: 25px at 769px, 10px at 900px). Shared tracks also let a `narrow:` column be
   max-content: it fits the widest cell of the whole table, not each row's. */
.data-table {
  display: grid;
  grid-template-columns: var(--data-table-template);
  column-gap: 1rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

.data-table-header,
.data-table-body,
.data-table-row {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
}

.data-table-header,
.data-table-row { padding: 0.75rem 1rem; }

/* A 1fr column is minmax(auto, 1fr), so an unbroken word — a project name has no length limit —
   widened its column and pushed the row's title past the table's clipped edge. Breaking anywhere
   brings the name's min-content width down, and with it the column. Scoped to the project name:
   on every cell it also split owners' emails mid-word at 769–900px, on pages this never meant to
   touch. See test/system/data_table_overflow_test.rb. */
.data-table-project { overflow-wrap: anywhere; }

/* An action item's id, in the lists that print one. */
.data-table-id,
.related-item-id,
.discussed-item-id { color: var(--ink-500); font-variant-numeric: tabular-nums; }

.data-table-header {
  background: var(--paper);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--ink-500);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.data-table-row + .data-table-row { border-top: 1px solid var(--line); }

/* ---------- Meeting page ---------- */
.muted { color: var(--ink-500); }

.prose p { margin: 0 0 0.75rem; line-height: 1.55; }
.prose p:last-child { margin-bottom: 0; }

.meeting-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
  margin: 0 0 1rem;
}

.action-item-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
  margin: 0 0 1rem;
  align-items: flex-start;
}

.meeting-fact dt {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--ink-500);
}

.meeting-fact dd { margin: 0.15rem 0 0; font-weight: 600; }

.filters {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 1rem;
  margin-bottom: 1rem;
}

.filters .form-group { margin-bottom: 0; }
.filters .form-input { max-width: 14rem; }

/* ---------- Transcript ---------- */
.transcript {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.75rem 1rem;
  margin-bottom: 1rem;
}

.transcript-summary { cursor: pointer; font-size: 0.9rem; font-weight: 600; color: var(--ink-700); }

.transcript-turns { margin-top: 1rem; }
.transcript-turn + .transcript-turn { margin-top: 0.75rem; }
.transcript-speaker { display: block; font-size: 0.75rem; font-weight: 600; color: var(--ink-500); }
.transcript-line { margin: 0.15rem 0 0; line-height: 1.5; }

.transcript-text {
  margin: 1rem 0 0;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-x: auto;
}

/* ---------- Comments ---------- */
.comment + .comment { border-top: 1px solid var(--line); }
.comment { padding: 0.75rem 0; }

.comment-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
  font-size: 0.8rem;
  color: var(--ink-500);
}

.comment-author { font-weight: 600; color: var(--ink-700); }
.comment-actions { margin-left: auto; display: flex; gap: 0.75rem; }
.comment-action { font-size: 0.8rem; }
.comment-body { margin-top: 0.35rem; line-height: 1.5; white-space: pre-wrap; }
.comment-form { margin-top: 1.25rem; border-top: 1px solid var(--line); padding-top: 1rem; }

/* ---------- Status badges ---------- */
.status-badge {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  border: 1px solid transparent;
  font-size: 0.75rem;
  font-weight: 600;
  white-space: nowrap;
}

.status-badge--todo { background: var(--paper); color: var(--ink-700); border-color: var(--line); }
.status-badge--in-progress { background: #E9EFFB; color: var(--accent-ink); }
.status-badge--done { background: #E8F2EC; color: var(--positive); }

.status-badge--dropped {
  background: var(--surface);
  color: var(--ink-500);
  border-color: var(--line);
  text-decoration: line-through;
}

/* ---------- Timeline ---------- */
.timeline {
  list-style: none;
  margin: 0;
  padding: 0 0 0 1.25rem;
  border-left: 2px solid var(--line);
}

.timeline-entry { position: relative; padding: 0 0 1.25rem 0.5rem; }
.timeline-entry:last-child { padding-bottom: 0; }

.timeline-entry::before {
  content: "";
  position: absolute;
  left: -1.85rem;
  top: 0.4rem;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid var(--surface);
}

.timeline-entry-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
}

.timeline-entry-heading { font-size: 0.85rem; font-weight: 600; }
.timeline-entry-meta { font-size: 0.75rem; color: var(--ink-500); }

.timeline-entry-body { margin-top: 0.35rem; line-height: 1.5; }
.timeline-entry-body p { margin: 0.35rem 0 0; white-space: pre-wrap; }

/* ---------- Action items on a meeting ---------- */
.discussed-item + .discussed-item { border-top: 1px solid var(--line); margin-top: 1rem; padding-top: 1rem; }

.discussed-item-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}

/* The title shrinks beside the id rather than wrapping under it: with the title's min-content
   basis, the id sat alone on a line below the breakpoint (measured at 390px with a two-digit id,
   a head grew from 44px to 70px). It grows no wider than its text, or the badge is pushed to the
   far end and the link covers the gap. */
.discussed-item-id { flex: none; }
.discussed-item-title {
  flex: 1 1 10rem;
  max-width: max-content;
  min-width: 0;
  overflow-wrap: anywhere;
  font-weight: 600;
}
.discussed-item-owner { margin-left: auto; font-size: 0.8rem; color: var(--ink-500); }

.raise-form { margin-top: 1.25rem; border-top: 1px solid var(--line); padding-top: 1rem; }

.update-form { margin-top: 0.75rem; }
.update-form .form-group { margin-bottom: 0.5rem; }

/* ---------- Related items, on an action item's page ---------- */
.related-items-group + .related-items-group { margin-top: 1rem; }

.related-items-heading {
  margin: 0 0 0.35rem;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--ink-500);
}

.related-items-summary { margin: 0 0 0.35rem; font-size: 0.85rem; }

.related-items-list { list-style: none; margin: 0; padding: 0; }

.related-item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem 0.5rem;
  padding: 0.4rem 0;
}

.related-item + .related-item { border-top: 1px solid var(--line); }

/* The title takes the rest of the line and breaks anywhere rather than pushing the row past the
   card: an item title is typed by a person and has no length the layout can count on. min-width: 0
   is what lets a flex child shrink below its longest word. */
.related-item-main { display: flex; align-items: center; gap: 0.5rem; flex: 1 1 12rem; min-width: 0; }
.related-item-id { flex: none; }
.related-item-title { flex: 1 1 12rem; min-width: 0; overflow-wrap: anywhere; font-weight: 600; }
.related-item-owner { font-size: 0.8rem; color: var(--ink-500); overflow-wrap: anywhere; min-width: 0; }

.related-item-remove { margin: 0; }

.btn-compact { padding: 0.2rem 0.6rem; font-size: 0.8rem; }

.related-items-form { margin-top: 1.25rem; border-top: 1px solid var(--line); padding-top: 1rem; }
.related-items-form .form-group { margin-bottom: 0.5rem; }

/* ---------- Dashboard ---------- */
.dashboard-panel { margin-bottom: 1.5rem; }
.dashboard-panel .sg-section-title { margin-top: 0; }

/* ---------- Flash ---------- */

/* A fixed overlay rather than a block at the top of the document.
 *
 * A page refresh now morphs and keeps the reader's scroll offset, so a message in the flow would be
 * off-screen for anyone who had scrolled — including the alert that says a write was rejected,
 * which is the only sign that anything happened at all on the failure path.
 *
 * Positioned on the *container* and not on .flash itself, so that /styleguide — which hand-writes
 * bare .flash divs outside any container to show what they look like — keeps them in the flow
 * instead of acquiring a permanent overlay over its own sections.
 *
 * Above the navbar's z-index of 100, and anchored to the bottom so it never has to know how tall
 * the sticky navbar is at a given viewport.
 *
 * One rule block, not two: the in-flow version's `max-width`, `margin` and `padding: 0 1rem` used
 * to live in a second `#flash-messages` block above this one. Left there they still applied, and
 * the message rendered 2rem narrower than the width below says — measured at 265px inside a 344px
 * viewport where the formula asks for 297. */
#flash-messages {
  position: fixed;
  bottom: 1rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 200;
  width: min(32rem, calc(100% - 2rem));
  /* It spans the width and sits over the page for five seconds, and there is nothing on it to
     click. Without this it swallows clicks on whatever is underneath — measured at 344px, the
     alert reporting a rejected comment covered the very button needed to submit it again, and a
     real MouseEvent at the button's top edge landed on the flash instead. Inherited by the
     messages too, deliberately: giving them `pointer-events: auto` is what created that dead zone.
     A flash that ever gains a control of its own has to take its clicks back then, and narrow
     itself to its text at the same time. */
  pointer-events: none;
}

#flash-messages .flash {
  box-shadow: var(--e1);
}

.flash {
  border-radius: var(--radius);
  padding: 0.65rem 1rem;
  font-size: 0.9rem;
  margin-bottom: 0.5rem;
}

.flash-notice { background: #E8F2EC; color: var(--positive); }
.flash-alert { background: #FBEAE8; color: var(--negative); }

/* ---------- Styleguide ---------- */
.sg-section-title { font-size: 1.1rem; margin: 2rem 0 0.75rem; }
.sg-subtitle { font-size: 0.85rem; color: var(--ink-500); margin: 1rem 0 0.5rem; }
.sg-section-body { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.25rem; }
.sg-row { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; }
.sg-swatches { display: flex; flex-wrap: wrap; gap: 1rem; }
.sg-swatch { width: 8rem; }
.sg-swatch-chip { height: 3rem; border-radius: 6px; border: 1px solid var(--line); }
.sg-swatch-name { display: block; font-size: 0.85rem; margin-top: 0.35rem; }
.sg-swatch-token { display: block; font-family: var(--font-mono); font-size: 0.75rem; color: var(--ink-500); }
.sg-type-row { display: flex; gap: 1.5rem; align-items: baseline; padding: 0.5rem 0; border-top: 1px solid var(--line); }
.sg-type-label { flex: 0 0 12rem; font-size: 0.75rem; color: var(--ink-500); font-family: var(--font-mono); }
.sg-ts-2xl { font-size: 2rem; font-weight: 700; }
.sg-ts-xl { font-size: 1.4rem; font-weight: 700; }
.sg-ts-base { font-size: 1rem; }
.sg-ts-sm { font-size: 0.85rem; }
.sg-ts-mono { font-family: var(--font-mono); font-size: 0.85rem; }

/* A `code` element holds something the user did not choose the length of — an OAuth redirect URI,
   an authorization grant — and the stylesheet had no rule for one at all, so it inherited
   `overflow-wrap: normal` and could not break. Measured in a real browser: the redirect_uri on the
   consent screen renders 305px of unbreakable text into a 318px content box at 390px wide, which
   fits with 13px to spare; a URI six characters longer overflows the card, and
   /oauth/authorize/native overflows at 344px whenever the grant token happens to contain no
   hyphen — which is about half of them.

   `anywhere` rather than `break-word`: it also lets the element shrink below its longest word when
   it is a flex or grid child, which is what these are. */
code {
  overflow-wrap: anywhere;
}

/* ---------- Below the breakpoint ----------
   768px, matching ApplicationSystemTestCase::BREAKPOINT and the --breakpoint token above. */
@media (max-width: 768px) {
  .navbar-inner {
    flex-wrap: wrap;
    height: auto;
    min-height: 56px;
    gap: 0;
  }

  .navbar-toggle { display: block; }

  .navbar-menu {
    display: none;
    width: 100%;
    padding-bottom: 0.75rem;
  }

  .navbar-menu--open { display: block; }

  .navbar-links { flex-direction: column; }
  .navbar-right { margin-left: 0; flex-wrap: wrap; }

  /* Rows restack into cards, each cell labelled by the column it came from — which is why
     Ui::DataTable copies the column name into data-label. */
  .data-table-header { display: none; }

  .data-table,
  .data-table-body { display: block; }

  .data-table-row { grid-template-columns: 1fr; gap: 0.25rem; }

  .data-table-cell::before {
    content: attr(data-label) " ";
    display: block;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--ink-500);
  }

  /* A header's actions drop under the title when they do not fit beside it, rather than pushing the
     last button off the screen — which three buttons did at 344px. Every header with a long title
     does this below the breakpoint, the action item's too: its buttons move under the title, which
     is taller between 500 and 768px and shorter at 390 than the squeezed row it replaces. */
  .page-header { flex-wrap: wrap; }

  .sg-type-row { flex-direction: column; gap: 0.25rem; }

  .filters { flex-direction: column; align-items: stretch; }
  .filters .form-input { max-width: 100%; }
  .meeting-facts { gap: 0.75rem; }
  .action-item-facts { gap: 0.75rem; }
  .comment-actions { margin-left: 0; width: 100%; }
  .discussed-item-owner { margin-left: 0; width: 100%; }
}

/* ---------- Recurrence ---------- */
/* Controls that sit inside a sentence ("On the [3rd] [Thursday]") rather than on a line of their
   own, wrapping below the breakpoint instead of overflowing it. */
.recurrence-fields .form-radio { flex-wrap: wrap; }
.form-input--inline { width: auto; }
.form-input--number { width: 6rem; }
