/* CS Emailer.
   Brand: #2D2E75 indigo and #DF2127 red.

   The two colours carry a real distinction rather than decorating: indigo is
   the Monday set (manager-only), red is all-hands (copied to corporate). That
   is the difference that actually changes who reads the email, so it is the one
   worth encoding in colour.

   Both need variants. The indigo is dark enough to disappear on a dark ground,
   so dark mode lifts it. The red at its brand value only just clears 4.5:1 on
   white, so small text uses a darkened variant and the brand value is kept for
   fills, bands and large numerals. */

:root {
  --brand: #2d2e75;
  --brand-deep: #23245c;
  --brand-lift: #3d3f96;
  --brand-on: #ffffff;
  --brand-soft: #ececf7;
  --brand-line: #c6c7e6;

  --accent: #df2127;
  --accent-deep: #b3161b;
  --accent-text: #b3161b;
  --accent-on: #ffffff;
  --accent-soft: #fdecec;
  --accent-line: #f4b8ba;

  --bg: #f4f5fa;
  --surface: #ffffff;
  --border: #dcdfea;
  --text: #16182a;
  --muted: #5d647a;

  --up: #12734a;
  --up-soft: #e6f4ec;
  --up-line: #a8d8bf;

  --warn-bg: #fdf3e0;
  --warn-border: #e2bd79;
  --warn-text: #6a4708;

  --chip-bg: #eef0f7;
  --radius: 12px;
  --shadow: 0 1px 2px rgba(22, 24, 42, .06), 0 6px 16px rgba(22, 24, 42, .05);
}

@media (prefers-color-scheme: dark) {
  :root {
    --brand: #7f80e4;
    --brand-deep: #1b1c46;
    --brand-lift: #9a9bef;
    --brand-on: #0f1020;
    --brand-soft: #21224e;
    --brand-line: #3b3d84;

    --accent: #ff6367;
    --accent-deep: #7d2226;
    --accent-text: #ff9093;
    --accent-on: #1c0f10;
    --accent-soft: #3a1b1d;
    --accent-line: #7d3336;

    --bg: #0e0f18;
    --surface: #181a26;
    --border: #2a2d3e;
    --text: #e9ebf3;
    --muted: #98a0b8;

    --up: #5fcf94;
    --up-soft: #14291f;
    --up-line: #2d5d43;

    --warn-bg: #2b2413;
    --warn-border: #5a4a22;
    --warn-text: #f0d9a8;

    --chip-bg: #232636;
    --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 6px 16px rgba(0, 0, 0, .3);
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 15px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

a { color: var(--brand); }

/* ---- top bar: solid brand ---- */

.topbar {
  display: flex;
  flex-wrap: wrap;
  gap: 14px 24px;
  align-items: center;
  padding: 12px 24px;
  background: var(--brand-deep);
  border-bottom: 3px solid var(--accent);
  color: #fff;
}

.brand { display: flex; align-items: center; gap: 9px; text-decoration: none; color: #fff; }

.brand-mark {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 8px;
  background: var(--accent);
  color: #fff;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .4px;
}

.brand-name { font-weight: 650; letter-spacing: .2px; }

.steps { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; flex: 1; }

.step {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 4px 12px 4px 5px;
  border-radius: 20px;
  font-size: 13px;
  text-decoration: none;
  color: rgba(255, 255, 255, .72);
  background: rgba(255, 255, 255, .06);
}

.step-n {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .16);
  font-size: 11px;
  font-weight: 700;
}

a.step:hover { color: #fff; background: rgba(255, 255, 255, .14); }
.step-now { background: #fff; color: var(--brand-deep); font-weight: 650; }
.step-now .step-n { background: var(--accent); color: #fff; }
.step-done { color: #fff; background: rgba(255, 255, 255, .16); }
.step-done .step-n { background: var(--accent); color: #fff; }
.step-todo { opacity: .55; }
.step-sep { color: rgba(255, 255, 255, .4); }

.week-form { display: flex; gap: 10px; align-items: flex-end; }
.week-form label { display: flex; flex-direction: column; gap: 3px; }

.week-form span {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .6px;
  color: rgba(255, 255, 255, .7);
}

input, select, button {
  font: inherit;
  padding: 7px 11px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text);
}

button {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-on);
  cursor: pointer;
  font-weight: 600;
}

button:hover { background: var(--accent-deep); border-color: var(--accent-deep); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

main { max-width: 1100px; margin: 0 auto; padding: 24px; }

/* ---- hero ---- */

.hero {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  align-items: center;
  justify-content: space-between;
  padding: 26px 28px;
  margin-bottom: 22px;
  border-radius: var(--radius);
  background: linear-gradient(135deg, var(--brand) 0%, var(--brand-deep) 100%);
  color: #fff;
  box-shadow: var(--shadow);
}

.hero-all-hands { background: linear-gradient(135deg, var(--accent) 0%, var(--accent-deep) 100%); }

.hero h1 { margin: 0; font-size: 26px; letter-spacing: -.3px; }
.hero p { margin: 6px 0 0; color: rgba(255, 255, 255, .84); max-width: 60ch; }

.hero-kicker {
  margin: 0 0 6px !important;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 1px;
  font-weight: 700;
  color: rgba(255, 255, 255, .78) !important;
}

.hero-sub .chip { background: rgba(255, 255, 255, .18); color: #fff; border-color: transparent; }

.hero-beats {
  margin: 0;
  padding-left: 18px;
  display: grid;
  gap: 4px;
  font-size: 13px;
  color: rgba(255, 255, 255, .85);
  max-width: 46ch;
}

.figures { display: flex; gap: 30px; }
.figure { display: flex; flex-direction: column; align-items: flex-end; }

.figure-value {
  font-size: 40px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  color: #fff;
}

.figure-value.up, .figure-value.down { color: #fff; }

.figure-label {
  margin-top: 4px;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .8px;
  color: rgba(255, 255, 255, .78);
}

/* ---- email cards ---- */

.group { margin-bottom: 30px; }
.group-head { margin-bottom: 14px; }

.group-head h2 {
  margin: 0;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--brand);
}

.group-all-hands .group-head h2 { color: var(--accent-text); }
.group-head p { margin: 5px 0 0; color: var(--muted); font-size: 14px; max-width: 78ch; }

.cards { display: grid; gap: 14px; }

.card {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  text-decoration: none;
  color: var(--text);
  box-shadow: var(--shadow);
  transition: transform .08s ease, border-color .08s ease;
}

.card:hover { transform: translateY(-2px); border-color: var(--brand); }
.card-all-hands:hover { border-color: var(--accent); }

.card-band { height: 5px; background: var(--brand); }
.card-all-hands .card-band { background: var(--accent); }

.card-body { padding: 16px 18px 12px; flex: 1; }
.card h3 { margin: 0; font-size: 17px; }
.card-summary { margin: 5px 0 10px; color: var(--muted); font-size: 14px; }

.beats { margin: 0; padding-left: 17px; display: grid; gap: 3px; font-size: 13px; color: var(--muted); }
.beats-wide { gap: 6px; font-size: 14px; max-width: 80ch; }

.card-foot {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  padding: 10px 18px 14px;
  border-top: 1px solid var(--border);
}

.tag {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 600;
}

.tag-rhythm { background: var(--chip-bg); color: var(--muted); }
.tag-managers { background: var(--brand-soft); color: var(--brand); border: 1px solid var(--brand-line); }
.tag-cc { background: var(--accent-soft); color: var(--accent-text); border: 1px solid var(--accent-line); }
.tag-picked { background: var(--accent); color: var(--accent-on); }

/* ---- banners ---- */

.banner {
  padding: 13px 17px;
  border: 1px solid;
  border-left-width: 5px;
  border-radius: var(--radius);
  margin-bottom: 14px;
  font-size: 14px;
}

.banner-warn { background: var(--warn-bg); border-color: var(--warn-border); color: var(--warn-text); }
.banner-stale { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-text); }
.banner-info { background: var(--brand-soft); border-color: var(--brand); color: var(--brand); }
.banner a { color: inherit; }

.lede { color: var(--muted); font-size: 14px; margin: 0 0 14px; max-width: 82ch; }

/* ---- search + customer list ---- */

.search { display: flex; gap: 10px; align-items: center; margin-bottom: 12px; }
.search input { flex: 1; padding: 11px 15px; font-size: 16px; }
.search button { padding: 11px 20px; }
.clear { font-size: 14px; white-space: nowrap; }
.result-count { color: var(--muted); font-size: 13px; margin: 0 0 14px; }

.org-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }

.org a {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: baseline;
  justify-content: space-between;
  padding: 12px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid transparent;
  border-radius: 10px;
  text-decoration: none;
  color: var(--text);
}

.org a:hover { border-color: var(--brand); border-left-color: var(--brand); }
.org-rostered a { border-left-color: var(--brand); background: linear-gradient(90deg, var(--brand-soft) 0%, var(--surface) 22%); }

.org-name { font-weight: 600; }
.org-meta { display: flex; gap: 8px; align-items: baseline; color: var(--muted); font-size: 13px; }
.org-count { font-variant-numeric: tabular-nums; font-weight: 700; color: var(--brand); font-size: 15px; }

/* ---- panels ---- */

.panels { display: grid; gap: 16px; }

.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-top: 4px solid var(--brand);
  border-radius: var(--radius);
  padding: 16px 20px 18px;
  box-shadow: var(--shadow);
}

.panel-selected { border-top-color: var(--accent); }
.panel-all { border-top-color: var(--accent); }

.panel header { display: flex; align-items: center; gap: 10px; margin-bottom: 2px; }
.panel h2 { margin: 0; font-size: 17px; }

.count {
  min-width: 24px;
  padding: 2px 9px;
  border-radius: 20px;
  background: var(--brand);
  color: var(--brand-on);
  font-size: 12px;
  font-weight: 700;
  text-align: center;
}

.panel-selected .count, .panel-all .count { background: var(--accent); color: var(--accent-on); }
.guidance { margin: 6px 0 14px; color: var(--muted); font-size: 13px; max-width: 82ch; }

table { width: 100%; border-collapse: collapse; }

th {
  text-align: left;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .7px;
  color: var(--muted);
  font-weight: 700;
  padding: 0 10px 7px 0;
  border-bottom: 2px solid var(--border);
}

td { padding: 10px 10px 10px 0; border-bottom: 1px solid var(--border); vertical-align: top; }
tbody tr:last-child td { border-bottom: none; }

.num { text-align: right; font-variant-numeric: tabular-nums; width: 76px; }
.strong { font-weight: 700; font-size: 16px; color: var(--brand); }
.muted { color: var(--muted); }

.site { display: block; font-weight: 600; }
.site-full { display: block; font-size: 12px; color: var(--muted); }

.notes { display: flex; flex-wrap: wrap; gap: 6px; }

.chip {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 20px;
  background: var(--chip-bg);
  border: 1px solid transparent;
  color: var(--muted);
  font-size: 12px;
  white-space: nowrap;
}

.chip-up { background: var(--up-soft); border-color: var(--up-line); color: var(--up); font-weight: 600; }
.chip-down { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-text); font-weight: 600; }
.chip-ok { background: var(--brand-soft); border-color: var(--brand-line); color: var(--brand); font-weight: 600; }

.chip-held,
.chip-standout,
.chip-warn {
  background: var(--warn-bg);
  border-color: var(--warn-border);
  color: var(--warn-text);
  white-space: normal;
}

.empty { color: var(--muted); font-size: 14px; margin: 4px 0 0; }

/* ---- notes ---- */

.note {
  margin-top: 22px;
  padding: 18px 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid var(--brand);
  border-radius: var(--radius);
}

.note h2 { margin: 0 0 8px; font-size: 15px; }
.note p { margin: 0; color: var(--muted); font-size: 14px; max-width: 82ch; }
.needs { margin: 0; padding-left: 20px; display: grid; gap: 10px; font-size: 14px; }

.foot {
  max-width: 1100px;
  margin: 0 auto;
  padding: 10px 24px 34px;
  color: var(--muted);
  font-size: 12px;
}

.foot p { margin: 0; }
.foot strong { color: var(--accent-text); }

code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .92em;
  background: var(--chip-bg);
  padding: 1px 5px;
  border-radius: 4px;
}

/* Panels stay full-width and stacked. Three columns fits on a wide screen but
   squeezes each table to a third of the page, wrapping site names onto three
   lines and turning the notes - the chips that actually change how a sentence
   gets written - into unreadable slivers. */
.panels { grid-template-columns: 1fr; }

@media (min-width: 720px) {
  .cards { grid-template-columns: repeat(3, 1fr); }
  th:last-child, td.notes { width: 44%; }
}

/* ---- sign in / setup ---- */

.signin { display: grid; place-items: center; min-height: 62vh; }

.signin-card {
  width: 100%;
  max-width: 460px;
  padding: 34px 32px 30px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-top: 5px solid var(--brand);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  text-align: center;
}

.signin-mark { margin: 0 auto 14px; width: 40px; height: 40px; border-radius: 11px; font-size: 15px; }
.signin-card h1 { margin: 0 0 6px; font-size: 22px; }
.signin-sub { margin: 0 0 20px; color: var(--muted); font-size: 14px; }
.signin-card .banner { text-align: left; }

.signin-button {
  display: block;
  padding: 13px 20px;
  margin: 4px 0 14px;
  background: var(--brand);
  color: var(--brand-on);
  border-radius: 9px;
  text-decoration: none;
  font-weight: 650;
}

.signin-button:hover { background: var(--brand-deep); }
.signin-note { margin: 0; color: var(--muted); font-size: 12.5px; }
.signin-card .needs { text-align: left; margin-top: 6px; }

/* Signed-in identity in the top bar. */
.who { display: flex; align-items: center; gap: 10px; font-size: 13px; color: rgba(255,255,255,.8); }
.who a { color: #fff; text-decoration: none; opacity: .8; }
.who a:hover { opacity: 1; text-decoration: underline; }

/* ---- template management ---- */

.hero-action { width: auto; margin: 0; padding: 12px 22px; white-space: nowrap; }
.card-meta { margin: 8px 0 0; font-size: 12px; color: var(--muted); }

.card-link {
  padding: 3px 10px;
  border-radius: 20px;
  border: 1px solid var(--border);
  font-size: 12px;
  font-weight: 600;
  text-decoration: none;
  color: var(--brand);
}

.card-link:hover { border-color: var(--brand); background: var(--brand-soft); }

.inline-form { display: inline; }

.link-button {
  padding: 3px 10px;
  border-radius: 20px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--accent-text);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}

.link-button:hover { background: var(--accent-soft); border-color: var(--accent-line); }

/* ---- forms ---- */

.template-form {
  display: grid;
  gap: 18px;
  padding: 22px 24px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-top: 4px solid var(--brand);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.field { display: grid; gap: 5px; }

.field > span {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .6px;
  font-weight: 700;
  color: var(--muted);
}

.field small { color: var(--muted); font-size: 12.5px; }

.field input,
.field select,
.field textarea {
  width: 100%;
  font: inherit;
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
  color: var(--text);
}

.field textarea { resize: vertical; line-height: 1.5; }
.field-row { display: grid; gap: 18px; }

.form-actions { display: flex; gap: 14px; align-items: center; }
.form-actions button { padding: 11px 22px; }

/* ---- recipients ---- */

.recipients-editor { display: grid; gap: 10px; }

.recipient {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 14px;
}

.recipient-dropped { opacity: .5; text-decoration: line-through; }
.recipient-added { border-left: 3px solid var(--brand); }
.recipient-foreign { border-left: 3px solid var(--accent); background: var(--accent-soft); }
.recipient-source { margin-left: auto; font-size: 12px; color: var(--muted); }

@media (min-width: 760px) {
  .field-row { grid-template-columns: repeat(3, 1fr); }
}

/* Text inputs and selects render at different intrinsic heights, so a row
   mixing them lands the controls on different baselines. Pin the height and
   align each field to the top of the row so labels, controls and help text
   line up across all three columns regardless of how many lines the help
   text wraps to. */
.field-row { align-items: start; }

.field input[type="text"],
.field input[type="search"],
.field input[type="date"],
.field select {
  height: 42px;
  line-height: 1.4;
}

.field select {
  appearance: none;
  padding-right: 34px;
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%),
                    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 18px) 18px, calc(100% - 13px) 18px;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

/* Help text sits at a fixed distance from its control rather than floating up
   under short ones, so a two-line hint does not shove its neighbour around. */
.field small { min-height: 2.6em; }
.field-row .field small { margin-top: 2px; }

/* ---- the writing step ---- */

/* The call to action at the foot of the review screen. Deliberately the
   loudest thing below the numbers: everything above it is checking, and this
   is the one control that starts the part a person actually came here for. */
.write {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  align-items: center;
  justify-content: space-between;
  margin-top: 24px;
  padding: 20px 24px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.write-text { flex: 1 1 380px; }
.write h2 { margin: 0 0 5px; font-size: 17px; }
.write p { margin: 0; color: var(--muted); font-size: 14px; max-width: 72ch; }

/* ---- draft screen ---- */

.draft-columns { display: grid; gap: 18px; align-items: start; }
.draft-side { display: grid; gap: 16px; align-content: start; }
.draft-side .panel { margin: 0; }
.draft-side .guidance { margin-bottom: 12px; }

/* The body is the whole point of the page, so it gets a readable measure and
   a monospace-adjacent rhythm rather than the cramped textarea a form field
   would normally get. */
.draft-columns textarea {
  font-size: 15px;
  line-height: 1.6;
  min-height: 420px;
}

.revise-form { display: flex; gap: 8px; }

/* flex-basis auto, not 0. With basis 0 the field has no intrinsic width to
   fall back on and any competing width elsewhere in the row wins outright. */
.revise-form input { flex: 1 1 auto; min-width: 0; }

.hint { margin: 10px 0 0; font-size: 12.5px; color: var(--muted); }

.visibility-form button { width: 100%; }

.addresses {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 5px;
  font-size: 13px;
  max-height: 260px;
  overflow-y: auto;
}

.addresses li {
  padding: 5px 9px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 7px;
  word-break: break-all;
}

.addresses .cc { border-left: 3px solid var(--accent); }

.delete-form { text-align: right; }

@media (min-width: 900px) {
  .draft-columns { grid-template-columns: minmax(0, 1.6fr) minmax(300px, 1fr); }
}

/* ---- draft actions strip ----

   These two controls - who can see it, and ask for a change - used to live in
   the right-hand column below a 420px textarea, which on a narrow window put
   them off the bottom of the screen entirely. A person reported the share
   option as simply missing, and they were right to: a control you have to hunt
   for is not a control. They now sit above the draft, side by side. */
.actions {
  display: grid;
  gap: 16px;
  /* Enough that the strip reads as its own band rather than as the top of the
     draft below it. Reported as the revise bar touching the draft. */
  margin-bottom: 26px;
}

.action {
  /* A column so the control can be pushed to the bottom. The two panels carry
     descriptions of different lengths, and the grid stretches them to equal
     height, so without this their buttons sit at different heights - which is
     exactly what it looks like: a mistake. */
  display: flex;
  flex-direction: column;
  padding: 16px 20px 18px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-top: 4px solid var(--accent);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.action h2 { margin: 0 0 7px; font-size: 15px; }

.action-state {
  margin: 0 0 12px;
  color: var(--muted);
  font-size: 13px;
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  align-items: baseline;
}

/* Pushes the control to the bottom of the panel, so both panels' buttons line
   up regardless of how many lines their descriptions wrap to. */
.action form { margin: auto 0 0; }

/* Full width only where the form IS one button. The revise form is an input
   and a button sharing a row: width:100% on that button resolves against the
   whole panel, and since the input is flex-basis 0 there is no free space left
   for it to grow into - it collapses to nothing. Which it did. */
.scope-form button { width: 100%; }

.revise-form button { flex: 0 0 auto; }

/* Two save buttons, so the scope is chosen at the moment of saving. The
   for-me one is secondary so the team option does not look like the only
   way out of the form. */
.form-actions { flex-wrap: wrap; }

.form-actions button[value="private"] {
  background: var(--surface);
  border-color: var(--brand);
  color: var(--brand);
}

.form-actions button[value="private"]:hover {
  background: var(--brand-soft);
  border-color: var(--brand-deep);
}

.form-actions .hint { flex-basis: 100%; margin: 0; }

@media (min-width: 760px) {
  .actions { grid-template-columns: 1fr 1fr; }
}

/* A template only its author can see. Uses the warning palette rather than the
   brand one: it is a state to notice and eventually change, not a feature. */
.tag-private {
  background: var(--warn-bg);
  border: 1px solid var(--warn-border);
  color: var(--warn-text);
}

/* ---- waiting on Claude ----

   Writing and revising take anywhere from a few seconds to most of a minute.
   Without a visible waiting state the page looks broken, somebody clicks again,
   and two drafts get written. */
.spinner {
  display: inline-block;
  width: 13px;
  height: 13px;
  margin-right: 8px;
  vertical-align: -2px;
  border: 2px solid currentColor;
  /* One transparent edge is what makes the rotation readable. */
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin .7s linear infinite;
}

.busy-label { vertical-align: baseline; }

@keyframes spin { to { transform: rotate(360deg); } }

/* Respect a system setting that asks for less motion: keep the shape, which
   still reads as "in progress", and stop it moving. */
@media (prefers-reduced-motion: reduce) {
  .spinner { animation-duration: 3s; }
}

button[disabled], button[aria-disabled="true"] {
  cursor: progress;
  opacity: .85;
}

.busy-status {
  margin: 10px 0 0;
  font-size: 13px;
  color: var(--muted);
}

/* On the review screen the status line sits under a right-aligned button. */
.write .busy-status { flex-basis: 100%; text-align: right; margin-top: 6px; }

/* ---- draft rows ----

   A row is a card containing a link and a delete form, rather than a card that
   IS a link. Deleting from the list was asked for directly: opening a draft
   only to throw it away is a page load for nothing, and a list of them is
   exactly where somebody notices the duplicates. */
.draft-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-right: 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid transparent;
  border-radius: 10px;
}

.draft-row:hover { border-color: var(--brand); border-left-color: var(--brand); }

.draft-row-shared {
  border-left-color: var(--brand);
  background: linear-gradient(90deg, var(--brand-soft) 0%, var(--surface) 22%);
}

/* The link fills the row so the whole width stays clickable - everything
   except the delete button, which is the point. */
.draft-row > a {
  display: flex;
  flex: 1;
  min-width: 0;
  flex-wrap: wrap;
  gap: 10px;
  align-items: baseline;
  justify-content: space-between;
  padding: 12px 0 12px 16px;
  text-decoration: none;
  color: var(--text);
}

.row-delete { margin: 0; flex: 0 0 auto; }

/* Present but quiet until the row is hovered, so a list of drafts does not
   read as a row of delete buttons. Always visible on touch, where there is no
   hover to reveal it, and always visible to keyboard focus. */
.row-delete button { opacity: .45; }
.draft-row:hover .row-delete button,
.row-delete button:focus-visible { opacity: 1; }

@media (hover: none) {
  .row-delete button { opacity: 1; }
}

/* ---- horizontal rails ----

   Six templates in a 3x2 grid pushed the second row below the fold, so the
   month-end and Friday ones were easy to miss entirely. One row that scrolls
   keeps every template in the same place and makes it obvious there are more
   than the three you can see.

   Widths are a fraction of the scroll container, so exactly three cards and
   their two gaps fill the visible width and the fourth is cut off at the edge -
   which is the affordance. Nothing here needs JavaScript. */
.rail {
  display: grid;
  grid-auto-flow: column;
  gap: 14px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  /* Room for the scrollbar without it overlapping the card shadows. */
  padding: 4px 4px 12px;
  margin: 0 -4px;
}

/* One at a time on a phone; the card still shows a sliver of the next. */
.rail { grid-auto-columns: 86%; }

/* No scroll-snap here on purpose. Snapping and programmatic smooth scrolling
   fight in Chrome - the snap engine reverts the animation and the row springs
   back to where it started. The arrows page by a measured whole number of
   cards, which gets the alignment snapping was for. */
.rail > .card {
  /* Grid stretches every card to the tallest, which is what keeps the Use and
     Copy links on one line across the whole row. */
  height: auto;
}

/* A card that has scrolled out of reach should not be a tab stop nobody can
   see - but it must stay reachable, so the rail itself takes focus and
   arrow keys scroll it. */
.rail:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.rail::-webkit-scrollbar { height: 9px; }
.rail::-webkit-scrollbar-track { background: var(--chip-bg); border-radius: 20px; }

.rail::-webkit-scrollbar-thumb {
  background: var(--brand-line);
  border-radius: 20px;
}

.rail::-webkit-scrollbar-thumb:hover { background: var(--brand); }
.group-all-hands .rail::-webkit-scrollbar-thumb { background: var(--accent-line); }
.group-all-hands .rail::-webkit-scrollbar-thumb:hover { background: var(--accent); }

/* Firefox has no pseudo-elements for this. */
.rail { scrollbar-width: thin; scrollbar-color: var(--brand-line) var(--chip-bg); }

.count-inline {
  display: inline-block;
  margin-left: 7px;
  padding: 1px 9px;
  border-radius: 20px;
  background: var(--brand);
  color: var(--brand-on);
  font-size: 12px;
  font-weight: 700;
  vertical-align: 2px;
}

.group-all-hands .count-inline { background: var(--accent); color: var(--accent-on); }

.rail-hint { color: var(--brand); font-weight: 600; }
.group-all-hands .rail-hint { color: var(--accent-text); }

/* Built-in is a fact about the template, not a warning, so it stays quiet
   next to the "Only you" chip. */
.tag-builtin {
  background: var(--chip-bg);
  border: 1px solid var(--border);
  color: var(--muted);
}

@media (min-width: 560px) {
  .rail { grid-auto-columns: calc((100% - 14px) / 2); }
}

@media (min-width: 900px) {
  .rail { grid-auto-columns: calc((100% - 28px) / 3); }
}

/* ---- rail arrows ----

   The page is 1100px inside a wider window, so on a desktop the arrows sit in
   the margin either side and take nothing away from the cards. Below that there
   is no margin to sit in, so they overlay the row's edges instead. */
.rail-wrap { position: relative; }

.rail-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border-radius: 50%;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--brand);
  box-shadow: var(--shadow);
  cursor: pointer;
}

.rail-arrow svg { width: 19px; height: 19px; }

.rail-arrow:hover {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--brand-on);
}

.group-all-hands .rail-arrow { color: var(--accent-text); }

.group-all-hands .rail-arrow:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-on);
}

.rail-prev { left: -52px; }
.rail-next { right: -52px; }

/* The scrollbar goes away only once the arrows have taken over, which is what
   app.js signals by adding this class. Trackpad and touch scrolling still
   work; the bar itself is just no longer the way through. */
.rail-paged { scrollbar-width: none; padding-bottom: 4px; }
.rail-paged::-webkit-scrollbar { display: none; }

/* No margin left to sit in, so they overlap the outermost cards. Standard
   carousel behaviour, and better than pushing the cards narrower. */
@media (max-width: 1249px) {
  .rail-prev { left: 4px; }
  .rail-next { right: 4px; }
}

/* ---- recipient editing ----

   Being able to point a draft at yourself is why this exists. Without it the
   only way to walk the whole flow was with live facility managers on the TO
   line, which is not a thing anyone should have to do to test a button. */
.addresses li {
  display: flex;
  align-items: center;
  gap: 7px;
}

.addresses .address { flex: 1; min-width: 0; word-break: break-all; }

.addresses li.ours { border-left: 3px solid var(--up); }
.addresses li.unfamiliar { border-left: 3px solid var(--accent); background: var(--accent-soft); }

.addresses .link-button { padding: 1px 8px; line-height: 1.4; }

.addresses-dropped li { opacity: .6; }
.addresses-dropped .address { text-decoration: line-through; }

/* The reassurance that makes testing comfortable rather than nerve-racking. */
.recipients-safe {
  padding: 8px 11px;
  border-radius: 8px;
  background: var(--up-soft);
  border: 1px solid var(--up-line);
  color: var(--up);
}

.add-recipient { display: flex; gap: 8px; margin-top: 12px; }
.add-recipient input { flex: 1; min-width: 0; }
.add-recipient button { flex: 0 0 auto; }

.recipient-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

/* Visible to a screen reader, not on screen. Used for labels where the
   placeholder already says what the field is. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ---- the custom route out of the customer list ----

   Above the search rather than in it. A list of 136 customers is the wrong
   shape for "email one manager, a colleague, or myself", and putting the way
   out below the list would mean only people who already knew about it would
   find it. */
.custom-card {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 16px;
  padding: 15px 18px;
  background: var(--surface);
  border: 1px solid var(--accent-line);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  text-decoration: none;
  color: var(--text);
}

.custom-card:hover { border-color: var(--accent); background: var(--accent-soft); }

.custom-mark {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  background: var(--accent);
  color: var(--accent-on);
  font-size: 21px;
  font-weight: 700;
  line-height: 1;
}

.custom-text { display: grid; gap: 3px; font-size: 13px; color: var(--muted); }
.custom-text strong { font-size: 15px; color: var(--text); }

/* ---- the custom compose form ---- */

.choice { border: 0; margin: 0; padding: 0; }
.choice legend { padding: 0; }

.choice-option {
  margin-top: 7px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 9px;
}

.choice-option:hover { border-color: var(--brand); }
.choice-option:has(input:checked) { border-color: var(--brand); background: var(--brand-soft); }

.choice-head {
  display: flex;
  gap: 11px;
  align-items: flex-start;
  padding: 12px 14px;
  cursor: pointer;
}

.choice-head input { flex: 0 0 auto; margin-top: 3px; width: auto; }

/* Only the chosen option shows its control. Done in CSS rather than script so
   it works on a page where the script never ran, and so there is no flash of
   both controls before JavaScript catches up.

   The hidden inputs still submit. That is fine and deliberate: the route reads
   `org` only in figures mode and `note` only in note mode, so a value left
   behind by a change of mind cannot leak into the other branch. */
.choice-body {
  display: none;
  padding: 0 14px 14px 41px;
}

.choice-option:has(input:checked) .choice-body { display: block; }
.choice-body > small { display: block; margin-top: 5px; }

/* A browser without :has() shows both bodies rather than neither, which is the
   behaviour this replaced - degraded, never broken. */
@supports not selector(:has(*)) {
  .choice-body { display: block; }
}

.choice-text { display: grid; gap: 2px; font-size: 13px; color: var(--muted); }
.choice-text strong { font-size: 14.5px; color: var(--text); }

/* ---- type-to-narrow a long select ---- */

.combo-filter {
  margin-bottom: 7px;
  /* Same metrics as the select below it, so the pair reads as one control
     rather than as a field that acquired a stray input. */
  height: 42px;
  line-height: 1.4;
}

.combo-filter[hidden] { display: none; }

/* A per-customer heading in the figures panel, when a draft covers several. */
.figures-group {
  margin: 14px 0 5px;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: .6px;
  color: var(--brand);
}

.figures-group:first-of-type { margin-top: 4px; }

/* The multi-select needs to show several rows without swallowing the page. */
#org-select[multiple] {
  height: auto;
  min-height: 190px;
  padding: 4px;
  /* The single-select arrow would be a lie on a list box. */
  background-image: none;
  padding-right: 12px;
}

#org-select[multiple] option { padding: 5px 8px; border-radius: 5px; }

/* ---- sending ----

   The one irreversible thing in this application. The visual weight is
   deliberate: everything else here is a draft nobody has seen. */
.panel-send { border-top-color: var(--up); }
.panel-send .count { background: var(--up); }

.send-link {
  display: block;
  padding: 11px 18px;
  background: var(--up);
  color: #fff;
  border-radius: 9px;
  text-align: center;
  text-decoration: none;
  font-weight: 650;
}

.send-link:hover { background: var(--up); filter: brightness(.92); }

.send-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  align-items: center;
  margin-top: 20px;
  padding: 18px 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.send-button { padding: 13px 26px; font-size: 15px; }

/* The one place a customer address is called out in red. Everywhere else the
   palette treats them as ordinary, because everywhere else nothing leaves. */
.send-warning {
  padding: 10px 13px;
  border-radius: 8px;
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  color: var(--accent-text);
}

.send-subject { margin: 0 0 12px; font-size: 14px; }

.send-body {
  margin: 0;
  padding: 14px 16px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 9px;
  font: inherit;
  white-space: pre-wrap;
  word-wrap: break-word;
  max-height: 420px;
  overflow-y: auto;
}

.banner-sent {
  background: var(--up-soft);
  border-color: var(--up-line);
  color: var(--up);
}

/* The violations panel is followed by the draft itself when nothing else sits
   between them - which is the case once a draft has been sent and the editing
   controls are gone. Without this they touch. */
.panel-blocked { margin-bottom: 22px; }

/* A draft that has gone out. Marked, not locked - it is still the best
   starting point for the next one. */
.chip-sent {
  background: var(--up-soft);
  border-color: var(--up-line);
  color: var(--up);
  font-weight: 600;
}

.send-history { display: grid; gap: 3px; }
.sent-line { display: block; font-size: 12.5px; }

/* ---- brand marks ----

   The shield replaces the "CS" tile in the top bar. Sized in CSS rather than
   left to the intrinsic 578px, and given a transparent background because the
   top bar is brand indigo and the artwork is not square-cropped to it. */
img.brand-mark {
  width: 30px;
  height: 30px;
  background: none;
  border-radius: 0;
  object-fit: contain;
  flex: 0 0 auto;
}

/* The full lockup on the sign-in card. Capped by width so the wordmark stays
   legible, and it is the first thing on the card so it carries the identity
   before any text does. */
.signin-logo {
  display: block;
  width: 100%;
  max-width: 260px;
  height: auto;
  margin: 0 auto 18px;
}

/* The shield is navy and the top bar is navy, so on its own it disappears.
   A white tile is what the logo is drawn to sit on. */
img.brand-mark {
  width: 34px;
  height: 34px;
  padding: 3px;
  background: #fff;
  border-radius: 8px;
}

/* The wordmark is gone from the bar, so the shield is the whole link and
   needs no gap after it. */
.brand { gap: 0; }

/* Brand red on the sign-in heading. Not a token, because the existing --accent
   shifts in dark mode for contrast against dark surfaces - and this sits on the
   white card in both. */
.signin-card h1 { color: #df2127; }

/* The bulk-or-individual choice on the send screen. Full width above the
   button, because it changes what the recipients see about each other. */
.send-mode { margin: 0 0 16px; flex-basis: 100%; }
.send-mode legend { margin-bottom: 2px; }

/* To-or-CC beside the address field. Narrow, because it is a two-item choice
   sitting next to the thing it qualifies. */
.add-field {
  flex: 0 0 auto;
  width: auto;
  min-width: 72px;
  height: 42px;
  padding-right: 26px;
  background-position: calc(100% - 12px) 18px, calc(100% - 7px) 18px;
}

/* CC rows carry the same remove control as TO rows, so the layout matches. */
.addresses li.cc .chip { flex: 0 0 auto; }
