/* The app shell: brand, topbar, navigation rail and the view area. */

/* The shell is exactly one viewport tall and never scrolls itself. Scrolling belongs to
   `.main`, or — for a view that opts into `view--fill` — to that view's data panel alone,
   so the page never stacks a document scrollbar behind a panel scrollbar. */
.shell {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr);
  grid-template-areas: "brand top" "rail main";
  height: 100dvh;
  overflow: hidden;
}

.brand {
  grid-area: brand;
  display: flex; align-items: center; gap: .625rem;
  padding: 0 1rem;
  height: 56px;
  border-bottom: 1px solid var(--line);
  border-right: 1px solid var(--line);
  background: var(--surface);
}
.brand__mark {
  display: grid; place-items: center;
  width: 28px; height: 28px; flex: none;
  border-radius: 8px;
  background: var(--accent); color: var(--accent-fg);
  font: 700 12px/1 var(--sans); letter-spacing: .02em;
}
.brand__name { font-weight: 640; letter-spacing: -.01em; }
.brand__sub {
  color: var(--fg-faint);
  font-size: .75rem; letter-spacing: .06em; text-transform: uppercase;
}

.topbar {
  grid-area: top;
  display: flex; align-items: center; gap: .5rem;
  padding: 0 1rem 0 1.25rem;
  height: 56px;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}
.topbar__spacer { flex: 1 1 auto; }

.rail {
  grid-area: rail;
  display: flex; flex-direction: column; gap: .125rem;
  padding: .75rem .625rem;
  border-right: 1px solid var(--line);
  background: var(--surface);
}
.rail__group {
  margin: 1rem .5rem .25rem;
  color: var(--fg-faint);
  font-size: .6875rem; letter-spacing: .08em; text-transform: uppercase;
}
.rail__link {
  display: flex; align-items: center; gap: .625rem;
  padding: .5rem .625rem;
  border-radius: var(--radius-s);
  color: var(--fg-muted); text-decoration: none;
  font-size: .875rem; font-weight: 500;
  transition: background-color .12s ease, color .12s ease;
}
.rail__link:hover { background: var(--surface-sunk); color: var(--fg); }
.rail__link[aria-current="page"] { background: var(--accent-soft); color: var(--fg); font-weight: 600; }
.rail__link svg { flex: none; width: 17px; height: 17px; opacity: .9; }
.rail__badge { margin-left: auto; }
.rail__foot {
  margin-top: auto;
  padding: .75rem .625rem 0;
  border-top: 1px solid var(--line);
  color: var(--fg-faint); font-size: .75rem;
}
.rail__credit { margin-top: .5rem; }
.rail__credit a { color: inherit; text-decoration-color: var(--line); }
.rail__credit a:hover { color: var(--accent); }

/* A flex column of definite height: a filling view then resolves against real leftover
   space instead of a percentage, which needs no `:has()` and cannot round the wrong way. */
.main {
  grid-area: main;
  display: flex; flex-direction: column;
  min-width: 0; min-height: 0;
  overflow: auto;
  padding: clamp(1rem, .6rem + 1.2vw, 1.75rem);
}

.view { display: flow-root; max-width: 1180px; }
.view[hidden] { display: none; }

/* Data views fill the viewport instead of growing the page: the head keeps its natural
   height and the last panel absorbs the remainder and scrolls internally.

   They also drop the reading width. The cap above exists so prose and forms do not stretch
   into unreadable lines; a table of controllers has the opposite need, and honouring the cap
   there made the actions column scroll sideways while several hundred pixels sat unused
   beside it. */
.view--fill {
  display: flex; flex-direction: column;
  flex: 1 1 auto; min-height: 0;
  max-width: none;
}
.view--fill > .view__head { flex: none; }

/* The filling card is marked explicitly rather than matched by position: these views end
   with a collapsed raw-payload <details>, so a `:last-child` rule silently matches nothing
   and the panel falls back to its fixed dvh cap. */
.card--fill { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
/* Heads and toolbars keep their intrinsic height; only the scrollable region absorbs the
   remainder, so the panel is the single scroll surface on the page. */
.card--fill > * { flex: none; }

/* The floor belongs on the scrolling region, not the card: put it on the card and the head
   and toolbar consume it first, leaving a table a couple of rows tall on a 720p window.
   When the floor wins, `.main` scrolls — a short scroll beats an unusable panel. */
.card--fill > .table-wrap,
.card--fill > .log,
.card--fill > .feed,
.card--fill > .card__body--flush {
  flex: 1 1 auto; min-height: min(13rem, 30dvh); max-height: none;
}
.card--fill > .card__body--flush { display: flex; flex-direction: column; }
.card--fill > .card__body--flush > .log { flex: 1 1 auto; min-height: 0; max-height: none; }

.view__head { margin-bottom: 1.25rem; }
.view__head--compact { display: flex; align-items: center; gap: .5rem; }
.view__head--compact h1 { margin-right: auto; }

/* Short windows: the explanatory paragraph is worth less than rows of data, so tighten it
   rather than let it push the panel down to its floor. */
@media (max-height: 820px) {
  .view--fill > .view__head { margin-bottom: .75rem; }
  .view--fill > .view__head p {
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
    overflow: hidden;
  }
}
.view__head p {
  margin-top: .375rem;
  color: var(--fg-muted);
  font-size: .875rem;
  max-width: 68ch;
}

@media (max-width: 860px) {
  /* Below the rail breakpoint the shell stacks, so a fixed viewport height would leave the
     data panel almost nothing. Hand scrolling back to the document, which is what a narrow
     screen expects anyway. */
  .shell {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "brand" "top" "rail" "main";
    height: auto; min-height: 100dvh; overflow: visible;
  }
  .main { display: block; overflow: visible; }
  .view--fill { display: flow-root; }
  .card--fill { display: block; min-height: 0; }
  .card--fill > .table-wrap { max-height: 62dvh; }
  .card--fill > .card__body--flush { display: block; }
  .card--fill > .card__body--flush > .log,
  .card--fill > .log { max-height: 46dvh; }
  .brand, .topbar { border-right: 0; }
  /* The topbar is a single non-wrapping row at desktop widths; below the breakpoint its
     buttons no longer fit and would push the whole document sideways. */
  .topbar {
    height: auto; min-height: 56px;
    flex-wrap: wrap;
    padding: .5rem 1rem;
  }
  .topbar__spacer { display: none; }
  .rail {
    flex-direction: row; overflow-x: auto; gap: .25rem;
    padding: .5rem;
    border-right: 0; border-bottom: 1px solid var(--line);
    scrollbar-width: thin;
  }
  .rail__group, .rail__foot { display: none; }
  .rail__link { white-space: nowrap; }
}
