/* ============================================================
   Screens, part two: calendar, customers, services, settings,
   agency, forms.
   ============================================================ */

/* --------------------------------------------------------- calendar */

.calendar-page { display: flex; flex-direction: column; min-height: 0; overflow: hidden; }

.cal-toolbar {
  display: flex;
  flex: none;
  align-items: center;
  gap: var(--s3);
  padding: var(--s3) var(--s6);
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}
.cal-title { font-size: var(--t-15); font-weight: 600; }
.cal-body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; overflow: auto; }

.cal-undated {
  display: flex;
  align-items: center;
  gap: var(--s3);
  flex-wrap: wrap;
  padding: var(--s3) var(--s6);
  background: var(--booked-soft);
  border-bottom: 1px solid color-mix(in oklab, var(--booked) 30%, var(--line));
  font-size: var(--t-12);
  color: var(--booked-text);
}
.cal-undated svg { flex: none; }
.cal-undated-list { display: flex; gap: 6px; flex-wrap: wrap; }
.cal-undated-list .chip { cursor: pointer; height: 24px; }

.cal-month-wrap { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.cal-month-head {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  padding: var(--s2) 0;
  border-bottom: 1px solid var(--line);
}
.cal-month-head span { text-align: center; }
.cal-month {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  grid-auto-rows: minmax(96px, 1fr);
  gap: 1px;
  background: var(--line);
  flex: 1 1 auto;
}
.cal-day {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 5px;
  background: var(--canvas);
  min-width: 0;
  overflow: hidden;
  /* The closed / over-capacity badge pins to this corner. */
  position: relative;
}
.cal-day.is-outside { background: var(--surface); }
.cal-day.is-outside .cal-day-num { color: var(--text-3); opacity: 0.5; }
.cal-day-num { font-size: var(--t-11); font-weight: 600; color: var(--text-2); font-variant-numeric: tabular-nums; }
.cal-day.is-today { background: var(--surface-2); }
.cal-day.is-today .cal-day-num {
  display: grid; place-items: center;
  width: 19px; height: 19px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--text-on-accent);
}
.cal-day-more { font-size: var(--t-11); color: var(--text-3); text-align: left; padding-left: 2px; }
.cal-day-more:hover { color: var(--text); }

.cal-chip {
  display: flex;
  align-items: center;
  gap: 5px;
  width: 100%;
  padding: 3px 5px;
  border-radius: 5px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  text-align: left;
  min-width: 0;
  transition: background var(--fast) var(--ease), border-color var(--fast) var(--ease);
}
.cal-chip:hover { background: var(--surface-3); border-color: var(--line-3); }
.cal-chip-rule { width: 2px; align-self: stretch; border-radius: var(--r-full); background: var(--trust); flex: none; }
.cal-chip[data-tone="action"] .cal-chip-rule { background: var(--attention); }
.cal-chip[data-tone="gold"]   .cal-chip-rule { background: var(--booked); }
.cal-chip[data-tone="go"]     .cal-chip-rule { background: var(--won); }
.cal-chip[data-tone="muted"]  .cal-chip-rule { background: var(--line-3); }
.cal-chip-name { font-size: var(--t-11); font-weight: 550; }
.cal-chip-sub { font-size: 10px; color: var(--text-3); }
.cal-chip-time { font-size: 10px; color: var(--text-3); flex: none; font-variant-numeric: tabular-nums; }
.cal-chip.is-follow { border-style: dashed; }

/* Week and day are one grid with N columns. */
.cal-time { display: flex; flex: 1 1 auto; min-height: 0; overflow: auto; }
.cal-gutter { flex: none; width: 46px; position: sticky; left: 0; z-index: 2; background: var(--canvas); border-right: 1px solid var(--line); }
.cal-gutter-head { height: 44px; border-bottom: 1px solid var(--line); }
.cal-hour-label { height: 52px; padding-right: 6px; text-align: right; font-size: var(--t-11); color: var(--text-3); }
.cal-hour-label span { position: relative; top: -6px; }

.cal-col { flex: 1 1 0; min-width: 118px; border-right: 1px solid var(--line); }
.cal-time.is-day .cal-col { min-width: 0; }
.cal-col-head {
  display: flex; align-items: center; justify-content: center; gap: 5px;
  height: 44px;
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 1;
  background: var(--canvas);
}
.cal-col-dow { font-size: var(--t-11); color: var(--text-3); text-transform: uppercase; }
.cal-col-num { font-size: var(--t-14); font-weight: 600; font-variant-numeric: tabular-nums; }
.cal-col.is-today .cal-col-num { color: var(--accent-text); }
/* The all-day band. Its height is fixed across every column so the
   hour grid below still lines up with the gutter. */
/* Both the band and its gutter label are the SAME fixed height. A band
   that grew with its contents pushed that column's hour grid out of
   step with the gutter beside it, so 9am in one column sat level with
   8am in the next. */
.cal-allday, .cal-allday-label {
  height: 72px;
  padding: 3px;
  border-bottom: 1px solid var(--line-2);
  display: flex;
  flex-direction: column;
  gap: 2px;
  overflow-y: auto;
  scrollbar-width: none;
}
.cal-allday::-webkit-scrollbar { display: none; }
.cal-allday .cal-chip { flex: none; }
.cal-allday-label {
  align-items: flex-end;
  justify-content: center;
  padding-right: 6px;
  font-size: 9px;
  overflow: hidden;
}

.cal-slots { position: relative; }
.cal-slot { height: 52px; border-bottom: 1px solid var(--line); }
.cal-block {
  position: absolute;
  top: var(--top);
  left: var(--left);
  width: var(--width);
  height: var(--height);
  padding: 0 2px;
}
.cal-block .cal-chip { height: 100%; align-items: flex-start; box-shadow: var(--lift-1); }

.cal-agenda { display: flex; flex-direction: column; gap: var(--s4); padding: var(--s5) var(--s6); }
.cal-agenda-head {
  display: flex; align-items: baseline; justify-content: space-between;
  padding-bottom: var(--s2);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--s2);
}
.cal-agenda-date { font-size: var(--t-13); font-weight: 600; }
.cal-agenda-items { display: flex; flex-direction: column; gap: 2px; }
.cal-agenda-row {
  display: flex; align-items: center; gap: var(--s3);
  width: 100%;
  padding: var(--s2);
  border-radius: var(--r-control);
  text-align: left;
  transition: background var(--fast) var(--ease);
}
.cal-agenda-row:hover { background: var(--surface-2); }
.cal-agenda-time { width: 58px; flex: none; font-size: var(--t-12); color: var(--text-2); font-variant-numeric: tabular-nums; }
.cal-agenda-rule { width: 3px; height: 30px; border-radius: var(--r-full); background: var(--trust); flex: none; }
.cal-agenda-rule[data-tone="action"] { background: var(--attention); }
.cal-agenda-name { font-size: var(--t-13); font-weight: 550; }
.cal-agenda-amount { font-size: var(--t-12); font-variant-numeric: tabular-nums; color: var(--text-2); }

/* -------------------------------------------------------- customers */

.contacts-table td:first-child { min-width: 200px; }
.contact-name { gap: 6px; font-size: var(--t-13); font-weight: 550; }

/* --------------------------------------------------------- services */

.catalog-head { align-items: flex-start; }
.catalog-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); gap: var(--s3); }
.catalog-card { display: flex; flex-direction: column; transition: border-color var(--fast) var(--ease); }
.catalog-card:hover { border-color: var(--line-2); }
.catalog-card.is-retired { opacity: 0.6; }
.catalog-card-body { flex: 1 1 auto; padding: var(--s4); display: flex; flex-direction: column; gap: var(--s2); }
.catalog-card h3 { font-size: var(--t-14); }
.catalog-desc { font-size: var(--t-12); color: var(--text-2); line-height: var(--lh-snug); }
.catalog-facts { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; margin-top: auto; padding-top: var(--s2); }
.catalog-price { font-size: var(--t-15); font-weight: 600; font-variant-numeric: tabular-nums; }
.catalog-card-foot { display: flex; gap: var(--s2); padding: var(--s2) var(--s4); border-top: 1px solid var(--line); }

/* --------------------------------------------------------- settings */

.settings { display: grid; grid-template-columns: 178px 1fr; gap: var(--s6); align-items: start; }
.settings-nav { display: flex; flex-direction: column; gap: 2px; position: sticky; top: var(--s4); }
.settings-tab {
  padding: 7px var(--s3);
  border-radius: var(--r-control);
  text-align: left;
  font-size: var(--t-13);
  color: var(--text-2);
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease);
}
.settings-tab:hover { background: var(--surface-2); color: var(--text); }
.settings-tab.is-on { background: var(--surface-3); color: var(--text); font-weight: 600; }
.settings-body { min-width: 0; }
.settings-stack { gap: var(--s4); }
.settings-card { min-width: 0; }
.settings-check { align-items: flex-start; gap: var(--s3); }
.settings-check input { margin-top: 3px; }

.color-input { width: 46px; height: 32px; padding: 3px; flex: none; cursor: pointer; }

.stage-rows, .tag-rows, .field-rows, .team-rows { display: flex; flex-direction: column; gap: var(--s2); }
.stage-row, .tag-row, .field-row, .team-row {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s2);
  border-radius: var(--r-control);
  border: 1px solid var(--line);
  background: var(--surface-2);
}
.stage-row-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--tone-neutral); flex: none; }
.stage-row[data-tone="action"] .stage-row-dot { background: var(--tone-action); }
.stage-row[data-tone="trust"]  .stage-row-dot { background: var(--tone-trust); }
.stage-row[data-tone="gold"]   .stage-row-dot { background: var(--tone-gold); }
.stage-row[data-tone="go"]     .stage-row-dot { background: var(--tone-go); }
.field-row-label { font-size: var(--t-13); font-weight: 500; }

/* A control in one of these rows must not claim the whole row.
   `.input` and `.select` are width:100% everywhere else, and in a flex
   row that resolves flex-basis to the full width. The label beside it
   has flex-basis 0 and min-width 0, so it collapses to nothing and
   wraps one letter per line: the stage list read vertically, S-c-h-e-d
   down the left edge. The name is the point of the row, so it keeps a
   floor and the control is what gives way. */
.stage-row > .select,  .stage-row > .input,
.tag-row > .select,    .tag-row > .input,
.field-row > .select,  .field-row > .input,
.team-row > .select,   .team-row > .input {
  flex: 0 1 15rem;
  width: auto;
  min-width: 0;
}

.stage-row > .grow, .tag-row > .grow,
.field-row > .grow, .team-row > .grow { min-width: 6rem; }

.stage-row > .check, .tag-row > .check,
.field-row > .check, .team-row > .check { flex: none; }

/* Narrow enough that a name and two controls cannot share a line: the
   name takes its own, rather than being squeezed again. */
@media (max-width: 680px) {
  .stage-row, .tag-row, .field-row, .team-row { flex-wrap: wrap; }
  .stage-row > .grow, .tag-row > .grow,
  .field-row > .grow, .team-row > .grow { flex-basis: 100%; min-width: 0; }
  .stage-row > .select, .tag-row > .select,
  .field-row > .select, .team-row > .select { flex: 1 1 auto; }
}

.tone-picker { display: flex; gap: 4px; flex: none; }
.tone-dot {
  width: 18px; height: 18px;
  border-radius: 50%;
  border: 2px solid transparent;
  background: var(--surface-3);
  transition: transform var(--fast) var(--ease);
}
.tone-dot[data-tone="neutral"] { background: var(--text-3); }
.tone-dot[data-tone="accent"] { background: var(--accent); }
.tone-dot[data-tone="action"] { background: var(--attention); }
.tone-dot[data-tone="gold"]   { background: var(--booked); }
.tone-dot[data-tone="go"]     { background: var(--won); }
.tone-dot[data-tone="trust"]  { background: var(--trust); }
.tone-dot:hover { transform: scale(1.14); }
.tone-dot.is-on { border-color: var(--text); }

.template-row {
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  padding: var(--s4);
  border-radius: var(--r-control);
  border: 1px solid var(--line);
  background: var(--surface-2);
}
.template-label { font-size: var(--t-13); }
.template-row .template-preview { margin-top: 0; background: var(--surface); }

.token-list { display: flex; flex-direction: column; gap: var(--s2); }
.token-list li { display: flex; align-items: center; gap: var(--s3); font-size: var(--t-13); }
.token {
  font-family: var(--mono);
  font-size: var(--t-12);
  padding: 2px 6px;
  border-radius: var(--r-chip);
  background: var(--surface-3);
  border: 1px solid var(--line);
  color: var(--accent-text);
  white-space: nowrap;
}

.agency-banner { border-color: var(--accent-line); background: var(--accent-soft); }
.agency-banner svg { color: var(--accent-text); flex: none; }

/* ----------------------------------------------------------- trash */

.trash-list { display: flex; flex-direction: column; }
.trash-row {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s3) var(--s5);
  border-top: 1px solid var(--line);
}
.trash-list li:first-child { border-top: none; }
.trash-name { font-size: var(--t-13); font-weight: 550; }
.trash-amount { font-size: var(--t-12); color: var(--text-2); font-variant-numeric: tabular-nums; flex: none; }

@media (max-width: 640px) {
  .trash-row { flex-wrap: wrap; padding: var(--s3) var(--s4); }
  .trash-row .btn { margin-left: auto; }
}

/* ----------------------------------------------------------- agency */

.agency-table td:first-child { min-width: 220px; }
.table-scroll { overflow-x: auto; }
.client-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: var(--s3); }
.client-card { display: flex; flex-direction: column; transition: border-color var(--fast) var(--ease), transform var(--fast) var(--ease); }
.client-card:hover { border-color: var(--line-2); transform: translateY(-1px); }
.client-card-body { padding: var(--s5); display: flex; flex-direction: column; gap: var(--s4); flex: 1 1 auto; }
.client-stat .label { white-space: nowrap; }
.client-card h3 { font-size: var(--t-15); }
.client-mark {
  background: color-mix(in oklab, var(--brand) 22%, var(--surface-2));
  border-color: color-mix(in oklab, var(--brand) 40%, var(--line));
  color: color-mix(in oklab, var(--brand) 64%, #ffffff);
}
.client-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s2); }
.client-stat { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.client-stat dd { margin: 0; }
.client-stat-value { font-size: var(--t-17); font-weight: 600; font-variant-numeric: tabular-nums; }
.client-stat-value.is-alert { color: var(--attention-text); }
.client-card-foot {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s2) var(--s3);
  flex-wrap: wrap;
  padding: var(--s2) var(--s5) var(--s3);
  border-top: 1px solid var(--line);
  font-size: var(--t-11);
}
/* Three buttons do not fit beside the last-lead line on a narrow card.
   They wrap as a group under it, right-aligned, rather than one being
   clipped off the edge. */
.client-card-foot > .row { flex-wrap: wrap; justify-content: flex-end; margin-left: auto; }

/* ------------------------------------------------------------ forms */

.form-split { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s4); align-items: start; }
.form-preview { display: flex; flex-direction: column; gap: var(--s3); }
.form-preview .field > label { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.form-preview .field.is-conditional {
  padding-left: var(--s3);
  border-left: 2px solid var(--accent-line);
  animation: rise 240ms var(--ease-out) both;
}
.intake-note { border-color: var(--accent-line); }
.intake-note svg { color: var(--accent-text); flex: none; margin-top: 2px; }

/* --------------------------------------------------------- skeleton */

.skeleton-list { display: flex; flex-direction: column; gap: var(--s2); }
.skeleton-row {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3);
  border-radius: var(--r-card);
  border: 1px solid var(--line);
  background: var(--surface);
}
.board.is-loading { grid-auto-columns: minmax(232px, 1fr); }
.board.is-loading .column { padding: var(--s3); }

/* ====================================================== responsive */

@media (max-width: 1080px) {
  .form-split { grid-template-columns: 1fr; }
  .client-stats { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 860px) {
  .filter-band, .cal-toolbar { padding: var(--s3) var(--s4); }
  .settings { grid-template-columns: 1fr; gap: var(--s4); }
  .settings-nav {
    position: static;
    flex-direction: row;
    gap: var(--s2);
    overflow-x: auto;
    padding-bottom: var(--s1);
    scrollbar-width: none;
  }
  .settings-nav::-webkit-scrollbar { display: none; }
  .settings-tab { flex: none; white-space: nowrap; }

  .board.is-single .column-body { padding-bottom: var(--s5); }
  /* Touch targets grow. A card that is comfortable with a mouse is a
     card you miss with a thumb in a workshop. */
  .lead-card { padding: var(--s4) var(--s3); gap: 6px; }
  .lead-name { font-size: var(--t-15); }

  .cal-toolbar { flex-wrap: wrap; }
  .cal-views { order: 3; width: 100%; }
  .cal-views button { flex: 1 1 0; }
  .cal-month { grid-auto-rows: minmax(62px, 1fr); }
  .cal-chip-sub, .cal-chip-time { display: none; }
  .cal-agenda { padding: var(--s4); }

  .col-hide-sm { display: none; }

  /* Pin the name column so a row stays identifiable while the numbers
     scroll past it. */
  .table-scroll .table th:first-child,
  .table-scroll .table td:first-child {
    position: sticky;
    left: 0;
    background: var(--surface);
    z-index: 1;
  }
  .table-scroll .table tr[data-clickable]:hover td:first-child { background: var(--surface-2); }
  .agency-table td:first-child, .contacts-table td:first-child { min-width: 168px; }
  .metric-row { grid-template-columns: repeat(2, 1fr); gap: var(--s2); }
  .metric { padding: var(--s3) var(--s4); }
  .metric-value { font-size: var(--t-21); }
  .attention-row, .card-head, .attention-more { padding-left: var(--s4); padding-right: var(--s4); }
  .upcoming-day { padding-left: var(--s4); padding-right: var(--s4); }
  .chart-card .card-body { padding: var(--s3) var(--s4) var(--s4); }
  .catalog-grid, .client-grid { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
  .col-hide-md { display: none; }
  .field-grid { grid-template-columns: 1fr; }
  .quick-action { height: 44px; }
}

/* ------------------------------------------------ customer panel */

.customer-stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s3); }
.customer-stat { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.customer-stat-value {
  font-size: var(--t-21); font-weight: 600;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.customer-jobs { display: flex; flex-direction: column; gap: 2px; }
.customer-job {
  display: flex; align-items: center; gap: var(--s3);
  width: 100%; padding: var(--s2);
  border-radius: var(--r-control); text-align: left;
  transition: background var(--fast) var(--ease);
}
.customer-job:hover { background: var(--surface-2); }
.customer-job-rule {
  width: 3px; height: 30px; flex: none;
  border-radius: var(--r-full); background: var(--tone-neutral);
}
.customer-job-rule[data-tone="action"] { background: var(--tone-action); }
.customer-job-rule[data-tone="trust"]  { background: var(--tone-trust); }
.customer-job-rule[data-tone="gold"]   { background: var(--tone-gold); }
.customer-job-rule[data-tone="go"]     { background: var(--tone-go); }
.customer-job-what { font-size: var(--t-13); font-weight: 550; }
.customer-job-amount { font-size: var(--t-12); font-variant-numeric: tabular-nums; color: var(--text-2); }

/* -------------------------------------------------- client health */

.health-list { display: flex; flex-direction: column; gap: 6px; margin-top: var(--s2); }
.health-row {
  display: flex; align-items: flex-start; gap: var(--s2);
  font-size: var(--t-12); line-height: var(--lh-snug); color: var(--text-2);
}
.health-row .chip { flex: none; margin-top: 1px; }
.health-row.is-blocking { color: var(--danger-text); }
.health-clear {
  display: flex; align-items: center; gap: var(--s2);
  margin-top: var(--s2);
  font-size: var(--t-12); color: var(--won-text);
}
.health-clear svg { flex: none; }

.health-line {
  display: flex; align-items: baseline; gap: var(--s2);
  margin: 0; padding: var(--s2) var(--s3);
  border-radius: var(--r-control);
  background: var(--surface-2);
  font-size: var(--t-12); line-height: var(--lh-snug); color: var(--text-2);
}
.health-line.is-blocking { background: var(--danger-soft); color: var(--danger-text); }
.health-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; transform: translateY(-1px); background: var(--booked); }
.health-line.is-blocking .health-dot { background: var(--danger); }
.health-more { flex: none; font-size: var(--t-12); white-space: nowrap; }

/* ----------------------------------------------- change requests */

.fb-list { display: flex; flex-direction: column; gap: var(--s2); }
.fb-row {
  display: flex; align-items: flex-start; gap: var(--s3);
  padding: var(--s3);
  border-radius: var(--r-control);
  border: 1px solid var(--line);
  background: var(--surface-2);
}
.fb-row.is-done { opacity: 0.55; }
.fb-row.is-done .fb-body { text-decoration: line-through; }
.fb-body { font-size: var(--t-13); line-height: var(--lh-snug); }
.fb-row .chip { flex: none; }
.fb-row .check { margin-top: 2px; }

@media (max-width: 560px) {
  .customer-stats { grid-template-columns: repeat(2, 1fr); }
}

/* ----------------------------------------------------- audit log */

.audit-list { display: flex; flex-direction: column; gap: 6px; }
.audit-row {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s2) var(--s3);
  border-radius: var(--r-control);
  border: 1px solid var(--line);
  background: var(--surface-2);
  font-size: var(--t-12);
}
.audit-row .chip { flex: none; }
.audit-row .micro { flex: none; }

@media (max-width: 640px) {
  .audit-row { flex-wrap: wrap; gap: var(--s2); }
}

/* The embed snippet on the Website tab. Monospace because it is code
   and will be pasted as code, wrapping because a horizontal scrollbar
   inside a settings card hides the end of the line that matters most. */
.snippet {
  margin: 0;
  padding: var(--s3);
  border-radius: var(--r-control);
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text-2);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: var(--t-12);
  line-height: var(--lh-snug);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  user-select: all;
}

/* ===================================================== agency overview
   The command centre. It leads with one number and the series that
   explains it, and everything arrives in sequence rather than all at
   once, which is the same language the first-login welcome speaks.

   Every animation is transform and opacity only, so none of it touches
   layout, and all of it stops dead under reduced motion. */

.agency-overview { gap: var(--s4); }

.rise-in { animation: overview-rise 460ms var(--delay, 0ms) var(--ease-out) both; }

@keyframes overview-rise {
  from { opacity: 0; transform: translateY(14px); }
}

/* ------------------------------------------------------------- hero */

.hero { position: relative; overflow: hidden; }

/* The atmosphere. Sits behind the content, never in front of it, and is
   pointer-transparent so it cannot eat a click on the chart. */
.hero-glow {
  position: absolute;
  inset: -40% -10% auto -10%;
  height: 320px;
  pointer-events: none;
  background:
    radial-gradient(52% 60% at 18% 30%,
      color-mix(in oklab, var(--accent) 26%, transparent), transparent 70%),
    radial-gradient(44% 52% at 82% 10%,
      color-mix(in oklab, #b8763f 18%, transparent), transparent 72%);
  filter: blur(72px);
  opacity: 0.9;
}

.hero-body { position: relative; padding: var(--s5); display: grid; gap: var(--s4); }

.hero-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s4);
}

/* The one number the screen leads with. Proportional figures, not
   tabular: at this size tabular-nums gives every digit the width of a
   zero and the number reads loose. */
.hero-figure {
  font-size: clamp(2.75rem, 1.6rem + 3.4vw, 4rem);
  line-height: 1;
  letter-spacing: -0.03em;
  font-weight: 620;
  color: var(--text);
}

.hero-aside { display: grid; gap: 6px; justify-items: flex-end; text-align: right; }
.hero-delta { align-items: baseline; gap: var(--s2); }
.hero-sub { font-size: var(--t-28, 1.75rem); line-height: 1; letter-spacing: -0.02em; }

.trend-delta {
  font-size: var(--t-12);
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text-2);
}
.trend-delta.is-up   { color: var(--tone-go); }
.trend-delta.is-down { color: var(--tone-action); }

/* ------------------------------------------------------------ chart */

.trend-wrap { position: relative; margin: 0; }
.trend { display: block; width: 100%; height: auto; overflow: visible; }

/* Recessive: one step off the surface, hairline, solid. Never dashed. */
.trend-grid { stroke: var(--line); stroke-width: 1; }
.trend-tick, .trend-end {
  fill: var(--text-3);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.trend-end { fill: var(--text-2); font-weight: 600; }

.trend-line {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}

/* A wash, never a saturated block. */
.trend-area { fill: color-mix(in oklab, var(--accent) 10%, transparent); stroke: none; }

/* The surface ring keeps the marker legible where it crosses the line. */
.trend-dot, .trend-hover-dot {
  fill: var(--accent);
  stroke: var(--surface);
  stroke-width: 2;
}
.trend-crosshair { stroke: var(--line-3); stroke-width: 1; }

.trend-tip {
  position: absolute;
  top: -4px;
  left: var(--at, 50%);
  transform: translateX(-50%);
  padding: 5px 9px;
  border-radius: var(--r-control);
  border: 1px solid var(--line-2);
  background: var(--surface-2);
  color: var(--text);
  font-size: var(--t-12);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--fast) var(--ease);
}
.trend-tip.is-on { opacity: 1; }

/* -------------------------------------------------------- attention */

.attention-strip {
  display: flex;
  align-items: center;
  gap: var(--s3);
  width: 100%;
  padding: var(--s3) var(--s4);
  text-align: left;
  cursor: pointer;
  border-color: color-mix(in oklab, var(--tone-action) 34%, var(--line));
  transition: transform var(--fast) var(--ease), border-color var(--fast) var(--ease);
}
.attention-strip:hover {
  transform: translateY(-1px);
  border-color: color-mix(in oklab, var(--tone-action) 55%, var(--line));
}

.attention-dot {
  width: 8px; height: 8px;
  flex: none;
  border-radius: 50%;
  background: var(--tone-action);
  box-shadow: 0 0 0 4px color-mix(in oklab, var(--tone-action) 18%, transparent);
}

@media (prefers-reduced-motion: reduce) {
  .rise-in { animation: none; }
  .attention-strip:hover { transform: none; }
}

@media (max-width: 680px) {
  .hero-body { padding: var(--s4); }
  .hero-head { flex-direction: column; align-items: flex-start; }
  .hero-aside { justify-items: flex-start; text-align: left; }
}

/* ------------------------------------------------- calendar drag */

/* The day under the pointer while a job is in the air. It has to be
   obvious from across a workshop, because the pointer is nowhere near
   the cell's edge when the drop happens. */
.cal-day.is-drop {
  background: color-mix(in oklab, var(--accent) 10%, var(--surface-2));
  box-shadow: inset 0 0 0 2px var(--accent);
}

/* The thing being carried. Faded and tilted, the same language the
   board uses, so a drag reads the same way in both places. */
.cal-chip.is-lifted, .chip.is-lifted { opacity: 0.4; transform: rotate(1.5deg); }

.cal-chip { cursor: grab; }
.cal-chip:active { cursor: grabbing; }

/* An undated job is a thing you pick up and put somewhere, so it says
   so before you touch it. */
.cal-undated-list .chip { cursor: grab; }
.cal-undated-list .chip:active { cursor: grabbing; }

@media (prefers-reduced-motion: reduce) {
  .cal-chip.is-lifted, .chip.is-lifted { transform: none; }
}

/* --------------------------------------------------- opening hours */

.hours-row { gap: var(--s4); }

/* The day name carries the row, so it gets a floor and does not
   collapse when the two time fields take their width. */
.hours-day { min-width: 5.5rem; font-weight: 500; }

.hours-times { gap: var(--s2); align-items: center; flex: 0 1 auto; }

/* A time field sizes itself to its content; left at width:100% it
   would claim the row the way a select does. */
.hours-row .input[type="time"] { width: auto; flex: none; min-width: 7.5rem; }

@media (max-width: 680px) {
  .hours-row { flex-wrap: wrap; }
  .hours-times { width: 100%; }
  .hours-row .input[type="time"] { flex: 1 1 auto; min-width: 0; }
}

/* A day that disagrees with the shop's own rules. Pointed at, never
   blocked: the badge says what is odd and the shop decides. */
.cal-day-warn {
  position: absolute;
  top: 4px;
  right: 6px;
  font-size: var(--t-11);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  padding: 1px 6px;
  border-radius: var(--r-full);
  background: color-mix(in oklab, var(--tone-action) 20%, transparent);
  color: var(--tone-action);
}

.cal-day.is-shut { background: color-mix(in oklab, var(--tone-muted) 6%, transparent); }
.cal-day.is-over .cal-day-warn { background: color-mix(in oklab, var(--tone-action) 28%, transparent); }

/* ------------------------------------------------------- roadmaps */

.roadmap-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: var(--s3);
}

/* Each card is a decision: what it is, and what applying it costs.
   The footer is pinned so the buttons line up across cards whose blurbs
   run to different lengths. */
.roadmap {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  background: var(--surface-2);
}
.roadmap h4 { font-size: var(--t-14); }
.roadmap-foot { margin-top: auto; gap: var(--s2); }
.roadmap-foot .faint { font-size: var(--t-12); min-width: 0; }

/* ------------------------------------------------- client to-do list */

.task-add { gap: var(--s2); }

.task-rows { display: flex; flex-direction: column; gap: 2px; }

.task-row {
  display: flex;
  align-items: flex-start;
  gap: var(--s2);
  padding: var(--s2);
  border-radius: var(--r-control);
  transition: background var(--fast) var(--ease);
}
.task-row:hover { background: var(--surface-2); }

/* The checkbox sits with the first line of text, not centred against a
   two-line item. */
.task-row .check { align-items: flex-start; }
.task-row .check input { margin-top: 2px; }

.task-body { font-size: var(--t-13); }
.task-meta { font-size: var(--t-11); }

/* Done stays readable. Struck through and dimmed says finished; hidden
   says it never happened, and the point of a list is the record. */
.task-row.is-done .task-body { text-decoration: line-through; color: var(--text-3); }

/* The remove button appears on hover on a pointer, and is always there
   on touch, where there is no hover to reveal it with. */
.task-remove { opacity: 0; transition: opacity var(--fast) var(--ease); flex: none; }
.task-row:hover .task-remove, .task-remove:focus-visible { opacity: 1; }
@media (hover: none) { .task-remove { opacity: 1; } }

.task-done-wrap summary { cursor: pointer; font-size: var(--t-12); padding: var(--s2) 0; }

/* -------------------------------------------- agency to-do list */

.todo-groups { display: grid; gap: var(--s4); }

/* A client heading that is also the way into their workspace. */
.todo-client {
  display: flex;
  align-items: center;
  gap: var(--s2);
  width: 100%;
  padding: var(--s2);
  border-radius: var(--r-control);
  text-align: left;
  font-size: var(--t-13);
  font-weight: 600;
  transition: background var(--fast) var(--ease);
}
.todo-client:hover { background: var(--surface-2); }
.todo-client .chip { flex: none; font-variant-numeric: tabular-nums; }

/* The items sit under their client, indented enough to read as belonging
   to it without becoming a second column. */
.todo-group .task-rows { padding-left: var(--s5); }

@media (max-width: 680px) {
  .todo-group .task-rows { padding-left: var(--s3); }
}

/* Adding a client's to-do without leaving the overview. */
.todo-add { display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; }
.todo-who { width: auto; flex: 0 1 190px; min-width: 0; }

@media (max-width: 560px) {
  .todo-who { flex-basis: 100%; }
  .todo-add .input { flex-basis: 100%; }
}

/* -------------------------------------------- agency to-do list */

/* Grouped by WHEN, because the question first thing in the morning is
   what has to happen today, not which client is loudest. */
.todo-groups { display: grid; gap: var(--s4); }

.todo-bucket {
  display: flex;
  align-items: center;
  gap: var(--s2);
  padding-bottom: var(--s2);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--s2);
}
.todo-bucket .faint { font-variant-numeric: tabular-nums; }

/* Overdue gets a warm edge down the whole group. One item late is a
   slip; four is a pattern, and the block should look different. */
.todo-group.is-overdue {
  padding-left: var(--s3);
  border-left: 2px solid var(--tone-action);
  margin-left: -2px;
}

/* Which client, under the item. Quiet, because the row is about the
   task; the client is context and a way in. */
.task-client {
  font-size: var(--t-11);
  color: var(--text-3);
  text-align: left;
  padding: 0;
  align-self: flex-start;
}
.task-client:hover { color: var(--text-2); text-decoration: underline; }

/* The date is editable in place. Narrow, and it never claims the row. */
.task-due {
  width: auto;
  flex: none;
  min-width: 8.5rem;
  font-size: var(--t-12);
  background: transparent;
  border-color: transparent;
  color: var(--text-3);
}
.task-row:hover .task-due, .task-due:focus { border-color: var(--line-2); color: var(--text-2); }
.todo-group.is-overdue .task-due { color: var(--tone-action); }

/* Adding one without leaving the overview. */
.todo-add { display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; }
.todo-who { width: auto; flex: 0 1 190px; min-width: 0; }
.todo-when { width: auto; flex: none; min-width: 8.5rem; }

@media (max-width: 680px) {
  .todo-who, .todo-when { flex-basis: 100%; }
  .todo-add .input.grow { flex-basis: 100%; }
  .task-due { min-width: 7.5rem; }
}

/* --------------------------------------------------- blocked time */

/* A block is not a job. Struck through the surface rather than coloured
   like a stage, so it reads as absence at a glance and can never be
   mistaken for work that is booked in. */
.cal-chip.is-block {
  background: repeating-linear-gradient(
    135deg,
    var(--surface-2) 0 6px,
    var(--surface-3) 6px 12px
  );
  border-style: dashed;
  border-color: var(--line-2);
}
.cal-chip.is-block .cal-chip-rule { background: var(--line-3); }
.cal-chip.is-block .cal-chip-name { color: var(--text-2); }
.cal-chip.is-block:hover { border-color: var(--tone-action); }

@media (prefers-reduced-motion: no-preference) {
  .cal-chip.is-block { transition: border-color var(--fast) var(--ease); }
}

/* ---------------------------------------------------------- packages */

.package-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--s3);
}

.package { display: flex; flex-direction: column; gap: var(--s3); }

/* A retired package still has clients on it, so it is dimmed rather
   than hidden: somebody is still paying for it and it still needs a
   name and a price. */
.package.is-retired { opacity: 0.6; }
.package.is-retired:hover { opacity: 1; }

.package-price { display: flex; align-items: baseline; gap: var(--s2); flex-wrap: wrap; }

.package-figure {
  font-size: var(--t-27);
  font-weight: 620;
  letter-spacing: -0.02em;
  line-height: 1;
}

.package-features {
  display: grid;
  gap: 5px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--t-12);
  color: var(--text-2);
}

/* A rule rather than a bullet glyph: it reads as a list without the
   dot becoming the loudest thing in the card. */
.package-features li { padding-left: var(--s3); position: relative; }
.package-features li::before {
  content: '';
  position: absolute;
  left: 0; top: 0.62em;
  width: 6px; height: 1px;
  background: var(--line-3);
}

.package-flags { gap: 5px; flex-wrap: wrap; }

.package-foot {
  margin-top: auto;
  padding-top: var(--s3);
  border-top: 1px solid var(--line);
  gap: var(--s2);
}
.package-foot .faint { font-size: var(--t-12); min-width: 0; }

/* ------------------------------------------------ quote composer */

.quote-composer { display: flex; flex-direction: column; gap: var(--s4); margin-bottom: var(--s5);
  border-color: var(--accent-line); box-shadow: 0 8px 28px -18px rgb(0 0 0 / .35); }
.quote-composer-head { display: flex; align-items: center; gap: var(--s3); }
.quote-price-input { font-size: 1.5rem; font-weight: 700; max-width: 14rem; }
.quote-pick-list { display: flex; flex-direction: column; max-height: 22rem; overflow-y: auto;
  border: 1px solid var(--line); border-radius: var(--r2, 10px); }
.quote-pick-list li + li { border-top: 1px solid var(--line); }
.quote-pick { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; width: 100%;
  padding: var(--s3) var(--s4); background: none; border: 0; text-align: left; cursor: pointer; color: var(--text); }
.quote-pick:hover, .quote-pick:focus-visible { background: var(--surface-2); }
.quote-pick-empty { padding: var(--s4); }
.quote-row[aria-current="true"] { border-color: var(--accent-line); background: var(--accent-soft); }
.panel-quote-link { align-self: flex-start; }
.quote-chips { display: flex; flex-wrap: wrap; gap: var(--s2); }
.quote-chip { display: inline-flex; align-items: center; gap: 6px; padding: 8px 12px; min-height: 40px;
  border: 1px solid var(--line); border-radius: 999px; background: var(--surface); color: var(--text);
  font: inherit; font-size: .9rem; cursor: pointer; transition: background var(--duration-fast, 150ms), border-color var(--duration-fast, 150ms); }
.quote-chip:hover { border-color: var(--accent-line); }
.quote-chip:focus-visible { outline: 2px solid var(--accent-line); outline-offset: 2px; }
.quote-chip.is-on { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-text); font-weight: 600; }
.quote-chip-price { color: var(--text-2); font-weight: 400; font-size: .82rem; }
.quote-chip.is-on .quote-chip-price { color: inherit; }
.quote-add-materials { align-self: flex-start; }
.quote-materials .input { max-width: 14rem; }
.qr-box { display: flex; flex-direction: column; align-items: center; gap: var(--s3); padding: var(--s2) 0; }
.qr-box svg { border-radius: 8px; box-shadow: 0 0 0 1px var(--line); }
.quote-items { margin: var(--s4) 0 0; padding: 0 0 var(--s3); border-bottom: 1px solid var(--line); }
.quote-item { display: flex; justify-content: space-between; gap: var(--s4); padding: 5px 0; }
.quote-item dt { color: var(--text-2); }
.quote-item dd { margin: 0; font-variant-numeric: tabular-nums; }

/* ------------------------------------------------ quiet destruction
   A Remove or Retire on every row of a list turned a settings screen into
   a column of red. The button is still there, plain until you point at
   it, and the confirm that follows is what does the warning. */
.tag-row .btn-danger,
.field-row .btn-danger,
.team-row .btn-danger,
.stage-row .btn-danger {
  color: var(--text-3);
  border-color: transparent;
  background: transparent;
}
.tag-row .btn-danger:hover,
.field-row .btn-danger:hover,
.team-row .btn-danger:hover,
.stage-row .btn-danger:hover,
.tag-row .btn-danger:focus-visible,
.field-row .btn-danger:focus-visible,
.team-row .btn-danger:focus-visible,
.stage-row .btn-danger:focus-visible {
  color: var(--danger-text);
  background: var(--danger-soft);
  border-color: transparent;
}
