/* ─────────────────────────────────────────────────────────────────────────
   base.css — shared foundation for every page.

   Design system: Steep (DESIGN.md + design_tokens.json).
   Rules this file exists to enforce:
     · Display type is Source Serif 4 at weight 400. Never a sans, never bold.
     · Buttons are 9999px pills. Content cards are 24px. Nothing in between.
     · Content cards never carry a shadow; only floating artifacts do.
     · Colour stays achromatic apart from the peach/sienna pair.

   Layer order: tokens.css → base.css → page css → chat-widget.css.

   CONTRACT NOTE — several class names here are not free to rename. The page
   scripts interpolate raw API values into class attributes (e.g.
   `status-word in_progress`) and toggle `.open` / `.active` / `.show` at
   runtime. Anything marked "contract" below is load-bearing.
   ───────────────────────────────────────────────────────────────────────── */

/* ═══ Reset ══════════════════════════════════════════════════════════════ */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--surface-canvas);
  color: var(--color-ink-black);
  font-family: var(--font-sohne);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  font-weight: var(--font-weight-regular);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img,
svg,
video {
  max-width: 100%;
  height: auto;
  display: block;
}

button {
  font: inherit;
  color: inherit;
}

/* ═══ Typography ═════════════════════════════════════════════════════════
   The serif is reserved for h1/h2 and the .display-* opt-ins. h3 and below
   are Inter half-steps — hierarchy without reaching for bold. */

h1,
h2,
.display,
.display-lg {
  font-family: var(--font-signifier);
  font-weight: var(--font-weight-regular);
  color: var(--color-ink-black);
  margin: 0;
  text-wrap: balance;
}

h1,
.display-lg {
  font-size: var(--text-heading-lg);
  line-height: var(--leading-heading-lg);
  letter-spacing: var(--tracking-heading-lg);
}

h2,
.display {
  font-size: var(--text-heading);
  line-height: var(--leading-heading);
  letter-spacing: var(--tracking-heading);
}

/* The one display size above h1 — hero only, once per page. */
.display-xl {
  font-family: var(--font-signifier);
  font-weight: var(--font-weight-regular);
  font-size: var(--text-display);
  line-height: var(--leading-display);
  letter-spacing: var(--tracking-display);
  margin: 0;
  text-wrap: balance;
}

/* An italic clause inside a display line is the system's signature flourish. */
.display-xl em,
h1 em,
h2 em,
.display em {
  font-style: italic;
}

h3 {
  font-family: var(--font-sohne);
  font-size: var(--text-heading-sm);
  line-height: var(--leading-heading-sm);
  letter-spacing: var(--tracking-heading-sm);
  font-weight: var(--font-weight-450);
  margin: 0;
}

h4 {
  font-family: var(--font-sohne);
  font-size: var(--text-subheading);
  line-height: var(--leading-subheading);
  font-weight: var(--font-weight-450);
  margin: 0;
}

h5,
h6 {
  font-family: var(--font-sohne);
  font-size: var(--text-body-lg);
  line-height: var(--leading-body-lg);
  font-weight: var(--font-weight-480);
  margin: 0;
}

p {
  margin: 0;
}

.lede {
  font-size: var(--text-body);
  line-height: var(--leading-body);
  color: var(--color-slate-gray);
  max-width: 62ch;
}

.lede-lg {
  font-size: var(--text-body-lg);
  line-height: var(--leading-body-lg);
  color: var(--color-slate-gray);
  max-width: 60ch;
}

.caption {
  font-size: var(--text-caption);
  line-height: var(--leading-caption);
  color: var(--color-slate-gray);
}

.muted {
  color: var(--color-slate-gray);
}

/* Eyebrow / section label — contract: emitted by dashboard.js and admin.js. Use slate, never ash, for AA contrast. */
.kicker {
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  font-weight: var(--font-weight-regular);
  letter-spacing: 0.06em;
  color: var(--color-slate-gray);
}

/* Typographic category tag — subtle background for FAQ/FAQ category.
   Contract: emitted by admin.js for FAQ category and outage severity. */
.tag {
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  font-weight: var(--font-weight-450);
  color: var(--color-ink-black);
  background: var(--status-active-surface);
  border: 1px solid var(--status-active-border);
  padding: 2px var(--spacing-8);
  border-radius: var(--radius-buttons);
  white-space: nowrap;
  text-transform: capitalize;
}

/* ─── Tag colors by value ────────────────────────────────────── */
.tag.critical { color: var(--color-error); border-color: var(--color-error); }
.tag.major    { color: var(--color-sienna-brown); }
.tag.minor    { color: var(--color-slate-gray); }
.tag.info     { color: var(--color-slate-gray); }
.tag.service  { color: var(--color-ink-black); background: var(--status-attention-surface); border-color: var(--status-attention-border); }
.tag.billing  { color: var(--color-ink-black); background: var(--status-attention-surface); border-color: var(--status-attention-border); }
.tag.admin    { color: var(--color-ink-black); background: var(--status-active-surface); border-color: var(--status-active-border); }
.tag.support  { color: var(--color-sienna-brown); }

/* When parent row is open (expanded), make the tag darker to
   signal the expanded state clearly. */
.admin-row.open .tag {
  color: var(--color-ink-black);
}

/* Contract: emitted by dashboard.js and admin.js. */
.mono {
  font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
  font-size: 0.92em;
  font-variant-numeric: tabular-nums;
}

.numeric {
  font-variant-numeric: tabular-nums;
}

/* ═══ Links ══════════════════════════════════════════════════════════════
   No underline at rest — the arrow suffix carries the affordance. */

a {
  color: var(--color-ink-black);
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.link-muted {
  color: var(--color-slate-gray);
}

/* ═══ Focus ══════════════════════════════════════════════════════════════
   An achromatic system may not whisper here. Ink ring, always visible. */

:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
  border-radius: var(--radius-inputs);
}

.skip-link {
  position: absolute;
  left: var(--spacing-16);
  top: calc(-1 * var(--spacing-64));
  z-index: 1000;
  padding: var(--spacing-12) var(--spacing-20);
  background: var(--color-ink-black);
  color: var(--color-paper-white);
  border-radius: var(--radius-buttons);
  font-size: var(--text-caption);
  transition: top var(--transition-fast);
}

.skip-link:focus {
  top: var(--spacing-16);
  text-decoration: none;
}

main:focus {
  outline: none;
}

/* ═══ Layout ═════════════════════════════════════════════════════════════ */

.wrap {
  width: 100%;
  max-width: var(--page-max-width);
  margin: 0 auto;
  padding: 0 var(--spacing-24);
}

/* Wider gutter variant used by the app shells. */
.wrap-wide {
  width: 100%;
  max-width: var(--page-max-width);
  margin: 0 auto;
  padding: var(--spacing-40) var(--spacing-24) 0;
}

.section {
  padding: var(--section-gap) 0;
}

.section-tight {
  padding: var(--spacing-64) 0;
}

.band-fog {
  background: var(--surface-section-fog);
}

.band-mist {
  background: var(--surface-card-mist);
}

.section-head {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-16);
  margin-bottom: var(--spacing-64);
  max-width: 68ch;
}

.section-head--center {
  align-items: center;
  text-align: center;
  margin-inline: auto;
}

/* App-shell page header (dashboard / admin / faq). */
.page-head {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-12);
  padding: var(--spacing-40) 0 var(--spacing-32);
}

.page-head h1 {
  font-size: var(--text-heading);
  line-height: var(--leading-heading);
  letter-spacing: var(--tracking-heading);
}

/* A titled content block — the standard container inside app shells. */
.editorial-block {
  background: var(--surface-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-cards);
  padding: var(--spacing-32);
}

.block-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-16);
  margin-bottom: var(--spacing-20);
}

.block-head h2,
.block-head h3 {
  font-family: var(--font-sohne);
  font-size: var(--text-subheading);
  line-height: var(--leading-subheading);
  letter-spacing: normal;
  font-weight: var(--font-weight-480);
}

/* ═══ Command bar ════════════════════════════════════════════════════════
   Transparent, no border, no shadow — "whisper-quiet" per DESIGN.md.
   A 3-column grid, not a wrapping flex row: the brand must never drop onto
   its own line (which is exactly what the previous build did). */

.command-bar {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(255, 255, 255, 0.82);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
}

.command-bar .inner,
.command-bar__inner {
  width: 100%;
  max-width: var(--page-max-width);
  margin: 0 auto;
  padding: 0 var(--spacing-24);
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--spacing-32);
  min-height: 72px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-12);
  flex-shrink: 0;
  font-size: var(--text-body);
  font-weight: var(--font-weight-480);
  letter-spacing: -0.01em;
  color: var(--color-ink-black);
  white-space: nowrap;
}

.brand:hover {
  text-decoration: none;
}

.brand .mark,
.brand__mark {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-images);
  background: var(--color-ink-black);
  color: var(--color-paper-white);
  flex-shrink: 0;
}

.brand .mark svg,
.brand__mark svg {
  width: 18px;
  height: 18px;
}

.nav-links,
.navlinks {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--spacing-28);
  list-style: none;
  margin: 0;
  padding: 0;
}

/* App shells put their utility links on the right rather than centred. */
.command-bar .navlinks {
  justify-content: flex-end;
  justify-self: end;
  grid-column: 3;
}

.nav-link,
.navlinks a,
.navlinks button {
  font-size: var(--text-body);
  font-weight: var(--font-weight-regular);
  color: var(--color-ink-black);
  padding: 2px 0;
  white-space: nowrap;
  background: none;
  border: 0;
  cursor: pointer;
}

.nav-actions {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-16);
  justify-self: end;
  flex-shrink: 0;
}

/* ═══ Buttons ════════════════════════════════════════════════════════════
   Every button is a pill. Filled and ghost share identical geometry so they
   sit on the same baseline as a matched pair. min-height meets the 44px
   touch target without breaking the spec's "height auto" intent. */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--spacing-8);
  min-height: 44px;
  padding: var(--spacing-12) var(--spacing-20);
  border-radius: var(--radius-buttons);
  border: 1px solid transparent;
  font-family: var(--font-sohne);
  font-size: 16px;
  line-height: 1.2;
  font-weight: var(--font-weight-regular);
  text-align: center;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast),
    border-color var(--transition-fast), opacity var(--transition-fast);
}

.btn:hover {
  text-decoration: none;
}

.btn:disabled,
.btn[aria-disabled='true'] {
  opacity: 0.45;
  cursor: not-allowed;
}

/* Primary — the solid black lozenge. */
.btn-primary {
  background: var(--color-ink-black);
  color: var(--color-paper-white);
  border-color: var(--color-ink-black);
}

.btn-primary:hover:not(:disabled) {
  background: #000;
  border-color: #000;
}

/* Destructive actions only — Delete FAQ, Remove agent. Reserved for irreversible loss. */
.btn-danger {
  background: var(--color-error);
  color: var(--color-paper-white);
  border-color: var(--color-error);
}

.btn-danger:hover:not(:disabled) {
  background: #3d1a0e;
  border-color: #3d1a0e;
}

/* Cancel / dismiss — reversible. Ghost treatment so Cancel never reads as destructive. */
.btn-cancel {
  background: transparent;
  color: var(--color-ink-black);
  border-color: var(--color-border);
}

.btn-cancel:hover:not(:disabled) {
  background: var(--color-mist-gray);
  border-color: var(--color-slate-gray);
}

/* Ghost — the matched secondary. */
.btn-secondary {
  background: transparent;
  color: var(--color-ink-black);
  border-color: var(--color-ink-black);
}

.btn-secondary:hover:not(:disabled) {
  background: var(--color-mist-gray);
}

/* Quiet button for mist/peach surfaces. */
.btn-quiet {
  background: var(--color-paper-white);
  color: var(--color-ink-black);
  border-color: var(--color-border);
}

.btn-quiet:hover:not(:disabled) {
  background: var(--color-fog-white);
}

/* Text link with arrow — lowest-emphasis action.
   Contract: .btn-text is emitted throughout dashboard.js and admin.js. */
.btn-text {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-8);
  min-height: 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-ink-black);
  font-family: var(--font-sohne);
  font-size: 16px;
  font-weight: var(--font-weight-regular);
  cursor: pointer;
  text-align: left;
}

.btn-text:hover:not(:disabled) {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.btn-text:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.btn-sm {
  min-height: 36px;
  padding: var(--spacing-8) var(--spacing-16);
  font-size: var(--text-caption);
}

.btn-block {
  width: 100%;
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--spacing-12);
}

/* ═══ Cards ══════════════════════════════════════════════════════════════ */

/* The workhorse: flat, soft, quiet. No shadow, no border — ever. */
.card,
.card-neutral {
  background: var(--surface-card-mist);
  border-radius: var(--radius-cards);
  padding: var(--spacing-32);
}

/* The single chromatic surface. At most once per page, and only on a white
   or mist background — never on another colour. */
.card-peach {
  background: var(--surface-accent-blush);
  color: var(--color-sienna-brown);
  border-radius: var(--radius-cards);
  padding: var(--spacing-40);
}

/* Text on peach takes the sienna ink. Buttons are deliberately excluded:
   .card-peach a would otherwise out-specify .btn-primary and repaint a
   filled pill's label sienna-on-ink, which is unreadable. */
.card-peach h1,
.card-peach h2,
.card-peach h3,
.card-peach h4,
.card-peach h5,
.card-peach p,
.card-peach a:not(.btn),
.card-peach .kicker,
.card-peach .lede,
.card-peach .caption,
.card-peach .tag {
  color: var(--color-sienna-brown);
}

/* Belt and braces: keep both pill variants legible on the peach surface. */
.card-peach .btn-primary {
  background: var(--color-ink-black);
  color: var(--color-paper-white);
  border-color: var(--color-ink-black);
}

.card-peach .btn-secondary {
  color: var(--color-sienna-brown);
  border-color: var(--color-sienna-brown);
}

.card-peach .btn-secondary:hover:not(:disabled) {
  background: rgba(93, 42, 26, 0.08);
}

.card-peach .kicker,
.card-peach .lede,
.card-peach .caption,
.card-peach .tag {
  opacity: 0.78;
}

.card-sm {
  background: var(--surface-card-mist);
  border-radius: var(--radius-smallcards);
  padding: var(--spacing-20);
}

/* Floating product artifact — the ONLY element allowed elevation. */
.artifact {
  background: var(--surface-elevated);
  border-radius: var(--radius-elevatedcards);
  box-shadow: var(--shadow-artifact);
  padding: var(--spacing-16) var(--spacing-20) var(--spacing-12);
}

.panel {
  background: var(--surface-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-cards);
  padding: var(--spacing-32);
}

/* ═══ Forms ══════════════════════════════════════════════════════════════ */

/* Contract: .field is emitted by dashboard.js and admin.js. */
.field {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-8);
}

.field > span,
.field > label,
label.field-label {
  font-size: var(--text-caption);
  line-height: var(--leading-caption);
  font-weight: var(--font-weight-450);
  color: var(--color-ink-black);
}

.field-hint {
  font-size: var(--text-sm);
  color: var(--color-slate-gray);
}

input,
select,
textarea {
  width: 100%;
  min-height: 44px;
  padding: var(--spacing-12) var(--spacing-16);
  background: var(--color-paper-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-inputs);
  font-family: var(--font-sohne);
  font-size: 16px;
  line-height: 1.4;
  color: var(--color-ink-black);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

textarea {
  min-height: 96px;
  resize: vertical;
}

input::placeholder,
textarea::placeholder {
  color: var(--color-smoke-gray);
}

input:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--color-ink-black);
  box-shadow: 0 0 0 1px var(--color-ink-black);
}

/* input:focus-visible — defer to global ::focus-visible for keyboard focus ring. */
/* The :focus block above already provides a box-shadow ring for click focus. */

input:disabled,
select:disabled,
textarea:disabled {
  background: var(--color-fog-white);
  color: var(--color-smoke-gray);
  cursor: not-allowed;
}

select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%23777b86' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--spacing-16) center;
  background-size: 12px 8px;
  padding-right: var(--spacing-40);
}

/* Contract: .inline-form is emitted by dashboard.js / admin.js and also
   wraps the static create-toggle buttons. */
.inline-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--spacing-16);
  padding-top: var(--spacing-20);
  margin-top: var(--spacing-4);
  border-top: 1px solid var(--color-border);
}

.inline-form > div:not(.field) {
  flex: 1 1 100%;
}

.inline-form .field {
  flex: 1 1 220px;
  min-width: 0;
}

/* ═══ Status badges ══════════════════════════════════════════════════════
   CONTRACT — the page scripts interpolate the raw API status straight into
   the class list, e.g. `class="status-word in_progress"`. Every value the
   API can return must therefore have a rule here, underscore included.

   DESIGN.md forbids chromatic colour beyond the peach/sienna pair, so status
   is carried by that pair plus the achromatic ramp — never an imported hue.
   The badge always renders the word too, so colour is never the sole signal
   (a WCAG requirement independent of palette).

   Three tiers:
     attention  overdue / unpaid / expired / cancelled / failed   (warm)
     live       active / open / in_progress / pending / confirmed (ink)
     settled    paid / resolved / closed / completed              (quiet) */

.status-word {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-4);
  padding: var(--spacing-4) var(--spacing-12);
  border-radius: var(--radius-buttons);
  border: 1px solid var(--status-quiet-border);
  background: var(--status-quiet-surface);
  color: var(--status-quiet-text);
  font-size: var(--text-sm);
  line-height: 1.4;
  font-weight: var(--font-weight-450);
  white-space: nowrap;
  text-transform: capitalize;
}

/* ═══ Status badges ══════════════════════════════════════════════
   Each status gets its own semantically justified color so admins
   can scan at a glance. Statuses are sorted by urgency:
   error/failure → overdue/unpaid → active/open/in-progress →
   confirmed/pending → resolved/completed → closed/paid. */

/* ─── Error / failure ─────────────────────────────────────────────── */
.status-word.failed {
  background: var(--color-error);
  color: var(--color-paper-white);
  border-color: var(--color-error);
}

/* ─── Money / service at risk ─────────────────────────────────────── */
.status-word.overdue {
  background: var(--status-attention-surface);
  color: var(--status-attention-text);
  border-color: var(--status-attention-border);
}

.status-word.unpaid {
  background: var(--status-attention-surface);
  color: var(--color-sienna-brown);
  border-color: var(--status-attention-border);
}

/* ─── Live / in progress ──────────────────────────────────────────── */
.status-word.active {
  background: var(--status-going-surface);
  color: var(--status-going-text);
  border-color: var(--status-going-border);
}

.status-word.open {
  background: var(--status-attention-surface);
  color: var(--status-attention-text);
  border-color: var(--status-attention-border);
}

.status-word.in_progress {
  background: var(--status-active-surface);
  color: var(--status-active-text);
  border-color: var(--status-active-border);
}

/* ─── Waiting / scheduled ─────────────────────────────────────────── */
.status-word.pending {
  background: var(--status-pending-surface);
  color: var(--status-pending-text);
  border-color: var(--status-pending-border);
}

.status-word.confirmed {
  background: var(--status-confirmed-surface);
  color: var(--status-confirmed-text);
  border-color: var(--status-confirmed-border);
}

/* ─── Resolved / finished ──────────────────────────────────────────── */
.status-word.resolved {
  background: var(--color-paper-white);
  color: var(--color-ink-black);
  border-color: var(--color-border);
}

.status-word.completed {
  background: var(--status-active-surface);
  color: var(--status-active-text);
  border-color: var(--status-active-border);
}

/* ─── Final / closed ──────────────────────────────────────────────── */
.status-word.closed {
  background: var(--status-quiet-surface);
  color: var(--status-quiet-text);
  border-color: var(--status-quiet-border);
}

/* ─── Financial ────────────────────────────────────────────────────── */
.status-word.paid {
  background: var(--color-paper-white);
  color: var(--color-ink-black);
  border-color: var(--color-border);
}

.status-word.cancelled {
  background: var(--color-smoke-gray);
  color: var(--color-paper-white);
  border-color: var(--color-smoke-gray);
}

.status-word.expired {
  background: var(--color-smoke-gray);
  color: var(--color-paper-white);
  border-color: var(--color-smoke-gray);
}

/* ═══ Key/value rows ══════════════════════════════════════════════
   Contract: emitted by dashboard.js and admin.js as .kv-row > .k + .v. */

.kv-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-16);
  padding: var(--spacing-12) 0;
  border-bottom: 1px solid var(--color-border);
}

.kv-row:last-child {
  border-bottom: 0;
}

.kv-row .k {
  font-size: var(--text-caption);
  color: var(--color-slate-gray);
  flex-shrink: 0;
}

.kv-row .v {
  font-size: var(--text-caption);
  font-weight: var(--font-weight-450);
  color: var(--color-ink-black);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Inputs sitting inside a kv-row (profile edit mode) shouldn't stretch. */
.kv-row input,
.kv-row select {
  max-width: 260px;
  min-height: 40px;
}

/* ═══ Expandable rows ════════════════════════════════════════════════════
   CONTRACT — used by both dashboard (.ticket-row) and admin (.admin-row).
   The scripts inject detail HTML into the inner container and toggle .open
   on the row. The max-height pair below IS the reveal mechanism: without it
   the injected detail never becomes visible. */

.ticket-row,
.admin-row {
  border-bottom: 1px solid var(--color-border);
}

.ticket-row:last-of-type,
.admin-row:last-of-type {
  border-bottom: 0;
}

/* .line is a <button> on expandable rows and a <div> on static ones. */
.ticket-row .line,
.admin-row .line {
  display: flex;
  align-items: center;
  gap: var(--spacing-16);
  width: 100%;
  padding: var(--spacing-16) 0;
  background: none;
  border: 0;
  text-align: left;
  cursor: pointer;
  font-family: var(--font-sohne);
  font-size: var(--text-caption);
  color: var(--color-ink-black);
  transition: background var(--transition-fast), color var(--transition-fast);
}

.ticket-row:hover,
.admin-row:hover {
  background: var(--color-fog-white);
}

.ticket-row .line:hover,
.admin-row .line:hover {
  background: var(--color-fog-white);
  color: var(--color-ink-black);
  border-radius: var(--radius-buttons);
}

.admin-row .primary,
.ticket-row .subject {
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--text-body);
  font-weight: var(--font-weight-450);
  color: var(--color-ink-black);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.admin-row .meta,
.ticket-row .meta {
  flex-shrink: 0;
  font-size: var(--text-sm);
  color: var(--color-slate-gray);
}

.ticket-detail,
.admin-detail {
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity var(--transition-slow), transform var(--transition-slow);
}

.ticket-row.open .ticket-detail {
  max-height: 1000px;
  opacity: 1;
  transform: translateY(0);
}

.admin-row.open .admin-detail {
  max-height: 2000px;
  opacity: 1;
  transform: translateY(0);
}

.admin-row.open .admin-detail {
  max-height: 2000px;
}

.ticket-detail-inner,
.admin-detail-inner {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-12);
  padding: 0 0 var(--spacing-24);
  font-size: var(--text-caption);
  color: var(--color-slate-gray);
}

.ticket-detail-inner > p,
.admin-detail-inner > p {
  font-size: var(--text-caption);
  line-height: var(--leading-caption);
  color: var(--color-ink-black);
}

/* Thread messages — needed by BOTH dashboard and admin, so they live here. */
.ticket-message {
  padding: var(--spacing-12) var(--spacing-16);
  background: var(--surface-card-mist);
  border-radius: var(--radius-smallcards);
  font-size: var(--text-caption);
  color: var(--color-ink-black);
}

.ticket-message .who {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--spacing-12);
  margin-bottom: var(--spacing-4);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-480);
  color: var(--color-ink-black);
}

.ticket-message .when {
  font-weight: var(--font-weight-regular);
  color: var(--color-slate-gray);
}

/* ═══ Filters & pagination (admin) ═══════════════════════════════════════
   CONTRACT — admin.js writes `class="active"` on the selected filter and
   `class=""` on the rest, so the base rule must style a bare button. */

.admin-filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-8);
  margin-bottom: var(--spacing-20);
}

.admin-filters button {
  padding: var(--spacing-8) var(--spacing-16);
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-buttons);
  font-size: var(--text-sm);
  color: var(--color-slate-gray);
  cursor: pointer;
  text-transform: capitalize;
  transition: background var(--transition-fast), color var(--transition-fast),
    border-color var(--transition-fast);
}

.admin-filters button:hover {
  color: var(--color-ink-black);
}

.admin-filters button.active {
  background: var(--color-ink-black);
  border-color: var(--color-ink-black);
  color: var(--color-paper-white);
}

.admin-pagination {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--spacing-16);
  padding-top: var(--spacing-20);
  border-top: 1px solid var(--color-border);
  font-size: var(--text-sm);
  color: var(--color-slate-gray);
}

/* ═══ App shell layout (dashboard / admin) ═══════════════════════════════ */

.dash-layout {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: var(--spacing-40);
  align-items: start;
  padding-bottom: var(--spacing-96);
}

.dash-sidebar {
  position: sticky;
  top: 96px;
  display: flex;
  flex-direction: column;
  gap: var(--spacing-4);
}

.dash-sidebar a {
  padding: var(--spacing-8) var(--spacing-12);
  border-radius: var(--radius-smallcards);
  font-size: var(--text-caption);
  color: var(--color-slate-gray);
  transition: background var(--transition-fast), color var(--transition-fast);
}

.dash-sidebar a:hover {
  background: var(--surface-card-mist);
  color: var(--color-ink-black);
  text-decoration: none;
}

/* Contract: dashboard.js / admin.js toggle .active as you scroll. */
.dash-sidebar a.active {
  background: var(--surface-card-mist);
  color: var(--color-ink-black);
  font-weight: var(--font-weight-480);
}

/* "More" dropdown for admin sidebar when sections exceed the visible limit. */
.nav-more {
  position: relative;
}

.nav-more-menu {
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 160px;
  background: var(--surface-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-smallcards);
  padding: var(--spacing-8);
  display: flex;
  flex-direction: column;
  gap: var(--spacing-4);
  z-index: 10;
  box-shadow: 0 var(--spacing-4) var(--spacing-16) rgba(0,0,0,0.06);
}

.nav-more-menu[hidden] {
  display: none;
}

.nav-more-menu a {
  padding: var(--spacing-8) var(--spacing-12);
  border-radius: var(--radius-smallcards);
  font-size: var(--text-caption);
  color: var(--color-slate-gray);
  text-decoration: none;
}

.nav-more-menu a:hover {
  background: var(--surface-card-mist);
  color: var(--color-ink-black);
}

.nav-more-menu a.active {
  background: var(--surface-card-mist);
  color: var(--color-ink-black);
  font-weight: var(--font-weight-480);
}

.dash-main {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-40);
  min-width: 0;
}

/* Live-connection dot — JS sets display:inline-block when SSE opens. */
.live-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-ink-black);
  vertical-align: middle;
  margin-left: var(--spacing-12);
}

/* ═══ States ═════════════════════════════════════════════════════════════ */

.is-hidden,
[hidden] {
  display: none;
}

/* Contract: both are injected as placeholder/empty content by the scripts. */
.empty-state,
.loading-state {
  padding: var(--spacing-40) var(--spacing-24);
  background: var(--surface-card-mist);
  border-radius: var(--radius-cards);
  text-align: center;
  color: var(--color-slate-gray);
  font-size: var(--text-caption);
}

/* An empty screen is an invitation to act, so leave room for a CTA. */
.empty-state .btn {
  margin-top: var(--spacing-20);
}

/* FUP data-usage meter on the plan page. */
.fup-meter {
  padding: var(--spacing-16) var(--spacing-20);
  background: var(--surface-card-mist);
  border-radius: var(--radius-smallcards);
  margin-bottom: var(--spacing-24);
}

.fup-meter .kicker {
  display: block;
  margin-bottom: var(--spacing-8);
}

.fup-bar-bg {
  height: 6px;
  background: var(--color-border);
  border-radius: 3px;
  overflow: hidden;
  margin-bottom: var(--spacing-8);
}

.fup-bar-fill {
  height: 100%;
  border-radius: 3px;
 
}

.fup-label {
  font-size: var(--text-caption);
  color: var(--color-slate-gray);
}

.error-text {
  color: var(--color-sienna-brown);
  font-size: var(--text-caption);
}

.notice {
  padding: var(--spacing-16) var(--spacing-20);
  border-radius: var(--radius-smallcards);
  border: 1px solid var(--status-attention-border);
  background: var(--status-attention-surface);
  color: var(--status-attention-text);
  font-size: var(--text-caption);
}

/* ═══ Toast ══════════════════════════════════════════════════════════════
   CONTRACT — showToast() REPLACES className with "toast", "toast show", or
   "toast show error". No other class may be required for its styling. */

.toast {
  position: fixed;
  left: 50%;
  bottom: var(--spacing-32);
  z-index: 900;
  transform: translate(-50%, 12px);
  max-width: min(92vw, 440px);
  padding: var(--spacing-12) var(--spacing-20);
  background: var(--color-ink-black);
  color: var(--color-paper-white);
  border-radius: var(--radius-buttons);
  box-shadow: var(--shadow-overlay);
  font-size: var(--text-caption);
  text-align: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transition-normal), transform var(--transition-normal);
}

.toast.show {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* Errors stay achromatic-warm: sienna ink on peach, per the palette rule. */
.toast.error {
  background: var(--color-blush-peach);
  color: var(--color-sienna-brown);
}

/* ═══ Footer ═════════════════════════════════════════════════════════════ */

.site-footer {
  border-top: 1px solid var(--color-border);
  padding: var(--spacing-64) 0 var(--spacing-40);
  color: var(--color-slate-gray);
  font-size: var(--text-caption);
}

.site-footer__grid {
  display: grid;
  grid-template-columns: 1.6fr repeat(3, 1fr);
  gap: var(--spacing-40);
  margin-bottom: var(--spacing-64);
}

.site-footer h5 {
  font-size: var(--text-caption);
  font-weight: var(--font-weight-480);
  color: var(--color-ink-black);
  margin-bottom: var(--spacing-16);
}

.site-footer ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--spacing-12);
}

.site-footer a {
  color: var(--color-slate-gray);
}

.site-footer a:hover {
  color: var(--color-ink-black);
}

.site-footer__base {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-16);
  padding-top: var(--spacing-24);
  border-top: 1px solid var(--color-border);
  font-size: var(--text-sm);
}

.site-footer__legal {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-20);
}

/* Simple inline link row used by the app-shell footers. */
.site-footer .flinks {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-20);
  justify-content: center;
  margin-bottom: var(--spacing-12);
}

/* ═══ Responsive ═════════════════════════════════════════════════════════
   Display sizes step down 90 → 64 → 44 → 34 → 30, keeping the serif in
   charge at every width. Tracking loosens as size drops. */

@media (max-width: 1024px) {
  .display-xl {
    font-size: var(--text-heading-lg);
    letter-spacing: var(--tracking-heading-lg);
  }

  h1,
  .display-lg {
    font-size: var(--text-heading);
    letter-spacing: var(--tracking-heading);
  }

  .dash-layout {
    grid-template-columns: 1fr;
    gap: var(--spacing-24);
  }

  .dash-sidebar {
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
    gap: var(--spacing-8);
    padding-bottom: var(--spacing-8);
  }

  .site-footer__grid {
    grid-template-columns: 1fr 1fr;
    gap: var(--spacing-32);
  }
}

@media (max-width: 768px) {
  .nav-links {
    display: none;
  }

  .command-bar .inner,
  .command-bar__inner {
    grid-template-columns: auto 1fr;
    min-height: 64px;
    gap: var(--spacing-16);
  }

  .command-bar .navlinks {
    grid-column: 2;
    gap: var(--spacing-16);
  }

  .section {
    padding: var(--spacing-64) 0;
  }

  .section-head {
    margin-bottom: var(--spacing-40);
  }

  .display-xl {
    font-size: var(--text-heading);
    letter-spacing: var(--tracking-heading);
  }

  h1,
  .display-lg,
  .page-head h1 {
    font-size: 34px;
    line-height: 1.22;
    letter-spacing: -0.4px;
  }

  h2,
  .display {
    font-size: 30px;
    line-height: 1.24;
    letter-spacing: -0.3px;
  }

  h3 {
    font-size: var(--text-subheading);
  }

  .card,
  .card-neutral,
  .card-peach,
  .panel,
  .editorial-block {
    padding: var(--spacing-24);
  }
}

@media (max-width: 640px) {
  .wrap,
  .command-bar .inner,
  .command-bar__inner {
    padding-left: var(--spacing-20);
    padding-right: var(--spacing-20);
  }

  .wrap-wide {
    padding: var(--spacing-24) var(--spacing-20) 0;
  }

  .site-footer__grid {
    grid-template-columns: 1fr;
  }

  .btn-row .btn {
    flex: 1 1 100%;
  }

  .kv-row {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--spacing-4);
  }

  .kv-row .v {
    text-align: left;
  }

  .kv-row input,
  .kv-row select {
    max-width: 100%;
  }
}

@media (max-width: 480px) {
  body {
    font-size: 16px;
  }

  .display-xl,
  h1,
  .display-lg,
  .page-head h1 {
    font-size: 30px;
    line-height: 1.22;
    letter-spacing: -0.3px;
  }
}
