/* Announcements (core/announcements.py): the one popup an admin queued for
   this account (#announce-backdrop), its replica in the admin's preview
   (.ann-preview-popup), and the admin's Announcements panel and drawer
   section (#admin-announce, .ann-*, .adm-ann-*).

   Loaded after soft.css and before phone.css: it sets corners, and every
   sheet between phone.css and rounded.css has to leave shape alone
   (tests/test_phone_shell.py). It mints no tokens (tests/test_beta_redesign.py):
   every colour is a token the design layer already defines, so dark mode
   follows without a rule of its own. Every word inside these boxes arrives
   as text (app.js builds them with textContent), so nothing here styles
   markup a catalog entry or an admin could inject. */

/* ── the popup ────────────────────────────────────────────────────────────
   Bigger than a confirm and centred at every width. The replica in the
   admin's preview uses the same classes, so what the admin sees is what a
   student gets. */
#announce-backdrop .announce,
.ann-preview-popup .announce {
  position: relative;
  width: 100%;
  max-width: 520px;
  display: grid;
  justify-items: center;
  gap: 12px;
  text-align: center;
  padding: 36px 34px 28px !important;
}
.announce-art {
  width: 72px;
  height: 72px;
  margin-bottom: 4px;
  display: grid;
  place-items: center;
  border-radius: var(--r-lg);
  background: var(--accent-soft);
  color: var(--accent);
}
.announce-art svg { width: 30px; height: 30px; display: block; }
.announce-kicker {
  margin: 0;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
}
.announce-kicker:empty { display: none; }
/* styles.css sets every .modal-title to 20px and 650 with !important. */
body:not(#_) :is(#announce-backdrop, .ann-preview-popup) .announce > .modal-title {
  font-family: var(--font-display);
  font-size: 2rem !important;
  font-weight: 700 !important;
  letter-spacing: -0.03em;
  line-height: 1.12;
  overflow-wrap: anywhere;
}
/* pre-line: a custom announcement's blank line is a paragraph break, and
   the text is never markup, so a newline is the only way to make one. */
body:not(#_) :is(#announce-backdrop, .ann-preview-popup) .announce > .modal-sub {
  margin: 0;
  max-width: 40ch;
  color: var(--text-secondary);
  font-size: 1.05rem !important;
  line-height: 1.55;
  white-space: pre-line;
  overflow-wrap: anywhere;
}
#announce-body { white-space: pre-line; }
/* The storage notice waits under it, as it does under a confirm. */
body:has(#announce-backdrop:not(.hidden)) #storage-notice { z-index: 99; }
.announce-points {
  width: 100%;
  margin: 4px 0 0;
  padding: 16px 18px;
  list-style: none;
  display: grid;
  gap: 10px;
  text-align: left;
  border-radius: var(--r-md);
  background: var(--bg-elev-2);
}
.announce-points[hidden] { display: none; }
.announce-points li {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  gap: 10px;
  align-items: start;
  font-size: 0.95rem;
  line-height: 1.45;
  color: var(--text);
  overflow-wrap: anywhere;
}
.announce-tick {
  width: 22px;
  height: 22px;
  margin-top: 1px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);
}
:is(#announce-backdrop, .ann-preview-popup) .announce > .modal-actions {
  width: 100%;
  margin-top: 8px;
  justify-content: center;
}
/* .ghost-btn sets its own display, which beats the hidden attribute: a
   popup whose button goes nowhere has "Got it" and no Not now. */
#announce-backdrop .announce > .modal-actions > [hidden] { display: none !important; }
/* 44px at every width: the close button is the first way out a student
   looks for, and a finger needs the room. */
.announce-x {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--text-tertiary);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}
.announce-x:hover { color: var(--text); background: var(--bg-elev-2); }
/* redesign.css gives every opening dialog its panel arrival with
   !important; this one rises a little further, once. */
#announce-backdrop:not(.hidden) > .announce {
  animation: announceIn 260ms var(--ease, ease-out) both !important;
}
@keyframes announceIn {
  from { opacity: 0; transform: translateY(12px) scale(0.98); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  #announce-backdrop:not(.hidden) > .announce,
  .ann-preview-popup .announce { animation: none !important; }
}
@media (max-width: 767px) {
  #announce-backdrop .announce,
  .ann-preview-popup .announce { padding: 26px 20px 20px !important; gap: 10px; }
  .announce-art { margin-bottom: 0; }
  body:not(#_) :is(#announce-backdrop, .ann-preview-popup) .announce > .modal-title { font-size: 1.65rem !important; }
  .announce-points { padding: 14px; }
  :is(#announce-backdrop, .ann-preview-popup) .announce > .modal-actions { flex-direction: column-reverse; }
  :is(#announce-backdrop, .ann-preview-popup) .announce > .modal-actions > button { width: 100%; }
  .announce-x { top: 6px; right: 6px; }
}

/* ── the admin's Announcements panel ─────────────────────────────────────
   Cards in the admin view's own soft language (soft.css: the panels, the
   segmented control, the pill buttons): one column under 900px, two to
   1399px, three from 1400px. */
body:not(#_) #admin-announce .admin-section-header { align-items: baseline; }
.admin-announce-note {
  margin: 0 0 14px;
  max-width: 76ch;
  color: var(--text-dim);
  font-size: 12.5px;
  line-height: 1.55;
}
.admin-announce-errors {
  margin: 0 0 14px;
  padding: 10px 14px;
  border-radius: 14px;
  background: rgb(var(--danger-rgb) / 0.10);
  font-size: 12.5px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}
.admin-announce-errors[hidden] { display: none; }
.admin-announce-errors ul { margin: 6px 0 0; padding-left: 18px; }
.admin-announce-tools {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin: 0 0 16px;
}
body:not(#_) .admin-announce-tools .admin-search-box { flex: 1 1 220px; max-width: none; min-width: 0; }
.admin-announce-tools select { flex: 0 1 auto; min-width: 0; max-width: 100%; }
.admin-announce-tools .primary-btn { white-space: nowrap; }
.admin-announce-list {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
  align-items: start;
}
@media (min-width: 900px) { .admin-announce-list { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1400px) { .admin-announce-list { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.admin-announce-empty {
  grid-column: 1 / -1;
  padding: 28px 16px;
  border-radius: var(--soft-row);
  background: rgb(var(--accent-rgb) / 0.04);
  color: var(--text-dim);
  font-size: 13px;
  text-align: center;
}

/* One card. An open preview takes the whole row: an email is too wide
   for a third of the panel. */
.ann-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
  padding: 16px;
  border-radius: var(--soft-row);
  background: rgb(var(--accent-rgb) / 0.035);
  border: 1px solid var(--border);
  transition: border-color 0.15s ease, background 0.15s ease;
}
.ann-card:hover { border-color: rgb(var(--accent-rgb) / 0.30); }
.ann-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ann-card.is-open { grid-column: 1 / -1; background: var(--bg-elev-1); }
.ann-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.ann-glyph {
  width: 34px;
  height: 34px;
  flex: none;
  display: grid;
  place-items: center;
  margin-right: 4px;
  border-radius: 12px;
  background: var(--accent-soft);
  color: var(--accent);
}
.ann-glyph svg { width: 19px; height: 19px; display: block; }
.ann-chip {
  display: inline-flex;
  align-items: center;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.6;
  white-space: nowrap;
  color: var(--text-muted);
  background: rgb(var(--accent-rgb) / 0.10);
}
.ann-chip-launch { color: var(--bg, #fff); background: var(--accent); }
.ann-chip-kind { background: var(--bg-elev-2); }
.ann-date { margin-left: auto; font-size: 11.5px; color: var(--text-dim); white-space: nowrap; }
.ann-title { margin: 2px 0 0; font-size: 15px; font-weight: 700; line-height: 1.3; overflow-wrap: anywhere; }
.ann-body {
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-dim);
  overflow-wrap: anywhere;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.ann-status {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  font-size: 12px;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.ann-status b { color: var(--text); font-weight: 600; }
.ann-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
body:not(#_) .ann-actions .admin-act,
body:not(#_) .adm-ann-row .admin-act { padding: 7px 13px !important; font-size: 12px; }
body:not(#_) .ann-actions .ann-send {
  color: var(--accent);
  border-color: rgb(var(--accent-rgb) / 0.35) !important;
  background: rgb(var(--accent-rgb) / 0.06);
}
body:not(#_) .ann-actions .ann-send:hover { background: rgb(var(--accent-rgb) / 0.12); }
body:not(#_) .ann-actions .admin-act:disabled,
body:not(#_) .adm-ann-row .admin-act:disabled { opacity: 0.5; cursor: not-allowed; }

/* The preview: Popup | Bell | Email, and a kind picker when it is for more
   than one kind of account. */
.ann-preview {
  display: grid;
  gap: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
  min-width: 0;
}
.ann-preview[hidden] { display: none; }
.ann-preview-bar { display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: center; justify-content: space-between; }
.ann-preview-pane { min-width: 0; }
.ann-preview-pane[hidden] { display: none; }
.ann-preview-popup {
  display: grid;
  place-items: center;
  padding: 24px 16px;
  border-radius: var(--r-lg);
  background: rgb(var(--accent-rgb) / 0.06);
  overflow: hidden;
}
.ann-preview-popup .announce { pointer-events: none; box-shadow: var(--shadow-md); }
.ann-bell {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr);
  gap: 12px;
  align-items: start;
  max-width: 460px;
  padding: 14px 16px;
  border-radius: var(--soft-row);
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
}
.ann-bell-title { margin: 0; font-size: 13.5px; font-weight: 700; overflow-wrap: anywhere; }
.ann-bell-body { margin: 3px 0 0; font-size: 13px; line-height: 1.5; color: var(--text-dim); overflow-wrap: anywhere; }
.ann-bell-opens { margin: 6px 0 0; font-size: 12px; color: var(--accent); font-weight: 600; }
.ann-none { margin: 0; padding: 14px 16px; border-radius: var(--soft-row); background: rgb(var(--accent-rgb) / 0.04); font-size: 13px; color: var(--text-dim); }
.ann-email-meta { display: grid; gap: 2px; margin: 0 0 10px; font-size: 13px; overflow-wrap: anywhere; }
.ann-email-meta span { color: var(--text-dim); }
.ann-email-frame {
  display: block;
  width: 100%;
  height: 560px;
  border: 1px solid var(--border);
  border-radius: var(--soft-row);
  background: #fff;
}
@media (max-width: 640px) { .ann-email-frame { height: 420px; } }

/* The job strip: what a send to everyone is doing right now. */
.admin-announce-job {
  position: relative;
  margin: 0 0 16px;
  padding: 14px 52px 14px 16px;
  border-radius: var(--soft-row);
  background: rgb(var(--accent-rgb) / 0.07);
  border: 1px solid rgb(var(--accent-rgb) / 0.22);
  font-size: 13px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}
.admin-announce-job[hidden] { display: none; }
.admin-announce-job.is-failed { background: rgb(var(--danger-rgb) / 0.08); border-color: rgb(var(--danger-rgb) / 0.25); }
.admin-announce-job.is-warn { background: rgb(var(--warning-rgb) / 0.12); border-color: rgb(var(--warning-rgb) / 0.30); }
.ann-job-head { margin: 0; font-weight: 700; }
.ann-job-track {
  height: 10px;
  margin: 10px 0 8px;
  border-radius: 999px;
  background: rgb(var(--accent-rgb) / 0.12);
  overflow: hidden;
}
.ann-job-fill { height: 100%; border-radius: 999px; background: var(--accent); transition: width 0.4s var(--ease-settle, ease); }
.ann-job-line { margin: 2px 0 0; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.ann-job-actions { display: flex; gap: 8px; margin-top: 10px; }
.ann-job-x {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--text-dim);
  font-size: 18px;
  cursor: pointer;
}
.ann-job-x:hover { color: var(--text); background: rgb(var(--accent-rgb) / 0.10); }

/* Dialogs: the confirm with its counts, the composer, the account picker. */
body:not(#_) .ann-dialog { max-width: 560px !important; width: calc(100% - 24px); max-height: calc(100vh - 32px); overflow-y: auto; }
.ann-dialog-quote { margin: 0; font-weight: 600; overflow-wrap: anywhere; }
.ann-counts { margin: 4px 0 0; padding: 0; list-style: none; display: grid; gap: 8px; }
.ann-counts > li {
  padding: 10px 14px;
  border-radius: 16px;
  background: rgb(var(--accent-rgb) / 0.05);
  font-size: 13px;
  overflow-wrap: anywhere;
}
.ann-counts b { font-variant-numeric: tabular-nums; }
.ann-reasons { margin: 4px 0 0; padding-left: 18px; color: var(--text-dim); font-size: 12.5px; }
.ann-check { display: flex; gap: 10px; align-items: flex-start; font-size: 13px; line-height: 1.45; cursor: pointer; }
.ann-check input { margin-top: 2px; flex: none; }
.ann-linkbtn {
  justify-self: start;
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.ann-warn { margin: 0; padding: 10px 14px; border-radius: 14px; background: rgb(var(--warning-rgb) / 0.14); font-size: 13px; }
.ann-field { display: grid; gap: 6px; min-width: 0; font-size: 13px; }
.ann-field[hidden] { display: none; }
.ann-field > span:first-child { font-weight: 600; }
.ann-field-row { display: flex; justify-content: space-between; gap: 8px; font-size: 12px; color: var(--text-dim); }
.ann-field input[type="text"], .ann-field textarea, .ann-field select { width: 100%; min-width: 0; }
.ann-field textarea { min-height: 120px; }
.ann-channels { display: flex; flex-wrap: wrap; gap: 8px 18px; }
.ann-error { margin: 0; padding: 10px 14px; border-radius: 14px; background: rgb(var(--danger-rgb) / 0.10); font-size: 13px; }
.ann-error[hidden] { display: none; }
.ann-hint { margin: 0; font-size: 12px; color: var(--text-dim); }
.ann-pick-list { display: grid; gap: 4px; margin: 0; padding: 0; list-style: none; max-height: 320px; overflow-y: auto; }
.ann-pick-list button {
  width: 100%;
  display: grid;
  gap: 2px;
  padding: 10px 14px;
  border: 1px solid transparent;
  border-radius: 16px;
  background: rgb(var(--accent-rgb) / 0.04);
  color: var(--text);
  font: inherit;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}
.ann-pick-list button:hover, .ann-pick-list button:focus-visible { border-color: rgb(var(--accent-rgb) / 0.4); background: rgb(var(--accent-rgb) / 0.08); }
.ann-pick-list small { color: var(--text-dim); overflow-wrap: anywhere; }

/* ── the report drawer's section: one announcement to one account ──────── */
.adm-ann-pick { display: grid; gap: 6px; margin: 0 0 12px; font-size: 13px; }
.adm-ann-pick select { width: 100%; max-width: 100%; }
.adm-ann-row { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; }
.adm-ann-history { margin-top: 4px; }

@media (max-width: 640px) {
  .admin-announce-tools > * { flex: 1 1 100%; }
  .admin-announce-tools .primary-btn { white-space: normal; }
  .ann-date { margin-left: 0; width: 100%; }
  body:not(#_) .ann-actions .admin-act { flex: 1 1 auto; }
}
