/* App layout. Every colour is a token from theme.css. */

/* Show and hide is a single .hidden flip in JS, so the rule has to be
   generic. Scoping it per element means a new element silently ignores the
   class, which is how a signed out account panel stays on screen.

   Modal backdrops opt out: they animate opacity and visibility, so they
   need their display value left alone. */
.hidden:not(.modal-backdrop) { display: none; }

.wrap {
  max-width: 720px;
  margin: 0 auto;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* ---- topbar ---- */
.topbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-right: auto;
  min-width: 0;
}
.brand-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 12px;
  background: var(--brand-fill);
  color: var(--on-brand);
  flex-shrink: 0;
}
.brand-mark svg { width: 18px; height: 18px; }
.brand-name { font-size: 1.05rem; color: var(--brand-ink); }

/* Chip style button, used for the coffee link. */
.chip-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 42px;
  padding: 0 14px;
  border-radius: 999px;
  background: var(--brand-fill);
  border: 1px solid var(--surface-border);
  color: var(--on-brand);
  font-size: 0.85rem;
  text-decoration: none;
  white-space: nowrap;
  transition: transform 0.15s ease, background 0.15s ease;
}
.chip-btn:link, .chip-btn:visited { color: var(--on-brand); }
.chip-btn:hover { transform: translateY(-1px); background: var(--brand-fill-strong); }
.chip-btn svg { width: 18px; height: 18px; flex-shrink: 0; }

@media (max-width: 480px) {
  .chip-btn { padding: 0 12px; }
  .chip-btn .chip-label { display: none; }
}

/* ---- panels ---- */
.panel { padding: 16px; display: flex; flex-direction: column; gap: 12px; }
.panel h1 { font-size: 1.15rem; color: var(--brand-ink); }
.panel h2 { font-size: 1rem; color: var(--brand-ink); }

/* An h2 starts a new section. The panel's flat 12px gap puts a heading as
   close to the section above it as to its own text, which reads as one long
   list rather than several sections. The first h2 is exempt, since the
   panel title is already directly above it.

   Descendant rather than child, because the Account tab wraps its sections
   in a signed in and a signed out div, so its headings are not direct
   children of the panel. :first-of-type is scoped to whichever of those
   contains it, which is exactly the exemption wanted. */
.panel h2:not(:first-of-type) {
  margin-top: 14px;
  padding-top: 18px;
  border-top: 1px solid var(--surface-border);
}
.panel p { font-size: 0.9rem; color: var(--muted); line-height: 1.5; }

/* ---- forms ---- */
.field { display: flex; gap: 8px; }
.field input[type="text"],
.field input[type="url"],
.field input[type="email"],
.field input[type="password"] {
  flex: 1;
  min-width: 0;
  height: 42px;
  padding: 0 12px;
  border-radius: 12px;
  background: var(--surface-strong);
  border: 1px solid var(--surface-border);
  color: var(--ink);
  font-size: 0.9rem;
}
.field input::placeholder { color: var(--muted-strong); opacity: 1; }
.field input:focus-visible { outline: 2px solid var(--brand-ink); outline-offset: 1px; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 42px;
  padding: 0 16px;
  border-radius: 12px;
  background: var(--brand-fill);
  border: 1px solid var(--surface-border);
  color: var(--on-brand);
  font-size: 0.88rem;
  transition: transform 0.15s ease, background 0.15s ease;
}
.btn:hover:not(:disabled) { transform: translateY(-1px); background: var(--brand-fill-strong); }
.btn svg { width: 16px; height: 16px; }

.btn.secondary {
  background: var(--surface-strong);
  color: var(--ink);
}
.btn.secondary:hover:not(:disabled) { background: var(--surface); }

.btn-row { display: flex; gap: 8px; flex-wrap: wrap; }

/* ---- item cards ---- */
.item-list { display: flex; flex-direction: column; gap: 10px; }

.item {
  display: flex;
  gap: 12px;
  padding: 12px;
  border-radius: 16px;
  background: var(--surface-strong);
  border: 1px solid var(--surface-border);
  text-decoration: none;
  transition: transform 0.15s ease, background 0.15s ease;
}
.item:hover { transform: translateY(-1px); }
.item-thumb {
  width: 96px;
  height: 54px;
  border-radius: 10px;
  object-fit: cover;
  background: var(--surface);
  flex-shrink: 0;
}
.item-body { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.item-title {
  font-size: 0.92rem;
  color: var(--ink);
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.item-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.76rem;
  color: var(--muted-strong);
}
.item-meta svg { width: 13px; height: 13px; }

/* ---- badges ---- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--brand-fill-strong);
  color: var(--on-brand);
  font-size: 0.74rem;
}
.badge svg { width: 12px; height: 12px; }

/* ---- status banners, tuned to read at 4.5:1 on a 14% tint of themselves ---- */
.banner {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  border-radius: 12px;
  font-size: 0.84rem;
}
.banner svg { width: 16px; height: 16px; flex-shrink: 0; }
.banner.ok { background: color-mix(in srgb, var(--ok) 14%, transparent); color: var(--ok); }
.banner.warn { background: color-mix(in srgb, var(--warn) 14%, transparent); color: var(--warn); }
.banner.error { background: color-mix(in srgb, var(--error) 14%, transparent); color: var(--error); }
.banner.busy { background: color-mix(in srgb, var(--busy) 14%, transparent); color: var(--busy); }

/* ---- empty state ---- */
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 32px 16px;
  text-align: center;
  color: var(--muted);
}
.empty svg { width: 34px; height: 34px; color: var(--muted); }
.empty p { font-size: 0.88rem; }

/* ---- forms stacked, used by sign in ---- */
.stack { display: flex; flex-direction: column; gap: 8px; }
.stack input {
  height: 42px;
  padding: 0 12px;
  border-radius: 12px;
  background: var(--surface-strong);
  border: 1px solid var(--surface-border);
  color: var(--ink);
  font-size: 0.9rem;
}
.stack input::placeholder { color: var(--muted-strong); opacity: 1; }
.stack input:focus-visible { outline: 2px solid var(--brand-ink); outline-offset: 1px; }

.whoami {
  margin-left: auto;
  font-size: 0.82rem;
  color: var(--muted);
  max-width: 30%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.brand { margin-right: 0; }

.signed-out-note { font-size: 0.9rem; color: var(--muted); }

.count { font-size: 0.78rem; color: var(--muted); }

/* ---- source cards ---- */
.source-list { display: flex; flex-direction: column; gap: 10px; }

.source {
  padding: 12px;
  border-radius: 16px;
  background: var(--surface-strong);
  border: 1px solid var(--surface-border);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.source-head { display: flex; align-items: center; gap: 8px; }
.source-title {
  flex: 1;
  min-width: 0;
  font-size: 0.92rem;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.source-meta { display: flex; gap: 6px; flex-wrap: wrap; }

.badge.warnish {
  background: color-mix(in srgb, var(--warn) 20%, transparent);
  color: var(--warn);
}

/* ---- per source routing ---- */
.routing { font-size: 0.84rem; }
.routing summary {
  cursor: pointer;
  color: var(--brand-ink);
  padding: 4px 0;
}
.route-hint { font-size: 0.78rem; color: var(--muted); margin: 4px 0 6px; }
.route {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 0;
  font-size: 0.84rem;
  color: var(--ink);
}
.route i { color: var(--muted-strong); font-style: normal; font-size: 0.78rem; }
.route input { accent-color: var(--brand-ink); width: 16px; height: 16px; }

.link-result {
  margin-top: 8px;
  padding: 10px;
  border-radius: 12px;
  background: var(--surface);
  border: 1px solid var(--surface-border);
}
.link-result code {
  display: inline-block;
  padding: 2px 6px;
  border-radius: 6px;
  background: var(--surface-strong);
  font-size: 0.76rem;
  user-select: text;
  word-break: break-all;
}

#loadMore { align-self: center; }

/* ---- delivery times ---- */
.destination-list { display: flex; flex-direction: column; gap: 8px; }
.destination {
  padding: 10px 12px;
  border-radius: 14px;
  background: var(--surface-strong);
  border: 1px solid var(--surface-border);
  font-size: 0.86rem;
}
.destination summary { cursor: pointer; color: var(--brand-ink); }
.destination i { color: var(--muted-strong); font-style: normal; font-size: 0.78rem; }
.destination .field { margin: 8px 0; }
.destination input[type="time"] {
  height: 38px;
  padding: 0 10px;
  border-radius: 10px;
  background: var(--surface);
  border: 1px solid var(--surface-border);
  color: var(--ink);
  font-size: 0.86rem;
}
.destination code {
  padding: 1px 5px;
  border-radius: 5px;
  background: var(--surface);
  font-size: 0.76rem;
}

/* ---- confirm dialog ---- */
.modal-body {
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--muted);
}
.modal-actions { margin-top: 4px; }
.modal-actions .btn { flex: 1; }

/* ---- footer ---- */
.footer {
  padding: 14px;
  text-align: center;
  font-size: 0.8rem;
  color: var(--muted);
}
.footer .heart { color: #34c759; }
.footer svg { width: 13px; height: 13px; vertical-align: -2px; }

@media (max-width: 480px) {
  .wrap { padding: 10px; }
  .item-thumb { width: 72px; height: 41px; }
}

/* ---- scope bar ---- */
/* Which account everything below is about. Only shown when there is a
   choice to make, since a picker with one option is just noise. */
.scope-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  flex-wrap: wrap;
}
.scope-label { font-size: 0.78rem; color: var(--muted); }
.scope-bar select {
  flex: 1 1 160px;
  min-width: 0;
  padding: 6px 8px;
  border-radius: 10px;
  border: 1px solid var(--surface-border);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
}
.scope-note { font-size: 0.78rem; color: var(--muted); flex-basis: 100%; }

/* A space scope is somebody else's room, so it should not look identical to
   your own feed. */
body.scoped .scope-bar { border-left: 3px solid var(--brand-ink); }

/* ---- provenance ---- */
.chip-origin {
  font-size: 0.7rem;
  padding: 1px 6px;
  border-radius: 999px;
  border: 1px solid var(--surface-border);
  color: var(--muted);
  white-space: nowrap;
}

/* ---- danger zone ---- */
/* Visually separated because everything in it is hard or impossible to
   undo, and because a destructive button that looks like every other button
   gets clicked like every other button. */
.danger-heading {
  color: var(--error);
}
.panel h2.danger-heading:not(:first-of-type) {
  border-top: 2px solid color-mix(in srgb, var(--error) 35%, transparent);
  margin-top: 22px;
  padding-top: 20px;
}

.btn.danger {
  background: color-mix(in srgb, var(--error) 16%, transparent);
  border-color: color-mix(in srgb, var(--error) 45%, transparent);
  color: var(--error);
}
.btn.danger:hover:not(:disabled) {
  background: color-mix(in srgb, var(--error) 26%, transparent);
}

/* ---- stepped modal ---- */
.step-count {
  font-size: 0.74rem;
  color: var(--muted);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.modal-step { display: flex; flex-direction: column; gap: 8px; }

/* ---- home and overview ---- */
.hero { display: flex; flex-direction: column; gap: 10px; padding: 12px 0 4px; }
.eyebrow {
  font-size: 0.74rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.hero-title { font-size: 1.7rem; line-height: 1.15; color: var(--brand-ink); }
.hero-lede { font-size: 0.95rem; max-width: 46ch; }

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px;
}
.stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px;
  border-radius: 14px;
  background: var(--surface-strong);
  border: 1px solid var(--surface-border);
}
.stat strong { font-size: 1.25rem; color: var(--brand-ink); }
.stat svg { width: 18px; height: 18px; color: var(--brand-ink); }
.stat.linky { text-decoration: none; transition: transform 0.15s ease; }
.stat.linky:hover { transform: translateY(-1px); }

/* ---- sidebar, a drawer at every width ---- */
/* One navigation instead of a sidebar on desktop and a tab bar on mobile.
   Off canvas until the hamburger opens it, which keeps the content column
   the same width at every size and means one thing to get right rather
   than two.

   .hidden still means display:none, which is the signed out state. The
   open and closed states are a transform, so they can animate. */
.sidebar:not(.hidden) {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px;

  position: fixed;
  z-index: 60;
  top: 0;
  left: 0;
  bottom: 0;
  width: min(268px, 82vw);
  border-radius: 0 16px 16px 0;
  overflow-y: auto;

  transform: translateX(-100%);
  transition: transform 0.22s ease;
}
.sidebar.open { transform: translateX(0); }

.nav-scrim {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: rgba(0, 0, 0, 0.45);
  opacity: 0;
  transition: opacity 0.22s ease;
}
.nav-scrim.open { opacity: 1; }

/* Nothing behind the drawer should scroll while it is open. */
body.nav-open { overflow: hidden; }

/* Timing lives here, so reduced motion is handled in one place. */
@media (prefers-reduced-motion: reduce) {
  .sidebar:not(.hidden), .nav-scrim { transition: none; }
}

.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 10px;
  font-size: 0.9rem;
  color: var(--muted);
  text-decoration: none;
  transition: background 0.15s ease, color 0.15s ease;
}
.nav-item svg { width: 17px; height: 17px; }
.nav-item:hover { background: var(--surface); }
.nav-item.active { background: var(--brand-fill); color: var(--on-brand); }
