@layer components {
  /* The operator's screens.
   *
   * **This one is allowed its own scale, and that is a change of mind.**
   * The rule everywhere else in this directory is that a component uses the
   * product's tokens and never invents values, because an internal page
   * quietly running a second design system is how tokens stop meaning
   * anything. That argument was made here too, and it was wrong about this
   * page: the product's scale is 19px body and 44px rows, built for a studio
   * with one task list open all day, and this is forty rows of numbers being
   * compared down a column by one person once a morning. Dressing a console in
   * a task app's clothes made it loud and hard to read.
   *
   * So the type and the spacing below are the admin's own, declared once on
   * `.admin` and used by everything inside it. **The colours are not** — every
   * one is still a product token, so light and dark keep working through
   * `light-dark()` with nothing here to maintain. That is the line: a console
   * may have its own rhythm; it does not get its own palette.
   *
   * The floor that survives: nothing smaller than 12px, and anything you press
   * is at least 40px. A table row is denser than that because the row is not
   * the target — the link inside it is. */

  .admin {
    /* Type. A console reads at 14, labels at 12, one size above for the page
       title. Fixed rather than clamped: this page has one width that matters
       and it is a desk. */
    --a-text: 0.875rem;
    --a-text-sm: 0.8125rem;
    --a-text-xs: 0.75rem;
    --a-title: 1.375rem;
    --a-heading: 1rem;
    --a-figure: 1.75rem;

    /* Space, on a 4px rhythm. */
    --a-1: 0.25rem;
    --a-2: 0.5rem;
    --a-3: 0.75rem;
    --a-4: 1rem;
    --a-6: 1.5rem;
    --a-8: 2rem;

    --a-radius: 0.5rem;
    --a-radius-sm: 0.3125rem;

    /* Anything you press. Below the product's 44px because this is a pointer
       surface, above the 36px a dense console would take because it is still
       sometimes opened on a phone. */
    --a-control: 2.5rem;

    background: var(--surface-sunk);
    color: var(--ink);
    font-size: var(--a-text);
    line-height: 1.45;
  }

  .admin :is(h1, h2, h3) { line-height: 1.25; }

  /* ---- The shell -------------------------------------------------------
     A rail and a column. Grid rather than flex so the content track can carry
     `minmax(0, 1fr)`: without that floor one wide table grows the track and the
     whole page slides sideways under the reader. */

  .admin__shell {
    display: grid;
    grid-template-columns: 14rem minmax(0, 1fr);
    min-height: 100dvh;
  }

  .admin__side {
    display: flex;
    flex-direction: column;
    gap: var(--a-6);
    padding: var(--a-4) var(--a-3);
    background: var(--surface);
    border-inline-end: 1px solid var(--line);

    /* The one sticky thing on this side of the product. A console is a place
       you move around in, not a page you read to the bottom, and navigation
       that scrolls away is navigation you scroll back up to reach. */
    position: sticky;
    top: 0;
    align-self: start;
    max-height: 100dvh;
    overflow-y: auto;
  }

  .admin__brand {
    display: flex;
    align-items: center;
    gap: var(--a-2);
    flex-wrap: wrap;
    padding-inline: var(--a-2);
  }

  .admin__mark {
    font-size: var(--a-heading);
    font-weight: var(--weight-heavy);
    letter-spacing: var(--tracking-tight);
  }

  /* Which database this is, and the only coloured thing in the rail.
     Production and beta look identical from a browser and every screen behind
     this is somebody else's data — so it must be legible at a glance, and must
     not be the first thing the eye lands on. */
  .admin__badge {
    padding: 0.05rem var(--a-2);
    border-radius: var(--radius-pill);
    font-family: var(--font-mono);
    font-size: var(--a-text-xs);
    letter-spacing: var(--tracking-label);
    text-transform: uppercase;
    background: var(--surface-sunk);
    color: var(--ink-faint);
  }

  .admin__badge--production { background: var(--danger-sunk); color: var(--danger); }
  .admin__badge--beta { background: var(--accent-sunk); color: var(--accent); }

  .admin__nav { display: flex; flex-direction: column; gap: 1px; }

  .admin__link {
    display: flex;
    align-items: center;
    gap: var(--a-2);
    min-height: var(--a-control);
    padding-inline: var(--a-2);
    border-radius: var(--a-radius-sm);
    font-size: var(--a-text);
    font-weight: var(--weight-medium);
    color: var(--ink-muted);
    text-decoration: none;
  }

  .admin__link:hover { background: var(--surface-hover); color: var(--ink); }
  .admin__link--on { background: var(--accent-sunk); color: var(--accent); }

  .admin__icon { inline-size: 17px; block-size: 17px; flex: 0 0 auto; }

  .admin__who {
    margin-block-start: auto;
    padding: var(--a-2);
    font-size: var(--a-text-xs);
    color: var(--ink-faint);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .admin__main {
    display: flex;
    flex-direction: column;
    gap: var(--a-6);
    min-width: 0;
    max-width: 74rem;
    padding: var(--a-6) var(--a-6) var(--a-8);
  }

  /* ---- The page header -------------------------------------------------
     One shape on every screen: what this is, a sentence saying what it is for,
     and whatever acts on it. */

  .admin-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--a-3);
  }

  .admin-head__titles { display: grid; gap: var(--a-1); min-width: 0; }

  .admin-head__titles h1 {
    margin: 0;
    font-size: var(--a-title);
    letter-spacing: var(--tracking-tight);
  }

  .admin-head__note {
    margin: 0;
    max-width: 46rem;
    font-size: var(--a-text);
    color: var(--ink-muted);
  }

  .admin-head__tools { display: flex; align-items: center; gap: var(--a-2); flex-wrap: wrap; }

  .admin-back a { font-size: var(--a-text-sm); }

  /* ---- The status line -------------------------------------------------
     Is anything broken. One row across the top of the overview, and it was two
     large cards carrying a title, a sentence, four counts, a footnote and a
     console incantation each — a great deal of furniture for a question whose
     answer is almost always "no".

     So: a dot, a sentence, and the numbers on the right for the times the
     answer is "yes". Green or red and nothing between, because a queue is
     draining or it is not, and an operator who has learnt two colours will not
     learn five. */

  .admin-statuses { display: grid; gap: var(--a-2); }

  .admin-status {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--a-2) var(--a-4);
    padding: var(--a-3) var(--a-4);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--a-radius);
  }

  .admin-status__dot {
    inline-size: 0.5rem;
    block-size: 0.5rem;
    flex: 0 0 auto;
    border-radius: var(--radius-pill);
    background: var(--go);
  }

  .admin-status__what { flex: 1 1 20rem; min-width: 0; margin: 0; }
  .admin-status__what strong { font-weight: var(--weight-bold); }

  /* The numbers, on the right, in the mono face because they are read across
     rather than down. Each is a value and the word for it, and the word is
     English rather than Solid Queue's vocabulary — "waiting" is something an
     operator can act on, "enqueued" is something they have to look up. */
  .admin-status__figures {
    display: flex;
    flex: 0 0 auto;
    /* Pushed to the far edge rather than following the sentence. When the
       sentence wraps, `flex: 1 1 20rem` on it stops short of the right margin
       and the numbers end up floating in the middle of the row. */
    margin-inline-start: auto;
    gap: var(--a-4);
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--a-text-sm);
    color: var(--ink-muted);
  }

  .admin-status__figures b {
    font-family: var(--font-mono);
    font-weight: var(--weight-bold);
    color: var(--ink);
  }

  .admin-status--bad { border-color: var(--danger); background: var(--danger-sunk); }
  .admin-status--bad .admin-status__dot { background: var(--danger); }
  .admin-status--bad .admin-status__what { color: var(--danger); }
  .admin-status--bad .admin-status__figures b { color: var(--danger); }

  /* ---- Figures ---------------------------------------------------------
     A grid with a minimum rather than a flex wrap, so four tiles are four equal
     columns and never three-and-a-stranded-one. */

  .admin-figures {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
    gap: var(--a-3);
    list-style: none;
    margin: 0;
    padding: 0;
  }

  .admin-figure {
    display: grid;
    gap: var(--a-1);
    padding: var(--a-3) var(--a-4);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--a-radius);
  }

  .admin-figure__value {
    font-family: var(--font-mono);
    font-size: var(--a-figure);
    font-weight: var(--weight-bold);
    line-height: 1;
    letter-spacing: var(--tracking-tight);
    font-variant-numeric: tabular-nums;
  }

  .admin-figure__label { font-size: var(--a-text); font-weight: var(--weight-medium); }
  .admin-figure__note { font-size: var(--a-text-xs); color: var(--ink-faint); }
  .admin-figure__note:empty { display: none; }

  /* ---- Two columns ------------------------------------------------------
     Two cards side by side on a desk and stacked on a phone. The only place on
     this side of the product where two things genuinely belong beside each
     other rather than under one another.

     `min-width: 0` on the children is not tidying: a grid item defaults to
     `min-width: auto`, so one long unbroken string widens its track and slides
     the whole page sideways. The scroll then belongs to whatever inside it
     asked for one. */

  .admin-split {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
    gap: var(--a-6);
    align-items: start;
  }

  .admin-split > * { min-width: 0; }

  /* ---- A card ----------------------------------------------------------
     What a section sits in. Its heading is sentence case at reading size, not a
     tiny uppercase label — six of those down a page is six things shouting at
     the same volume as the data. */

  .admin-card {
    display: flex;
    flex-direction: column;
    min-width: 0;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--a-radius);
    overflow: hidden;
  }

  .admin-card__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--a-3);
    padding: var(--a-3) var(--a-4);
    border-bottom: 1px solid var(--line);
  }

  .admin-card__head h2 {
    margin: 0;
    font-size: var(--a-heading);
    font-weight: var(--weight-bold);
  }

  .admin-card__aside { font-size: var(--a-text-sm); color: var(--ink-faint); }
  .admin-card__body { padding: var(--a-4); }

  /* A card whose whole body is a table or a list has no padding of its own —
     the rows carry it, and the rules have to reach the card's edges. */
  .admin-card--flush .admin-card__body { padding: 0; }
  .admin-card--flush .admin-table { border: 0; border-radius: 0; }

  /* ---- Tables ----------------------------------------------------------
     The scroll belongs to the table, never to the page. */

  .admin-table__scroll { overflow-x: auto; }

  .admin-table {
    width: 100%;
    border-collapse: collapse;
    background: var(--surface);
  }

  .admin-table th,
  .admin-table td {
    padding: var(--a-3) var(--a-4);
    text-align: left;
    vertical-align: middle;
    font-size: var(--a-text);
    white-space: nowrap;
  }

  .admin-table th {
    padding-block: var(--a-2);
    font-size: var(--a-text-xs);
    font-weight: var(--weight-bold);
    letter-spacing: var(--tracking-label);
    text-transform: uppercase;
    color: var(--ink-faint);
    background: var(--surface-sunk);
    border-bottom: 1px solid var(--line);

    /* The heading stays while the rows move. A hundred customers is a real
       scroll, and a column of numbers with no heading in sight is a column
       nobody can read. */
    position: sticky;
    top: 0;
    z-index: 1;
  }

  .admin-table tbody tr:hover { background: var(--surface-hover); }
  .admin-table tbody td { border-top: 1px solid var(--line); }
  .admin-table tbody tr:first-child td { border-top: 0; }

  .admin-table__quiet { color: var(--ink-muted); }

  /* Numbers compared down a column line up on their right edge or they are not
     being compared. Qualified by the element because `.admin-table th` is a
     class *and* a type, so a bare class would lose to it and the column would
     stay ragged with nothing looking broken. */
  .admin-table th.admin-table__number,
  .admin-table td.admin-table__number {
    text-align: right;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
  }

  /* A sortable heading. The whole label is the control, and the arrow appears
     only on the column actually in use — an arrow on every heading is six
     arrows saying nothing. */
  .admin-sort {
    display: inline-flex;
    align-items: center;
    gap: var(--a-1);
    color: inherit;
    text-decoration: none;
    font: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
  }

  .admin-sort:hover { color: var(--ink); }
  .admin-sort--on { color: var(--accent); }
  .admin-table__number .admin-sort { flex-direction: row-reverse; }

  /* ---- Lists -----------------------------------------------------------
     Where the thing on the row is an event rather than a set of columns. */

  .admin-list { list-style: none; margin: 0; padding: 0; }

  .admin-row {
    display: flex;
    align-items: baseline;
    gap: var(--a-3);
    padding: var(--a-3) var(--a-4);
    font-size: var(--a-text);
  }

  .admin-row + .admin-row { border-top: 1px solid var(--line); }

  .admin-row__when {
    flex: 0 0 auto;
    min-width: 7.5rem;
    font-family: var(--font-mono);
    font-size: var(--a-text-xs);
    color: var(--ink-faint);
  }

  .admin-row__what { flex: 1 1 12rem; min-width: 0; }
  .admin-row__note { color: var(--ink-muted); }

  /* Pushed to the far edge rather than following the text: a column of tags
     that do not line up is a column nobody reads down, which is the only reason
     to have one. */
  .admin-row__tag,
  .admin-row > .admin-tag { margin-inline-start: auto; }

  /* ---- A person in a row -----------------------------------------------
     A face, a name, and an address under it. The face is the product's own
     avatar because an operator scanning for the person in a support email
     recognises the picture before the spelling of the address. */

  .admin-person { display: flex; align-items: center; gap: var(--a-2); min-width: 0; }
  .admin-person__names { display: grid; min-width: 0; }

  /* The underline has to come off the anchor rather than be cancelled on the
     child: `text-decoration` is drawn by the element that declares it and
     propagates to every descendant, and a descendant cannot switch one off. */
  a.admin-person,
  a.admin-person__names { text-decoration: none; color: inherit; }

  .admin-person__name { font-weight: var(--weight-medium); color: var(--accent); }

  a.admin-person:hover .admin-person__name,
  a.admin-person__names:hover .admin-person__name { text-decoration: underline; }

  .admin-person__email {
    font-size: var(--a-text-xs);
    color: var(--ink-faint);
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* ---- Facts ------------------------------------------------------------
     A detail page's header block: label above value. 11rem and not less — the
     longest label here is "Notification email", and below that it wraps, its
     value drops with it, and the row of values stops lining up, which is the
     one thing a row of facts has to do. */

  .admin-facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: var(--a-4);
    margin: 0;
  }

  .admin-fact { display: grid; gap: var(--a-1); min-width: 0; }

  .admin-fact__label {
    font-size: var(--a-text-xs);
    letter-spacing: var(--tracking-label);
    text-transform: uppercase;
    color: var(--ink-faint);
  }

  .admin-fact__value { margin: 0; overflow-wrap: anywhere; }

  /* ---- Counts ----------------------------------------------------------
     A breakdown, where the figures are a headline. One panel with the counts
     running along it rather than a card each — six cards holding one digit
     makes the panel the thing you see and the number the detail, which is
     backwards. */

  .admin-counts {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--a-2) var(--a-6);
    list-style: none;
    margin: 0;
    padding: 0;
  }

  .admin-count { display: flex; align-items: baseline; gap: var(--a-2); }

  .admin-count__value {
    font-family: var(--font-mono);
    font-size: var(--a-heading);
    font-weight: var(--weight-bold);
    font-variant-numeric: tabular-nums;
  }

  .admin-count__label { color: var(--ink-muted); }

  /* ---- Tags ------------------------------------------------------------
     Roles, plans, states. One shape, three tones, and no more — the moment a
     fourth colour appears nobody reads any of them. */

  .admin-tag {
    display: inline-flex;
    align-items: center;
    padding: 0.05rem var(--a-2);
    border-radius: var(--radius-pill);
    font-size: var(--a-text-xs);
    font-weight: var(--weight-medium);
    background: var(--surface-sunk);
    color: var(--ink-muted);
    white-space: nowrap;
  }

  .admin-tag--strong { background: var(--accent-sunk); color: var(--accent); }
  .admin-tag--warn { background: var(--warn-sunk); color: var(--warn); }

  /* ---- Small parts ----------------------------------------------------- */

  .admin-slug {
    font-family: var(--font-mono);
    font-size: var(--a-text-xs);
    color: var(--ink-faint);
  }

  .admin-slug--large { font-size: var(--a-text-sm); }

  /* "never" is a finding, not a missing value, and it is the reason to read
     that column at all. */
  .admin-never { color: var(--warn); }

  .admin-empty {
    margin: 0;
    padding: var(--a-6) var(--a-4);
    color: var(--ink-muted);
    text-align: center;
  }

  .admin-search { display: flex; gap: var(--a-2); }

  .admin-search__field {
    min-height: var(--a-control);
    min-inline-size: 13rem;
    padding-inline: var(--a-3);
    border: 1px solid var(--line);
    border-radius: var(--a-radius-sm);
    background: var(--surface);
    color: var(--ink);
    font: inherit;
  }

  .admin-search__field:focus-visible { outline: var(--focus-ring); outline-offset: 1px; }

  /* The product's button at the console's size. Borrowed rather than redrawn —
     the palette line holds even where the scale does not. */
  .admin .button { min-height: var(--a-control); font-size: var(--a-text); }

  /* ---- Writing an entry -------------------------------------------------
     The one part of /admin that is a form rather than a report. It
     borrows the product's card, field and button wholesale — the point of
     defining those once is that a screen like this needs no design of
     its own — and adds only what says which panel does what.

     These screens keep the product's reading measure, because everything in
     them is a sentence somebody is writing rather than a number being
     compared. */

  .admin-head code, .admin-publish code {
    font-family: var(--font-mono);
    font-size: 0.9em;
  }

  .admin-panel { max-width: var(--measure); }

  /* Whether anybody can see this. A dot and a word rather than a sentence in
     faint type, because it is the first question an operator opening this
     screen has and it should be answerable without reading.

     Named `state` while the machine panels are named `health`: the two were
     both called state for one commit, and the later rule won on source order
     and drew this pill as a full-width grid block on a page nobody had
     opened. */
  .admin-state {
    display: inline-flex;
    align-items: center;
    gap: var(--a-2);
    padding: 0.15rem var(--a-2);
    border-radius: var(--radius-pill);
    font-size: var(--a-text-xs);
    font-weight: var(--weight-medium);
    white-space: nowrap;
  }

  .admin-state__dot {
    inline-size: 0.5rem;
    block-size: 0.5rem;
    border-radius: var(--radius-pill);
    background: currentcolor;
  }

  /* Ochre for not settled yet and green for live, which is what those two
     colours already mean everywhere else in the product. */
  .admin-state--draft { background: var(--warn-sunk); color: var(--warn); }
  .admin-state--live  { background: var(--go-sunk);   color: var(--go); }

  .admin-publish h2 { font-size: var(--a-heading); }
  .admin-publish__note { color: var(--ink-muted); max-width: var(--measure); }

  /* Deleting is neither of the two panels above and does not belong in either.
     Set apart at the bottom with room around it, which is the whole of its
     design: distance is what stops a permanent action being pressed on the way
     past something reversible. */
  .admin-danger { padding-top: var(--a-8); }
  .admin-danger h3 { font-size: var(--a-text); }

  /* The picture already on an entry, at the shape the changelog will draw it.
     A filename does not answer "is this the right screenshot". */
  .admin-thumb {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--a-2);
    max-width: var(--measure);
  }

  .admin-thumb__image {
    display: block;
    width: 100%;
    height: auto;
    border-radius: var(--a-radius);
    background: var(--surface-sunk);
  }

  /* Trix, when it is a field in a form rather than the writing surface of a
     task. notes.css draws the editor as a page you write on — no border, no
     paper, pulled into the margin — which is right on the task detail and
     wrong inside a card on a form. */
  .admin trix-editor.textarea { margin-inline: 0; }

  /* ---- The narrow layout ------------------------------------------------
     The rail lies down and becomes a bar. Not a drawer and not a hamburger:
     five links fit across a phone at this size, and a console nobody can
     navigate without a tap is worse than one that wraps. */

  @media (max-width: 60rem) {
    .admin__shell { grid-template-columns: minmax(0, 1fr); }

    .admin__side {
      position: static;
      max-height: none;
      flex-direction: row;
      align-items: center;
      flex-wrap: wrap;
      gap: var(--a-3);
      border-inline-end: 0;
      border-block-end: 1px solid var(--line);
    }

    .admin__nav { flex-direction: row; flex-wrap: wrap; flex: 1 1 auto; gap: var(--a-1); }

    /* The address is the first thing to go when there is no room: it is a fact
       to check occasionally, and the deployment badge beside the name is the
       one that must never be missed. */
    .admin__who { display: none; }
  }

  @media (max-width: 40rem) {
    .admin__main { padding-inline: var(--a-4); }
    .admin__side { padding-inline: var(--a-4); }
    .admin-row__when { min-width: 100%; }
  }
}
