/* SAB Portal — A detail page: a box, a pipe, the cards down its side, the note that says
 * something about the data, and the empty state when there is nothing to say.
 *
 * One of the files listed in layers.css; read that first. Every rule below
 * is in the `app` cascade layer, so it beats Pico without needing to be
 * more specific than Pico. Sizes come from tokens.css and nowhere else. */

@layer app {

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

.sab-headline {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 0.75rem var(--sab-gap-wide);
  margin-bottom: var(--sab-gap-loose);
}

/* Beside the small square, the card is about two thirds of the row, and at
 * eleven rem a track that is two facts wide leaves the other half of the card
 * empty — four short facts reading as two, with a hole beside them. The floor
 * is lowered rather than the count fixed, so the row still folds to two on a
 * narrow window instead of squeezing four. */
.sab-detail-top-brief .sab-headline {
  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
}

.sab-fact {
  border-top: 2px solid var(--sab-rule);
  padding-top: var(--sab-gap);
}

.sab-fact dt {
  font-size: var(--sab-text-micro);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--pico-muted-color);
  margin-bottom: 0.15rem;
}

.sab-fact dd {
  margin: 0;
  font-size: var(--sab-text-base);
  line-height: 1.35;
}

.sab-fact .sab-against {
  display: block;
  font-size: var(--sab-text-small);
  color: var(--pico-muted-color);
  margin-top: 0.1rem;
}

/* --- A pipe's two ends, one card each -----------------------------------
 *
 * Two cards side by side, one per end. A card holds a whole box — its name,
 * then what it is doing — so a reader never has to carry a state across the
 * page to the name it belongs to, and the two read straight across for the
 * comparison the page exists to support.
 *
 * The pipe's length is not drawn between them. It belongs to neither box and
 * is stated in the analysis card, where the pipe's other measurements are. */
.sab-pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sab-gap-loose);
}

/* One gap between every line in a card, so the two ends stay in step, and
 * children carry no margin of their own — a component dropped in here cannot
 * bring its own spacing with it. */
.sab-end-card {
  min-width: 0;
  display: grid;
  align-content: start;
  justify-items: start;
  gap: var(--sab-gap);
  padding: var(--sab-gap-loose);
}

.sab-end-card > * {
  margin: 0;
}

/* A note is about the whole end, not one line of it, so it takes the card's
 * width rather than sitting at the start of it like the facts above. */
.sab-end-note {
  justify-self: stretch;
}

.sab-end-card h3 {
  font-size: var(--sab-text-small);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--pico-muted-color);
  margin-bottom: var(--sab-gap);
}

.sab-end-card .sab-end-name {
  font-size: var(--sab-text-lead);
  font-weight: var(--sab-weight-strong);
  display: block;
  margin-bottom: 0.35rem;
}

/* --- Notes: a statement about the data, not a decoration ---------------- */

.sab-note {
  border-left: 3px solid var(--sab-rule);
  padding: 0.4rem 0 0.4rem 0.85rem;
  margin: 0.75rem 0;
  color: var(--pico-muted-color);
  font-size: var(--sab-text-body);
}

.sab-note strong {
  color: var(--pico-color);
}

.sab-note-warn {
  border-left-color: var(--sab-silent);
}

/* --- A card list --------------------------------------------------------
 *
 * The portal's one list that is not a table:
 * `portal/components/card_list.html`, and the only place it is styled.
 *
 * A table when the reader compares a column down — the fleet listings do, and
 * that is what a table is for. A card list when each entry is read on its own:
 * *which box, down which pipes, when this one listens*. Three ruled columns
 * nobody compares are three columns of noise, and a card that carries its own
 * facts still reads at a phone's width, where a table has to be scrolled
 * sideways.
 *
 * The overview's figures in the same material — border, radius, ground and a
 * marked corner — because a card is a card wherever the reader meets one. The
 * measurements are `.sab-kpi`'s, in overview.css, and are followed rather than
 * invented so the two cannot drift apart by a tenth of a rem.
 *
 * As many cards to a row as the page has room for. The floor is wide enough
 * for a pipe's name and its capture time on one line, which is the widest
 * thing a card holds. */
.sab-card-list {
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(21rem, 1fr));
  gap: var(--sab-gap-loose);
}

/* On the list item and not only on the list: Pico marks a list item from the
 * item itself, so a bullet survives `list-style: none` set one level up and
 * sits in the margin beside the card. */
.sab-card-list > li {
  list-style: none;
  margin: 0;
  padding: 0;
}

.sab-card-row {
  display: flex;
  flex-direction: column;
  gap: var(--sab-gap);
  height: 100%;
  margin: 0;
  padding: var(--sab-block);
}

/* A card with a page behind it is a press, anywhere on it — row-link.js — and
 * says so by lifting under the pointer. The name inside it is the link, and is
 * what a reader without the script uses. */
.sab-card-row-link {
  cursor: pointer;
}

.sab-card-row-link:hover {
  border-color: var(--sab-absent);
  background: var(--sab-quiet-bg);
}

/* The name, and the mark in the corner. The same line as a figure's on the
 * overview, read the same way round. */
.sab-card-row-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sab-gap);
}

/* The card's subject, set like the figure it stands in place of: this is a
 * box's name, and naming the box *is* the answer the card gives. */
.sab-card-row-name {
  color: var(--sab-ink);
  font-size: var(--sab-text-title);
  font-weight: var(--sab-weight-strong);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
  /* The name gives up its tail before anything else does: a chamber's name is
   * as long as it is, and it must not push the card wider than its column. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

a.sab-card-row-name {
  text-decoration: none;
}

/* The mark in the corner: the same square, the same quiet ground and the same
 * outline icon as a figure's badge on the overview. Decoration over the name
 * beside it and never instead of it — the card is named in words. */
.sab-card-row-badge {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 1.85rem;
  height: 1.85rem;
  border-radius: var(--sab-radius);
  background: var(--sab-quiet-bg);
  color: var(--pico-muted-color);
}

.sab-card-row-badge svg {
  width: 1rem;
  height: 1rem;
}

/* Why the card is the way it is — a box the unit list does not carry, a box
 * with no coordinates. A sentence, because it is a record somebody can go and
 * correct, and only ever there when there is something to say. */
.sab-card-row-sub {
  margin: 0;
  font-size: var(--sab-text-meta);
  color: var(--pico-muted-color);
}

/* The facts, one per line. Down and not across: two facts side by side in a
 * card this width wrap into each other, and a label that has come away from
 * its value is worse than no label. */
.sab-card-row-facts {
  display: grid;
  gap: var(--sab-gap-tight);
}

.sab-card-fact {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--sab-gap-tight) var(--sab-gap);
  font-size: var(--sab-text-label);
}

/* What the fact is about, and the way into it. Carries the weight because it
 * is the name of a thing — the value beside it is a reading of it. */
.sab-card-fact-label {
  font-weight: var(--sab-weight-medium);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sab-card-fact-value {
  color: var(--pico-muted-color);
}

/* True of this fact rather than of the card — most often that nothing has been
 * measured down this pipe. The commonest case, so it is said quietly. */
.sab-card-fact-note {
  color: var(--sab-absent);
  font-size: var(--sab-text-meta);
  font-style: italic;
}

/* The picture beside a fact, at the size the fact is set in.
 *
 * By position, not by class. Each icon component carries the class of the
 * place it was first written for — a tab strip, a capture-time line — and a
 * card's fact is a third place; sizing what it is handed is what keeps an icon
 * usable in all three without either file learning about the other. */
.sab-card-fact svg {
  width: 0.9rem;
  height: 0.9rem;
  flex: none;
  color: var(--pico-muted-color);
  align-self: center;
}

/* What the card amounts to, on the line every card ends on — the same place
 * the overview puts what its figure is measured against. `margin-top: auto`
 * is what holds it there when one card in a row carries more facts than the
 * next. */
.sab-card-row-tail {
  margin: 0;
  margin-top: auto;
  padding-top: var(--sab-gap);
  border-top: var(--sab-hairline) solid var(--sab-rule);
  color: var(--pico-muted-color);
  font-size: var(--sab-text-meta);
}

/* --- Recordings --------------------------------------------------------- */

/* Every night a box has on disk, as many tiles to a row as the page has room
 * for. The tile itself is one component and is described where it is declared;
 * this is only how many go side by side.
 *
 * The floor is wide enough for the widest thing in a tile — a native audio
 * player, which stops being usable long before it stops fitting: below about
 * twenty rem it is a row of buttons with no track left between them. */
.sab-recordings {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
  gap: var(--sab-gap-loose);
}

/* --- Advanced disclosure ------------------------------------------------ */

/* Native <details>. No JavaScript, no dependency, and it will behave the same
 * in every browser for as long as there are browsers. */
.sab-advanced {
  border-top: var(--sab-hairline) solid var(--sab-rule);
  padding-top: var(--sab-gap-loose);
  margin-top: var(--sab-block-loose);
}

.sab-advanced > summary {
  cursor: pointer;
  font-weight: var(--sab-weight-strong);
  list-style: revert;
}

/* The triangle is the marker; Pico's chevron at the far edge would be a second. */
.sab-advanced > summary::after {
  display: none;
}

.sab-advanced > summary small {
  font-weight: var(--sab-weight-normal);
  color: var(--pico-muted-color);
  margin-left: var(--sab-gap);
}

/* A `.sab-table` turned on its side: rows, cells and labels are the listing's.
 * Only the label width and wrapping are its own. */
.sab-record {
  margin-top: var(--sab-gap-loose);
}

.sab-record th {
  width: 16rem;
  vertical-align: baseline;
}

.sab-record td {
  width: 100%;
  white-space: normal;
}

/* --- Empty states ------------------------------------------------------- */

/* "No data" is not an answer. Every empty state names its own next action. */
.sab-empty {
  border: var(--sab-hairline) dashed var(--sab-rule);
  border-radius: var(--pico-border-radius);
  padding: var(--sab-block-loose);
  text-align: center;
  color: var(--pico-muted-color);
}

.sab-empty strong {


  display: block;
  color: var(--pico-color);
  margin-bottom: 0.35rem;
}
}
