/* IHRDC Status — additions
 *
 * Loaded after styles.css, which is the supplied design file and is kept byte-for-byte.
 * Anything here covers behaviour the design did not specify. Same custom properties, so
 * it inherits the palette and the dark-mode overrides for free.
 * ------------------------------------------------------------------ */

/* Whole-card links. The card is the click target rather than just its title, so the
   pointer does not have to find a small word. The inner title is a span, not a nested
   anchor, because an anchor inside an anchor is invalid and browsers recover from it
   unpredictably. */
.card-link { display: block; color: inherit; text-decoration: none; }
.card-link:hover { color: inherit; text-decoration: none; }
.card-link:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; border-radius: 4px; }
.card-link .card-name { color: var(--ihrdc-blue); }
.card-link:hover .card-name { color: var(--ihrdc-blue-shade-1); text-decoration: underline; }

/* A site whose hostname is not shown to readers still needs something in the slot the
   design gives the slug, or the title baseline shifts against its neighbours. */
.card-kind {
  font-size: 12px; color: var(--fg-3); white-space: nowrap;
  text-transform: uppercase; letter-spacing: 0.12em; font-weight: 700;
}

/* ---- calendar -----------------------------------------------------------
 * A year of history is too much for the strip: ninety cells is already
 * slivers, and three hundred and sixty-five would be noise. Months give the
 * eye something to navigate by, and a date to name when reporting a problem.
 * ----------------------------------------------------------------------- */

.cal-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; }
.cal-nav { display: flex; align-items: center; gap: 12px; }
.cal-step { font-size: 13px; font-weight: 700; color: var(--ihrdc-blue); white-space: nowrap; }
.cal-step.is-disabled { color: var(--fg-3); font-weight: 400; cursor: default; }
.cal-views { display: flex; align-items: center; gap: 2px; }
.cal-view {
  font-size: 13px; font-weight: 700; color: var(--fg-2);
  padding: 6px 12px; border: 1px solid var(--border-1); border-radius: 2px;
  white-space: nowrap;
}
.cal-view:hover { text-decoration: none; color: var(--ihrdc-blue); }
.cal-view.is-active { color: var(--ihrdc-blue); background: var(--bg-subtle); border-color: var(--ihrdc-blue); }

.cal-block { display: flex; flex-direction: column; gap: 8px; }
.cal-months { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }
.cal-month { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.cal-month-label {
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.12em; color: var(--fg-3);
}
/* Cells are capped rather than stretched: three months of 1fr columns in a 1200px card
   gives 46px squares, which reads as a poster instead of a calendar. */
.cal-weekdays, .cal-grid {
  display: grid; grid-template-columns: repeat(7, minmax(0, 34px)); gap: 3px;
  justify-content: start;
}
.cal-weekdays span {
  font-size: 10px; color: var(--fg-3); text-align: center; font-variant-numeric: tabular-nums;
}

.cal-day {
  aspect-ratio: 1; display: flex; align-items: center; justify-content: center;
  border: 0; padding: 0; border-radius: 2px;
  font-family: var(--font-sans); font-size: 10px;
  background: var(--none); color: transparent;
  font-variant-numeric: tabular-nums;
}
/* The date is carried by the tooltip and only revealed on interaction, so a month reads as
   a block of colour first. Showing every number turns the grid into a wall of digits and
   defeats the point of a heat map. */
.cal-day.ok { background: var(--ok); }
.cal-day.partial { background: var(--warn); }
.cal-day.down { background: var(--bad); }
.cal-day.nodata { background: var(--none); }
.cal-day.future { background: transparent; border: 1px dashed var(--border-1); }
.cal-day.cal-blank { background: transparent; }

/* The ring carries hover and selection on its own. Revealing the date in white would be
   unreadable on the light no-data grey, and the panel names the day anyway. */
.cal-openable { cursor: pointer; }
.cal-openable:hover, .cal-openable:focus-visible,
.cal-openable[aria-pressed="true"] {
  box-shadow: 0 0 0 2px var(--ihrdc-dark-navy); outline: none;
}
@media (prefers-color-scheme: dark) {
  .cal-openable:hover, .cal-openable:focus-visible,
  .cal-openable[aria-pressed="true"] { box-shadow: 0 0 0 2px #FFFFFF; }
}

/* ---- day detail --------------------------------------------------------- */

.day-detail {
  border: 1px solid var(--border-1); border-radius: 4px;
  background: var(--bg-subtle); padding: 20px 24px; margin: 0 0 64px;
}

/* Anchored to the cell that was clicked. A day cell is 34px across and a strip cell is
   thinner still; a panel at the foot of the page means losing sight of the thing you are
   reading about. Positioned absolutely in page coordinates, so it travels with the cell as
   the page scrolls rather than detaching from it. */
.day-detail.is-pop {
  position: absolute; z-index: 40; margin: 0;
  background: var(--bg-card, var(--bg-page));
  box-shadow: 0 8px 24px rgba(17, 42, 70, .18), 0 2px 6px rgba(17, 42, 70, .10);
  padding: 16px 18px;
}
.day-detail.is-pop .day-window { font-size: 13px; padding: 8px 10px; }
.day-detail.is-pop .day-windows { gap: 6px; }
.day-detail.is-pop h3 { font-size: 16px; }
@media (prefers-color-scheme: dark) {
  .day-detail.is-pop { box-shadow: 0 8px 24px rgba(0, 0, 0, .45), 0 2px 6px rgba(0, 0, 0, .35); }
}
.day-detail-head {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 12px;
}
.day-detail h3 { margin: 0; font-size: 18px; font-weight: 700; color: var(--fg-1); }
.day-detail-sub { font-size: 13px; color: var(--fg-3); }
.day-detail-close {
  background: none; border: 0; cursor: pointer; padding: 4px 0;
  font-family: var(--font-sans); font-size: 13px; font-weight: 700; color: var(--ihrdc-blue);
}
.day-windows { list-style: none; margin: 14px 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.day-window {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 12px;
  padding: 10px 12px; background: var(--bg-page); border: 1px solid var(--border-1); border-radius: 2px;
  font-size: 14px;
}
.day-window-time { font-family: var(--font-mono); font-size: 13px; font-variant-numeric: tabular-nums; }
.day-window-length { font-weight: 700; }
.day-window.degraded .day-window-length { color: var(--warn); }
.day-window.down .day-window-length { color: var(--bad); }
.day-causes { margin: 14px 0 0; font-size: 13px; color: var(--fg-2); }
.day-causes ul { margin: 6px 0 0; padding-left: 18px; }
.day-empty { margin: 12px 0 0; font-size: 13px; color: var(--fg-3); }

.not-counted {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--fg-3); white-space: nowrap;
}

@media (max-width: 900px) {
  .cal-months { grid-template-columns: minmax(0, 1fr); }
}

/* ---- strip cells -------------------------------------------------------
 * The supplied stylesheet colours .cell.ok / .degraded / .down / .nodata, but the history
 * module emits 'partial' for a day that had both good and bad checks - which fell through
 * to the default green, so a partly degraded day looked perfect. Same amber as the
 * calendar, because it means the same thing.
 * ----------------------------------------------------------------------- */

.cell.partial { background: var(--warn); }

/* A day worth reading about is a button. Same target, same panel as the calendar. */
.strip button.cell {
  border: 0; padding: 0; margin: 0; font: inherit; color: inherit; appearance: none;
}
.strip-openable { cursor: pointer; }
.strip-openable:hover, .strip-openable:focus-visible,
.strip-openable[aria-pressed="true"] {
  /* Drawn over the neighbours rather than inside a 10px cell, where an inset ring would
     swallow the colour it is meant to point at. */
  box-shadow: 0 0 0 2px var(--ihrdc-dark-navy); outline: none;
  position: relative; z-index: 1;
}
@media (prefers-color-scheme: dark) {
  .strip-openable:hover, .strip-openable:focus-visible,
  .strip-openable[aria-pressed="true"] { box-shadow: 0 0 0 2px #FFFFFF; }
}

/* ---- staff configuration ------------------------------------------------
 * The design file has no form controls, because the pages it was drawn for had none.
 * These follow its radii, borders and focus ring rather than inventing a second language.
 * ----------------------------------------------------------------------- */

.settings { display: flex; flex-direction: column; gap: 16px; }

/* Deliberately not `table.signals`: status-signals.js collapses every table with that
   class into a heat map, which would take the checkboxes with it. Same visual language,
   its own name. */
.settings-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.settings-table th {
  text-align: left; padding: 12px 20px; white-space: nowrap;
  background: var(--bg-subtle); border-bottom: 1px solid var(--border-1);
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.12em; color: var(--fg-3);
}
.settings-table td { padding: 12px 20px; border-bottom: 1px solid var(--border-1); vertical-align: top; }
.settings-table tbody tr:last-child td { border-bottom: 0; }
.settings-table tbody tr:hover { background: var(--bg-subtle); }
.settings-table code.inline {
  font-size: 12px; background: var(--bg-subtle); border-radius: 2px; padding: 1px 5px;
}
.settings-table th.opt, .settings-table td.opt { text-align: center; width: 150px; }
.settings-table label { font-weight: 700; cursor: pointer; }
.settings-table code.inline { margin-left: 6px; }
.settings-table .muted { margin-top: 4px; font-size: 13px; }
.settings-table input[type="checkbox"] {
  width: 18px; height: 18px; accent-color: var(--ihrdc-blue); cursor: pointer;
}
.settings-table input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--focus-ring); outline-offset: 2px;
}

.settings-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 20px; }
.settings-foot .muted { margin: 0; flex: 1 1 320px; font-size: 13px; }

.btn {
  font-family: var(--font-sans); font-size: 14px; font-weight: 700;
  color: var(--fg-on-dark); background: var(--ihrdc-blue);
  border: 1px solid var(--ihrdc-blue); border-radius: 2px;
  padding: 10px 22px; cursor: pointer;
  transition: background 200ms var(--ease), border-color 200ms var(--ease);
}
.btn:hover { background: var(--ihrdc-blue-shade-1); border-color: var(--ihrdc-blue-shade-1); }
.btn:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

.settings-saved {
  margin: 0 0 16px; padding: 12px 16px; font-size: 14px;
  border: 1px solid var(--ok); border-left-width: 3px; border-radius: 2px;
  background: var(--bg-subtle); color: var(--fg-1);
}

/* ---- notices ------------------------------------------------------------
 * What the page says after a form. The text always comes from a fixed table in the
 * handler, never from the query string, so nothing here has to escape anything.
 * ----------------------------------------------------------------------- */

.notice {
  margin: 0 0 32px; padding: 14px 18px; font-size: 14px;
  border: 1px solid var(--border-1); border-left-width: 3px; border-radius: 2px;
  background: var(--bg-subtle); color: var(--fg-1);
}
.notice.ok { border-left-color: var(--ok); }
.notice.bad { border-left-color: var(--bad); }

/* ---- incidents ---------------------------------------------------------- */

.incident {
  background: var(--bg-card, var(--bg-page)); border: 1px solid var(--border-1);
  border-radius: 4px; padding: 20px 24px; margin-bottom: 16px;
  box-shadow: 0 1px 2px rgba(17, 42, 70, .06);
}
/* The same 3px top stripe the dimension cards use, so severity reads the same way. */
.incident { border-top: 3px solid var(--none); }
.incident.degraded { border-top-color: var(--warn); }
.incident.down { border-top-color: var(--bad); }
.incident.resolved, .incident.is-closed { border-top-color: var(--ok); }
.incident.is-closed { opacity: .82; }

.incident-head {
  display: flex; flex-wrap: wrap; align-items: flex-start;
  justify-content: space-between; gap: 12px;
}
.incident-head h3 { margin: 0; font-size: 18px; font-weight: 700; color: var(--fg-1); }
.incident-when { margin: 4px 0 0; font-size: 13px; color: var(--fg-3); }

.incident-updates {
  list-style: none; margin: 18px 0 0; padding: 0 0 0 20px;
  border-left: 2px solid var(--border-1);
  display: flex; flex-direction: column; gap: 18px;
}
.incident-update { position: relative; }
.incident-update::before {
  content: ""; position: absolute; left: -27px; top: 5px;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--ihrdc-blue); border: 2px solid var(--bg-page);
}
.incident-update.is-internal::before { background: var(--none-fg); }
.incident-update-head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 12px; font-size: 13px;
}
.incident-state { font-weight: 700; color: var(--fg-1); }
.incident-pub { color: var(--ok); font-weight: 700; }
.incident-unpub { color: var(--fg-3); }
.incident-update p { margin: 6px 0 0; font-size: 14px; white-space: pre-wrap; }

/* ---- incident console --------------------------------------------------- */

.incident-form {
  margin-top: 20px; padding-top: 20px; border-top: 1px solid var(--border-1);
  display: flex; flex-direction: column; gap: 12px;
}
.incident-form-row { display: flex; align-items: center; gap: 10px; font-size: 14px; }
.incident-form-row label { font-weight: 700; }
.incident-form select, .incident-form textarea, .subscribe input {
  font-family: var(--font-sans); font-size: 14px; color: var(--fg-1);
  background: var(--bg-page); border: 1px solid var(--border-1); border-radius: 2px;
  padding: 9px 12px;
}
.incident-form textarea { width: 100%; resize: vertical; min-height: 76px; line-height: 1.5; }
.incident-form select:focus-visible, .incident-form textarea:focus-visible,
.subscribe input:focus-visible {
  outline: 2px solid var(--focus-ring); outline-offset: 1px; border-color: var(--ihrdc-blue);
}
.incident-form-foot {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px;
}
.incident-publish {
  display: flex; align-items: center; gap: 10px; font-size: 14px; font-weight: 700;
  cursor: pointer;
}
.incident-publish input {
  width: 18px; height: 18px; accent-color: var(--ihrdc-blue); cursor: pointer;
}

/* ---- subscribe ---------------------------------------------------------- */

.subscribe { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.subscribe input { flex: 0 1 320px; }
.subscribe .muted { flex: 1 1 100%; margin: 4px 0 0; font-size: 13px; max-width: 780px; }

/* Labels that exist for assistive technology, where the placeholder carries the visual
   cue. A label is still required - a placeholder is not one. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* ---- the last few hours ------------------------------------------------
 * The strip's smallest unit is a day, which cannot answer "what is it doing right now".
 * These are the individual collections behind today's cell.
 * ----------------------------------------------------------------------- */

.recent { margin-top: 18px; padding-top: 16px; border-top: 1px dashed var(--border-1); }
.recent-head {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: 12px; margin-bottom: 8px;
}
.recent-title {
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.12em; color: var(--fg-3);
}
.recent-note { font-size: 12px; color: var(--fg-3); }

.recent-row { display: flex; gap: 2px; height: 20px; align-items: stretch; }
/* Shorter and slimmer than the strip on purpose: this is the supporting detail, and giving
   it the same weight would make a card read as two strips of equal standing. */
.tick { flex: 1; min-width: 2px; border-radius: 1px; background: var(--none); }
.tick.operational { background: var(--ok); }
.tick.degraded, .tick.partial { background: var(--warn); }
.tick.down { background: var(--bad); }
.tick.maintenance { background: var(--info); }
.tick.nodata, .tick.unknown { background: var(--none); }
/* The cycle in progress. Outlined rather than filled, like a future day in the calendar -
   it has not missed anything yet. */
.tick.pending { background: transparent; border: 1px dashed var(--border-1); }
.tick:hover { box-shadow: 0 0 0 2px var(--ihrdc-dark-navy); position: relative; z-index: 1; }
@media (prefers-color-scheme: dark) {
  .tick:hover { box-shadow: 0 0 0 2px #FFFFFF; }
}

.recent-legend {
  display: flex; justify-content: space-between; margin-top: 6px;
  font-size: 12px; color: var(--fg-3);
}

/* The supplied stylesheet hides the strip's trailing label on the grounds that "today" is
   implied by the right edge. Asked for back: the left end is dated and the right end was
   not, which left the reader to infer what could simply be said. Pushed to the right edge
   so it labels the end of the strip rather than trailing the middle text. */
.strip-legend > span:last-child { display: inline; }
.strip-legend .strip-today { margin-left: auto; font-weight: 700; color: var(--fg-2); }

/* ---- subscribe, in the header ------------------------------------------ */

.btn-sm { padding: 7px 16px; font-size: 13px; }

.subscribe-menu { position: relative; }
.subscribe-menu > summary {
  list-style: none; cursor: pointer; display: inline-block;
  /* A summary is not a button; these are the parts of one it does not get for free. */
  color: var(--fg-on-dark); background: var(--ihrdc-blue); border: 1px solid var(--ihrdc-blue);
  border-radius: 2px; font-weight: 700;
}
.subscribe-menu > summary::-webkit-details-marker { display: none; }
.subscribe-menu > summary:hover {
  background: var(--ihrdc-blue-shade-1); border-color: var(--ihrdc-blue-shade-1);
}
.subscribe-menu > summary:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.subscribe-menu[open] > summary { background: var(--ihrdc-blue-shade-1); border-color: var(--ihrdc-blue-shade-1); }

.subscribe-pop {
  position: absolute; top: calc(100% + 10px); right: 0; z-index: 50; width: 360px;
  background: var(--bg-card, var(--bg-page)); border: 1px solid var(--border-1);
  border-radius: 4px; padding: 18px 20px;
  box-shadow: 0 8px 24px rgba(17, 42, 70, .18), 0 2px 6px rgba(17, 42, 70, .10);
}
@media (prefers-color-scheme: dark) {
  .subscribe-pop { box-shadow: 0 8px 24px rgba(0, 0, 0, .45), 0 2px 6px rgba(0, 0, 0, .35); }
}
.subscribe-pop label { display: block; font-size: 13px; font-weight: 700; margin-bottom: 8px; }
.subscribe-row { display: flex; gap: 8px; }
.subscribe-row input { flex: 1 1 auto; min-width: 0; }
.subscribe-pop .muted { margin: 10px 0 0; font-size: 12px; line-height: 1.5; }

@media (max-width: 700px) {
  .subscribe-pop { position: fixed; left: 12px; right: 12px; width: auto; top: 78px; }
}

/* ---- rings, tooltips, and cells that respond ---------------------------
 * Hover and selection rings are plain black on light and plain white on dark, as asked:
 * the highest-contrast thing available against every one of the four status colours.
 * ----------------------------------------------------------------------- */

:root { --ring: #000000; }
@media (prefers-color-scheme: dark) { :root { --ring: #FFFFFF; } }

.cell-openable { cursor: pointer; }
.strip button.cell, .recent-row button.tick {
  border: 0; padding: 0; margin: 0; font: inherit; color: inherit; appearance: none;
}
.tick.pending { border: 1px dashed var(--border-1); }
.strip .cell:hover, .strip .cell:focus-visible, .strip .cell[aria-pressed="true"],
.tick:hover, .tick:focus-visible, .tick[aria-pressed="true"],
.cal-openable:hover, .cal-openable:focus-visible, .cal-openable[aria-pressed="true"],
.strip-openable:hover, .strip-openable:focus-visible, .strip-openable[aria-pressed="true"] {
  box-shadow: 0 0 0 2px var(--ring); outline: none; position: relative; z-index: 1;
}

/* A cell that has just arrived, or a reading whose state has just changed, pulses a ring
   for ten seconds so a reader watching the page can see the collector land. A ring, not a
   fade: the first version faded the cell towards the page background, and a coloured cell
   at a fifth of its opacity on a white page reads as a white cell - a new state, not a new
   reading. The colour now never changes; the ring does the announcing. Under reduced
   motion it holds the ring for the same ten seconds instead - the point is to be findable,
   and a static ring is findable. */
@keyframes cell-new { 0%, 100% { box-shadow: 0 0 0 0 var(--ring); } 50% { box-shadow: 0 0 0 3px var(--ring); } }
.is-new { animation: cell-new 1s ease-in-out 10; position: relative; z-index: 1; }
@media (prefers-reduced-motion: reduce) {
  .is-new { animation: none; box-shadow: 0 0 0 2px var(--ring); position: relative; z-index: 1; }
}

/* Hover tooltip. One element, moved to whatever is hovered. The native title tooltip is
   kept in the markup for the no-script case, and removed when this takes over so the two
   do not stack. */
.tip {
  position: absolute; z-index: 60; pointer-events: none;
  max-width: 320px; padding: 8px 10px; border-radius: 2px;
  background: var(--ihrdc-dark-navy); color: var(--fg-on-dark);
  font-size: 12px; line-height: 1.45;
  box-shadow: 0 4px 12px rgba(17, 42, 70, .25);
}
.tip strong { display: block; font-size: 13px; }
.tip .tip-state { font-weight: 700; }
.tip .tip-state.operational { color: #9BD26F; }
.tip .tip-state.degraded, .tip .tip-state.partial { color: #F2CF5B; }
.tip .tip-state.down { color: #F09A5B; }
.tip .tip-state.nodata, .tip .tip-state.pending, .tip .tip-state.unknown { color: var(--fg-on-dark-2); }
@media (prefers-color-scheme: dark) {
  .tip { background: #FFFFFF; color: var(--ihrdc-dark-navy); box-shadow: 0 4px 12px rgba(0, 0, 0, .45); }
  .tip .tip-state.operational { color: var(--ok); }
  .tip .tip-state.degraded, .tip .tip-state.partial { color: #A57F12; }
  .tip .tip-state.down { color: var(--bad); }
  .tip .tip-state.nodata, .tip .tip-state.pending, .tip .tip-state.unknown { color: var(--fg-3); }
}

/* A cycle's readings, inside the popover. */
.cycle-readings { width: 100%; border-collapse: collapse; font-size: 13px; margin-top: 12px; }
.cycle-readings td { padding: 6px 8px; border-bottom: 1px solid var(--border-1); vertical-align: top; }
.cycle-readings tr:last-child td { border-bottom: 0; }
.cycle-readings .num { text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
.cycle-readings .state-text { font-size: 12px; }
.cycle-readings .muted { font-size: 12px; }
.day-summary { margin: 10px 0 0; font-size: 14px; }
.day-summary strong { font-size: 18px; }

/* The next-check label. Overdue is called out, because "next check at 20:30" at 20:45 is
   a claim the reader can see is false. */
.next-check.is-overdue { color: var(--warn); font-weight: 700; }

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

.display-settings { margin-top: 28px; padding-top: 24px; border-top: 1px solid var(--border-1); }
.display-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; font-size: 14px; }
.display-row input[type="number"] {
  width: 90px; font-family: var(--font-mono); font-size: 14px; color: var(--fg-1);
  background: var(--bg-page); border: 1px solid var(--border-1); border-radius: 2px;
  padding: 8px 10px; text-align: right; font-variant-numeric: tabular-nums;
}
.display-row input[type="number"]:focus-visible {
  outline: 2px solid var(--focus-ring); outline-offset: 1px; border-color: var(--ihrdc-blue);
}
.display-settings .muted { margin: 10px 0 0; font-size: 13px; max-width: 780px; }

/* ---- the staff heat map --------------------------------------------------
 * Every reading of every site on one screen. Denser than the design file's staff-view heat
 * map on purpose: that one sits inside a single site's page with room to breathe; this one
 * has six sites to fit and is meant to be taken in at a glance.
 * ----------------------------------------------------------------------- */

.heat-head { margin-bottom: 24px; }
.sites-heat {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px 28px;
  margin-bottom: 20px;
}
@media (max-width: 1100px) { .sites-heat { grid-template-columns: minmax(0, 1fr); } }

.site-heat {
  background: var(--bg-card, var(--bg-page)); border: 1px solid var(--border-1);
  border-top: 3px solid var(--none); border-radius: 4px; padding: 14px 18px 16px;
  box-shadow: 0 1px 2px rgba(17, 42, 70, .06); min-width: 0;
}
.site-heat.operational { border-top-color: var(--ok); }
.site-heat.degraded { border-top-color: var(--warn); }
.site-heat.down { border-top-color: var(--bad); }
.site-heat.maintenance { border-top-color: var(--info); }

.site-heat-head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 12px; margin-bottom: 12px; }
.site-heat-head h2 { margin: 0; font-size: 17px; font-weight: 700; flex: 1 1 auto; min-width: 0; }
.site-heat-head h2 a { color: var(--ihrdc-blue); }
.site-heat-head h2 a:hover { color: var(--ihrdc-blue-shade-1); text-decoration: underline; }
.site-heat-head .card-slug { white-space: nowrap; }
/* The chip that used to carry the hostname is the way to the site's readings table. */
.card-slug-link { color: var(--ihrdc-blue); }
.card-slug-link:hover { color: var(--ihrdc-blue-shade-1); text-decoration: underline; }

/* ---- the readings page ---------------------------------------------------
 * The table the site page's staff section used to hold. Each state is a button carrying the
 * same data attributes as a heat-map cell, so the popover and live-update scripts treat it as
 * one: hover for the summary, click for the last six hours, a ring when its state changes. */
button.state-text {
  background: none; border: 0; padding: 0 2px; margin: 0 -2px;
  font-family: inherit; font-size: inherit; line-height: inherit; cursor: pointer; border-radius: 2px;
}
button.state-text:hover { text-decoration: underline; }
.state-text.info { color: var(--info); font-weight: 400; }
.readings-note { margin: 12px 0 0; font-size: 13px; }
.external-status { margin: 0 0 20px; font-size: 13px; }
.display-check { display: inline-flex; align-items: center; gap: 8px; }
.display-check input { width: 16px; height: 16px; }
.external-status a { color: var(--ihrdc-blue); }

/* The design file's .heatmap is a bordered, padded panel; inside a site block the block is
   the panel, so the inner one goes flat. */
.heatmap.dense { padding: 0; border: 0; background: transparent; box-shadow: none; gap: 5px; display: flex; flex-direction: column; }
.heatmap.dense .heat-row { grid-template-columns: 148px minmax(0, 1fr); gap: 10px; align-items: center; }
.heatmap.dense .heat-label {
  font-size: 12px; line-height: 1.3; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px;
  /* The design's label is one line with an ellipsis, which would clip "Content & Video
     Services" at this width. Here a label may take two lines. */
  white-space: normal; overflow: visible; text-overflow: clip;
}
.heatmap.dense .heat-cells { gap: 2px; }
.heatmap.dense .heat-cell { width: 18px; height: 18px; border-radius: 2px; border: 0; padding: 0; cursor: pointer; }
.heatmap.dense .heat-cell:hover, .heatmap.dense .heat-cell:focus-visible,
.heatmap.dense .heat-cell[aria-pressed="true"] {
  box-shadow: 0 0 0 2px var(--ring); outline: none; position: relative; z-index: 1;
}
.heat-cell.maintenance { background: var(--info); }

/* Excluded dimensions are drawn, not dropped - marked so the exclusion is visible. Uncounted
   cells are hatched: the colour is still there to read, and the stripes say it is not being
   scored. Hidden ones are faded further and tagged. */
.heat-tag {
  font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .1em;
  color: var(--fg-3); border: 1px dashed var(--border-2, var(--border-1)); border-radius: 2px;
  padding: 1px 5px; white-space: nowrap;
}
.heat-row.is-uncounted .heat-cell, .heat-row.is-hidden .heat-cell {
  background-image: repeating-linear-gradient(135deg, transparent 0 3px, rgba(255, 255, 255, .55) 3px 5px);
}
.heat-row.is-uncounted .heat-label, .heat-row.is-hidden .heat-label { color: var(--fg-3); }
.heat-row.is-hidden .heat-cell { opacity: .45; }
@media (prefers-color-scheme: dark) {
  .heat-row.is-uncounted .heat-cell, .heat-row.is-hidden .heat-cell {
    background-image: repeating-linear-gradient(135deg, transparent 0 3px, rgba(17, 42, 70, .6) 3px 5px);
  }
}
.heat-swatch.hatched {
  background: var(--ok);
  background-image: repeating-linear-gradient(135deg, transparent 0 3px, rgba(255, 255, 255, .55) 3px 5px);
}
.heat-swatch.faded { background: var(--ok); opacity: .45; }
.heat-legend-page { margin-bottom: 40px; }

/* Inside the popover: a reading's last six hours. */
.mini-history { margin-top: 14px; }
.mini-history .recent-title { margin-bottom: 6px; }
.mini-ticks { display: flex; gap: 2px; height: 14px; }
.mini-history .muted { margin-top: 6px; font-size: 12px; }
.day-detail .heat-facts { margin-top: 10px; }

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

.hero-slim { padding: 40px 0 36px; }
.hero-slim .hero-lead { margin-top: 10px; }
.display-settings-page { margin-top: 0; padding-top: 0; border-top: 0; }
.site-settings { margin-bottom: 36px; }
.site-settings-title { margin: 0 0 12px; font-size: 18px; display: flex; align-items: center; gap: 12px; }
.site-settings-title a { color: var(--ihrdc-blue); }
.site-settings + .muted { max-width: 780px; font-size: 13px; }

/* ---- the clocks tick ------------------------------------------------------
 * Every colon in a displayed time blinks once a second. It is the oldest way a clock says
 * "I am running, not a picture of a clock", and on a page that updates itself in place
 * that is exactly the reassurance a reader wants. Held steady under reduced motion, where
 * a blink is a distraction rather than a signal.
 * ----------------------------------------------------------------------- */

@keyframes colon-blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
.colon { display: inline-block; animation: colon-blink 1s step-end infinite; }
@media (prefers-reduced-motion: reduce) { .colon { animation: none; } }

/* ---- settings page, 2026-09-09 ------------------------------------------
 * Three groups of settings and a per-site readings editor, laid out as a side index and a
 * column of cards rather than one long list. Cards share one grammar: eyebrow, title, lead,
 * body, footer with the state in words on the left and the one button on the right. Switches
 * are real checkboxes drawn as toggles, so they post like checkboxes and read like switches.
 * ----------------------------------------------------------------------- */

.settings-layout { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: 48px; align-items: start; }
.settings-nav { position: sticky; top: 24px; display: flex; flex-direction: column; gap: 2px; }
.settings-nav-link {
  display: flex; flex-direction: column; gap: 2px; padding: 10px 14px; border-left: 2px solid var(--border-1);
  font-size: 14px; font-weight: 700; color: var(--fg-2); text-decoration: none; transition: color 150ms var(--ease), border-color 150ms var(--ease);
}
.settings-nav-link:hover { color: var(--ihrdc-blue); }
.settings-nav-link.is-current { color: var(--ihrdc-blue); border-left-color: var(--ihrdc-blue); }
.settings-nav-hint { font-size: 12px; font-weight: 400; color: var(--fg-3); }
.settings-main { display: flex; flex-direction: column; gap: 32px; min-width: 0; }

.settings-card {
  background: var(--bg-card, var(--bg-page)); border: 1px solid var(--border-1); border-radius: 6px;
  box-shadow: 0 1px 2px rgba(17, 42, 70, 0.06); scroll-margin-top: 24px;
}
.settings-card-head { padding: 28px 32px 8px; display: flex; flex-direction: column; gap: 8px; }
.settings-card-head h2 { margin: 0; font-size: 22px; font-weight: 700; line-height: 1.3; color: var(--fg-1); }
.settings-card-lead { margin: 4px 0 0; font-size: 14px; line-height: 1.6; color: var(--fg-2); max-width: 72ch; text-wrap: pretty; }
.settings-card-body { padding: 16px 32px 24px; display: flex; flex-direction: column; gap: 24px; }
.settings-card-foot {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px;
  padding: 16px 32px; border-top: 1px solid var(--border-1); background: var(--bg-subtle); border-radius: 0 0 6px 6px;
}
.settings-card-meta { font-size: 13px; color: var(--fg-3); }

.field { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; }
.field-label { font-size: 15px; font-weight: 700; color: var(--fg-1); }
.field-control { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.field-control input[type="number"] {
  width: 120px; padding: 9px 12px; font: inherit; font-variant-numeric: tabular-nums;
  color: var(--fg-1); background: var(--bg-page); border: 1px solid var(--border-1); border-radius: 4px;
}
.field-control input:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }
.field-unit { font-size: 14px; color: var(--fg-2); }
.field-hint { margin: 0; font-size: 13px; line-height: 1.6; color: var(--fg-3); max-width: 72ch; }

/* A switch is a checkbox: the input is present and focusable, the track is drawn from its state. */
.switch { position: relative; display: inline-flex; align-items: center; flex: none; width: 44px; height: 24px; }
.switch input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
.switch-track {
  width: 44px; height: 24px; border-radius: 999px; background: var(--border-1);
  transition: background 200ms var(--ease); position: relative;
}
.switch-track::after {
  content: ""; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 999px;
  background: #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25); transition: transform 200ms var(--ease);
}
.switch input:checked + .switch-track { background: var(--ihrdc-blue); }
.switch input:checked + .switch-track::after { transform: translateX(20px); }
.switch input:focus-visible + .switch-track { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.switch input:disabled + .switch-track { opacity: 0.4; }
.switch input:disabled { cursor: not-allowed; }
.switch-row { display: flex; align-items: flex-start; gap: 16px; cursor: pointer; }
.switch-row .switch { margin-top: 2px; }
.switch-text { display: flex; flex-direction: column; gap: 4px; }
.switch-label { font-size: 15px; font-weight: 700; color: var(--fg-1); }
.switch-hint { font-size: 13px; line-height: 1.6; color: var(--fg-3); max-width: 72ch; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* Readings: a tab strip of sites, then one site's dimensions as collapsible groups. */
.settings-card-wide .settings-card-head { padding-bottom: 16px; }
.tabs { display: flex; flex-wrap: wrap; gap: 4px; padding: 0 32px; border-bottom: 1px solid var(--border-1); }
.tab {
  display: inline-flex; align-items: center; gap: 8px; padding: 10px 14px; margin-bottom: -1px;
  font-size: 14px; font-weight: 700; color: var(--fg-2); text-decoration: none; border-bottom: 2px solid transparent;
}
.tab:hover { color: var(--ihrdc-blue); }
.tab.is-active { color: var(--ihrdc-blue); border-bottom-color: var(--ihrdc-blue); }
.tab-badge {
  font-size: 11px; font-weight: 700; line-height: 1; padding: 3px 7px; border-radius: 999px;
  background: var(--warn); color: #fff; font-variant-numeric: tabular-nums;
}
.tab-panel { display: none; padding: 8px 32px 24px; }
.tab-panel.is-active { display: block; }
/* Without script every panel is on the page, each under its own heading. */
.no-js .tab-panel, html:not(.js) .tab-panel { display: block; }
.panel-tools { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 16px; padding: 16px 0 12px; }
.panel-title { display: flex; flex-direction: column; gap: 4px; }
.panel-site { margin: 0; font-size: 18px; font-weight: 700; display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; }
.panel-site a { color: var(--ihrdc-blue); text-decoration: none; }
.panel-site a:hover { text-decoration: underline; }
.panel-count { font-size: 13px; color: var(--fg-3); }
.filter-input {
  width: 260px; max-width: 100%; padding: 9px 12px 9px 34px; font: inherit; font-size: 14px;
  color: var(--fg-1); background: var(--bg-page); border: 1px solid var(--border-1); border-radius: 999px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2344546B' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.5-3.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: 12px center;
}
.filter-input:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }

.dim-group { border: 1px solid var(--border-1); border-radius: 6px; margin-top: 12px; background: var(--bg-page); }
.dim-summary {
  list-style: none; cursor: pointer; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 12px; padding: 14px 18px; user-select: none;
}
.dim-summary::-webkit-details-marker { display: none; }
.dim-summary:hover { background: var(--bg-subtle); }
.dim-summary-main { display: flex; flex-wrap: wrap; align-items: baseline; gap: 12px; min-width: 0; }
.dim-name { font-size: 15px; font-weight: 700; color: var(--fg-1); }
.dim-desc { font-size: 13px; color: var(--fg-3); }
.dim-summary-side { display: flex; align-items: center; gap: 12px; }
.dim-count { font-size: 12px; color: var(--fg-3); white-space: nowrap; }
.dim-chevron { width: 8px; height: 8px; border-right: 2px solid var(--fg-3); border-bottom: 2px solid var(--fg-3); transform: rotate(45deg); transition: transform 200ms var(--ease); margin: 0 4px 4px 0; }
.dim-group[open] .dim-chevron { transform: rotate(-135deg); margin: 4px 4px 0 0; }
.dim-empty { margin: 0; padding: 0 18px 16px; font-size: 13px; color: var(--fg-3); }

.readings-table { width: 100%; border-collapse: collapse; font-size: 14px; border-top: 1px solid var(--border-1); }
.readings-table th {
  text-align: left; padding: 10px 18px; white-space: nowrap; background: var(--bg-subtle);
  border-bottom: 1px solid var(--border-1); font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.12em; color: var(--fg-3);
}
.readings-table td { padding: 10px 18px; border-bottom: 1px solid var(--border-2); vertical-align: middle; }
.readings-table tbody tr:last-child td { border-bottom: 0; }
.readings-table tbody tr:hover { background: var(--bg-subtle); }
.readings-table th.opt, .readings-table td.opt { text-align: center; width: 130px; }
.reading-cell { display: flex; flex-direction: column; gap: 2px; }
.reading-label { font-weight: 700; color: var(--fg-1); }
.reading-meta { font-size: 12px; color: var(--fg-3); }
.reading-meta code.inline { font-size: 11px; background: var(--bg-subtle); border-radius: 2px; padding: 1px 5px; }
.now-cell { white-space: nowrap; }
.state-text.info { color: var(--info); font-weight: 400; }
.reading-row.is-hidden .reading-label, .reading-row.is-hidden .now-cell { opacity: 0.55; }
.reading-row.is-hidden .reading-label::after { content: "hidden"; margin-left: 8px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: var(--fg-3); }
.reading-row.is-uncounted .reading-label::after { content: "not counted"; margin-left: 8px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: var(--warn); }

.panel-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 16px; padding-top: 20px; }
.changes { font-size: 13px; color: var(--warn); font-weight: 700; }
.btn.is-primary-pending { box-shadow: 0 0 0 3px rgba(217, 171, 43, 0.35); }

@media (prefers-color-scheme: dark) {
  .settings-card { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35); }
  .settings-card-foot, .readings-table th, .dim-summary:hover, .readings-table tbody tr:hover, .reading-meta code.inline { background: var(--bg-subtle); }
  .dim-group, .field-control input[type="number"], .filter-input { background: var(--bg-card); }
  .switch-track { background: color-mix(in srgb, #C9D6E2 30%, #112A46); }
  .filter-input { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23C9D6E2' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.5-3.5'/%3E%3C/svg%3E"); }
}

@media (max-width: 900px) {
  .settings-layout { grid-template-columns: minmax(0, 1fr); gap: 24px; }
  .settings-nav { position: static; flex-direction: row; flex-wrap: wrap; gap: 8px; }
  .settings-nav-link { border-left: 0; border-bottom: 2px solid var(--border-1); padding: 8px 10px; }
  .settings-nav-link.is-current { border-bottom-color: var(--ihrdc-blue); }
  .settings-nav-hint { display: none; }
  .settings-card-head, .settings-card-body, .settings-card-foot, .tabs, .tab-panel { padding-left: 20px; padding-right: 20px; }
  .readings-table th.opt, .readings-table td.opt { width: 72px; }
  .readings-table th, .readings-table td { padding-left: 12px; padding-right: 12px; }
  .filter-input { width: 100%; }
}

/* Readings staff hid or stopped counting, on the heat map and the readings table. */
.heat-cell.is-hidden { opacity: 0.3; outline: 1px dashed var(--fg-3); outline-offset: -1px; }
.heat-cell.is-uncounted { background-image: repeating-linear-gradient(135deg, rgba(255,255,255,0.45) 0 3px, transparent 3px 6px); }
table.signals tr.is-hidden td { opacity: 0.55; }

/* Autosave: the fallback button is for browsers without script; the note is a passing toast. */
.js .save-fallback { display: none; }
.settings-card.is-saving .settings-card-foot, .tab-panel.is-saving .panel-foot { opacity: 0.7; }
.settings-card-accent { border-color: var(--ihrdc-blue); box-shadow: 0 0 0 1px var(--ihrdc-blue) inset, 0 1px 2px rgba(17, 42, 70, 0.06); }
.toast-region { position: fixed; left: 50%; bottom: 28px; transform: translateX(-50%); display: flex; flex-direction: column; align-items: center; gap: 8px; z-index: 50; pointer-events: none; }
.toast {
  padding: 10px 16px; font-size: 14px; font-weight: 700; border-radius: 999px; color: var(--fg-on-dark);
  background: var(--ihrdc-dark-navy); box-shadow: 0 6px 20px rgba(17, 42, 70, 0.25);
  opacity: 0; transform: translateY(8px); transition: opacity 250ms var(--ease), transform 250ms var(--ease);
}
.toast.is-in { opacity: 1; transform: translateY(0); }
.toast.ok::before { content: "\2713"; margin-right: 8px; color: #9BE07A; }
.toast.bad { background: var(--bad); }
@media (prefers-reduced-motion: reduce) { .toast { transition: none; } }

/* The sites under Readings in the side index. */
.settings-subnav { list-style: none; margin: 0 0 0 14px; padding: 0 0 0 14px; border-left: 2px solid var(--border-1); display: flex; flex-direction: column; gap: 1px; }
.settings-subnav-link { display: block; padding: 5px 0; font-size: 13px; color: var(--fg-2); text-decoration: none; }
.settings-subnav-link:hover { color: var(--ihrdc-blue); }
.settings-subnav-link.is-current { color: var(--ihrdc-blue); font-weight: 700; }
.tab-badge.is-empty { display: none; }
@media (max-width: 900px) {
  .settings-subnav { display: none; }
  .toast-region { left: 16px; right: 16px; transform: none; align-items: stretch; }
}
