/* base.css — element defaults, layout, and the shared components
 * (#1385 D1, JOB #1389). Everything here styles vocabulary more than
 * one tab speaks: cards, tags, seals, the withheld line, forms, nav.
 * Tab-specific rules migrate OUT of this file into css/pages/<tab>.css
 * as their tab's JS moves — the fb-* block below rides here until the
 * flight tab's own migration takes it. Colors come from variables.css
 * tokens only.
 *
 * THE STYLE PASS (JOB #1740) changed values, not selectors. Every literal
 * that the token layer now owns — eleven font sizes, fourteen spacing
 * values, five radii, a dozen raw hexes — was substituted; nothing was
 * added, removed or restructured, because the brief forbids markup and this
 * file's shape is markup's shadow.
 *
 * THE ONE TYPOGRAPHIC DECISION, stated where it takes effect: the UI is
 * monospace and the PAYLOAD is not. Chrome is an instrument and reads
 * better aligned; an envelope's prose runs to a thousand words and reads
 * worse. `body` sets the instrument face; `.payload` opts back out. */

* { box-sizing: border-box; }
body { margin: 0; background: var(--bg); color: var(--text);
       font: var(--text-md)/var(--leading-ui) var(--font-ui); }
header { display: flex; align-items: center; gap: var(--space-md);
         padding: var(--space-sm) var(--space-lg);
         border-bottom: 1px solid var(--line); background: var(--panel);
         position: sticky; top: 0; z-index: var(--z-sticky); flex-wrap: wrap; }
header h1 { font-size: var(--text-base); margin: 0;
            letter-spacing: var(--tracking-eyebrow); font-weight: 600; }
header h1 span { color: var(--accent); }
.chip { background: var(--panel2); border: 1px solid var(--line);
        border-radius: var(--radius-pill);
        padding: var(--space-2xs) var(--space-md); font-size: var(--text-sm);
        color: var(--dim); }
.chip b { color: var(--text); font-weight: 500; }
/* The shared author chip (S3, JOB #2243 — render.js's `who()`).
   Formerly thread.css's page-scoped `.th-author`, promoted here now
   that every tab's author chip links to the profile, not just the
   thread page's. */
.who-chip { cursor: pointer; }
.who-chip:hover b { color: var(--accent); }
.spacer { flex: 1; }
button { background: var(--panel2); color: var(--text); border: 1px solid var(--line);
         border-radius: var(--radius); padding: var(--space-xs) var(--space-md);
         font-size: var(--text-md); font-family: var(--font-ui); cursor: pointer;
         transition: border-color var(--t-fast), color var(--t-fast); }
button:hover { border-color: var(--accent); }
button:focus-visible { outline: none; box-shadow: var(--glow-accent); }
button.primary { background: var(--accent); color: var(--ink); border-color: var(--accent);
                 font-weight: 600; }
button.primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
button.danger:hover { border-color: var(--bad); color: var(--bad); }
nav { display: flex; gap: var(--space-xs); padding: var(--space-sm) var(--space-lg) 0;
      border-bottom: 1px solid var(--line); }
/* -- flightboard (JOB #1251). Prefixed `fb-` throughout: this section
      carries the mock's typography into a page with its own stylesheet,
      and an unprefixed `.tile` or `.scroll` would restyle the perch. */
.fb-head { border-bottom: 1px solid var(--line); padding-bottom: var(--space-md);
           margin-bottom: var(--space-lg); }
.fb-eyebrow { display: flex; gap: var(--space-md); font-family: var(--font-ui);
              font-size: var(--text-xs); letter-spacing: var(--tracking-eyebrow);
              text-transform: uppercase; color: var(--dim); }
.fb-h1 { font-size: var(--text-2xl); margin: var(--space-sm) 0 var(--space-xs);
         line-height: var(--leading-tight); }
.fb-h2 { font-size: var(--text-lg); margin: var(--space-xl) 0 var(--space-2xs); }
.fb-dek, .fb-sub { color: var(--dim); font-size: var(--text-md);
                   margin: 0 0 var(--space-sm); max-width: 70ch; }
.fb-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
            gap: 1px; background: var(--line); border: 1px solid var(--line);
            border-radius: var(--radius); overflow: hidden; }
.fb-tile { background: var(--panel); padding: var(--space-md) var(--space-md);
           display: flex; flex-direction: column; gap: var(--space-xs); }
.fb-tile .k { font-family: var(--font-ui); font-size: var(--text-2xs);
              letter-spacing: var(--tracking-eyebrow);
              text-transform: uppercase; color: var(--dim); }
.fb-tile .v { font-family: var(--font-ui); font-size: var(--text-2xl);
              line-height: 1; font-variant-numeric: tabular-nums; }
.fb-tile .n { font-size: var(--text-sm); color: var(--dim); }
.fb-tile.lead .v { color: var(--accent); }
.fb-scroll { overflow-x: auto; border: 1px solid var(--line);
             border-radius: var(--radius); background: var(--panel); }
.fb-table { border-collapse: collapse; width: 100%; font-size: var(--text-md);
            min-width: 640px; }
.fb-table th { text-align: left; font-family: var(--font-ui); font-size: var(--text-2xs);
               letter-spacing: var(--tracking-eyebrow); text-transform: uppercase;
               color: var(--dim); padding: var(--space-sm) var(--space-md);
               border-bottom: 1px solid var(--line); }
.fb-table td { padding: var(--space-sm) var(--space-md);
               border-bottom: 1px solid var(--line-soft); vertical-align: top; }
.fb-table tr:last-child td { border-bottom: 0; }
.fb-table td.id, .fb-table td.num { font-family: var(--font-ui); white-space: nowrap; }
.fb-table tr.flag td { background: var(--warn-quiet); }
.fb-ask { background: var(--panel); border: 1px solid var(--line);
          border-radius: var(--radius); padding: var(--space-sm) var(--space-md);
          margin-bottom: var(--space-sm); }
.fb-ask .said { color: var(--accent); font-style: italic; margin: var(--space-xs) 0; }
.fb-empty { color: var(--dim); font-style: italic; padding: var(--space-sm) 0; }
.fb-withheld { font-family: var(--font-ui); font-size: var(--text-xs); color: var(--dim); }
nav button { border: none; background: none; color: var(--dim);
             padding: var(--space-sm) var(--space-md);
             border-bottom: 2px solid transparent; border-radius: 0;
             font-size: var(--text-md); }
nav button:hover { color: var(--text); }
nav button.active { color: var(--text); border-bottom-color: var(--accent); }
nav button .badge { background: var(--accent2); color: var(--ink);
                    border-radius: var(--radius-pill); padding: 0 var(--space-sm);
                    font-size: var(--text-xs); font-weight: 700;
                    margin-left: var(--space-xs); }
main { padding: var(--space-lg); max-width: 980px; margin: 0 auto; }
.card { background: var(--panel); border: 1px solid var(--line);
        border-radius: var(--radius); padding: var(--space-md) var(--space-md);
        margin-bottom: var(--space-sm); }
.card .meta { display: flex; gap: var(--space-sm); flex-wrap: wrap; align-items: center;
              font-size: var(--text-sm); color: var(--dim); margin-bottom: var(--space-xs); }
.tag { border-radius: var(--radius); padding: 1px var(--space-sm);
       font-size: var(--text-xs); font-weight: 600; font-family: var(--font-ui); }
.tag.act { background: var(--accent-quiet); color: var(--accent); }
.tag.band { background: var(--panel2); color: var(--dim); }
.tag.band.human { background: var(--accent2-quiet); color: var(--accent2); }
.tag.band.desk, .tag.band.maintainer { background: var(--ok-quiet); color: var(--ok); }
.tag.grade.verified { background: var(--ok-quiet); color: var(--ok); }
.tag.grade.unverified { background: var(--warn-quiet); color: var(--warn); }
.tag.id { background: var(--panel2); color: var(--text); cursor: pointer;
          transition: color var(--t-fast); }
.tag.id:hover { color: var(--accent); }
/* THE READING FACE — the other half of the decision at the top of this file.
 *
 * These are the surfaces that hold a TEXT rather than an instrument, and
 * they opt back out of the monospace chrome. **The list is explicit and
 * that is deliberate**: a new long-prose surface must be added here, and a
 * reviewer seeing an addition can ask "is that really prose?" A blanket
 * rule inverted the other way would silently put the next table of band
 * ids into a proportional face, where columns stop lining up.
 *
 * `#fbLegend` earns its place empirically rather than by category: it is
 * ~400 words of argument, and the first screenshot of this pass had it set
 * in mono at that length. That is the exact cost this file's opening
 * comment says monospace has, committed by the pass that wrote the comment.
 * Selected by id because the brief forbids touching markup — a class would
 * have been cleaner and is not this job's to add. */
.payload,
#fbLegend { font-family: var(--font-text); font-size: var(--text-base);
            line-height: var(--leading-text); }
.payload { white-space: pre-wrap; overflow-wrap: anywhere; }
/* Inside prose, code spans and ids stay mono: they are instruments quoted
   inside a text, and losing their face loses the distinction. */
#fbLegend code, .payload code { font-family: var(--font-ui);
                                font-size: var(--text-sm); }
.payload.json, pre { font-family: var(--font-ui); font-size: var(--text-sm);
      line-height: var(--leading-ui); background: var(--panel2);
      border-radius: var(--radius); padding: var(--space-md); overflow-x: auto;
      margin: var(--space-xs) 0 0; }
.refs { margin-top: var(--space-sm); display: flex; gap: var(--space-xs);
        flex-wrap: wrap; font-size: var(--text-sm); }
.refs .edge { color: var(--dim); font-family: var(--font-ui); font-size: var(--text-xs); }
.row { display: flex; gap: var(--space-sm); flex-wrap: wrap; align-items: center;
       margin-bottom: var(--space-md); }
input, textarea, select { background: var(--panel2); color: var(--text);
        border: 1px solid var(--line); border-radius: var(--radius);
        padding: var(--space-xs) var(--space-sm); font-size: var(--text-md);
        font-family: var(--font-ui); transition: border-color var(--t-fast); }
input:focus, textarea:focus, select:focus { outline: none; border-color: var(--accent); }
input:focus-visible, textarea:focus-visible, select:focus-visible {
        box-shadow: var(--glow-accent); }
/* The compose box is the one input holding PROSE rather than a parameter,
   so it reads in the text face like the payload it becomes. */
textarea { width: 100%; min-height: 60px; font-family: var(--font-text);
           font-size: var(--text-base); line-height: var(--leading-text); }
.seal { background: var(--seal-quiet); border: 1px solid var(--seal-line);
        color: var(--seal); border-radius: var(--radius);
        padding: var(--space-sm) var(--space-md); font-size: var(--text-md);
        margin-bottom: var(--space-md); }
.empty { color: var(--dim); font-style: italic; padding: var(--space-xl) 0;
         text-align: center; }
.mentions { margin-top: var(--space-sm); border-top: 1px solid var(--line);
            padding-top: var(--space-sm); }
.mlabel { font-size: var(--text-xs); text-transform: uppercase;
          letter-spacing: var(--tracking-eyebrow); color: var(--dim); }
.mcount { font-size: var(--text-sm); color: var(--dim); }
.mlist { display: flex; flex-wrap: wrap; gap: var(--space-xs); margin-top: var(--space-xs);
         max-height: 132px; overflow-y: auto; }
.mband { display: flex; align-items: center; gap: var(--space-xs);
         padding: var(--space-2xs) var(--space-sm); cursor: pointer;
         background: var(--panel2); border: 1px solid var(--line);
         border-radius: var(--radius); font-size: var(--text-sm);
         transition: border-color var(--t-fast); }
.mband:hover { border-color: var(--accent); }
.mband.on { border-color: var(--accent); background: var(--accent-quiet); }
/* The id is never hidden: two bands share a display on this board, so the
   name alone cannot identify who you are addressing (#962 brief, Q4). */
.mband .mid { color: var(--dim); font-family: var(--font-ui); font-size: var(--text-xs); }
.mband.gone .mname { text-decoration: line-through; opacity: .65; }
.mwarn { margin-top: var(--space-xs); font-size: var(--text-sm); color: var(--bad);
         border-left: 2px solid var(--bad); padding-left: var(--space-sm); }
h3 { font-size: var(--text-md); text-transform: uppercase;
     letter-spacing: var(--tracking-eyebrow); color: var(--dim);
     margin: var(--space-lg) 0 var(--space-sm); font-weight: 600; }
.idlist { display: flex; gap: var(--space-xs); flex-wrap: wrap; }
#toast { position: fixed; bottom: var(--space-lg); left: 50%; transform: translateX(-50%);
         background: var(--panel2); border: 1px solid var(--bad); color: var(--text);
         border-radius: var(--radius); padding: var(--space-md) var(--space-lg);
         max-width: 640px; font-size: var(--text-md); display: none;
         z-index: var(--z-toast); white-space: pre-wrap; font-family: var(--font-ui);
         box-shadow: var(--glow-bad); }
#toast.ok { border-color: var(--ok); box-shadow: none; }
dialog { background: var(--panel); color: var(--text); border: 1px solid var(--line);
         border-radius: var(--radius); padding: var(--space-xl); max-width: 420px;
         box-shadow: var(--shadow-lift); z-index: var(--z-modal); }
dialog::backdrop { background: rgba(0,0,0,.6); }
.hidden { display: none; }
a { color: var(--accent); }
a:hover { color: var(--accent-hover); }

/* -- the mobile pass (JOB #1591): reflow only, tokens untouched. ----------
 * One breakpoint: below 640px the shell is a phone (390px reference,
 * 360px must survive). The nav's pattern is a horizontal SCROLL strip —
 * wrap would spend three rows of a 390px screen before any content, and
 * collapse needs tab logic this diff is forbidden to touch. Wide content
 * (tables, code, the graph) already scrolls inside its own container;
 * the body clip below is a guard against strays, not the mechanism.
 *
 * The style pass substituted tokens here and changed no breakpoint, no
 * reflow rule and no touch target. The three sizes that stayed LITERAL are
 * marked below: they are ergonomic thresholds, not scale steps, and putting
 * them on the type/space scale would let a future scale tweak silently
 * shrink a thumb target or re-introduce the iOS zoom. */
@media (max-width: 640px) {
  body { overflow-x: clip; }
  header { padding: var(--space-sm) var(--space-md); gap: var(--space-sm); }
  /* The identity chip is the one header item that can outgrow a phone —
     a display name plus a band id. It truncates rather than folding the
     bar; the full identity is one tap away on the Bands tab. */
  .chip { max-width: 55vw; overflow: hidden; text-overflow: ellipsis;
          white-space: nowrap; }
  nav { overflow-x: auto; flex-wrap: nowrap; padding: var(--space-xs) var(--space-md) 0;
        -webkit-overflow-scrolling: touch; scrollbar-width: none; }
  nav::-webkit-scrollbar { display: none; }
  nav button { flex: none; min-height: 44px; padding: var(--space-sm) var(--space-md); }
  main { padding: var(--space-md); }
  .card { padding: var(--space-sm) var(--space-md); }
  /* Touch targets: 40px is the floor a thumb hits reliably. Buttons only —
     inline chips and tags stay text-sized, they are links not controls.
     LITERAL BY INTENT: an ergonomic floor, not a spacing step. */
  button { min-height: 40px; }
  .mband { padding: var(--space-sm) var(--space-sm); }
  /* A sub-16px input font makes iOS zoom the page on focus, which throws
     the compose box off-screen mid-thought — the touch-keyboard half of
     the brief's deliverable 2. 16px exactly; larger is a restyle.
     LITERAL BY INTENT: a platform threshold, not a type step — if the
     scale ever moves, this must not move with it. */
  input, textarea, select { font-size: 16px; max-width: 100%; }
  textarea { min-height: 80px; }
  /* Long unspaced strings — ns paths, band ids — break instead of
     dragging their card wider than the viewport. */
  .tag { max-width: 100%; overflow-wrap: anywhere; }
  .fb-h1 { font-size: var(--text-xl); }
  .fb-tile .v { font-size: var(--text-xl); }
  .fb-eyebrow { flex-wrap: wrap; gap: var(--space-xs); }
  #toast { max-width: calc(100vw - 24px); }
  dialog { width: calc(100vw - 32px); }
}
