/* ══ primitives ══════════════════════════════════════════════════════════
 * The five or six objects every screen is built out of: the slab, the button,
 * the chip, the badge, the small capsule action, and the grid they sit in.
 * Nothing in here knows what tab it is on.
 */

/* ── the slab ───────────────────────────────────────────────────────── */
/* Two pixels of border rather than one is most of what separates this look
   from the flat one it replaced: at 1px a card is an outline, at 2px it is an
   edge. */
.card { background: var(--panel-2); border: 2px solid var(--border); border-radius: var(--r-lg); }
/* A card that belongs to one of the systems in `tokens.css`. Add the class and
   the slab picks up that family's fill and rule - a rest card is green, a wage
   card is amber, the mixing bench is purple - without any screen inventing its
   own colors. This is the whole mechanism by which "what is this card about?"
   is answerable before it is read. */
.card.tint-ok    { background: var(--tint-ok);    border-color: var(--tint-ok-line); }
.card.tint-gold  { background: var(--tint-gold);  border-color: var(--tint-gold-line); }
.card.tint-cool  { background: var(--tint-cool);  border-color: var(--tint-cool-line); }
.card.tint-magic { background: var(--tint-magic); border-color: var(--tint-magic-line); }
.card.tint-err   { background: var(--tint-err);   border-color: var(--tint-err-line); }
/* Nothing here yet - the shape of a card rather than a card. A filled slab is
   what a *loaded* card looks like, so an empty state drawn as one reads as
   content that arrived wrong; an outline reads as the space something will
   occupy, which is what "no requests right now" actually means. Every "nothing
   here yet" in Orbis comes out of `kit::card::cards`, so this is one rule. */
.card.hollow { background: transparent; border-style: dashed;
  border-color: var(--border-soft); }

/* ── utilities ──────────────────────────────────────────────────────── */
.pad { padding: 16px; }
.muted { color: var(--muted); }
.fine { font-size: 12.5px; color: var(--muted); line-height: 1.45; font-weight: 600; }
.row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.col { display: flex; flex-direction: column; gap: 8px; }
.logo { font-size: 44px; color: var(--accent); }
.logo.glow { text-shadow: 0 0 26px rgba(75, 123, 236, .55); }

/* ── the pressable thing ──────────────────────────────────────────────
   Every button in Orbis stands on a hard, blurless drop and travels down into
   it when pressed. The drop is a variable so a colored button only has to
   name its own floor; the travel is the same everywhere, which is what makes
   the whole app feel like one object rather than a page of controls. */
button { font: inherit; font-family: var(--font); cursor: pointer;
  border-radius: var(--r-md);
  border: 1.5px solid var(--border-hi); background: var(--panel-3); color: var(--text);
  padding: 9px 16px; font-weight: 700;
  transition: background .15s, border-color .15s, color .15s,
              transform .12s, box-shadow .12s;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
/* Unavailable, not broken: a locked button is quiet, flat on the table, never
   red. Losing the drop is the clearest possible "this does nothing". */
button:disabled { background: var(--panel); border-color: var(--border);
  color: var(--muted-2); cursor: not-allowed; box-shadow: none; transform: none; }

/* The thing a card is *for*. Blue by default; the modifiers below only swap
   which floor it stands on, so a green "Rest" and a gold "Sell" are the same
   object in a different system. */
button.primary { background: var(--accent); border-color: var(--accent);
  color: var(--on-accent); font-weight: 800;
  box-shadow: 0 var(--lift) 0 var(--accent-deep); }
button.primary.good { background: var(--ok-btn); border-color: var(--ok-btn);
  box-shadow: 0 var(--lift) 0 var(--ok-deep); }
button.primary.money { background: var(--gold-btn); border-color: var(--gold-btn);
  box-shadow: 0 var(--lift) 0 var(--gold-deep); }
button.primary.magic { background: var(--magic-btn); border-color: var(--magic-btn);
  box-shadow: 0 var(--lift) 0 var(--magic-deep); }
button.primary.cool { background: var(--cool-btn); border-color: var(--cool-btn);
  box-shadow: 0 var(--lift) 0 var(--cool-deep); }
button.primary:disabled { background: var(--panel); border-color: var(--border);
  color: var(--muted-2); }
/* Quiet by construction: an outline with nothing under it. Used for the second
   choice on a row, where the first one is the one that lifts. */
button.ghost { background: transparent; border-color: var(--border); color: var(--muted);
  box-shadow: none; font-weight: 700; }
button.small { padding: 6px 13px; font-size: 12.5px; border-radius: var(--r-sm); }
/* Undoing something, or ending it. Red is only ever this. */
button.danger { background: var(--err); border-color: var(--err); color: #fff; }

/* Buttons on a form are the width of the card - it is a form, and a form's
   buttons are its full-width steps, not a row of options. */
button.big { padding: 14px; border-radius: var(--r-pill); font-size: 15px; }
button.wide { width: 100%; padding: 12px; border-radius: var(--r-pill); }
/* The one place a button gets a glow as well as its drop: the way in is the
   only screen with room for it, and the only one where a single button is the
   whole point of the page. */
button.primary.big { box-shadow: 0 var(--lift) 0 var(--accent-deep),
  0 16px 34px -14px rgba(75, 123, 236, .95); }
button.primary.big:active:not(:disabled) { box-shadow: 0 1px 0 var(--accent-deep),
  0 10px 24px -14px rgba(75, 123, 236, .95); }
button.primary.big:disabled { box-shadow: none; }

/* A finger has no hover, and a sticky lift left behind after a tap reads as
   "still selected". Feedback belongs to pointers that can leave - except the
   press itself, which every pointer gets, below. */
@media (hover: hover) {
  button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
  button.primary:hover:not(:disabled) { color: var(--on-accent); }
  button.primary:hover:not(:disabled),
  button.ghost:hover:not(:disabled) { border-color: inherit; }
  button.ghost:hover:not(:disabled) { background: var(--panel-3); color: var(--text);
    border-color: var(--border-hi); }
  button.danger:hover:not(:disabled) { filter: brightness(1.1); }
}
/* Pressing it. The button sinks by exactly the height of its own drop, so the
   bottom edge stays put and only the face moves - which is what a real key
   does and why it reads as physical rather than as an animation. */
button:active:not(:disabled) { transform: translateY(2px); }
button.primary:active:not(:disabled) { box-shadow: 0 1px 0 var(--accent-deep); }
button.primary.good:active:not(:disabled) { box-shadow: 0 1px 0 var(--ok-deep); }
button.primary.money:active:not(:disabled) { box-shadow: 0 1px 0 var(--gold-deep); }
button.primary.magic:active:not(:disabled) { box-shadow: 0 1px 0 var(--magic-deep); }
button.primary.cool:active:not(:disabled) { box-shadow: 0 1px 0 var(--cool-deep); }
button:focus-visible { outline: 2px solid var(--accent-2); outline-offset: 2px; }

/* ── the chip ───────────────────────────────────────────────────────── */
/* A chip is a small fact, read rather than pressed. It is a capsule like every
   other small round thing here, and it sits on the *page* color rather than
   the card color, so a row of them reads as holes punched in the slab. */
.chip { display: inline-block; background: var(--panel); border: 1.5px solid var(--border);
  border-radius: var(--r-pill); padding: 4px 11px; margin: 2px;
  font-size: 11.5px; font-weight: 700; color: var(--muted); }
.chip.removable { cursor: pointer; border-color: var(--border-hi); color: var(--text); }
@media (hover: hover) { .chip.removable:hover { border-color: var(--err); color: var(--err); } }
/* What a mouthful will actually put back, drawn on the row before the press.
   A promise, so it reads as a number and not as a caption: figures, and the
   green a gain is written in everywhere else in Orbis. `.danger` is the body
   throwing more than half of it away - still worth eating, no longer worth
   eating *now*, which is why it dims rather than warns. */
.chip.restores { font-family: var(--font-num); font-weight: 700; color: var(--ok);
  background: var(--tint-ok); border-color: rgba(64, 214, 143, .3); }
.chip.restores.danger { color: var(--muted); background: var(--panel);
  border-color: var(--border); }

/* ── the badge ──────────────────────────────────────────────────────── */
/* Smaller and louder than a chip, and never a border: a badge says what kind
   of thing this is, a chip says a fact about it. */
.badge { font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em;
  padding: 3px 9px; border-radius: var(--r-pill);
  background: rgba(126, 166, 255, .16); color: var(--accent-2); }
.badge.mayor { background: rgba(255, 159, 67, .16); color: var(--warn); }
/* A number waiting on you: requests, unread messages, notices. */
.badge.count { background: var(--err-solid); color: #fff; border-radius: var(--r-pill);
  min-width: 18px; padding: 1px 6px; text-align: center; margin-left: auto;
  letter-spacing: 0; text-transform: none; font-size: 10.5px; font-weight: 800; }

/* ── the small capsule action ───────────────────────────────────────── */
/* An action on a post, a profile or a dossier, the size of a fingertip.
   Words-as-buttons were the older, quieter choice; with reactions in the row
   the whole strip reads better as one family of small pressable things. */
.link-act { padding: 5px 11px; border: 1.5px solid var(--border); background: transparent;
  border-radius: var(--r-pill); box-shadow: none;
  color: var(--muted); font-size: 12.5px; font-weight: 700; }
@media (hover: hover) {
  .link-act:hover:not(:disabled) { border-color: var(--border-hi);
    background: var(--panel-3); color: var(--text); }
}

/* ── the rule between two parts of a tab ────────────────────────────── */
/* The title is set in the display face at reading size rather than as small
   caps: this is a heading in a game, and a game's headings are spoken, not
   filed. */
.section-title { font-family: var(--font-display); font-size: 16px;
  font-weight: 600; letter-spacing: -.01em; color: var(--text-hi); margin-top: 6px;
  text-transform: none;
  display: flex; align-items: center; gap: 12px; }
.section-title::after { content: ""; flex: 1; height: 2px; border-radius: 2px;
  background: var(--border-soft); }
/* How many are under it. Between the name and the rule, so it reads as part of
   the heading rather than as the first item in the list. */
.section-count { flex: none; font-weight: 700; color: var(--muted-2);
  font-family: var(--font-mono); }

/* ── icons ──────────────────────────────────────────────────────────── */
/* Via the Icon component: emoji spans or images, same footprint either way. */
.icon { font-size: 18px; }
.big-icon { font-size: 22px; line-height: 1.1; }
.mini-icon { font-size: 15px; }
.shelf-icon { font-size: 24px; }
img.icon, img.mini-icon { width: 18px; height: 18px; object-fit: contain; }
img.big-icon { width: 24px; height: 24px; object-fit: contain; }
img.shelf-icon { width: 26px; height: 26px; object-fit: contain; }

/* ── content grids & action cards ───────────────────────────────────── */
/* `min(100%, …)` on the track floor rather than a bare 250px: a bare minimum
   larger than the column overflows the page instead of shrinking, which is how
   a grid inside a narrow panel ends up scrolling sideways. */
.grid { display: grid; gap: 13px;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 250px), 1fr)); }
/* Cards that are mostly a sentence - a job with a paragraph of requirements, a
   building with two rows of chips - and would be unreadable in half a phone's
   width. The opt-out, not the rule: see the phone block at the foot of this
   file for why the rule went the other way. */
.grid.wide { grid-template-columns: repeat(auto-fill, minmax(min(100%, 250px), 1fr)); }
/* An action card is a column with its button nailed to the floor. Cards in a row
   are different heights; their buttons are not - so a row of choices never
   becomes a staircase the eye has to climb, and nothing moves as a card grows. */
.action-card { padding: 16px; display: flex; flex-direction: column; gap: 11px;
  transition: transform .15s, border-color .15s; }
.action-card > *:not(:last-child) { flex: none; }
.action-card > *:last-child { margin-top: auto; }
/* Reaching for a card lifts it off the sheet. The same physical idea as the
   buttons, running the other way: a card rises to be picked, a button sinks
   to be pressed. */
@media (hover: hover) {
  .action-card:hover { transform: translateY(-2px); border-color: var(--border-hi); }
}
/* A card holding an open menu does not lift, and the reason is not taste: a
   `transform` makes the card a stacking context, and the card being opened is
   always the one under the cursor. Inside one, `.menu-pop`'s z-index can only
   outrank the card's own contents - so the next card in the grid paints over
   the menu - and the `.menu-scrim`'s `position: fixed` resolves against the
   card instead of the viewport, leaving the rest of the grid live. Those two
   then chase each other: the pointer leaves the card, the lift drops, the menu
   comes forward, the pointer is back on the card. Hence the flicker.

   A transform *animating* back to none is still a transform, so the transition
   has to go with it: settling over .15s is the half-second of the menu sitting
   behind its neighbour before it snaps forward. The border keeps its fade. */
.action-card.menu-open, .action-card.menu-open:hover {
  transform: none; transition: border-color .15s; }
/* Out of reach is dim, never crossed out - it's a goal. */
.action-card.locked { opacity: .8; }
.action-card.locked:hover { transform: none; }
.action-head { display: flex; gap: 10px; align-items: flex-start; }
.action-head > div { min-width: 0; }
.action-head b { font-family: var(--font-display); font-size: 15.5px; font-weight: 600;
  color: var(--text-hi); }

/* ── the phone ──────────────────────────────────────────────────────── */
@media (max-width: 920px) {
  /* A finger is not a cursor. Nothing tappable is smaller than a fingertip. */
  button { min-height: 42px; }
  .chip.removable { min-height: 0; }
  .link-act { min-height: 34px; }
  /* Reference sheets pinned to the right of a card's head have no width to be
     pinned into here - two-word buttons wrap to two lines each and shove the
     sentence beside them into a column. They drop to their own row instead. */
  .action-head { flex-wrap: wrap; }
}
@media (max-width: 560px) {
  /* **A grid stays a grid.** This was `1fr` - every grid in Orbis became a
     single column on a phone, so a bag of forty items, a street of twenty
     buildings and a board of a dozen jobs were all one endless vertical list.
     Scrolling was the only way to see anything, and the cards were sized for a
     desktop while they did it: enormous slabs, one per screenful.

     Two columns at 340px and up, which is every phone anybody is holding. The
     cards get denser to pay for it (below), and anything that genuinely needs
     the full width asks for it with `.wide` rather than every grid being
     punished for the few that do. */
  .grid { gap: 9px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 152px), 1fr)); }
  .grid.wide { grid-template-columns: 1fr; }
  .logo { font-size: 38px; }
  /* Half the width means the padding has to give way - it is the part of a card
     carrying no information. Names and prices keep theirs. */
  .action-card { padding: 11px; gap: 8px; }
  .action-head { gap: 7px; }
  .action-head b { font-size: 14px; }
  /* A button that is the whole width of a half-column reads as the card's own
     action rather than as a loose control sitting under it. */
  .action-card .row { gap: 5px; }
  .action-card .row > button { flex: 1 1 auto; }
}
/* Below this a second column would be two words wide. */
@media (max-width: 339px) {
  .grid { grid-template-columns: 1fr; }
}
