/* --------------------------------------------------------------------------------
   Night Shift product layer.

   Anything genuinely specific to this app lives here as --ns-* / .ns-*. Overriding a
   --gm-* value in place would create invisible drift across products, so we don't
   (SPEC §6.2).

   Phone first throughout: the most important screen is not a desk, it is a phone at
   03:00 — one-handed, no zoom, and never a horizontally scrolling page.
   -------------------------------------------------------------------------------- */

:root {
  --ns-max-width: 68rem;
  --ns-row-gap: var(--gm-space-3);
}

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

body {
  margin: 0;
  background: var(--gm-bg-base);
  color: var(--gm-text-primary);
  font-family: var(--gm-font-sans, Inter, system-ui, sans-serif);
  font-size: 16px;
  line-height: 1.5;
  -webkit-text-size-adjust: 100%;
}

/* Sticky footer: the shell is at least as tall as the viewport and lays out as a column, so
   the footer sits on the window's bottom edge on a short page and after the content on a long
   one. dvh first, because on mobile 100vh includes the browser chrome and would push the
   footer just out of view. */
.ns-shell {
  max-width: var(--ns-max-width); margin: 0 auto; padding: var(--gm-space-4);
  min-height: 100vh;
  min-height: 100dvh;
  display: flex; flex-direction: column;
}
/* Grows to fill whatever the header and footer leave, and is itself a column so a page can
   centre its content vertically (the login screen does). */
#main { flex: 1 0 auto; display: flex; flex-direction: column; }

/* ---- Header ---------------------------------------------------------------- */

/* One optical row. Baseline alignment was the bug: a padded button and bare text links have
   different box heights, so their baselines land at different heights and the links appear to
   float above the button. Everything in the bar is centred on a shared axis instead, and the
   items that are boxes (links, button) get the same height so their edges line up too. */
.ns-header {
  display: flex; flex-wrap: wrap; gap: var(--gm-space-3) var(--gm-space-5);
  align-items: center; justify-content: space-between;
  padding: var(--gm-space-3) 0; border-bottom: 1px solid var(--gm-border-subtle);
}
.ns-header__brand {
  /* The glow below is absolutely positioned against this box; without `relative` it resolves
     against an ancestor and lands nowhere near the moon. */
  position: relative;
  display: inline-flex; align-items: center; gap: var(--gm-space-2);
  min-height: 44px;
  font-weight: 650; letter-spacing: -0.01em; text-decoration: none; color: inherit;
}
/* The crescent's visual mass sits low-left inside its box, so a hair of optical nudging aligns
   it with the cap height of the wordmark instead of its bounding box. */
.ns-moon { flex: none; color: var(--gm-accent); translate: 0 -1px; }

/* Home link hover: the moon comes up. Dim green at rest, full moonlight on hover.
   The glow is a round pseudo-element behind the icon, NOT a filter on the SVG: stacked
   drop-shadows on an inline SVG rendered as a hard-edged rectangle the size of the element box,
   which looked like a yellow background rather than moonlight. A radial gradient is round by
   construction and cannot be clipped to a box. */
:root { --ns-moonlight: #ffd45c; }
.ns-header__brand::before {
  content: "";
  position: absolute; left: -12px; top: 50%; translate: 0 -50%;
  width: 44px; height: 44px; border-radius: 50%;
  /* Long, gentle falloff: a short one leaves a visible circle edge, which reads as a disc rather
     than light. */
  background: radial-gradient(circle,
    rgba(255, 216, 110, 0.80) 0%,
    rgba(255, 202, 60, 0.46) 26%,
    rgba(255, 186, 20, 0.22) 44%,
    rgba(255, 176, 0, 0.08) 62%,
    rgba(255, 176, 0, 0.02) 78%,
    transparent 100%);
  /* A round box-shadow on top of the gradient carries the bloom further out than a gradient can
     without banding — and unlike a filter it cannot be clipped to a rectangle. */
  box-shadow: 0 0 26px 6px rgba(255, 198, 48, 0.22);
  /* Behind the icon, above the header background. */
  z-index: -1;
  opacity: 0; pointer-events: none;
  transition: opacity var(--gm-duration-base) var(--gm-ease-out);
}
.ns-header__brand:hover::before,
.ns-header__brand:focus-visible::before { opacity: 1; }
.ns-header__brand .ns-moon {
  transition: color var(--gm-duration-base) var(--gm-ease-out);
}
.ns-header__brand:hover .ns-moon,
.ns-header__brand:focus-visible .ns-moon { color: var(--ns-moonlight); }
/* The wordmark warms with it, so the glow reads as one gesture instead of a loose icon. */
.ns-header__brand span { transition: color var(--gm-duration-base) var(--gm-ease-out); }
.ns-header__brand:hover span,
.ns-header__brand:focus-visible span { color: var(--ns-moonlight); }
@media (prefers-reduced-motion: reduce) {
  /* Keep the state change — it carries focus information — but drop the fade. */
  .ns-header__brand::before, .ns-header__brand .ns-moon, .ns-header__brand span { transition: none; }
}

/* ---- Hover never moves anything ---------------------------------------------
   A deliberate deviation from the design system, which lifts its buttons by 1px on hover
   (`transform: translateY(-1px)` throughout buttons.css). Colour, shadow and border may change on
   hover; position may not. A control that shifts under the cursor makes a dense table twitch as
   the pointer crosses it, and it costs a click when the thing you aimed at moves.
   Press feedback on :active is untouched — that is direct manipulation, not hover. */
.gm .gm-web-btn:hover,
.gm .gm-btn:hover,
.gm [class*="gm-btn-"]:hover,
.gm .gm-card:hover,
.gm .gm-pill:hover,
.gm .ns-card-row:hover,
.gm .ns-btn-quiet:hover { transform: none; }
}
.ns-header__nav { display: flex; align-items: center; gap: var(--gm-space-1); flex-wrap: wrap; }
/* Links are boxes of the same height as the button, so the row has one shared centre line and
   each link is a 44px touch target rather than a bare word. */
.ns-header__nav a {
  display: inline-flex; align-items: center; min-height: 44px;
  padding: 0 var(--gm-space-2);
  color: var(--gm-text-secondary); text-decoration: none; border-radius: var(--gm-radius-sm, 4px);
}
.ns-header__nav a:hover { color: var(--gm-text-primary); }
.ns-header__nav a[aria-current="page"] { color: var(--gm-text-primary); font-weight: 600; }
/* Signing out is the least important thing in the bar, so it stops shouting: same control, less
   weight, and set apart by space rather than by a heavy border.
   Scoped with .gm because the style guide's own rules are `.gm .gm-web-btn` — a single product
   class would lose the specificity contest and silently do nothing. */
.ns-header__nav form { margin: 0; margin-left: var(--gm-space-3); }
.gm .ns-header__signout {
  min-height: 34px; height: auto; padding: 0 var(--gm-space-3);
  font-size: 0.8125rem; font-weight: 500;
}

/* ---- Filters --------------------------------------------------------------- */

.ns-filters { display: flex; gap: var(--gm-space-2); flex-wrap: wrap; margin: var(--gm-space-4) 0; }
.ns-filter {
  display: inline-flex; gap: var(--gm-space-2); align-items: center;
  padding: var(--gm-space-2) var(--gm-space-3);
  border: 1px solid var(--gm-border-subtle); border-radius: var(--gm-radius-full, 999px);
  color: var(--gm-text-secondary); text-decoration: none; font-size: 0.875rem;
  min-height: 44px; /* thumb target, web scope minimum */
}
.ns-filter[aria-current="page"] { color: var(--gm-text-primary); border-color: var(--gm-accent); font-weight: 600; }
/* An exhausted alert must never be something you have to go looking for. */
.ns-filter--exhausted[data-nonzero="true"] { border-color: var(--ns-severity-critical); color: var(--gm-text-primary); }
.ns-filter__count { font-variant-numeric: tabular-nums; opacity: 0.8; }

/* ---- Alert list ------------------------------------------------------------ */

.ns-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--ns-row-gap); }
.ns-row {
  display: grid; gap: var(--gm-space-2);
  grid-template-columns: auto 1fr auto;
  align-items: start;
  padding: var(--gm-space-3);
  border: 1px solid var(--gm-border-subtle); border-radius: var(--gm-radius-md, 8px);
  background: var(--gm-bg-elevated, transparent);
}
.ns-row__link { color: inherit; text-decoration: none; font-weight: 600; }
.ns-row__link:hover { text-decoration: underline; }
.ns-row__meta { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: var(--gm-space-3);
  color: var(--gm-text-secondary); font-size: 0.8125rem; }
.ns-row__meta time { font-variant-numeric: tabular-nums; }

/* Severity and status are NEVER colour alone — the badge always carries text
   (SPEC §6.2). Colour is the redundant cue, not the message. */
.ns-badge {
  display: inline-flex; align-items: center; gap: var(--gm-space-1);
  padding: 2px var(--gm-space-2); border-radius: var(--gm-radius-sm, 4px);
  font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  border: 1px solid currentColor; white-space: nowrap;
}
:root {
  --ns-severity-critical: #c0392b;
  --ns-severity-error: #d35400;
  --ns-severity-warning: #b7950b;
  --ns-severity-info: #2874a6;
}
.ns-severity--critical { color: var(--ns-severity-critical); }
.ns-severity--error    { color: var(--ns-severity-error); }
.ns-severity--warning  { color: var(--ns-severity-warning); }
.ns-severity--info     { color: var(--ns-severity-info); }

/* ---- Detail ---------------------------------------------------------------- */

.ns-detail__title { font-size: 1.375rem; line-height: 1.3; margin: var(--gm-space-2) 0; }
.ns-detail__actions { display: flex; flex-wrap: wrap; gap: var(--gm-space-2); margin: var(--gm-space-4) 0; }
.ns-detail__actions form { margin: 0; }

.ns-timeline { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--gm-space-2); }
.ns-timeline li { display: grid; grid-template-columns: 10rem 1fr; gap: var(--gm-space-3);
  padding-bottom: var(--gm-space-2); border-bottom: 1px solid var(--gm-border-subtle);
  font-size: 0.875rem; }
.ns-timeline time { color: var(--gm-text-secondary); font-variant-numeric: tabular-nums; }

/* Wide content scrolls inside its own container — the page never scrolls sideways. */
.ns-scroll-x { overflow-x: auto; }
.ns-table { width: 100%; border-collapse: collapse; font-size: 0.875rem; }
.ns-table th, .ns-table td {
  text-align: left; padding: var(--gm-space-2) var(--gm-space-3);
  border-bottom: 1px solid var(--gm-border-subtle); white-space: nowrap;
  vertical-align: middle; /* rows carry controls of different heights */
}
.ns-table th {
  font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--gm-text-secondary); padding-bottom: var(--gm-space-2);
}
.ns-table tbody tr:last-child td { border-bottom: 0; }
/* First and last cells align with the section edge instead of floating inside padding. */
.ns-table th:first-child, .ns-table td:first-child { padding-left: 0; }
.ns-table th:last-child, .ns-table td:last-child { padding-right: 0; }
/* The action column hugs the right edge and shrinks to its content, so the columns that carry
   information get the width. */
.ns-table td:last-child.ns-cell-actions,
.ns-table th:last-child.ns-cell-actions { width: 1%; text-align: right; }
/* Numbers align on their digits and use tabular figures, so a column of them can be compared
   at a glance rather than read. */
.ns-num { font-variant-numeric: tabular-nums; }
/* Written with the table in the selector because `.ns-table th` would otherwise win on
   specificity and keep everything left-aligned. */
.ns-table th.ns-num, .ns-table td.ns-num { text-align: right; padding-right: var(--gm-space-5); }

/* ---- Login ------------------------------------------------------------------
   One action on the whole page, so it is centred in the viewport instead of stuck
   under the top edge. */

.ns-login {
  /* Fills <main>, then centres inside it — so "centred" stays centred whatever the window height. */
  flex: 1 0 auto;
  display: flex; flex-direction: column; justify-content: center; align-items: center;
  gap: var(--gm-space-5); text-align: center;
}
.ns-login__title {
  display: flex; align-items: center; gap: var(--gm-space-3);
  margin: 0; font-size: 2rem; letter-spacing: -0.02em;
}
.ns-login__button { min-width: 18rem; min-height: 52px; }

@media (max-width: 40rem) {
  .ns-login__title { font-size: 1.625rem; }
  .ns-login__button { min-width: 0; width: 100%; }
}

/* ---- Ack page (the 03:00 screen) ------------------------------------------- */

.ns-ack { max-width: 34rem; margin: 0 auto; padding: var(--gm-space-5) var(--gm-space-4); }
.ns-ack__severity { font-size: 0.75rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; }
.ns-ack__title { font-size: 1.5rem; line-height: 1.25; margin: var(--gm-space-3) 0 var(--gm-space-4); }
.ns-ack__meta { display: grid; grid-template-columns: auto 1fr; gap: var(--gm-space-2) var(--gm-space-4);
  font-size: 0.9375rem; margin-bottom: var(--gm-space-5); }
.ns-ack__meta dt { color: var(--gm-text-secondary); }
.ns-ack__meta dd { margin: 0; }
/* Thumb-sized, full width, hard to miss half-awake. */
.ns-ack__button, .ns-ack__button button { width: 100%; min-height: 56px; font-size: 1.0625rem; }
.ns-ack__hint, .ns-ack__done { color: var(--gm-text-secondary); font-size: 0.875rem; }

/* ---- Page head --------------------------------------------------------------
   Title and its actions on one line, so the actions read as belonging to the title rather than
   floating in the gap below it. */

.ns-page-head {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--gm-space-3);
  margin: var(--gm-space-5) 0 var(--gm-space-6);
}
.ns-page-head h1 { margin: 0; font-size: 1.5rem; letter-spacing: -0.01em; }

/* ---- Sections --------------------------------------------------------------- */

/* One rhythm for the whole page: equal air between sections, a tight bond between a
   heading and the thing it labels. Uneven gaps are most of what reads as "noise". */
.ns-section { margin: 0 0 var(--gm-space-7, 3rem); }
.ns-section > h2 {
  font-size: 0.8125rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--gm-text-secondary);
  margin: 0 0 var(--gm-space-3);
}

/* ---- Action rows ------------------------------------------------------------
   Rails' button_to renders a <form>, which is block-level — that is why page actions
   stacked instead of sitting side by side. One row, one gap, forms stripped of margin. */

.ns-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--gm-space-2); }
.ns-actions form { margin: 0; }
.ns-actions--end { justify-content: flex-end; }
/* Inside a table cell the actions never wrap: a second line doubles the row height and breaks
   the horizontal rhythm of the whole table. The cell scrolls with the table instead. */
.ns-cell-actions .ns-actions { flex-wrap: nowrap; justify-content: flex-end; }

/* Row-level actions are secondary by definition: they belong to one line of a table, not to
   the page. Full-size buttons in every row made each row 60px tall and gave a "Remove" the
   same visual weight as the primary action. Quiet text controls instead — scoped with .gm to
   win against the style guide's own `.gm .gm-web-btn`. */
.gm .ns-btn-quiet {
  min-height: 32px; height: auto; padding: 0 var(--gm-space-2);
  background: transparent; border-color: transparent;
  color: var(--gm-text-secondary); font-size: 0.8125rem; font-weight: 500;
}
.gm .ns-btn-quiet:hover { color: var(--gm-text-primary); border-color: var(--gm-border-subtle); }

/* ---- Forms ------------------------------------------------------------------
   The style guide styles text/number/url/select but not the date-time inputs, so those
   rendered as raw browser widgets — white boxes in a dark UI. Same treatment here, from the
   same tokens. (Worth upstreaming; noted in TODO.md.) */

.gm input[type="datetime-local"],
.gm input[type="date"],
.gm input[type="time"] {
  font: inherit; color: var(--gm-text-primary);
  background: var(--gm-bg-elevated, transparent);
  border: 1px solid var(--gm-border-subtle); border-radius: var(--gm-radius-sm, 4px);
  padding: var(--gm-space-2) var(--gm-space-3);
  min-height: 40px;
}
.gm input[type="datetime-local"]:focus,
.gm input[type="date"]:focus,
.gm input[type="time"]:focus { outline: 2px solid var(--gm-accent); outline-offset: 1px; }
/* The native calendar glyph is near-black on our dark surface without this. */
.gm input[type="datetime-local"]::-webkit-calendar-picker-indicator,
.gm input[type="date"]::-webkit-calendar-picker-indicator { filter: invert(1) opacity(0.6); }

/* An add-row form: labels on one line, controls on the next, everything sharing both.
   Replaces the old flex row, where a five-line checkbox stack dragged the other labels out
   of alignment. */
.ns-form-row {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--gm-space-3);
  margin-top: var(--gm-space-4); padding-top: var(--gm-space-4);
  border-top: 1px dashed var(--gm-border-subtle);
}
.ns-form-row .gm-field { margin: 0; }
.ns-form-row .gm-field-label,
.ns-form-row label { display: block; margin-bottom: var(--gm-space-1);
  font-size: 0.75rem; color: var(--gm-text-secondary); }
/* Same box height for every control, borders included — the labels sit on top of them, so a
   4px difference in height is a 4px difference in label baseline. 44px is the design system's
   own control height; forcing a smaller box clipped the select's descenders. */
.ns-form-row input, .ns-form-row select, .ns-form-row .gm-web-btn {
  height: 44px; min-height: 44px; padding-top: 0; padding-bottom: 0; box-sizing: border-box;
}
/* Selects size to their longest option instead of stretching to 100% of the row. */
.ns-form-row select { width: auto; min-width: 13rem; padding-inline: var(--gm-space-3); }
/* A minute count needs a few characters, not a third of the row — but enough that its label
   fits above it without dictating the column width. */
.ns-form-row input[type="number"] { width: 8rem; }
.ns-form-row .gm-field { gap: var(--gm-space-1); }
.ns-form-row__grow { flex: 1 1 12rem; max-width: 24rem; }
/* One explanatory line for the whole row, so no single label has to carry it. */
.ns-form-row__hint {
  flex: 1 0 100%; margin: 0; font-size: 0.75rem; color: var(--gm-text-secondary);
}

/* Checkboxes in a row, each label inline with its box — as a column it was taller than every
   other control and broke the row. */
.ns-checks { display: flex; flex-wrap: wrap; gap: var(--gm-space-1) var(--gm-space-3); }
.ns-checks label {
  display: inline-flex; align-items: center; gap: var(--gm-space-1);
  margin: 0; min-height: 40px;
  font-size: 0.875rem; color: var(--gm-text-primary);
}
.ns-checks input { margin: 0; accent-color: var(--gm-accent-fill, var(--gm-accent)); }
.ns-token {
  font-family: var(--gm-font-mono, ui-monospace, monospace); word-break: break-all;
  padding: var(--gm-space-3); border: 1px dashed var(--gm-accent); border-radius: var(--gm-radius-sm, 4px);
}
.ns-empty { color: var(--gm-text-secondary); padding: var(--gm-space-5) 0; }

/* ---- Footer ----------------------------------------------------------------- */

.ns-footer {
  /* auto is what pins it down: it absorbs the leftover space above the footer. */
  margin-top: auto;
  /* Extra bottom room so a flash bar — which is fixed to the window — cannot sit on top of
     the colophon. */
  padding: var(--gm-space-6, 2.5rem) 0 var(--gm-space-7, 3rem);
  border-top: 1px solid var(--gm-border-subtle);
  text-align: center;
}
.ns-colophon { color: var(--gm-text-secondary); font-size: 0.75rem; }

/* ---- Record list (teams) -----------------------------------------------------
   Its own two-column shape rather than the alert grid: identity on the left, counts on the
   right, and the whole row is the target — a name-sized click area is a needless miss at 03:00. */

.ns-cards { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--gm-space-2); }
.ns-card-row {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--gm-space-2) var(--gm-space-4);
  padding: var(--gm-space-3) var(--gm-space-4);
  border: 1px solid var(--gm-border-subtle); border-radius: var(--gm-radius-md, 8px);
  background: var(--gm-bg-elevated, transparent);
}
.ns-card-row:hover { border-color: var(--gm-accent); }
.ns-card-row__name {
  display: inline-flex; align-items: center; gap: var(--gm-space-2);
  font-weight: 600; color: inherit; text-decoration: none;
}
.ns-card-row__name::after { content: ""; position: absolute; inset: 0; } /* whole row clickable */
.ns-card-row { position: relative; }
.ns-card-row__meta {
  display: flex; flex-wrap: wrap; gap: var(--gm-space-4);
  color: var(--gm-text-secondary); font-size: 0.8125rem; font-variant-numeric: tabular-nums;
}

/* ---- Single-record form ------------------------------------------------------
   A field as wide as the page is unreadable and implies the content should be long. One
   column at a comfortable measure, consistent vertical rhythm, and an explicit way out. */

.ns-form { max-width: 34rem; }
.ns-form .gm-field { margin-bottom: var(--gm-space-5); gap: var(--gm-space-1); }
.ns-form input, .ns-form select, .ns-form textarea { width: 100%; }
.ns-form__hint {
  margin: var(--gm-space-1) 0 0; font-size: 0.75rem; color: var(--gm-text-secondary);
}
.ns-form__actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--gm-space-3);
  margin-top: var(--gm-space-5);
}
.ns-form__actions form { margin: 0; }

/* ---- Small pieces ----------------------------------------------------------- */

/* Names as a wrapped row of their own, each with room to carry a state badge. */
.ns-people { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--gm-space-2) var(--gm-space-4); }
.ns-people li { display: inline-flex; align-items: center; gap: var(--gm-space-2); }

/* Timestamps and identifiers: tabular so columns of them line up character by character. */
.ns-time { font-variant-numeric: tabular-nums; color: var(--gm-text-secondary); }
.ns-code {
  font-family: var(--gm-font-mono, ui-monospace, monospace); font-size: 0.8125rem;
  color: var(--gm-text-secondary);
}

/* The one-time token stays put and stays legible — it exists to be copied. */
.ns-token-reveal { margin-bottom: var(--gm-space-6); }
.ns-token-reveal__url { font-size: 0.8125rem; color: var(--gm-text-secondary); word-break: break-all; }

/* Available to screen readers, invisible on screen — for the header of an action column, which
   needs no visible label but must not be an empty cell. */
.ns-visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ---- Flashes ---------------------------------------------------------------
   A fixed bar at the bottom, like rollmonkey and deployed: it can auto-dismiss
   without shifting the layout, and on a phone it sits where the thumb already is.
   Colours are chosen apart from the severity palette above, so a green flash can
   never be mistaken for an alert severity. */

.ns-flash-region {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  display: flex; flex-direction: column;
}
.ns-flash {
  padding: var(--gm-space-3) var(--gm-space-4);
  text-align: center; font-size: 0.875rem; font-weight: 600;
  color: #fff; cursor: pointer;
  animation: ns-flash-in 260ms cubic-bezier(0.22, 1, 0.36, 1);
}
.ns-flash--notice { background: #256029; }
.ns-flash--alert  { background: #a02622; }
@keyframes ns-flash-in { from { transform: translateY(100%); } to { transform: translateY(0); } }
@media (prefers-reduced-motion: reduce) { .ns-flash { animation: none; } }

@media (max-width: 40rem) {
  /* Stacked, left-aligned: a wrapped nav pushed to the right edge reads as debris. */
  .ns-header { justify-content: flex-start; row-gap: 0; }
  .ns-header__nav { margin-left: calc(var(--gm-space-2) * -1); }
  .ns-row { grid-template-columns: auto 1fr; }
  .ns-timeline li { grid-template-columns: 1fr; gap: 0; }
  .ns-ack { padding: var(--gm-space-4) var(--gm-space-3); }
}
