:root {
  color-scheme: light dark;

  --color-background: #f5f3ee;
  --color-surface: #ffffff;
  --color-text: #1f1f24;
  --color-text-muted: #5c5c66;
  --color-border: #dcd8d0;
  --color-accent: #b8560f;
  --color-accent-contrast: #ffffff;
  --color-accent-tint: #f8e9dc;
  --color-focus: #1d4ed8;
  --color-error: #a4262c;
  --color-error-tint: #fbe9e9;
  --color-open: #8a5a00;
  --color-open-tint: #fff3d6;
  --color-paid: #1f6b3a;
  --color-paid-tint: #dff3e6;
  --color-cancelled: #5c5c66;
  --color-cancelled-tint: #ebebef;
  --color-seen: #1a7f37;
  --color-unseen: #c62828;

  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;

  --radius: 0.75rem;
  --tap-target: 2.75rem;
  --header-height: 3.5rem;
  --bottom-navigation-height: 3.75rem;
  --sidebar-width: 14rem;
  --content-max-width: 64rem;
  --text-measure: 72ch;
  --story-measure: 68ch;

  --font-family:
    system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
    sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-background: #17171b;
    --color-surface: #232329;
    --color-text: #ececf1;
    --color-text-muted: #a6a6b3;
    --color-border: #37373f;
    --color-accent: #f0a05a;
    --color-accent-contrast: #1f1f24;
    --color-accent-tint: #3a2a1c;
    --color-focus: #8ab4f8;
    --color-error: #f2a8a4;
    --color-error-tint: #3a2222;
    --color-open: #f5c76a;
    --color-open-tint: #3a2f16;
    --color-paid: #8fd9a8;
    --color-paid-tint: #1d3a28;
    --color-cancelled: #b5b5c0;
    --color-cancelled-tint: #2f2f36;
    --color-seen: #57d27a;
    --color-unseen: #ff8a80;
  }
}

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

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

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  /* The column may shrink below the header's content width, so that the
     node bar scrolls within itself instead of widening the page. */
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    'header'
    'main'
    'navigation';
  font-family: var(--font-family);
  font-size: 1rem;
  line-height: 1.5;
  color: var(--color-text);
  background: var(--color-background);
  overflow-wrap: anywhere;
}

:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
}

a {
  color: var(--color-accent);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.app-header {
  grid-area: header;
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  height: var(--header-height);
  padding: 0 var(--space-4);
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
}

.app-title {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-target);
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--color-text);
  text-decoration: none;
  white-space: nowrap;
}

/*
 * The node bar lists every node of the environment next to the title. From
 * 768 px the header has room for a row of nodes; should it still overflow,
 * the bar scrolls sideways within itself instead of the page growing wider,
 * and the active badge comes first so that it always stays in view. Below
 * 768 px a bar with other nodes takes a row of its own under the title and
 * wraps, so that every node is visible without scrolling (see the phone
 * rule further down).
 */
.node-bar {
  /* Positioned so that the visually hidden labels inside the links are
     clipped with the bar instead of sticking out of the sticky header. */
  position: relative;
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  height: 100%;
  overflow-x: auto;
  scrollbar-width: thin;
}

/*
 * Right-aligned while there is room; `justify-content: flex-end` would
 * push an overflowing bar's start, the active badge, into the unscrollable
 * side, whereas an auto margin collapses to zero once the bar overflows.
 */
.node-bar > :first-child {
  margin-left: auto;
}

@media (max-width: 767.98px) {
  .app-header {
    flex-wrap: wrap;
    row-gap: 0;
    height: auto;
    min-height: var(--header-height);
  }

  .node-bar:has(.node-link) {
    flex-basis: 100%;
    flex-wrap: wrap;
    height: auto;
    padding-bottom: var(--space-2);
    overflow: visible;
  }

  .node-bar:has(.node-link) > :first-child {
    margin-left: 0;
  }
}

.node-badge,
.node-link {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: var(--space-1);
  min-height: var(--tap-target);
  margin: 0;
  padding: var(--space-1) var(--space-3);
  border: 2px solid var(--color-border);
  border-radius: 999px;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--color-text);
  white-space: nowrap;
  text-decoration: none;
}

.node-badge-active {
  border-color: var(--color-accent);
  background: var(--color-accent-tint);
}

.node-link-seen {
  border-color: var(--color-seen);
}

.node-link-unseen {
  border-color: var(--color-unseen);
}

/*
 * The browser's own probe is the secondary signal, so it is a small glyph
 * inside the link rather than the outline: a check when this browser
 * reached the node, a cross when it did not, an ellipsis while pending.
 */
.browser-probe {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1rem;
  height: 1rem;
  border-radius: 50%;
  font-size: 0.6875rem;
  font-weight: 700;
  line-height: 1;
  color: var(--color-accent-contrast);
  background: var(--color-text-muted);
}

.browser-probe::before {
  content: '…';
}

.browser-probe-ok {
  background: var(--color-seen);
}

.browser-probe-ok::before {
  content: '✓';
}

.browser-probe-failed {
  background: var(--color-unseen);
}

.browser-probe-failed::before {
  content: '✕';
}

.topology-dot {
  display: inline-block;
  flex: none;
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 50%;
}

.topology-dot-seen {
  background: var(--color-seen);
}

.topology-dot-unseen {
  background: var(--color-unseen);
}

.probe-mark {
  display: inline-block;
  flex: none;
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 0.125rem;
}

.probe-mark-ok {
  background: var(--color-seen);
}

.probe-mark-failed {
  background: var(--color-unseen);
}

.app-navigation {
  grid-area: navigation;
  position: sticky;
  bottom: 0;
  z-index: 1;
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
}

.app-navigation ul {
  display: flex;
  margin: 0;
  padding: 0;
  list-style: none;
}

.app-navigation li {
  flex: 1 1 0;
  min-width: 0;
}

.app-navigation a {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  min-width: var(--tap-target);
  min-height: var(--bottom-navigation-height);
  padding: var(--space-2);
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--color-text-muted);
  text-decoration: none;
}

.app-navigation a[aria-current='page'] {
  color: var(--color-accent);
}

.app-main {
  grid-area: main;
  width: 100%;
  min-width: 0;
  max-width: var(--content-max-width);
  padding: var(--space-4);
}

.view-title {
  margin: 0 0 var(--space-4);
  font-size: 1.5rem;
  line-height: 1.25;
}

.card-list {
  display: grid;
  gap: var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

.card {
  padding: var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

a.card {
  display: block;
  min-height: var(--tap-target);
  color: inherit;
  text-decoration: none;
}

.species-name {
  margin: 0;
  font-size: 1.25rem;
  line-height: 1.3;
}

.species-latin-name {
  margin: var(--space-1) 0 var(--space-3);
  font-size: 0.9375rem;
  color: var(--color-text-muted);
}

.species-description {
  max-width: var(--text-measure);
  margin: 0 0 var(--space-4);
}

.animal-name {
  margin: 0;
  font-size: 1.25rem;
  line-height: 1.3;
}

.animal-meta {
  display: flex;
  flex-wrap: wrap;
  column-gap: var(--space-3);
  row-gap: var(--space-1);
  margin: var(--space-1) 0 var(--space-3);
  font-size: 0.9375rem;
  color: var(--color-text-muted);
}

.animal-price {
  margin: 0;
  font-weight: 600;
}

.breeder-farm-name {
  margin: 0;
  font-size: 1.25rem;
  line-height: 1.3;
}

.breeder-meta {
  display: flex;
  flex-wrap: wrap;
  column-gap: var(--space-3);
  row-gap: var(--space-1);
  margin: var(--space-1) 0 0;
  font-size: 0.9375rem;
  color: var(--color-text-muted);
}

.back-link {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-target);
  margin-bottom: var(--space-2);
  color: var(--color-text-muted);
  text-decoration: none;
}

.animal-facts,
.facts {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: var(--space-4);
  row-gap: var(--space-2);
  max-width: var(--text-measure);
  margin: 0 0 var(--space-6);
  font-size: 0.9375rem;
}

.animal-facts dt,
.facts dt {
  margin: 0;
  color: var(--color-text-muted);
}

.animal-facts dd,
.facts dd {
  min-width: 0;
  margin: 0;
}

.network-section {
  margin: 0 0 var(--space-6);
}

.network-section-title {
  margin: 0 0 var(--space-3);
  font-size: 1.125rem;
  line-height: 1.3;
}

.network-section .facts {
  margin-bottom: 0;
}

.role-badge {
  display: inline-block;
  padding: 0 var(--space-2);
  border-radius: 999px;
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.5;
  color: var(--color-text-muted);
  background: var(--color-background);
  border: 1px solid var(--color-border);
}

.role-hub {
  color: var(--color-accent-contrast);
  background: var(--color-accent);
  border-color: var(--color-accent);
}

.role-client {
  color: var(--color-text);
  background: var(--color-accent-tint);
  border-color: var(--color-accent-tint);
}

.node-id {
  font-size: 0.8125rem;
  overflow-wrap: anywhere;
}

.node-card-name {
  margin: 0;
  font-size: 1.125rem;
  line-height: 1.3;
}

.node-card-self {
  font-weight: 400;
  color: var(--color-text-muted);
}

.node-card-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: var(--space-1) 0 var(--space-3);
  font-size: 0.875rem;
  color: var(--color-text-muted);
}

.node-signals {
  display: grid;
  gap: var(--space-1);
  margin: 0 0 var(--space-3);
  padding: 0;
  list-style: none;
  font-size: 0.9375rem;
}

.node-signal {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.node-card-seen {
  margin: 0;
  font-size: 0.875rem;
  color: var(--color-text-muted);
}

.peer-card .facts {
  margin: var(--space-3) 0 0;
  font-size: 0.875rem;
}

/*
 * The background story is the reading-comfort surface of this view: at
 * least 17px so it stays comfortable on a phone, a relaxed line height, and
 * a measure kept to roughly 65 to 70 characters on wide screens so a line
 * of text never grows too long to track by eye.
 */
.animal-story {
  max-width: var(--story-measure);
}

.animal-story p {
  margin: 0 0 var(--space-5);
  font-size: 1.0625rem;
  line-height: 1.6;
}

.animal-story p:last-child {
  margin-bottom: 0;
}

/*
 * The search field sits above the filters of the animals view: full width,
 * the same 44px control as every other input, with the count line below the
 * filters telling how many of the matching animals are on the page and the
 * "Load more" button after the cards fetching the next page.
 */
.search-field {
  margin: 0 0 var(--space-4);
}

.search-input {
  max-width: var(--text-measure);
}

.animal-count {
  margin: 0 0 var(--space-3);
  font-size: 0.9375rem;
  color: var(--color-text-muted);
}

.load-more {
  width: 100%;
  max-width: 20rem;
  margin: var(--space-4) 0 0;
}

/*
 * The animals view combines up to three filter groups (species, traits and,
 * while a breeder is selected, a compact breeder summary) that must all fit
 * on a 360px phone without the page scrolling horizontally: each is one
 * labelled row whose own chips scroll sideways within the row
 * (`overflow-x: auto` below) instead of the page growing wider than the
 * viewport. The breeder group stays a two-chip summary rather than a full
 * chip row (see `breederSummary` in `animals-list.js`) precisely so a third
 * row never has more content than the phone can show at once.
 */
.animal-filters {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin: 0 0 var(--space-4);
}

.filter-group {
  min-width: 0;
}

.filter-group-label {
  margin: 0 0 var(--space-1);
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--color-text-muted);
}

.chip-row {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--space-2);
  padding-bottom: var(--space-1);
  overflow-x: auto;
}

.animal-traits {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0 0 var(--space-6);
  padding: 0;
  list-style: none;
}

.chip {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  min-height: var(--tap-target);
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  background: var(--color-surface);
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--color-text);
  white-space: nowrap;
  text-decoration: none;
}

.chip[aria-current='page'] {
  border-color: var(--color-accent);
  background: var(--color-accent);
  color: var(--color-accent-contrast);
}

.status {
  max-width: var(--text-measure);
  margin: 0;
  color: var(--color-text-muted);
}

.status-error {
  padding: var(--space-4);
  border: 1px solid var(--color-error);
  border-radius: var(--radius);
  color: var(--color-text);
}

.status-headline {
  margin: 0;
  font-weight: 600;
  color: var(--color-error);
}

.status-detail {
  margin: var(--space-2) 0 var(--space-4);
  color: var(--color-text-muted);
}

.not-found p {
  max-width: var(--text-measure);
  margin: 0 0 var(--space-4);
}

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--tap-target);
  min-height: var(--tap-target);
  padding: var(--space-2) var(--space-5);
  border: 0;
  border-radius: 999px;
  font: inherit;
  font-weight: 600;
  color: var(--color-accent-contrast);
  background: var(--color-accent);
  text-decoration: none;
  cursor: pointer;
}

.button:disabled {
  opacity: 0.6;
  cursor: default;
}

.button-secondary {
  border: 1px solid var(--color-accent);
  color: var(--color-accent);
  background: var(--color-surface);
}

/*
 * The invoices view puts its one action, "New invoice", next to the title
 * so it is reachable without scrolling past the list; on a phone the two
 * wrap onto separate lines rather than squeezing the title.
 */
.view-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin: 0 0 var(--space-4);
}

.view-header .view-title {
  margin: 0;
}

.section-title {
  margin: var(--space-6) 0 var(--space-3);
  font-size: 1.125rem;
  line-height: 1.3;
}

.status-badge {
  display: inline-block;
  padding: 0 var(--space-2);
  border-radius: 999px;
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.5rem;
  text-transform: capitalize;
  white-space: nowrap;
}

.status-badge-open {
  color: var(--color-open);
  background: var(--color-open-tint);
}

.status-badge-paid {
  color: var(--color-paid);
  background: var(--color-paid-tint);
}

.status-badge-cancelled {
  color: var(--color-cancelled);
  background: var(--color-cancelled-tint);
}

.invoice-card-heading {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.invoice-number {
  margin: 0;
  font-size: 1.25rem;
  line-height: 1.3;
}

.invoice-meta {
  display: flex;
  flex-wrap: wrap;
  column-gap: var(--space-3);
  row-gap: var(--space-1);
  margin: var(--space-1) 0 var(--space-3);
  font-size: 0.9375rem;
  color: var(--color-text-muted);
}

.invoice-total {
  margin: 0;
  font-weight: 600;
}

/*
 * Invoice lines are shared by the form (with a quantity stepper) and the
 * detail view (with the quantity as text): name and price on the left,
 * the line total on the right, the stepper between them when present.
 */
.invoice-line-list {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.invoice-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

.invoice-line-text {
  display: flex;
  flex: 1 1 10rem;
  flex-direction: column;
  min-width: 0;
}

.invoice-line-name {
  font-weight: 600;
}

.invoice-line-price {
  font-size: 0.9375rem;
  color: var(--color-text-muted);
}

.invoice-line-total {
  margin-left: auto;
  font-weight: 600;
  white-space: nowrap;
}

.invoice-total-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin: var(--space-4) 0 0;
  padding: var(--space-3) var(--space-4);
  border-top: 2px solid var(--color-border);
  font-size: 1.0625rem;
}

.invoice-total-amount {
  font-size: 1.25rem;
}

.invoice-change-set {
  margin: var(--space-6) 0 0;
  font-size: 0.8125rem;
  color: var(--color-text-muted);
  overflow-wrap: anywhere;
}

/* The invoice form: every control is at least a 44 px target. */
.invoice-form {
  display: flex;
  flex-direction: column;
  max-width: var(--text-measure);
}

.form-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin: 0 0 var(--space-4);
}

.form-label {
  font-size: 0.9375rem;
  font-weight: 600;
}

.select,
.text-input {
  width: 100%;
  min-height: var(--tap-target);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  font: inherit;
  color: var(--color-text);
  background: var(--color-surface);
}

.animal-picker-list {
  display: grid;
  gap: var(--space-2);
  max-height: 22rem;
  margin: 0;
  padding: 0;
  overflow-y: auto;
  list-style: none;
}

.animal-picker-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

.animal-picker-text {
  display: flex;
  flex: 1 1 0;
  flex-direction: column;
  min-width: 0;
}

.animal-picker-name {
  font-weight: 600;
}

.animal-picker-meta {
  font-size: 0.9375rem;
  color: var(--color-text-muted);
}

.animal-picker-empty {
  padding: var(--space-3) 0;
  color: var(--color-text-muted);
}

.animal-picker-hint {
  margin: 0 0 var(--space-2);
  font-size: 0.9375rem;
  color: var(--color-text-muted);
}

.animal-picker-hint:empty {
  display: none;
}

.stepper {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  background: var(--color-surface);
}

.stepper-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--tap-target);
  min-height: var(--tap-target);
  border: 0;
  border-radius: 999px;
  font: inherit;
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--color-accent);
  background: transparent;
  cursor: pointer;
}

.stepper-value {
  min-width: 2rem;
  font-weight: 600;
  text-align: center;
}

.form-error {
  margin: var(--space-4) 0 0;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-error);
  border-radius: var(--radius);
  color: var(--color-text);
  background: var(--color-error-tint);
}

.invoice-form .button[type='submit'] {
  align-self: flex-start;
  margin-top: var(--space-4);
}

/*
 * The animal edit form: the same fields and controls as the invoice form,
 * plus a story field that grows with its text, trait toggle chips and a
 * per-field validation message that appears below its control.
 */
.animal-form {
  display: flex;
  flex-direction: column;
  max-width: var(--text-measure);
}

.textarea {
  min-height: 6rem;
  resize: vertical;
  line-height: 1.6;
  overflow: hidden;
}

.form-fieldset {
  margin: 0 0 var(--space-4);
  padding: 0;
  border: 0;
}

.form-fieldset legend {
  padding: 0;
  margin-bottom: var(--space-1);
}

.trait-toggles {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.chip[aria-pressed='true'] {
  border-color: var(--color-accent);
  background: var(--color-accent);
  color: var(--color-accent-contrast);
}

button.chip {
  font: inherit;
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
}

.field-error {
  margin: 0;
  font-size: 0.9375rem;
  color: var(--color-error);
}

[aria-invalid='true'] {
  border-color: var(--color-error);
}

.form-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-4);
}

/*
 * The version list on the animal detail: one tappable row per version,
 * newest first, the version on screen marked, the tip badged "current".
 */
.version-notice {
  max-width: var(--text-measure);
  margin: 0 0 var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-open);
  border-radius: var(--radius);
  color: var(--color-text);
  background: var(--color-open-tint);
}

.animal-versions {
  margin-top: var(--space-6);
}

.version-list {
  display: grid;
  gap: var(--space-2);
  max-width: var(--text-measure);
  margin: 0;
  padding: 0;
  list-style: none;
}

.version-link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--tap-target);
  padding: var(--space-2) var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  color: inherit;
  text-decoration: none;
}

.version-link[aria-current='page'] {
  border-color: var(--color-accent);
}

.version-text {
  display: flex;
  flex: 1 1 0;
  flex-direction: column;
  min-width: 0;
}

.version-time {
  font-weight: 600;
}

.version-summary {
  font-size: 0.9375rem;
  color: var(--color-text-muted);
}

.version-badge {
  padding: 0 var(--space-2);
  border-radius: 999px;
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.5rem;
  color: var(--color-paid);
  background: var(--color-paid-tint);
  white-space: nowrap;
}

@media (hover: hover) {
  .app-navigation a:hover {
    color: var(--color-accent);
  }

  .button:hover {
    filter: brightness(1.1);
  }

  .stepper-button:hover {
    background: var(--color-accent-tint);
  }

  .chip:not([aria-current='page']):not([aria-pressed='true']):hover {
    border-color: var(--color-accent);
  }

  .version-link:hover {
    border-color: var(--color-accent);
  }

  a.card:hover {
    border-color: var(--color-accent);
  }

  .back-link:hover {
    color: var(--color-accent);
  }
}

@media (min-width: 768px) {
  body {
    grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
    grid-template-rows: auto 1fr;
    grid-template-areas:
      'header header'
      'navigation main';
  }

  .app-header {
    padding: 0 var(--space-6);
  }

  .app-navigation {
    top: var(--header-height);
    bottom: auto;
    align-self: start;
    height: calc(100vh - var(--header-height));
    height: calc(100dvh - var(--header-height));
    padding: var(--space-4) var(--space-3);
    border-top: 0;
    border-right: 1px solid var(--color-border);
  }

  .app-navigation ul {
    flex-direction: column;
    gap: var(--space-1);
  }

  .app-navigation a {
    flex-direction: row;
    justify-content: flex-start;
    gap: var(--space-3);
    min-height: var(--tap-target);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius);
    font-size: 1rem;
  }

  .app-navigation a[aria-current='page'] {
    background: var(--color-accent-tint);
  }

  .app-main {
    padding: var(--space-6) var(--space-8);
  }

  .view-title {
    font-size: 1.75rem;
  }

  .card-list {
    grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
    gap: var(--space-5);
  }

  .card {
    padding: var(--space-5);
  }
}
