/* Aldertwig OS — console chrome.
 *
 *  The shape is deliberately the Twilio console's: a fixed left rail of
 *  grouped sections, a white working area, one idea per card. Eric asked for
 *  it by name, and the reason it works is that it scales — a single scrolling
 *  page stops being readable at about six panels and we are past that.
 *
 *  Light, because this screen is read in daylight on a phone and because the
 *  old dark panel made a red error and an amber warning look the same colour
 *  at arm's length.
 */
:root {
  --bg: #f4f6f9;
  --panel: #ffffff;
  --rail: #f7f8fc;
  --line: #e2e5ed;
  --line-soft: #eef0f6;
  --ink: #121c2d;
  --ink-dim: #5a6577;
  --ink-faint: #8a93a6;
  --accent: #0263e0;
  --accent-soft: #e8f0fe;
  --ok: #14803c;
  --ok-soft: #e6f4ea;
  --warn: #9a5b00;
  --warn-soft: #fdf1dd;
  --bad: #c9271f;
  --bad-soft: #fdecea;
  --unknown: #8a93a6;
  --unknown-soft: #f0f1f5;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, system-ui, sans-serif;
  --rail-width: 252px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 15px/1.5 var(--sans);
  -webkit-font-smoothing: antialiased;
}

.shell { display: flex; min-height: 100vh; }

/* ------------------------------------------------------------- left rail */

.sidebar {
  width: var(--rail-width);
  flex: none;
  background: var(--rail);
  border-right: 1px solid var(--line);
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  padding: 14px 12px 18px;
  gap: 6px;
}

/* The brand block is a control now, so the box that used to BE the block is a
 * button inside a positioned wrapper — the switcher menu hangs off the wrapper
 * and the button keeps the grid. */
.account { position: relative; margin-bottom: 10px; }
.accountbtn {
  width: 100%;
  display: grid;
  grid-template-columns: 34px 1fr auto;
  grid-template-rows: auto auto;
  align-items: center;
  column-gap: 10px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 9px 12px;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
}
.accountbtn:hover:not([disabled]) { border-color: var(--accent); }
/* One destination: no caret, because there is no list to drop down. The block
 * still names the project and still navigates — it is a link wearing a button.
 * It used to DISABLE itself here instead, which is how a client with one
 * project ended up with no route to that project's screens at all. */
.accountbtn.single .caret { visibility: hidden; }
/* Nothing at all: an account with no project scoped to it yet. */
.accountbtn[disabled] { cursor: default; opacity: 1; }
.accountbtn[disabled] .caret { visibility: hidden; }
.accountbtn .mark {
  grid-row: 1 / span 2;
  width: 34px; height: 34px;
  border-radius: 9px;
  background: var(--accent);
  color: #fff;
  display: grid;
  place-items: center;
  font-weight: 700;
  font-size: 17px;
}
.accountbtn .mark.logo { background: none; overflow: hidden; }
.accountbtn .mark.logo img { width: 100%; height: 100%; object-fit: contain; display: block; }
.accountbtn .caret { grid-row: 1 / span 2; grid-column: 3; color: var(--ink-faint); font-size: 11px; }
.account-name { font-weight: 650; font-size: 14.5px; }
.account-sub { font-size: 11.5px; color: var(--ink-faint); }

nav { display: grid; gap: 2px; }
nav .group {
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  padding: 14px 10px 5px;
}
nav a {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 10px;
  border-radius: 8px;
  color: var(--ink);
  text-decoration: none;
  font-size: 14px;
}
nav a:hover { background: #eceff6; }
nav a.on { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
nav a .glyph { width: 18px; text-align: center; opacity: 0.85; font-size: 13px; }
nav a .badge {
  margin-left: auto;
  font: 600 11px/1 var(--sans);
  padding: 3px 6px;
  border-radius: 20px;
  background: var(--bad-soft);
  color: var(--bad);
}
nav a .badge.warn { background: var(--warn-soft); color: var(--warn); }
/* A project's OWN screens, spliced into the rail under Home. Indented and a
 * shade quieter than the fixed items above them, because they belong to
 * whatever is named at the top of the rail and change when it does. */
nav a.sub { padding-left: 24px; font-size: 13.5px; }
nav a.sub .glyph { opacity: 0.7; }
nav a.sub2 { padding-left: 40px; font-size: 13px; }
/* A screen's sections, in a project's rail: their glyph sits past the
 * parent's label start, so they read as children. */
nav a.sec { padding-left: 34px; font-size: 13.5px; }
nav a .glyph { display: inline-grid; place-items: center; flex: none; }
nav a .glyph svg { width: 16px; height: 16px; }
nav a.sub .glyph svg, nav a.sub2 .glyph svg { width: 15px; height: 15px; }

/* ---------------------------------------------------------------- column */

.column { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
  padding: 10px 26px;
  display: flex;
  align-items: center;
  gap: 12px;
}
.topbar-title { display: flex; align-items: center; gap: 8px; min-width: 0; font-size: 15px; white-space: nowrap; }
.crumb-where { color: var(--ink-dim); font-weight: 500; flex-shrink: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.crumb-sep { color: var(--ink-faint); }
.crumb-what { color: var(--ink); font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.crumb-what .dot { margin-left: 8px; vertical-align: middle; }
.topbar-title.crumb-one .crumb-sep, .topbar-title.crumb-one .crumb-what:empty { display: none; }
.topbar-title.crumb-one:has(.crumb-what:not(:empty)) .crumb-where { display: none; }
.topbar-right { margin-left: auto; display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.topfact { font-size: 13px; color: var(--ink-dim); }
.topfact b { color: var(--ink); }
.stampx { font: 11.5px/1 var(--mono); color: var(--ink-faint); }
.menu {
  display: none;
  background: none;
  border: 1px solid var(--line);
  border-radius: 8px;
  font-size: 15px;
  padding: 5px 9px;
}

/* `minmax(0, 1fr)`, not the implicit `auto` track: an auto track grows to its
 * widest child's min-content, so one nowrap table widened the whole page on a
 * phone instead of scrolling inside its own box. */
main { padding: 26px; display: grid; grid-template-columns: minmax(0, 1fr); gap: 18px; align-content: start; max-width: 1320px; min-width: 0; }
.loading { color: var(--ink-faint); }

/* ------------------------------------------------------------ page title */

.page-title { display: grid; gap: 6px; }
.page-title h1 { margin: 0; font-size: 26px; line-height: 1.2; font-weight: 700; letter-spacing: -0.015em; color: var(--ink); }
.page-title p { margin: 0; color: var(--ink-dim); max-width: 78ch; }

/* ----------------------------------------------------------------- cards */

.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  overflow: hidden;
}
.card > h2 {
  margin: 0;
  padding: 15px 20px;
  font-size: 17px;
  font-weight: 650;
  display: flex;
  gap: 12px;
  align-items: baseline;
  border-bottom: 1px solid var(--line-soft);
}
.card > h2 .sub { margin-left: auto; font-size: 12.5px; font-weight: 400; color: var(--ink-faint); text-align: right; }
.body { padding: 18px 20px; }
.grid2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); gap: 18px; }

/* stat blocks — the console's figure row */
/* Hairlines are drawn per cell rather than as grid gaps: an auto-fit grid that
   wraps leaves an empty final cell, and a gap-coloured background painted that
   cell as a grey block on every phone-width screen. */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(168px, 1fr)); background: var(--panel); }
.stat {
  background: var(--panel);
  padding: 16px 20px;
  border-left: 1px solid var(--line-soft);
  border-top: 1px solid var(--line-soft);
  margin: -1px 0 0 -1px;
}
.stat .label { font-size: 12px; color: var(--ink-faint); }
.stat .value { font: 650 27px/1.15 var(--sans); letter-spacing: -0.02em; margin-top: 5px; font-variant-numeric: tabular-nums; }
.stat .note { font-size: 12.5px; color: var(--ink-dim); margin-top: 6px; }
.stat .value.bad { color: var(--bad); }
.stat .value.ok { color: var(--ok); }
.stat .value.warn { color: var(--warn); }
.stat .value.unknown { color: var(--unknown); font-size: 18px; font-weight: 500; }

.card > .evidence {
  padding: 12px 20px;
  border-top: 1px solid var(--line-soft);
  background: #fafbfd;
  color: var(--ink-faint);
  font: 11.5px/1.6 var(--mono);
}

.reading { padding: 16px 20px; border-top: 1px solid var(--line-soft); color: var(--ink-dim); }
.reading b { color: var(--ink); }

/* progress */
.bar { height: 7px; background: var(--line-soft); border-radius: 4px; overflow: hidden; }
.bar > i { display: block; height: 100%; background: var(--accent); }
.bar > i.ok { background: var(--ok); }

/* rows */
.rows { display: grid; }
.row { padding: 14px 20px; border-top: 1px solid var(--line-soft); display: grid; gap: 4px; }
.rows > .row:first-child { border-top: 0; }
.row .top { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; }
.row .title { font-weight: 600; }
.row .detail { color: var(--ink-dim); font-size: 13.5px; }
.row .evidence { color: var(--ink-faint); font-size: 11.5px; font-family: var(--mono); overflow-wrap: anywhere; }

.tag {
  font: 600 10.5px/1 var(--sans);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  padding: 4px 7px;
  border-radius: 5px;
  background: var(--unknown-soft);
  color: var(--ink-dim);
  white-space: nowrap;
}
.tag.overdue, .tag.down { background: var(--bad-soft); color: var(--bad); }
.tag.due-soon, .tag.open, .tag.warn { background: var(--warn-soft); color: var(--warn); }
.tag.up, .tag.good { background: var(--ok-soft); color: var(--ok); }
.tag.money, .tag.accent { background: var(--accent-soft); color: var(--accent); }
.tag.unscheduled { background: transparent; border: 1px dashed var(--line); color: var(--unknown); }

.pill {
  font: 600 12px/1 var(--sans);
  padding: 6px 10px;
  border-radius: 20px;
  background: var(--ok-soft);
  color: var(--ok);
  white-space: nowrap;
}
.pill.bad { background: var(--bad-soft); color: var(--bad); }
.pill.warn { background: var(--warn-soft); color: var(--warn); }

/* source chips */
.chips { display: flex; gap: 7px; flex-wrap: wrap; }
.chip {
  font: 12px/1 var(--mono);
  padding: 6px 9px;
  border-radius: 6px;
  background: var(--ok-soft);
  color: var(--ok);
}
.chip.bad { background: var(--bad-soft); color: var(--bad); }

/* estate + venture tiles */
.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); background: var(--panel); }
.tile {
  background: var(--panel);
  padding: 16px 20px;
  display: grid;
  gap: 9px;
  align-content: start;
  border-left: 1px solid var(--line-soft);
  border-top: 1px solid var(--line-soft);
  margin: -1px 0 0 -1px;
}
.tile .name { font-weight: 650; display: flex; align-items: center; gap: 8px; }
.tile .line { font-size: 13px; color: var(--ink-dim); }
.tile .facts { display: flex; gap: 14px; flex-wrap: wrap; font: 12px/1.4 var(--mono); color: var(--ink-dim); }
.tile .facts b { color: var(--ink); font-weight: 600; }
.tile .facts .bad { color: var(--bad); }

/* One dot, two vocabularies. The venture tiles say up/down; the client cards
 * say ok/bad, because there the dot IS the healthy state — Eric: "the 'live
 * now' could just be a green dot". Both map to the same three colours here
 * rather than to two competing `.dot` blocks, where whichever was written
 * later silently repainted the other's default. UNKNOWN STAYS THE DEFAULT: a
 * venture nothing has probed must not inherit green from a rule meant for a
 * client's card. */
.dot { width: 9px; height: 9px; border-radius: 50%; background: var(--unknown); flex: none; }
.dot.up, .dot.ok { background: var(--ok); }
.dot.down, .dot.bad { background: var(--bad); }
.dot.unknown { background: var(--unknown); }

/* `h2` is a baseline-aligned flex row, so an empty dot sits on the text
 * baseline on its own. Only the extra breathing room is set here. */
.card > h2 .dot { margin-left: 8px; }
/* The same dot on the page title, for the single-project client whose heading
 * IS the project name. `display: inline-block` because an h1 is not a flex
 * row, and a 9px square with no box would collapse to nothing. */
.page-title h1 .dot { display: inline-block; margin-left: 10px; vertical-align: middle; }

.spark { display: flex; align-items: flex-end; gap: 2px; height: 28px; }
.spark i { flex: 1; background: var(--accent); min-height: 1px; opacity: 0.8; border-radius: 2px 2px 0 0; }

a { color: var(--accent); }
.err { color: var(--bad); font-size: 13px; }
.muted { color: var(--ink-faint); font-size: 13px; }

/* Off entirely until the drawer exists, which is only below the breakpoint. */
.scrim { display: none; }

/* ---------------------------------------------------------------- mobile */

@media (max-width: 900px) {
  .sidebar {
    position: fixed;
    z-index: 40;
    left: 0; top: 0;
    /* 100vh on iOS is the viewport with the toolbars HIDDEN, so the drawer's
     * last item sat under Safari's bar and the scroll bounced back over it.
     * dvh is the viewport you can see; contain stops the page scrolling too. */
    height: 100vh;
    height: 100dvh;
    overscroll-behavior: contain;
    padding-bottom: calc(18px + env(safe-area-inset-bottom, 0px));
    transform: translateX(-100%);
    transition: transform 0.16s ease-out;
  }
  /* Shadow only while open: on the parked drawer it bled a grey band down
   * the left edge of every phone screen. */
  /* The page under an open drawer does not scroll, so a flick at the end of
   * the menu cannot drag the page and snap the menu back. */
  body.nav-open { overflow: hidden; }
  body.nav-open .sidebar { transform: none; box-shadow: 0 10px 40px rgba(18, 28, 45, 0.18); }
  body.nav-open .scrim {
    position: fixed;
    inset: 0;
    z-index: 35;
    background: rgba(18, 28, 45, 0.34);
    display: block;
  }
  .menu { display: block; }
  main { padding: 16px; gap: 14px; }
  .topbar { padding: 10px 16px; }
  .page-title h1 { font-size: 26px; }
  .stat .value { font-size: 23px; }
}

/* ------------------------------------------------------- account & preview */

/* The avatar sits last in the top bar and owns the only menu on the screen.
 * Sign-out lives in it, because a dashboard with no way out is one Eric had to
 * ask for twice. */
.who { position: relative; }
.avatar {
  width: 30px; height: 30px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--accent-soft);
  color: var(--accent);
  font: 600 12px/1 var(--sans);
  display: grid; place-items: center;
  cursor: pointer;
  padding: 0;
  overflow: hidden;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.avatar:hover { border-color: var(--accent); }

.whomenu {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  min-width: 232px;
  max-height: 70vh;
  overflow-y: auto;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 11px;
  box-shadow: 0 10px 30px rgba(18, 28, 45, 0.13);
  padding: 6px;
  z-index: 40;
  text-align: left;
}
.whohead { padding: 8px 10px 10px; border-bottom: 1px solid var(--line-soft); margin-bottom: 4px; }
.whoname { font-weight: 650; font-size: 13.5px; }
.whomail { font-size: 11.5px; color: var(--ink-dim); word-break: break-all; }
.whorole { font: 11px/1.4 var(--mono); color: var(--ink-faint); margin-top: 3px; }
.whogroup {
  font-size: 10.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding: 9px 10px 4px;
}
.whonote { font-size: 11.5px; color: var(--ink-faint); padding: 3px 10px 6px; }
.whomenu a,
.whomenu button.whoout {
  display: block;
  padding: 7px 10px;
  border-radius: 7px;
  font-size: 13.5px;
  color: var(--ink);
  text-decoration: none;
}
.whomenu a:hover { background: var(--accent-soft); color: var(--accent); }
.whomenu a.on { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.whomenu a.whoback { color: var(--accent); font-weight: 600; }
.whomenu a.whoout,
.whomenu button.whoout { color: var(--bad); width: 100%; text-align: left; background: none; border: 0; font: inherit; cursor: pointer; }
.whomenu a.whoout:hover,
.whomenu button.whoout:hover { background: var(--bad-soft); color: var(--bad); }

/* Same popover as the account menu, opened from the left rail rather than the
 * top-right corner. Only the anchoring differs. */
.switchmenu { left: 0; right: auto; min-width: 100%; }

/* Loud on purpose: an admin three screens into a client preview, seeing a
 * dashboard with no money on it, must not be able to mistake it for a fault. */
/* `display: flex` beats the `hidden` attribute's UA `display: none`, so without
 * this line the empty bar paints as an amber strip across the top of every
 * screen on a dashboard nobody is previewing. */
.preview[hidden] { display: none; }
.preview {
  position: sticky;
  top: 0;
  z-index: 25;
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  background: var(--warn-soft);
  border-bottom: 1px solid #f0d9ae;
  color: var(--warn);
  font-size: 13px;
  padding: 7px 26px;
}
.preview b { font-weight: 650; }
.preview a { color: var(--warn); font-weight: 600; margin-left: auto; }

/* ------------------------------------------------------------- comments */
/* The first thing on this dashboard a person types into rather than reads.
 * Deliberately plain: a conversation about a broken site is not the place for
 * chat-app styling, and the two sides have to be tellable apart at a glance
 * without colour alone carrying the meaning — the side is also in the name. */
.thread { display: flex; flex-direction: column; gap: 10px; margin-bottom: 14px; }
.bubble {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 9px 11px;
  max-width: 62ch;
  background: var(--panel);
}
.bubble.team {
  border-color: var(--accent-soft);
  background: var(--accent-soft);
  align-self: flex-end;
}
.bhead { display: flex; gap: 10px; align-items: baseline; font-size: 12px; margin-bottom: 4px; }
.bhead b { font-weight: 650; }
.bwhen { color: var(--ink-faint); }
.btext { font-size: 13.5px; line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere; }
.composer { display: flex; flex-direction: column; gap: 8px; }
.composer textarea, .bedit textarea {
  width: 100%;
  font: inherit;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--ink);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 9px 11px;
  resize: vertical;
}
.composer textarea:focus, .bedit textarea:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.composer textarea:disabled { opacity: 0.6; cursor: not-allowed; }
.crow { display: flex; align-items: center; gap: 12px; }
.composer button, .bedit button.primary {
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: #fff;
  background: var(--accent);
  border: 0;
  border-radius: 8px;
  padding: 7px 16px;
  cursor: pointer;
}
.composer button:disabled, .bedit button.primary:disabled { opacity: 0.5; cursor: not-allowed; }
.composer input {
  font: 14px/1.5 var(--sans);
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fff;
  color: var(--ink);
}
.composer input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
/* A destructive action that is not a button-shaped invitation to press it. */
.linky {
  margin-left: auto;
  border: 0;
  background: none;
  padding: 0;
  font: 12px var(--sans);
  color: var(--ink-faint);
  cursor: pointer;
  text-decoration: underline;
}
.linky:hover { color: var(--bad); }
.linky:disabled { opacity: 0.5; cursor: not-allowed; }
.cstatus { font-size: 12px; color: var(--ink-faint); }
.cstatus.err { color: var(--bad); }
.cstatus.ok { color: var(--ok); }
/* A thread we owe an answer to is marked on the card, not only in the list —
 * the attention item scrolls away, the card is where the reply gets written. */
.card.owed { border-color: var(--warn); }

/* ------------------------------------------------ a client's own screens */

/* The live site, photographed by Netlify from the published deploy. Boxed at a
   fixed aspect so a tall page and a short one do not make two cards of wildly
   different heights on the same screen. */
.shot {
  display: block;
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
  background: var(--panel);
  max-height: 340px;
}
.shot img { display: block; width: 100%; height: auto; }

/* The project explainer. Wider measure than a card note and narrower than the
   page, because it is meant to be read rather than scanned. */
.prose { padding: 4px 20px 18px; color: var(--ink-dim); }
.prose p { margin: 0 0 10px; max-width: 74ch; line-height: 1.55; }
.prose p:last-child { margin-bottom: 0; }

/* The timeline. One column, one row per event, with the kind carried by a
   glyph rather than by colour alone. */
.feed { display: grid; }
.event { padding: 13px 20px; border-top: 1px solid var(--line-soft); display: grid; gap: 4px; }
.feed > .event:first-child { border-top: 0; }
.event .top { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; }
.event .glyph { color: var(--ink-faint); font-size: 12px; width: 14px; flex: none; }
.event .title { font-weight: 600; }
.event .detail { color: var(--ink-dim); font-size: 13.5px; white-space: pre-wrap; overflow-wrap: anywhere; padding-left: 24px; }
.event .evidence { color: var(--ink-faint); font: 11.5px/1.5 var(--mono); padding-left: 24px; }
.event.release .glyph { color: var(--accent); }
.event.update .glyph { color: var(--ok); }
.event.comment { background: var(--panel); }
.event.comment.theirs .glyph { color: var(--warn); }

/* A question we are still waiting on. The left edge is the only difference,
   so an answered one does not look like a different kind of thing. */
.row.open { box-shadow: inset 3px 0 0 var(--warn); }

/* The kind selector beside the send button, and the tag it produces. */
.composer select, .composer input[type="date"] {
  font: inherit;
  font-size: 13px;
  padding: 7px 9px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: #fff;
  color: var(--ink);
}
.composer select:disabled { opacity: 0.5; cursor: not-allowed; }
.tag.kind-bug { background: var(--bad-soft); color: var(--bad); }
.tag.kind-scope { background: var(--warn-soft); color: var(--warn); }
.tag.kind-request { background: var(--accent-soft); color: var(--accent); }
.tag.kind-enquiry { background: var(--ok-soft); color: var(--ok); }

/* The ledger editor: a row of small labelled fields rather than a form that
   runs down the page, because seven short answers read as one action. */
.editor { padding: 16px 20px; border-top: 1px solid var(--line-soft); }
.fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
.field { display: grid; gap: 4px; }
.field > span { font-size: 11.5px; color: var(--ink-faint); }
.field input, .field select { width: 100%; box-sizing: border-box; }

/* A tick box reads as one sentence, not as a labelled field above a control.
   "Keep this card on file" is the label AND the thing being agreed to, so the
   box sits inside the sentence rather than above it. */
.field.inline { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
.field.inline > span { font-size: 13px; color: var(--ink-dim); }
.field.inline input { width: auto; accent-color: var(--accent); }

/* `.composer button` is more specific than `.linky`, so a text affordance
   inside a form was rendering as a primary button — which made "change the
   defaults" louder than "issue the invoice". It is a link again, and on the
   left, under the fields it opens. */
.composer button.linky {
  margin-left: 0;
  align-self: flex-start;
  background: none;
  border: 0;
  padding: 0;
  font: 12px var(--sans);
  color: var(--ink-faint);
  text-decoration: underline;
}
.composer button.linky:hover { color: var(--ink); }

/* ------------------------------------------------------------- paying up */

/* An outstanding invoice with the ways to settle it. Boxed and set apart from
   the history underneath, because it is the only thing on a client's billing
   screen that asks them to do something. */
.pay {
  padding: 16px 20px;
  border-top: 1px solid var(--line-soft);
  background: color-mix(in srgb, var(--warn) 7%, transparent);
  display: grid;
  gap: 8px;
}
.pay .top { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; }
.pay .title { font-weight: 600; font-size: 17px; }
.pay .detail { color: var(--ink-dim); font-size: 13.5px; }
.pay .crow { flex-wrap: wrap; gap: 10px; }
/* The card button is the primary one — Eric: "a pay now button via stripe
   helps getting paid". Every other rail is a link beside it. */
.pay .crow > button:first-child:not(.linky) {
  background: var(--accent);
  color: #fff;
  border: 0;
  border-radius: 8px;
  padding: 10px 16px;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.pay .crow > button:first-child:not(.linky):disabled { opacity: 0.5; cursor: not-allowed; }
.pay .reading { border-top: 0; padding: 10px 0 0; white-space: pre-wrap; }
/* The other rails are alternatives beside the button, not the destructive
   after-thought `.linky` is everywhere else on this page. `margin-left: auto`
   would push them to the far edge, where they read as unrelated. */
.pay .crow .linky {
  margin-left: 0;
  font-size: 13.5px;
  color: var(--accent);
  align-self: center;
}
.pay .crow .linky:hover { color: var(--accent); }

/* The answer to "did that payment work?", at the top of the page they land
   on. Green or red, never quiet: this is the one message a client is
   actively waiting for. */
.pay-result {
  margin: 0 0 16px;
  padding: 14px 18px;
  border-radius: 10px;
  font-weight: 600;
  border: 1px solid var(--line);
}
.pay-result.ok { background: color-mix(in srgb, var(--ok) 14%, transparent); color: var(--ink); }
.pay-result.err { background: color-mix(in srgb, var(--bad) 14%, transparent); color: var(--ink); }


/* A row that is a link. Same row, one destination. */
a.row { color: inherit; text-decoration: none; }
a.row:hover .title { color: var(--accent); }

/* The two faces of a project. Two links, not a stateful control: the side is
 * in the URL, so it survives a reload and can be pasted to somebody else. */
.titlerow { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.titlerow h1 { margin: 0; }
/* `.sides` (the our/their toggle) removed 2026-09-28 with the toggle itself. */

/* A link that performs an action rather than naming a place. Bordered so a
 * thumb can find it, and quiet so it does not compete with the row it sits
 * under. */
.linkbtn {
  display: inline-block;
  margin-top: 2px;
  padding: 5px 11px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel);
  font-size: 12.5px;
  color: var(--ink-dim);
  text-decoration: none;
}
.linkbtn:hover { background: var(--accent-soft); color: var(--accent); border-color: var(--accent); }

/* The screens a project has of its own: `#/project/<id>/<screen>`.
 *
 * An underline strip rather than a second pill group. The pills next to the
 * title are the two FACES of one project and are a choice about who is
 * looking; these are places inside it. Two identical-looking controls a
 * centimetre apart doing different things is how a reader stops trusting
 * either.
 *
 * Scrolls sideways rather than wrapping. A project with five screens on a
 * phone would otherwise push the whole page down by two rows before the first
 * number, and the horizontal scroll is the one place a tab strip is allowed
 * to hide something — the active tab is always in view because the page was
 * reached by it. */
/* The way back up from one project screen to that project's overview. The tab
 * strip that used to carry an "Overview" tab is gone — the screens are rail
 * items now — so this is the one link that had nowhere else to go. */
.backto {
  display: inline-block;
  margin-top: 10px;
  font-size: 13px;
  color: var(--ink-faint);
  text-decoration: none;
}
.backto:hover { color: var(--accent); }

.tabs {
  display: flex;
  gap: 2px;
  margin-top: 14px;
  border-bottom: 1px solid var(--line);
  overflow-x: auto;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tabs .tab {
  padding: 9px 14px;
  font-size: 13.5px;
  color: var(--ink-dim);
  text-decoration: none;
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  display: flex;
  align-items: center;
  gap: 7px;
}
.tabs .tab:hover { color: var(--accent); }
.tabs .tab.on { color: var(--ink); font-weight: 600; border-bottom-color: var(--accent); }
.tabs .tab .glyph { color: var(--ink-faint); font-size: 12px; }
.tabs .tab.on .glyph { color: var(--accent); }
/* The nav badge does not reach here — its rule is scoped to `nav a`. Restated
 * rather than widened, because a badge in a tab strip sits beside the label
 * instead of being pushed to the far edge of a rail. */
.tabs .tab .badge {
  font: 600 11px/1 var(--sans);
  padding: 3px 6px;
  border-radius: 20px;
  background: var(--bad-soft);
  color: var(--bad);
}
.tabs .tab .badge.warn { background: var(--warn-soft); color: var(--warn); }


/* ------------------------------------------------------- the record editor */

/* The first form in this dashboard that changes a client's own data, so it is
   deliberately not styled like the ledger editor above. That one is a row of
   short answers that read as one action; this is a long form where each field
   is a separate decision and one of them can be a wrong legal answer. So:
   stacked, labelled, generously spaced, and the fields that assert the law are
   marked. */
form.record { display: block; }
form.record .field { display: grid; gap: 5px; margin: 0 0 16px; }
form.record .field > label { font-size: 12px; color: var(--ink-dim); font-weight: 600; }
form.record .field > .note { font-size: 11.5px; color: var(--ink-faint); line-height: 1.5; }
form.record .field input[type="text"],
form.record .field input[type="number"],
form.record .field select,
form.record .field textarea {
  width: 100%;
  box-sizing: border-box;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel);
  color: var(--ink);
  font: 13px var(--sans);
}
form.record .field textarea { resize: vertical; min-height: 64px; line-height: 1.5; }
form.record .field input:focus, form.record .field select:focus, form.record .field textarea:focus {
  outline: 2px solid var(--accent); outline-offset: -1px;
}
form.record .field input:disabled, form.record .field textarea:disabled, form.record .field select:disabled {
  opacity: 0.55; cursor: not-allowed;
}
form.record .field input[type="checkbox"] { width: auto; accent-color: var(--accent); justify-self: start; }

/* A field carrying an assertion about the law. Marked rather than coloured in:
   an amber input reads as an error, and most of these are simply true. */
form.record .field.lawful > label::after {
  content: ' · legal value';
  font-weight: 400;
  color: var(--warn);
}

form.record .actions { padding: 0 20px 18px; }
form.record button.primary {
  padding: 9px 16px;
  border: 0;
  border-radius: 6px;
  background: var(--accent);
  color: #fff;
  font: 600 13px var(--sans);
  cursor: pointer;
}
form.record button.primary:disabled { opacity: 0.5; cursor: not-allowed; }

/* One finding: a row that disagrees with itself, said in a sentence. Bordered
   on the left rather than filled, so a form carrying six of them is still a
   form rather than a wall of colour. */
.finding {
  padding: 8px 12px;
  margin: 0 0 8px;
  border-left: 3px solid var(--warn);
  background: var(--warn-soft);
  color: var(--ink-dim);
  font-size: 12.5px;
  line-height: 1.55;
  border-radius: 0 4px 4px 0;
}
.finding.bad { border-left-color: var(--bad); background: var(--bad-soft); }
.finding strong { color: var(--ink); font-family: var(--mono, monospace); font-size: 12px; }
.ok-line { color: var(--ok); font-size: 13px; margin-bottom: 6px; }
.rows .detail.bad { color: var(--bad); }

/* ---- the `i` that holds a source ----------------------------------------
 *
 *  Eric, 2026-09-28: sources and provenance lines "can be hidden behind a
 *  tooltip". They are still on the screen, one keystroke away, because a
 *  figure whose origin is unrecoverable is worse than a cluttered card.
 *
 *  Absolutely positioned against the card, not the button, so a bubble on a
 *  card's last row is not clipped by the row's own overflow.
 */
.tip { position: relative; display: inline-flex; vertical-align: baseline; margin-left: 6px; }

.tipbtn {
  width: 15px; height: 15px; padding: 0; border: 1px solid var(--line);
  border-radius: 50%; background: var(--panel); color: var(--ink-faint);
  font: italic 600 10px/13px var(--sans); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.tipbtn:hover { color: var(--accent); border-color: var(--accent); }
.tipbtn[aria-expanded="true"] { color: var(--panel); background: var(--accent); border-color: var(--accent); }

.tipbody {
  position: absolute; z-index: 20; left: 0; top: 20px; width: max-content; max-width: 320px;
  background: var(--ink); color: #fff; border-radius: 6px; padding: 8px 10px;
  font: 11.5px/1.5 var(--mono); overflow-wrap: anywhere; white-space: normal;
  box-shadow: 0 6px 20px rgba(18, 28, 45, .22);
}
/* Near the right edge the bubble would run off a phone screen. */
@media (max-width: 620px) { .tipbody { left: auto; right: 0; max-width: 72vw; } }

/* Three booklets side by side, one per column, collapsing to a single column
 * on a phone. Eric, 2026-09-28: "a 3 column section instead of 3 boxed rows". */
.regcols { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
.regcols > .card { margin: 0; }
.regcols .linkbtn { white-space: normal; }
@media (max-width: 1100px) { .regcols { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 720px) { .regcols { grid-template-columns: 1fr; } }

/* The response time beside the live dot, not as a stat of its own. */
.dotms { margin-left: 6px; color: var(--ink-faint); font: 400 12px/1 var(--mono); vertical-align: middle; }

/* The way back out of a project's rail. Set apart from the screens under it,
 * because it leaves the project rather than moving inside it. */
nav a.back { color: var(--ink-faint); font-size: 13px; margin-bottom: 6px; }
nav a.back:hover { color: var(--accent); }
/* Only we get this item: marked with our mark, never labelled (Eric, 2026-11-12). */
nav a .ours-mark { width: 14px; height: 14px; margin-left: auto; opacity: .7; border-radius: 3px; }

/* ---- the full-catalogue browser --------------------------------------- */
.searchbar { display: flex; gap: 8px; align-items: center; padding: 12px 16px 0; flex-wrap: wrap; }
.searchbar input[type="search"] {
  flex: 1 1 260px; min-width: 0; padding: 7px 10px; font: 14px var(--sans);
  border: 1px solid var(--line); border-radius: 6px; background: var(--panel); color: var(--ink);
}
.searchbar input[type="search"]:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }
.searchbar button.primary {
  padding: 7px 14px; border: 0; border-radius: 6px; background: var(--accent); color: #fff;
  font: 600 13.5px var(--sans); cursor: pointer;
}
.searchbar button.primary:hover { filter: brightness(1.08); }

.pager { display: flex; gap: 12px; align-items: center; justify-content: center; padding: 12px 0 4px; }

.detail.italic { font-style: italic; }

/* ---- removing a row -----------------------------------------------------
 *
 *  Deliberately not a button beside Save. A link that opens a box, and the box
 *  will not submit without a typed reason — the reason IS the confirmation
 *  step, and it is the thing that makes the log entry readable a year later.
 */
.body.danger { border-top: 1px solid var(--line-soft); }
.linkbtn.quiet { color: var(--ink-faint); font-weight: 400; }
.linkbtn.quiet:hover { color: var(--bad); }
.removebox { margin-top: 10px; padding: 12px; border: 1px solid var(--bad); border-radius: 6px; background: var(--bad-soft); }
.removebox .detail { color: var(--bad); margin-bottom: 10px; }
.removeline { display: flex; gap: 8px; flex-wrap: wrap; }
.removeline input {
  flex: 1 1 260px; min-width: 0; padding: 7px 10px; font: 14px var(--sans);
  border: 1px solid var(--line); border-radius: 6px; background: var(--panel); color: var(--ink);
}
button.danger {
  padding: 7px 14px; border: 0; border-radius: 6px; background: var(--bad); color: #fff;
  font: 600 13.5px var(--sans); cursor: pointer;
}
button.danger:disabled { background: var(--unknown); cursor: not-allowed; }

/* ---- editing and withdrawing a comment --------------------------------- */
.btools { display: flex; gap: 10px; margin-top: 6px; }
.btools .linkbtn { font-size: 12px; }
.btools .linkbtn.armed { color: var(--bad); font-weight: 600; }
.bwhen.edited { font-style: italic; }
.bubble.withdrawn { opacity: 0.7; }
.bubble.withdrawn .btext { font-style: italic; }
.bubble:has(.bedit) { width: 100%; max-width: 100%; min-width: 0; }
.bedit { margin-top: 6px; }
.bedit textarea { display: block; min-height: 120px; overflow-y: auto; }
.bedit .removeline { margin-top: 6px; align-items: center; }

/* ---- asking a client something ----------------------------------------- */
.askform { display: flex; flex-direction: column; gap: 8px; padding: 12px 16px 16px; border-top: 1px solid var(--line-soft); }
.askform input[type="text"], .askform select {
  padding: 7px 10px; font: 14px var(--sans); border: 1px solid var(--line);
  border-radius: 6px; background: var(--panel); color: var(--ink);
}
.askform input[type="text"]:focus, .askform select:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }
.askrow { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.askrow input[type="text"] { flex: 0 1 180px; min-width: 0; }
.askrow .reqlabel { font-size: 13px; color: var(--ink-dim); cursor: pointer; }
.askform button.primary {
  padding: 7px 16px; border: 0; border-radius: 6px; background: var(--accent); color: #fff;
  font: 600 13.5px var(--sans); cursor: pointer;
}
.askform button.primary:disabled { background: var(--unknown); cursor: not-allowed; }

/* ---- a note, rendered ---------------------------------------------------
 *  The markdown is escaped before any markup is applied — see `markdown()` —
 *  so nothing here is defending against content, only laying it out.
 */
.md { padding: 4px 16px 18px; max-width: 78ch; }
.md h2, .md h3, .md h4, .md h5, .md h6 { margin: 20px 0 8px; line-height: 1.3; }
.md h2 { font-size: 20px; }
.md h3 { font-size: 17px; }
.md h4, .md h5, .md h6 { font-size: 15px; color: var(--ink-dim); }
.md p { margin: 0 0 12px; }
.md ul, .md ol { margin: 0 0 12px; padding-left: 22px; }
.md li { margin: 3px 0; }
.md code { font: 12.5px var(--mono); background: var(--unknown-soft); padding: 1px 4px; border-radius: 4px; overflow-wrap: anywhere; }
.md pre {
  background: var(--ink); color: #e8ecf4; padding: 12px 14px; border-radius: 6px;
  overflow-x: auto; margin: 0 0 14px;
}
.md pre code { background: none; color: inherit; padding: 0; font-size: 12.5px; }
.md blockquote {
  margin: 0 0 12px; padding: 4px 0 4px 14px; border-left: 3px solid var(--line);
  color: var(--ink-dim);
}
.md hr { border: 0; border-top: 1px solid var(--line); margin: 20px 0; }
.md a { color: var(--accent); overflow-wrap: anywhere; }

/* ---- a project's API: keys, a request you can send, and the reference -----
 *
 *  Eric, 2026-10-04: "a page for the API, being able to generate keys, have a
 *  playground and api docs that his clients will eventually use."
 *
 *  The one piece of deliberate loudness on this screen is `.reveal`. A minted
 *  key is shown exactly once and never again, so the moment it appears is the
 *  only moment it can be copied — a quiet row there is how somebody closes the
 *  tab and has to revoke a key they never used.
 */
.row.revoked .title { text-decoration: line-through; color: var(--ink-faint); }
.row.revoked .detail { color: var(--ink-faint); }

.reveal {
  margin: 14px 0; padding: 14px 16px; border: 2px solid var(--accent);
  border-radius: 8px; background: var(--accent-soft); display: grid; gap: 10px;
}
.revealhead { font: 600 13px var(--sans); color: var(--accent); text-transform: uppercase; letter-spacing: .04em; }
.revealkey {
  font: 13px/1.5 var(--mono); background: var(--panel); border: 1px solid var(--line);
  border-radius: 6px; padding: 10px 12px; overflow-wrap: anywhere; user-select: all;
}

.endpoint { padding: 14px 20px; border-top: 1px solid var(--line-soft); display: grid; gap: 7px; }
.endpointhead { display: flex; gap: 9px; align-items: baseline; flex-wrap: wrap; }
.endpointhead .verb {
  font: 600 11.5px var(--mono); padding: 2px 7px; border-radius: 4px;
  background: var(--unknown-soft); color: var(--ink-dim);
}
.endpointhead .verb.get { background: var(--ok-soft); color: var(--ok); }
.endpointhead .verb.post { background: var(--accent-soft); color: var(--accent); }
.endpointhead .route { font: 13.5px var(--mono); color: var(--ink); }
.endpointhead .api-cost { white-space: nowrap; }
.pull-refresh { position: fixed; top: env(safe-area-inset-top, 0px); left: 50%; transform: translateX(-50%); z-index: 100; padding: 10px 18px; border-radius: 0 0 12px 12px; background: var(--paper, white); color: var(--ink); box-shadow: 0 2px 10px #0002; font-size: 13px; }

.params { margin: 0; padding-left: 20px; display: grid; gap: 5px; font-size: 13.5px; }
.params code { font: 12.5px var(--mono); background: var(--unknown-soft); padding: 1px 5px; border-radius: 3px; }

/* Two names for one treatment, deliberately. `playfield` belongs to the
 * playground and `formfield` to the package form, and they are kept distinct
 * because a test has to be able to address one without matching the other —
 * sharing the class put the package name field first in the DOM and the
 * playground check started filling it instead. */
.playfields, .formfields { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); margin: 12px 0; }
.playfield, .formfield { display: grid; gap: 4px; }
.playfield > .label, .formfield > .label { font: 600 12px var(--sans); color: var(--ink-dim); }
.playfield input, .playfield select,
.formfield input, .formfield select { width: 100%; min-width: 0; }

.playresult { display: grid; gap: 8px; }
.payload {
  margin: 0; padding: 12px 14px; background: var(--ink); color: #e8ecf4;
  border-radius: 6px; font: 12px/1.55 var(--mono); overflow-x: auto;
  max-height: 420px; overflow-y: auto; white-space: pre-wrap; overflow-wrap: anywhere;
}

/* ---- the API screen's design system -------------------------------------
 *
 *  Eric, 2026-10-05: "remove all plaintext explainations, for stuff that
 *  really needs one add a infobox, several of the form fields are different
 *  design than others, even buttons differ designwise, hide revoked keys in
 *  an archive."
 *
 *  SCOPED TO `.card.api` ON PURPOSE. Three rules in this sheet already style
 *  `button.primary` at two classes of specificity — `.askform`, `.searchbar`,
 *  `form.record` — and a fourth global one would have been a tie decided by
 *  position in the file, i.e. a change to screens nobody reviewed. Three
 *  classes beats all of them and reaches exactly the four cards that opt in.
 *
 *  The `Run` button was the proof that this was needed: it carried
 *  `class="primary"` and matched no rule at all, because every primary rule
 *  in this sheet needed an `.askform` or `.searchbar` ancestor it did not
 *  have. It rendered as a raw browser button beside an accent-filled one.
 */

/* One button, four kinds, no fifth. */
.card.api button.primary,
.card.api button.secondary,
.card.api button.danger,
.screen.website-screen button.primary,
.screen.website-screen button.secondary,
.site-generator button.primary,
.site-generator button.secondary {
  padding: 7px 16px; border-radius: 6px; font: 600 13.5px var(--sans);
  cursor: pointer; border: 1px solid transparent; line-height: 1.3;
}
.card.api button.primary, .screen.website-screen button.primary, .site-generator button.primary { background: var(--accent); color: #fff; }
.screen.website-screen button:disabled, .site-generator button:disabled { opacity: 0.5; cursor: not-allowed; }
.card.api button.primary:hover:not(:disabled) { filter: brightness(1.08); }
.card.api button.secondary, .screen.website-screen button.secondary, .site-generator button.secondary {
  background: var(--panel); color: var(--ink-dim); border-color: var(--line);
}
.card.api button.secondary:hover:not(:disabled) { color: var(--accent); border-color: var(--accent); }
.card.api button.danger { background: var(--bad); color: #fff; }
.card.api button.danger:hover:not(:disabled) { filter: brightness(1.08); }
/* QUIET UNTIL IT IS AIMED AT. Five keys meant five filled red buttons running
 * down the card, which made the list read as an alarm — the loudest thing on
 * a screen should be the thing that is wrong, and nothing here is wrong. A
 * destructive action you deliberately armed stays solid; one that sits in
 * every row of a list is an outline that fills under the pointer. */
.card.api .row button.danger {
  background: transparent; color: var(--bad); border-color: var(--bad);
}
.card.api .row button.danger:hover:not(:disabled) {
  background: var(--bad); color: #fff; filter: none;
}
.card.api .row button.danger:disabled { background: transparent; color: var(--unknown); border-color: var(--line); }
.card.api button:disabled { opacity: 0.55; cursor: not-allowed; filter: none; }
.card.api button.primary:disabled { background: var(--unknown); opacity: 1; }
.card.api button.danger:disabled { background: var(--unknown); opacity: 1; }

/* One field. Every input type the API screen uses is named, because the one
 * that was missing — `input[type="email"]` on the client form — was drawn by
 * the browser while the text box beside it was drawn by this sheet. */
.card.api input[type="text"],
.card.api input[type="email"],
.card.api input[type="number"],
.card.api input[type="url"],
.card.api input[type="search"],
.card.api select {
  padding: 7px 10px; font: 14px var(--sans); border: 1px solid var(--line);
  border-radius: 6px; background: var(--panel); color: var(--ink);
  box-sizing: border-box;
}
.card.api input:focus, .card.api select:focus {
  outline: 2px solid var(--accent-soft); border-color: var(--accent);
}
.card.api input:disabled, .card.api select:disabled { opacity: 0.6; cursor: not-allowed; }
/* The flex fallback that used to size every control in an `.askrow` is gone:
 * on this screen an `.askrow` now holds buttons and a status line only. */
.card.api .askrow { align-items: center; }

/* A form's own heading. Four forms on two cards needed naming once the
 * paragraphs that used to introduce them came out. */
.card.api .formhead {
  margin: 0; font: 600 13px var(--sans); color: var(--ink-dim);
  text-transform: uppercase; letter-spacing: .05em;
}

/* The one fact per card that is not allowed to be behind a click. */
.infobox {
  display: flex; gap: 10px; align-items: flex-start; margin: 14px 0;
  padding: 11px 13px; border-radius: 7px; border: 1px solid var(--accent);
  background: var(--accent-soft); font-size: 13.5px; color: var(--ink-dim);
}
.infobox .infomark {
  flex: none; width: 18px; height: 18px; border-radius: 50%; background: var(--accent);
  color: #fff; font: 700 12px/18px var(--sans); text-align: center;
}
.infobox.warn { border-color: var(--warn); background: var(--warn-soft); }
.infobox.warn .infomark { background: var(--warn); }
.askform > .infobox:first-child, .askform > .formhead + .infobox { margin-top: 4px; }

/* Rows that are over. Folded, counted, never dropped. */
.archive { border-top: 1px solid var(--line-soft); }
.archive > summary {
  padding: 11px 20px; cursor: pointer; list-style: none;
  font: 600 12.5px var(--sans); color: var(--ink-faint);
  text-transform: uppercase; letter-spacing: .05em;
  display: flex; align-items: center; gap: 8px;
}
.archive > summary::-webkit-details-marker { display: none; }
.archive > summary::after { content: '▸'; margin-left: auto; font-size: 11px; }
.archive[open] > summary::after { content: '▾'; }
.archive > summary:hover { color: var(--accent); }
.archive[open] > summary { color: var(--ink-dim); }
.archive .rows > .row:first-child { border-top: 1px solid var(--line-soft); }

/* An endpoint is a route you can scan, with its detail one click in.
 *
 * `display: block` is not cosmetic. The rule above this one in the sheet sets
 * `display: grid`, and a `details` laid out as a grid keeps its contents on
 * screen when it is closed — the fold would have been a caret that did
 * nothing. */
.endpoint { padding: 0; display: block; }
.endpoint > summary.endpointhead {
  padding: 13px 20px; cursor: pointer; list-style: none;
}
.endpoint > summary::-webkit-details-marker { display: none; }
.endpoint > summary::after { content: '▸'; margin-left: auto; color: var(--ink-faint); font-size: 11px; }
.endpoint[open] > summary::after { content: '▾'; }
.endpoint > summary:hover { background: var(--accent-soft); }
.endpointbody { padding: 2px 20px 15px; display: grid; gap: 7px; }
.endpointblurb { color: var(--ink-dim); font-size: 13.5px; }

/* Go live: a progress bar and one tile per step still to do. */
.go-live-bar { height: 6px; margin: 4px 20px 0; border-radius: 3px; background: var(--line-soft); overflow: hidden; }
.go-live-bar > span { display: block; height: 100%; background: var(--accent); }
.go-live-steps { display: grid; gap: 10px; padding: 14px 20px 18px; }
.go-live-step { display: grid; grid-template-columns: 40px 1fr auto; gap: 12px; align-items: center;
  padding: 12px 14px; border: 1px solid var(--line-soft); border-radius: 12px; }
.go-live-logo { width: 40px; height: 40px; border-radius: 10px; background: var(--line-soft);
  display: grid; place-items: center; font-size: 20px; }
.go-live-logo img { width: 22px; height: 22px; }
.go-live-actions { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
.go-live-actions button.primary { background: var(--accent); color: #fff; border: 0; border-radius: 8px;
  padding: 8px 14px; font: inherit; font-weight: 600; cursor: pointer; }
.go-live-actions button.primary:disabled { opacity: .55; cursor: default; }
@media (max-width: 560px) { .go-live-step { grid-template-columns: 40px 1fr; } .go-live-actions { grid-column: 1 / -1; justify-content: stretch; } .go-live-actions button { flex: 1; } }

/* AI: pick the model by its logo. */
.ai-body { display: grid; gap: 14px; }
.ai-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; }
.ai-tile { position: relative; display: grid; justify-items: center; gap: 8px; padding: 18px 10px 14px;
  border: 1.5px solid var(--line-soft); border-radius: 14px; background: #fff; font: inherit; font-weight: 600; cursor: pointer; }
.ai-tile img { width: 32px; height: 32px; }
.ai-tile[aria-checked="true"] { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.ai-tile:disabled { cursor: default; opacity: .6; }
.ai-live { position: absolute; top: 8px; right: 8px; font-size: 10.5px; font-weight: 700; text-transform: uppercase;
  color: #fff; background: var(--ok, #1a7f37); padding: 2px 6px; border-radius: 6px; }
.ai-fp:empty { display: none; }
.ai-body .askrow input[type="password"] { flex: 1 1 260px; min-width: 0; padding: 9px 12px;
  border: 1px solid var(--line, #dfe3ec); border-radius: 8px; font: inherit; }
.ai-body .askrow { padding: 0; border: 0; }
.go-live-logo[data-logo="cloudflare"] { background: #f38020; }
.go-live-logo[data-logo="stripe"] { background: #635bff; }
.go-live-logo[data-logo="wise"] { background: #9fe870; }
.go-live-logo[data-logo="cloudflare"] img, .go-live-logo[data-logo="stripe"] img { filter: invert(1); }
.go-live-bar { margin-top: 12px; }

/* Eric, 2026-10-10: Billing and the three service panels in the Go live look —
   a logo by the heading, and the ladder as priced tiles with one button each. */
.go-live-logo[data-logo="netlify"] { background: #00c7b7; }
.go-live-logo[data-logo="twilio"] { background: #f22f46; }
.go-live-logo[data-logo="netlify"] img, .go-live-logo[data-logo="twilio"] img { filter: invert(1); }
.plan-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 12px; padding: 14px 20px 18px; }
.plan-tile { display: flex; flex-direction: column; gap: 10px; padding: 16px; border: 1.5px solid var(--line-soft);
  border-radius: 14px; background: #fff; min-width: 0; }
.plan-tile.current { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 14%, transparent); }
.plan-head { display: flex; align-items: center; gap: 10px; }
.plan-name { font-weight: 600; }
.plan-price strong { font-size: 28px; font-weight: 700; letter-spacing: -.02em; }
.plan-price span { color: var(--muted, #6b7280); margin-left: 2px; }
.plan-gets { margin: 0; padding: 0; list-style: none; display: grid; gap: 6px; font-size: 13px; color: var(--muted, #4b5563); }
.plan-gets li::before { content: '✓'; color: var(--accent); font-weight: 700; margin-right: 6px; }
.plan-foot { margin-top: auto; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.plan-foot button.primary { background: var(--accent); color: #fff; border: 0; border-radius: 8px; padding: 8px 14px;
  font: inherit; font-weight: 600; cursor: pointer; width: 100%; }
.plan-foot button.primary:disabled { opacity: .55; cursor: default; }
.plan-foot .crow { width: 100%; }
.plans > .evidence { padding: 0 20px 16px; }
.plan-current { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 12px; padding: 14px 20px 0; }
.plan-current-price { font-weight: 600; }
.plan-current-gets { flex-basis: 100%; font-size: 13px; color: var(--muted, #6b7280); }
.go-live-logo[data-logo="aldertwig"] { background: #fff; overflow: hidden; }
.go-live-logo[data-logo="aldertwig"] img { width: 40px; height: 40px; }
.plan-foot .crow { display: grid; gap: 6px; }
.plan-foot .crow button { width: 100%; border: 1.5px solid var(--accent); color: var(--accent); background: #fff;
  border-radius: 8px; padding: 8px 14px; font: inherit; font-weight: 600; cursor: pointer; }
.plan-foot .crow button:disabled { opacity: .55; cursor: default; }
.plan-foot .crow .cstatus { font-size: 12px; }

/* ---- the full-catalogue browser: filters, A–Z, sortable table ---------- */
.catcontrols { padding: 4px 16px 0; display: grid; gap: 8px; }
.catfilters { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.catfilters select {
  width: 190px; padding: 6px 26px 6px 10px; font: 13px var(--sans); color: var(--ink);
  border: 1px solid var(--line); border-radius: 999px; background-color: var(--panel);
  text-overflow: ellipsis; white-space: nowrap; overflow: hidden; cursor: pointer;
}
.catfilters select:hover { border-color: var(--accent); }
.catfilters select.on { border-color: var(--accent); background-color: var(--accent-soft); color: var(--accent); font-weight: 600; }
.catfilters .linkbtn { font-size: 13px; margin-left: 2px; }
.catcount { padding-top: 6px; padding-bottom: 0; font-size: 13.5px; }
.azbar { display: flex; flex-wrap: wrap; gap: 2px; font: 600 13px var(--sans); border-top: 1px solid var(--line-soft); padding-top: 8px; }
.azbar a, .azbar span { min-width: 24px; padding: 4px 6px; text-align: center; border-radius: 5px; }
.azbar a { color: var(--accent); text-decoration: none; }
.azbar a:hover { background: var(--accent-soft); }
.azbar a.on { background: var(--accent); color: #fff; }
.azbar span.off { color: var(--ink-faint); opacity: 0.45; }
.cattable { overflow-x: auto; padding: 8px 0 0; }
.cattable table { width: 100%; border-collapse: collapse; font-size: 14px; }
.cattable th, .cattable td { text-align: left; padding: 8px 12px; border-bottom: 1px solid var(--line-soft); vertical-align: top; }
.cattable th a { color: var(--ink-faint); font: 600 12.5px var(--sans); text-decoration: none; white-space: nowrap; }
.cattable th a.on, .cattable th a:hover { color: var(--accent); }
.cattable td .tag { margin-left: 8px; }
.cattable tr.open td:first-child { box-shadow: inset 3px 0 0 var(--bad, #dc2626); }

/* Cloudflare connection and the admin's explicit landing-domain action. */
.cloudflare-card > .detail { margin: 0; padding: 16px 20px; color: var(--ink-dim); }
.cloudflare-card > .crow { padding: 12px 20px; }
.cloudflare-card > .cstatus, .cloudflare-card > .reading { padding: 12px 20px; }
.cloudflare-actions .linky { display: block; margin-top: 12px; }
.cloudflare-actions .detail + .linky, .cloudflare-actions > .linky:first-child { margin-top: 0; }
.dns-records > summary { cursor: pointer; color: var(--ink-faint); font-size: 12.5px; width: max-content; }
.dns-records > summary:hover { color: var(--ink-dim); }
.dns-records[open] > summary { margin-bottom: 6px; }
.dns-records > .evidence { margin-bottom: 6px; }
.dns-table { width: 100%; table-layout: fixed; border-collapse: collapse; font: 12px/1.5 var(--mono); color: var(--ink-dim); }
.dns-table td { padding: 3px 10px 3px 0; border-top: 1px solid var(--line-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: top; }
.dns-table .dns-type { width: 56px; color: var(--ink-faint); }
.dns-table .dns-name { width: 32%; }
.dns-table .dns-proxy { width: 64px; color: var(--ink-faint); text-align: right; padding-right: 0; }
.cloudflare-actions { padding: 16px 20px; border-top: 1px solid var(--line-soft); }
.cloudflare-actions .detail { margin: 0 0 12px; color: var(--ink-dim); }
.cloudflare-actions button.primary { border: 0; border-radius: 8px; padding: 10px 16px; background: var(--accent); color: #fff; font: inherit; cursor: pointer; }
.cloudflare-actions button.primary:disabled { opacity: .55; cursor: default; }
.cattable .thumbcol { width: 72px; padding-right: 0; }
.cattable td.thumbcol { padding-top: 6px; padding-bottom: 6px; }
.cattable .thumb { display: block; width: 64px; height: 44px; border-radius: 6px; overflow: hidden;
  background: #fff; border: 1px solid var(--line-soft); }
.cattable .thumb img { width: 100%; height: 100%; object-fit: contain; display: block; }
.cattable .thumb.none { background: repeating-linear-gradient(135deg, var(--bg), var(--bg) 6px, #fff 6px, #fff 12px); }

/* ---- the picture on a record's edit page, and drawing a new one ------- */
.recimage { display: grid; gap: 10px; }
.recimage .frame { background: #fff; border: 1px solid var(--line-soft); border-radius: 10px; overflow: hidden;
  display: grid; place-items: center; min-height: 160px; }
.recimage .frame img { display: block; width: 100%; max-height: 520px; object-fit: contain; }
.recimage .frame .muted { padding: 40px 16px; }
.recimage .picbar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.drawer .picbar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.genbox { display: grid; gap: 10px; border: 1px solid var(--line); border-radius: 10px; padding: 12px; background: var(--bg); }
.genbox .keys { display: grid; gap: 6px; }
.genbox .keys label { display: flex; gap: 8px; align-items: baseline; font-size: 14px; }
.genbox .keys label.off { color: var(--ink-faint); }
.genbox .compare, .drawer .compare { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.genbox .compare figure, .drawer .compare figure { margin: 0; display: grid; gap: 4px; grid-template-rows: 1fr auto; }
.genbox .compare img, .drawer .compare img { width: 100%; background: #fff; border: 1px solid var(--line-soft); border-radius: 8px; object-fit: contain; max-height: 320px; }
.genbox .compare figcaption, .drawer .compare figcaption { font-size: 12.5px; color: var(--ink-faint); }
.genbox details summary { cursor: pointer; font-size: 13px; color: var(--ink-faint); }
.genbox details pre { white-space: pre-wrap; font-size: 12.5px; margin: 6px 0 0; }
@media (max-width: 640px) { .genbox .compare { grid-template-columns: 1fr; } .catfilters select { width: 100%; } }

/* The picture review on a catalogue screen. */
.recimage button.primary, .drawer button.primary, .picture-viewer button.primary {
  border: 0; border-radius: 8px; padding: 8px 14px; background: var(--accent); color: #fff;
  font: 600 13.5px/1.2 var(--sans); cursor: pointer;
}
.recimage button.primary:hover:not(:disabled), .drawer button.primary:hover:not(:disabled), .picture-viewer button.primary:hover:not(:disabled) { filter: brightness(1.08); }
.recimage button.primary:disabled, .drawer button.primary:disabled, .picture-viewer button:disabled { opacity: .55; cursor: default; }
.drawer .compare figure > .muted { display: grid; place-items: center; min-height: 120px; background: var(--bg);
  border: 1px dashed var(--line); border-radius: 8px; }
.rv-mini { width: 48px; height: 32px; }
.rv-title { margin: 8px 0 0; font-size: 15px; font-weight: 650; }
.rv-thumb { display: block; width: 64px; height: 44px; object-fit: contain; background: #fff;
  border: 1px solid var(--line-soft); border-radius: 6px; }
.rv-none { display: grid; place-items: center; color: var(--ink-faint); }

/* -------------------------------------------------------------- template
 *
 * Eric, 2026-10-10: one template across every page, at the Stripe / Twilio
 * bar. Page head, tabs, KPI strip, data table, drawer — see `pageHead`,
 * `tabStrip`, `kpis`, `dataTable` and `openDrawer` in app.js.
 */
.screen { display: grid; grid-template-columns: minmax(0, 1fr); gap: 18px; min-width: 0; }
.phead { gap: 0; }
.phead-row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; min-height: 36px; }
.phead-row h1 { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
/* A head with nothing left but its hidden name leaves the grid, so it takes
 * no row and no gap. */
.phead:not(:has(.phead-actions)):not(:has(.tabs)) { position: absolute; }
.phead-row:not(:has(.phead-actions)) { min-height: 0; }
.phead-actions { margin-left: auto; display: flex; flex-wrap: wrap; gap: 8px; }
.phead .tabs { margin-top: 14px; }

.tabs { display: flex; gap: 24px; border-bottom: 1px solid var(--line); overflow-x: auto; }
.tab {
  appearance: none; background: none; border: 0; border-bottom: 2px solid transparent;
  margin-bottom: -1px; padding: 8px 0 10px; font: 600 14px/1 var(--sans); color: var(--ink-dim);
  cursor: pointer; white-space: nowrap; display: inline-flex; align-items: center; gap: 7px;
}
.tab:hover { color: var(--ink); }
.tab.on { color: var(--accent); border-bottom-color: var(--accent); }
.tabcount {
  font: 600 11.5px/1 var(--sans); padding: 3px 7px; border-radius: 999px;
  background: var(--unknown-soft); color: var(--ink-dim);
}
.tab.on .tabcount { background: var(--accent-soft); color: var(--accent); }

.kpis {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px; overflow: hidden;
}
.kpi { padding: 14px 18px; border-left: 1px solid var(--line-soft); min-width: 0; }
.kpi:first-child { border-left: 0; }
.kpi-label { font-size: 12.5px; color: var(--ink-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kpi-value { font-size: 22px; font-weight: 650; letter-spacing: -0.01em; margin-top: 4px; font-variant-numeric: tabular-nums; }
.kpi-value.warn { color: var(--warn); }
.kpi-value.bad { color: var(--bad); }

.pill2 {
  display: inline-block; font: 600 12px/1 var(--sans); padding: 4px 8px; border-radius: 6px;
  background: var(--unknown-soft); color: var(--ink-dim); white-space: nowrap;
}
.pill2.ok { background: var(--ok-soft); color: var(--ok); }
.pill2.warn { background: var(--warn-soft); color: var(--warn); }
.pill2.bad { background: var(--bad-soft); color: var(--bad); }
.pill2.accent { background: var(--accent-soft); color: var(--accent); }
.pill2.unknown { background: transparent; border: 1px dashed var(--line); color: var(--unknown); }

.dtable { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; overflow: hidden; min-width: 0; }
.dt-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--line); }
.dt-search, .dt-filter {
  font: 13.5px/1.2 var(--sans); color: var(--ink); background: var(--panel);
  border: 1px solid var(--line); border-radius: 7px; padding: 7px 10px; height: 34px;
}
.dt-search { width: 260px; max-width: 100%; }
.dt-search:focus, .dt-filter:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }
.dt-count { font-size: 12.5px; color: var(--ink-faint); margin-left: 4px; font-variant-numeric: tabular-nums; }
.dt-actions { margin-left: auto; display: flex; gap: 8px; }
.dt-scroll { overflow-x: auto; }
table.dt { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.dt th {
  text-align: left; font: 600 12px/1 var(--sans); color: var(--ink-dim); padding: 0 14px; height: 36px;
  background: var(--rail); border-bottom: 1px solid var(--line); white-space: nowrap; position: sticky; top: 0;
}
.dt th.num, .dt td.num { text-align: right; font-variant-numeric: tabular-nums; }
.dt-sort { appearance: none; background: none; border: 0; padding: 0; font: inherit; color: inherit; cursor: pointer; }
.dt th.sorted { color: var(--ink); }
.dt th.sorted .dt-sort::after { content: ' ↑'; }
.dt th.sorted[data-dir="desc"] .dt-sort::after { content: ' ↓'; }
.dt td { padding: 10px 14px; border-bottom: 1px solid var(--line-soft); vertical-align: middle; white-space: nowrap; }
.dt tbody tr:last-child td { border-bottom: 0; }
.dt tr.dt-link { cursor: pointer; }
.dt tr.dt-link:hover td, .dt tr.dt-link:focus td { background: #f8f9fc; }
.dt tr.dt-link:focus { outline: none; }
.dt-empty td { color: var(--ink-faint); text-align: center; padding: 28px 14px; }
.cell-main { font-weight: 600; color: var(--ink); }
.cell-sub { font-size: 12.5px; color: var(--ink-faint); }
.cell-clip { display: inline-block; max-width: 340px; overflow: hidden; text-overflow: ellipsis; vertical-align: bottom; }
.mono { font-family: var(--mono); font-size: 12px; }
.dt-act { font-weight: 600; font-size: 13px; color: var(--accent); text-decoration: none; }
.dt-act:hover { text-decoration: underline; }
.dt-pager { display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding: 0 12px; }
.dt-pager:not(:empty) { padding: 10px 12px; border-top: 1px solid var(--line); }
.dt-page {
  font: 600 13px/1 var(--sans); background: var(--panel); color: var(--ink);
  border: 1px solid var(--line); border-radius: 7px; padding: 8px 12px; cursor: pointer;
}
.dt-page:disabled { color: var(--ink-faint); cursor: default; }
.dt-loading { color: var(--ink-faint); padding: 18px 0; }
table.dt-mini { border: 1px solid var(--line); border-radius: 8px; border-collapse: separate; border-spacing: 0; overflow: hidden; }
table.dt-mini th { position: static; }

.drawer-scrim { position: fixed; inset: 0; background: rgba(18, 28, 45, 0.28); z-index: 60; }
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(520px, 100vw); z-index: 61;
  background: var(--panel); border-left: 1px solid var(--line); box-shadow: -12px 0 32px rgba(18, 28, 45, 0.12);
  overflow-y: auto; animation: drawer-in 140ms ease-out;
}
@keyframes drawer-in { from { transform: translateX(24px); opacity: 0; } to { transform: none; opacity: 1; } }
.drawer-head {
  position: sticky; top: 0; background: var(--panel); z-index: 1;
  display: flex; align-items: flex-start; gap: 12px; padding: 20px 24px 16px; border-bottom: 1px solid var(--line);
}
.drawer-head h2 { margin: 0 0 6px; font-size: 19px; font-weight: 700; word-break: break-word; }
.drawer-sub { display: flex; gap: 8px; align-items: center; }
.drawer-x {
  margin-left: auto; appearance: none; background: none; border: 1px solid var(--line); border-radius: 7px;
  width: 32px; height: 32px; font-size: 20px; line-height: 1; color: var(--ink-dim); cursor: pointer; flex: none;
}
.drawer-sec { padding: 18px 24px; border-bottom: 1px solid var(--line-soft); display: grid; gap: 10px; }
.drawer-sec h3 { margin: 0; font-size: 13px; font-weight: 650; color: var(--ink); }
dl.fields { margin: 0; display: grid; grid-template-columns: 130px 1fr; row-gap: 9px; column-gap: 16px; font-size: 13.5px; }
dl.fields dt { color: var(--ink-dim); }
dl.fields dd { margin: 0; color: var(--ink); word-break: break-word; }
a.btn {
  display: inline-block; font: 600 13.5px/1 var(--sans); background: var(--accent); color: #fff;
  border-radius: 7px; padding: 10px 14px; text-decoration: none;
}
a.btn:hover { filter: brightness(1.08); }

@media (max-width: 760px) {
  .dt-search { width: 100%; }
  .kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kpi { border-left: 0; border-top: 1px solid var(--line-soft); padding: 10px 14px; }
  .kpi:nth-child(-n+2) { border-top: 0; }
  .kpi:nth-child(even) { border-left: 1px solid var(--line-soft); }
  .kpi-value { font-size: 19px; }
  .dt th, .dt td { padding-left: 10px; padding-right: 10px; }
  dl.fields { grid-template-columns: 1fr; row-gap: 2px; }
  dl.fields dd { margin-bottom: 8px; }
}
.drawer a:not(.btn):not(.dt-act) { color: var(--accent); text-decoration: none; font-weight: 600; }

/* A capture in a table row. Top-anchored: a homepage is read from the top. */
.dt-thumb { display: block; width: 72px; height: 45px; border: 1px solid var(--line-soft); border-radius: 4px; overflow: hidden; background: var(--bg); }
.dt-thumb img { width: 100%; height: 100%; object-fit: cover; object-position: top center; display: block; }
.dt-name { display: inline-flex; align-items: center; gap: 8px; font-weight: 600; color: var(--ink); }

/* The client's project: the live shot beside what it is. */
.client-about { display: grid; grid-template-columns: minmax(0, 320px) minmax(0, 1fr); gap: 20px; align-items: start; }
.client-about .shot { margin: 0; }
.client-about p { margin: 12px 0 0; line-height: 1.55; }
.client-about.no-shot { display: block; }
@media (max-width: 720px) { .client-about { grid-template-columns: 1fr; } }

.device-previews { display: flex; flex-wrap: wrap; justify-content: center; align-items: flex-end; gap: 28px; padding: 20px; overflow: hidden; }
.device { position: relative; flex: none; }
.device-body { position: absolute; left: 0; top: 0; transform-origin: 0 0; }
.device-link { position: absolute; inset: 0; z-index: 1; border-radius: 12px; }
.device iframe { display: block; border: 0; background: #fff; transform-origin: 0 0; pointer-events: none; }

/* Key Vault: one picker per use, above the keys table. */
.ai-uses { display: flex; flex-wrap: wrap; gap: 12px 24px; margin: 4px 0 16px; }
.ai-use { display: grid; gap: 4px; min-width: 220px; }
.ai-use select { padding: 7px 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--card, #fff); font: inherit; }
.ai-logo { width: 16px; height: 16px; vertical-align: -3px; margin-right: 6px; }
.ai-add { display: grid; gap: 12px; }
.ai-add input[type="text"], .ai-add input[type="password"] { padding: 9px 12px; border: 1px solid var(--line); border-radius: 8px; font: inherit; }
.ai-use-boxes { display: flex; flex-wrap: wrap; gap: 8px 16px; }
.ai-use-box input:disabled + * , .ai-use-box:has(input:disabled) { color: var(--ink-faint); }

/* Remove an Update from Latest work. Quiet until hovered; the second click is
   the confirmation, so the armed state reads as a question. */
.dt-x { appearance: none; background: none; border: 0; padding: 2px 6px; border-radius: 6px; font: 600 15px/1 var(--sans); color: var(--ink-faint); cursor: pointer; }
.dt-x:hover { color: var(--bad); background: var(--bad-soft); }
.dt-x.armed { font-size: 12.5px; color: var(--bad); background: var(--bad-soft); }

/* ONE CHEVRON FOR EVERY SELECT. Eric, 2026-10-11: the native arrow sat hard
   against the right edge. Drawn here instead, inset 10px, with room reserved
   for it. Longhands with !important because several form rules set the
   `background` shorthand, which resets background-image — a chevron that
   silently vanished on half the selects is the bug this replaces. */
select:not([multiple]) {
  appearance: none !important;
  -webkit-appearance: none !important;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5l3 3 3-3' fill='none' stroke='%235a6577' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") !important;
  background-repeat: no-repeat !important;
  background-position: right 10px center !important;
  background-size: 12px 12px !important;
  padding-right: 30px !important;
}

/* Comment actions stay in the top corner and open on click or keyboard. */
.bubble { position: relative; }
.bubble:has(.comment-menu) .bhead { padding-right: 38px; }
.comment-menu { position: absolute; top: 1px; right: 1px; }
.comment-menu-toggle { cursor: pointer; list-style: none; display: grid; place-items: center; width: 36px; height: 36px; color: var(--ink); border-radius: 6px; }
.comment-menu-toggle svg { display: block; }
.comment-menu-toggle::-webkit-details-marker { display: none; }
.comment-menu-toggle:hover, .comment-menu-toggle:focus-visible { background: var(--line-soft); }
.comment-menu[open] { z-index: 2; }
.comment-menu-actions { position: absolute; right: 0; min-width: 120px; padding: 5px; display: grid; gap: 4px; background: var(--panel); border: 1px solid var(--line); border-radius: 8px; box-shadow: 0 4px 14px #0002; }
.comment-menu-actions button { text-align: left; padding: 8px 12px; }
.comment-menu-actions .err { padding: 6px; font-size: 12px; }

/* Website enquiries are usually a single message, not a work table. */
.website-enquiry { padding: 18px 20px; }
.website-enquiry + .website-enquiry { border-top: 1px solid var(--line-soft); }
.enquiry-meta { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; font-size: 12px; }
.enquiry-message { margin: 14px 0 18px; white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.6; }
.website-enquiry .linkbtn { max-width: 100%; white-space: normal; overflow-wrap: anywhere; }

/* Customer welcome and inbox use the dashboard's existing cards and buttons. */
.customer-steps { margin: 0; padding: 0 20px 8px 44px; }
.customer-step { padding: 18px 0; }
.customer-step + .customer-step { border-top: 1px solid var(--line-soft); }
.customer-step-title { display: inline-block; margin-right: 20px; font-weight: 600; }
.customer-home-status { color: var(--ink-dim); font-size: 13px; }
.website-enquiries .tabs { padding: 0 20px; }
.enquiry-sender { margin-top: 12px; font-weight: 600; overflow-wrap: anywhere; }
.enquiry-contact { margin-top: 4px; font-size: 13px; overflow-wrap: anywhere; }
.enquiry-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.enquiry-actions .linkbtn { min-height: 36px; display: inline-flex; align-items: center; cursor: pointer; }
.enquiry-actions button:disabled { opacity: .5; cursor: wait; }
@media (max-width: 600px) {
  .customer-step-title { display: block; margin-bottom: 10px; }
}

/* Species approval viewer: native modal keeps the underlying drawer inert. */
.picture-open { display: block; padding: 0; border: 0; background: transparent; cursor: zoom-in; width: 100%; }
.picture-open:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.picture-viewer { position: fixed; inset: 0; margin: 0; width: 100vw; height: 100dvh; max-width: none; max-height: none; border: 0; padding: 0; background: var(--bg); color: var(--ink); }
.picture-viewer[open] { display: grid; grid-template-rows: auto minmax(0, 1fr) auto auto; }
.picture-viewer-head, .picture-viewer-actions { display: flex; align-items: center; gap: 12px; padding: 16px 24px; background: var(--surface, #fff); }
.picture-viewer-head { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); border-bottom: 1px solid var(--line-soft); }
.picture-viewer-head h2 { font-size: 18px; margin: 0; }
.picture-viewer-stage { min-height: 0; padding: 16px; display: grid; grid-template-columns: 44px minmax(0, 1fr) 44px; gap: 8px; align-items: center; touch-action: pan-y pinch-zoom; }
.picture-viewer-stage img { width: 100%; height: 100%; min-width: 0; min-height: 0; object-fit: contain; }
.picture-viewer-actions { justify-content: center; flex-wrap: wrap; border-top: 1px solid var(--line-soft); padding-bottom: max(16px, env(safe-area-inset-bottom)); }
.picture-viewer-status { text-align: center; padding: 4px 16px; }
@media (max-width: 600px) { .picture-viewer-head, .picture-viewer-actions { padding-left: 12px; padding-right: 12px; gap: 8px; } .picture-viewer-stage { padding: 4px; } }

.picture-viewer button { min-height: 44px; }

.picture-viewer-arrow { width: 44px; padding: 0; font-size: 32px; text-align: center; }
.picture-viewer-count { text-align: center; font-size: 12px; font-weight: 700; }
.picture-viewer-head > button { justify-self: end; }
.picture-viewer-head h2 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.picture-viewer-status:empty { display: none; }

.image-key-picker { width: min(480px, calc(100vw - 32px)); box-sizing: border-box; max-height: 90dvh; overflow: auto; border: 1px solid var(--line-soft); border-radius: 12px; padding: 24px; background: var(--bg); color: var(--ink); }
.image-key-picker::backdrop { background: #0008; }
.image-key-list { display: grid; gap: 10px; margin-bottom: 16px; }
.image-key-option { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; padding: 12px; border: 1px solid var(--line-soft); border-radius: 8px; cursor: pointer; }
.image-key-option img { width: 24px; height: 24px; }
.image-key-option small { font-size: 11px; }


/* Generation picker and image approval controls. */
.image-key-picker { position: fixed; }
.image-key-picker h2 { text-align: center; margin: 0 32px 24px; }
.image-key-picker .image-key-close { position: absolute; top: 20px; right: 24px; }
.image-key-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.image-key-option { position: relative; flex-direction: column; justify-content: center; text-align: center; min-height: 100px; min-width: 0; }
.image-key-option:has(input:checked) { border-color: var(--blue, #2563eb); background: #2563eb12; }
.image-key-option input { position: absolute; top: 8px; left: 8px; }
.image-key-option img { width: 32px; height: 32px; }
.image-key-picker .image-key-add { margin: 0; background: transparent; color: inherit; }
.image-key-always { display: flex; align-items: center; gap: 5px; justify-content: center; font-size: 12px; color: var(--muted); margin: 12px 0; }
.picbar .action-generate, .picture-viewer-actions .action-generate { margin-left: auto; }
.picture-entry-open { margin-left: 8px; padding: 2px 6px; font-size: 16px; vertical-align: middle; }
.key-spinner { width: 24px; height: 24px; margin: 32px auto; border: 3px solid #8884; border-top-color: #15803d; border-radius: 50%; animation: key-spin .8s linear infinite; }
@keyframes key-spin { to { transform: rotate(360deg); } }

/* Shared actions: identical geometry across drawers, viewers and key selection. */
button.action-button {
  appearance: none; display: inline-flex; align-items: center; justify-content: center;
  box-sizing: border-box; min-height: 0; margin: 0; border: 0; border-radius: 8px;
  padding: 8px 14px; font: 600 13.5px/1.2 var(--sans); color: #fff; cursor: pointer;
}
button.action-approve { background: #2563eb; }
button.action-reject { background: #b91c1c; }
button.action-generate { background: #15803d; }
button.action-button:hover:not(:disabled) { filter: brightness(1.08); }
button.action-button:disabled { opacity: .55; cursor: default; }
.image-key-picker .action-generate { display: flex; margin: 0 auto; }
.image-key-add { appearance: none; font: inherit; border: 1px solid var(--line); }
.image-key-plus { position: relative; display: block; width: 32px; height: 32px; border-radius: 50%; background: linear-gradient(#00bde9, #4266ff); }
.image-key-plus::before, .image-key-plus::after { content: ''; position: absolute; background: white; border-radius: 2px; }
.image-key-plus::before { width: 18px; height: 4px; left: 7px; top: 14px; }
.image-key-plus::after { width: 4px; height: 18px; left: 14px; top: 7px; }

.image-prompt-editor { display: block; box-sizing: border-box; width: 100%; min-height: 260px; max-height: 50dvh; resize: vertical; padding: 12px; margin: 0 0 16px; border: 1px solid var(--line); border-radius: 8px; background: var(--bg); color: var(--ink); font: 13px/1.5 var(--sans); }

/* A row action in a table, drawn as the link the "View as" cell already is. */
.dt button.dt-act { background: none; border: 0; padding: 0; cursor: pointer; font-family: var(--sans); }
.dt button.dt-act:disabled { color: var(--unknown); cursor: default; text-decoration: none; }
.plans-editor { margin-top: 18px; }

/* Website screen: Jose's title, subtitle, favicon and link image. */
.site-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 420px); gap: 24px; margin-top: 12px; }
@media (max-width: 900px) { .site-grid { grid-template-columns: 1fr; } }
.site-form { display: grid; gap: 14px; }
.site-form textarea { width: 100%; box-sizing: border-box; font: inherit; }
.site-count { margin-left: auto; font-size: 11.5px; font-weight: 400; color: var(--ink-faint); }
.site-pictures { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; margin-top: 20px; }
@media (max-width: 560px) { .site-pictures { grid-template-columns: 1fr; } }
.site-picture { display: grid; gap: 6px; align-content: start; }
.site-picture > .label { font: 600 12px var(--sans); color: var(--ink-dim); }
.site-picture img, .site-picture video, .site-empty { display: block; box-sizing: border-box; width: 100%; height: 96px; object-fit: contain; border: 1px solid var(--line); border-radius: 8px; background: var(--rail); }
.site-empty { display: grid; place-items: center; color: var(--ink-faint); }
.site-picture .cell-sub { font-size: 11.5px; line-height: 1.4; min-height: 2.8em; }
.site-serp { border: 1px solid var(--line); border-radius: 8px; padding: 12px 14px; }
.serp-site { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ink-dim); }
.serp-site img { width: 18px; height: 18px; border-radius: 50%; }
.serp-title { color: #1a0dab; font-size: 18px; margin: 4px 0 2px; }
.serp-sub { font-size: 13px; color: var(--ink-dim); }
.site-card { border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.site-card .card-img { display: block; width: 100%; aspect-ratio: 1200 / 630; object-fit: cover; }
.site-card .card-img.none { display: grid; place-items: center; color: var(--ink-faint); background: var(--rail); }
.site-card .card-text { padding: 10px 12px; display: grid; gap: 2px; }
.site-card .card-host { font-size: 11.5px; color: var(--ink-faint); text-transform: uppercase; }
.site-card .card-title { font-weight: 600; }
.site-card .card-sub { font-size: 13px; color: var(--ink-dim); }
.site-form input[type="text"], .site-form input[type="email"], .site-form input[type="url"], .site-form textarea { padding: 9px 12px; border: 1px solid var(--line); border-radius: 8px; font: inherit; }
.site-picture .picbar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.site-form .picbar { display: flex; gap: 8px; align-items: center; }
.site-previews { display: grid; gap: 14px; align-content: start; }
.site-previews .formhead { margin: 0 0 -8px; font: 600 12px var(--sans); color: var(--ink-dim); }
.screen.website-screen .tile-button, .site-picture button.bolt { position: static; display: inline-grid; place-items: center; width: 32px; height: 32px; padding: 0; margin: 0; border: 1px solid var(--line); border-radius: 8px; background: var(--panel, #fff); color: var(--ink-dim); cursor: pointer; }
.screen.website-screen .tile-button:hover:not(:disabled) { color: var(--ink); background: var(--rail); }
.site-picture button.bolt { transform: none; }
.generator .image-key-option.unavailable { opacity: 0.45; cursor: not-allowed; filter: grayscale(1); }
.generator .site-generator-result video { display: block; width: 100%; border-radius: 8px; border: 1px solid var(--line-soft); margin-bottom: 10px; }

/* Generate on the Website screen (site-generate). */
.site-form .formfield > .label { display: flex; align-items: center; gap: 8px; }
.screen.website-screen .site-form .site-generate { margin-left: auto; padding: 2px 10px; font-size: 12px; }
.site-generator .image-key-list { grid-template-columns: 1fr; }
.site-generator .model-name { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; }
.site-generator .image-key-option img { width: 32px; height: 32px; border-radius: 6px; }
.site-generator .site-generator-hint { min-height: 72px; margin: 0; }
.site-generator-result img { display: block; width: 100%; border-radius: 8px; border: 1px solid var(--line); margin: 12px 0 8px; }
.site-generator-result .picbar { display: flex; gap: 8px; justify-content: center; margin-bottom: 8px; }
.site-generator-result .picbar .action-generate { margin: 0; }
.site-generator .formfield { margin-bottom: 16px; }

/* Personal settings keep labels and controls usable on a phone. */
.settings-form { display: grid; gap: 16px; max-width: 640px; }
.settings-form label:not(.settings-check) { display: grid; gap: 6px; }
.settings-form input:not([type=checkbox]) { width: 100%; box-sizing: border-box; padding: 10px; }
.settings-form .settings-check { display: flex; align-items: center; gap: 10px; margin: 12px 0; }
.settings-form .profile-photo { width: 80px; height: 80px; border-radius: 50%; object-fit: cover; }
.settings-form section { display: grid; gap: 12px; }
.settings-form input:not([type=checkbox]), .settings-form button {
  font: inherit; color: var(--ink); background: var(--panel);
  border: 1px solid var(--line); border-radius: 7px; min-height: 42px;
}
.settings-form button { cursor: pointer; padding: 9px 14px; }
.settings-form button:hover { border-color: var(--accent); }
.settings-form button.primary { background: var(--accent); color: white; border-color: var(--accent); }
.settings-form button:disabled { opacity: .55; cursor: wait; }
.settings-form input:focus-visible, .settings-form button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.settings-form input[type=checkbox] { accent-color: var(--accent); width: 18px; height: 18px; flex: 0 0 auto; }
.settings-form fieldset { border: 1px solid var(--line); border-radius: 8px; padding: 14px; min-width: 0; }
.settings-form p { margin: 0; }
.settings-form section { border-top: 1px solid var(--line); padding-top: 12px; }
.settings-form .cstatus:empty { display: none; }

.profile-avatar-wrap { position: relative; width: 160px; margin: 8px auto 16px; }
.profile-avatar { width: 160px; height: 160px; box-sizing: border-box; border-radius: 50%; padding: 5px; background: linear-gradient(135deg, #3686ff, #b2a0ff); display: grid; place-items: center; font-size: 48px; color: white; overflow: hidden; }
.profile-avatar img { width: 100%; height: 100%; min-height: 0; border-radius: 50%; object-fit: cover; border: 3px solid var(--panel); box-sizing: border-box; }
.settings-form .profile-photo-edit { position: absolute; bottom: 3px; right: -3px; width: 42px; height: 42px; padding: 0; border-radius: 50%; border: 3px solid var(--panel); background: var(--ink); color: white; font-size: 27px; line-height: 1; }
.profile-photo-dialog .profile-avatar { margin: 0 auto 12px; }
.profile-photo-dialog[open] { display: grid; }
.profile-photo-dialog:not([open]) { display: none; }
.profile-photo-dialog .image-key-close { min-height: 32px; }
.settings-form .notification-toggle { display: flex !important; flex-direction: row; align-items: center; gap: 12px; font-weight: 600; cursor: pointer; }
.notification-toggle input { position: absolute; opacity: 0; width: 1px !important; height: 1px !important; }
.toggle-track { margin-left: auto; width: 44px; height: 26px; border-radius: 20px; background: #919aa9; position: relative; transition: background .15s; flex: 0 0 auto; }
.toggle-track::after { content: ''; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%; background: white; transition: transform .15s; }
.notification-toggle input:checked + .toggle-track { background: var(--accent); }
.notification-toggle input:checked + .toggle-track::after { transform: translateX(18px); }
.notification-toggle input:focus-visible + .toggle-track { outline: 2px solid var(--accent); outline-offset: 3px; }
.notification-toggle input:disabled + .toggle-track { opacity: .45; }
.notification-control p { margin-top: 8px; }
.settings-form fieldset:disabled { opacity: .45; }

/* ⚡ inside the right edge of an editable text field: the one generator, for that field. */
.bolted { position: relative; display: block; width: 100%; min-width: 0; }
/* !important: a screen's own input rule sets `padding` and would put the text under the ⚡. */
.bolted > input, .bolted > textarea { display: block; width: 100%; padding-right: 38px !important; box-sizing: border-box; }
button.bolt { position: absolute; top: 6px; right: 5px; display: grid; place-items: center; width: 28px; height: 28px; padding: 0; margin: 0; border: 0; border-radius: 6px; background: transparent; color: #15803d; font-size: 14px; line-height: 1; cursor: pointer; }
.bolted > input + button.bolt { top: 50%; transform: translateY(-50%); }
button.bolt:hover:not(:disabled) { background: #15803d12; }
button.bolt:disabled { opacity: 0.4; cursor: not-allowed; }
.generator .generator-model { display: block; margin: 0 auto 10px; font-size: 12.5px; }
.generator .image-prompt-editor { width: 100%; box-sizing: border-box; margin-bottom: 12px; }
.generator .site-generator-result img { width: 100%; border-radius: 8px; border: 1px solid var(--line-soft); margin-bottom: 10px; }
.image-key-option .model-name { display: inline-flex; align-items: center; gap: 6px; }
.release-note { white-space: pre-wrap; overflow-wrap: anywhere; margin: 0; }

/* ---- Developer: Docs widget card and the Daily Bag screen ---------------- */
.card.api .snippet { position: relative; margin-bottom: 14px; }
.card.api .snippet .payload { padding-right: 84px; }
.card.api .snippet button { position: absolute; top: 8px; right: 8px; }
.card.api[data-widget] .dt-scroll { margin-top: 12px; }
.card.api[data-widget] td code { font: 12.5px var(--mono); }
.bag-screen .bag-bar, .bag-screen .bag-make { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; margin-bottom: 16px; }
.bag-screen .bag-bar .formfield, .bag-screen .bag-make .formfield { width: 220px; }
.bag-screen .bag-bar .note { padding-bottom: 8px; }
.bag-screen .bag-stage { display: flex; justify-content: center; padding: 24px 0 8px; }
.bag-screen .bag-stage fishy-bag { width: 100%; max-width: 440px; }

.identification-page { display: grid; gap: 16px; }
.identification-page .dt-actions { align-items: center; flex-wrap: wrap; }
.identification-page .btn, .identification-dialog .btn {
  display: inline-flex; align-items: center; gap: 6px; height: 34px; padding: 0 12px; border: 1px solid var(--line); border-radius: 7px;
  background: var(--panel); color: var(--ink); font: 600 13px/1 var(--sans); cursor: pointer; white-space: nowrap;
}
.identification-page .btn.primary, .identification-dialog .btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.identification-page .btn:disabled, .drawer .identification-review .btn:disabled { opacity: .5; cursor: default; }
.identification-refresh { font-size: 16px; }
.identification-chosen img { width: 16px; height: 16px; object-fit: contain; }
.identification-chosen span { max-width: 180px; overflow: hidden; text-overflow: ellipsis; }
.identification-status { font-size: 12.5px; color: var(--ink-dim); max-width: 320px; }
.identification-thumb { width: 56px; height: 40px; }
.identification-thumb img { object-fit: cover; object-position: center; }

.identification-comparison { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.identification-comparison figure { margin: 0; min-width: 0; }
.identification-comparison figcaption { font-size: 12px; color: var(--ink-dim); margin-bottom: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.identification-comparison img { display: block; width: 100%; height: 160px; object-fit: contain; background: var(--bg); border: 1px solid var(--line-soft); border-radius: 6px; }
.identification-no-photo { display: grid; place-items: center; height: 160px; background: var(--bg); border-radius: 6px; color: var(--ink-faint); }
.identification-reasoning { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--ink); }
.identification-review { display: grid; gap: 10px; }
.identification-review .btn {
  display: inline-flex; align-items: center; height: 32px; padding: 0 12px; border: 1px solid var(--line); border-radius: 7px;
  background: var(--panel); color: var(--ink); font: 600 13px/1 var(--sans); cursor: pointer;
}
.identification-review .btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.identification-review-actions { display: flex; gap: 8px; }
.identification-review-actions .identification-delete { margin-left: auto; color: var(--bad); }
.identification-correction:not([hidden]) { display: grid; gap: 8px; }
.identification-correction input { height: 34px; padding: 0 10px; border: 1px solid var(--line); border-radius: 7px; font: 13.5px var(--sans); }
.identification-correction-actions { display: flex; gap: 8px; }
.identification-message { margin: 0; font-size: 12.5px; color: var(--ink-dim); }
.identification-message:empty { display: none; }
.identification-matches { max-height: 240px; overflow-y: auto; display: grid; gap: 4px; }
.identification-match { display: flex; align-items: center; gap: 10px; width: 100%; padding: 6px 8px; border: 1px solid var(--line-soft); border-radius: 6px; background: var(--panel); color: var(--ink); text-align: left; cursor: pointer; font: 13px var(--sans); }
.identification-match img { width: 44px; height: 32px; object-fit: contain; flex: none; }
.identification-match small { display: block; color: var(--ink-dim); font-style: italic; }

.identification-dialog { width: min(440px, calc(100vw - 48px)); border: 1px solid var(--line); border-radius: 12px; padding: 20px; color: var(--ink); }
.identification-dialog::backdrop { background: #0006; }
.identification-dialog h2 { margin: 0 0 14px; font-size: 15px; }
.identification-providers { display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); gap: 8px; }
.identification-provider { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px; min-height: 70px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel); padding: 8px 4px; color: var(--ink); font: 12px var(--sans); cursor: pointer; text-decoration: none; }
.identification-provider img { width: 22px; height: 22px; object-fit: contain; }
.identification-provider[aria-pressed="true"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); background: var(--accent-soft); }
.identification-provider:disabled { opacity: .5; cursor: default; }
.identification-provider small { font-size: 10px; color: var(--ink-dim); }
.identification-add-icon { font-size: 26px; line-height: 1; font-weight: 300; }
.identification-model { display: flex; align-items: center; gap: 10px; margin: 16px 0; font-size: 12.5px; color: var(--ink-dim); }
.identification-model select { flex: 1; min-width: 0; height: 34px; padding: 0 8px; border: 1px solid var(--line); border-radius: 7px; font: 13.5px var(--sans); }
/* In the modal the shared input rule sets 16px type and 10px padding, which a
   34px box clipped to half a line (Eric, 2026-10-30). Let the modal size it. */
dialog.app-modal .identification-model select { height: auto; }
/* Done: a button, not a full-width bar. */
dialog.app-modal.identification-dialog > .btn.primary { justify-self: center; justify-content: center; min-width: 120px; }
@media (max-width: 760px) {
  .identification-page .dt-actions { margin-left: 0; width: 100%; }
  .identification-status { order: 5; flex-basis: 100%; }
}

/* Integrations — an App Store shelf, not a table (Eric, 2026-10-21). */
.app-shelf { margin: 22px 0 10px; font-size: 13px; font-weight: 600; letter-spacing: .02em; color: var(--ink-dim); }
.app-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; }
.app-tile { display: grid; grid-template-columns: 64px 1fr auto; grid-template-areas: "icon text act" "icon state state";
  column-gap: 14px; row-gap: 6px; align-items: center; padding: 16px; background: var(--panel); border: 1px solid var(--line);
  border-radius: 16px; transition: box-shadow .15s, transform .15s; }
.app-tile:hover { box-shadow: 0 6px 20px rgba(18, 28, 45, .08); transform: translateY(-1px); }
.app-icon { grid-area: icon; width: 64px; height: 64px; border-radius: 15px; display: grid; place-items: center;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .06), 0 2px 6px rgba(18, 28, 45, .12); }
.app-icon img { width: 34px; height: 34px; filter: brightness(0) invert(1); }
.app-text { grid-area: text; min-width: 0; }
.app-name { font-weight: 600; font-size: 16px; }
.app-kind { font-size: 13px; color: var(--ink-faint); }
.app-act { grid-area: act; }
.app-state { grid-area: state; font-size: 12.5px; display: flex; gap: 10px; align-items: center; min-height: 18px; min-width: 0; }
.app-state > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app-get { display: inline-block; min-width: 76px; padding: 5px 16px; border-radius: 999px; border: 0; background: var(--accent-soft);
  color: var(--accent); font: 600 13px/1.4 var(--sans); text-align: center; cursor: pointer; }
.app-get:hover:not(:disabled) { background: var(--accent); color: #fff; }
.app-get:disabled { opacity: .5; cursor: default; }
.app-get.done { background: var(--ok-soft); color: var(--ok); min-width: 0; padding: 5px 11px; cursor: default; }
.app-get.off { background: var(--unknown-soft); color: var(--ink-faint); cursor: default; }
.app-on { color: var(--ok); }
.app-dim { color: var(--ink-faint); }
.app-err { color: var(--bad); }
.app-off { font-size: 12.5px; margin-left: auto; }
.app-tile:has(.app-accounts) { grid-template-areas: "icon text act" "icon state state" "icon list list"; }
.app-accounts { grid-area: list; margin: 0; padding: 0; list-style: none; font-size: 12.5px; color: var(--ink-dim); }
.app-accounts li { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app-tile.soon .app-icon { opacity: .45; filter: grayscale(.3); }
.app-tile.soon .app-name { color: var(--ink-dim); }

/* ----------------------------------------------------------- rolodex */
/* Eric, 2026-10-22: "Make the profiles very visual." Picture-led tiles in the
   directory, a cover-photo hero on each profile, every contact a button. */

.rx-bar { display: flex; gap: 10px; margin: 4px 0 16px; }
.rx-search {
  flex: 1; max-width: 420px; padding: 9px 12px; font: inherit; font-size: 14px;
  border: 1px solid var(--line); border-radius: 8px; background: var(--panel); color: var(--ink);
}
.rx-search:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }
.rx-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 14px; }
.visual-tile, .rx-tile {
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: 6px;
  padding: 20px 14px 16px; background: var(--panel); border: 1px solid var(--line); border-radius: 14px;
  color: var(--ink); text-decoration: none; transition: border-color .15s, box-shadow .15s, transform .15s;
  min-width: 0;
}
.rx-tile:hover { border-color: var(--accent); box-shadow: 0 6px 20px rgba(18, 28, 45, .08); transform: translateY(-1px); }
.rx-tile-name { font-weight: 650; font-size: 15px; margin-top: 6px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rx-tile-sub { font-size: 12.5px; color: var(--ink-dim); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rx-tile-brand { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--ink-dim); max-width: 100%; }
.rx-tile-brand span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rx-tile-facts { font-size: 12px; color: var(--ink-faint); margin-top: 2px; }
.rx-tile-facts b { color: var(--ink); font-weight: 600; }
.rx-tile-tags, .rx-tags { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; }
.rx-tags { justify-content: flex-start; margin-top: 8px; }
.visual-tag, .rx-tag {
  display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 11.5px; font-weight: 600;
  background: var(--accent-soft); color: var(--accent); white-space: nowrap;
}
.rx-foot { display: flex; justify-content: center; padding: 18px 0; }
.rx-empty { grid-column: 1 / -1; padding: 40px; text-align: center; color: var(--ink-faint); }

.rx-pic {
  flex: none; display: inline-grid; place-items: center; overflow: hidden; border-radius: 12px;
  background: linear-gradient(135deg, #dfe8f7, #eef1f8); color: var(--accent); font-weight: 700;
}
.rx-pic img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rx-pic.rx-round { border-radius: 50%; }
.rx-pic.rx-logo { background: #fff; border: 1px solid var(--line-soft); }
.rx-pic.rx-logo img { object-fit: contain; padding: 8%; }
.rx-xs { width: 22px; height: 22px; font-size: 9px; border-radius: 6px; }
.rx-md { width: 52px; height: 52px; font-size: 16px; }
.rx-lg { width: 96px; height: 96px; font-size: 28px; }
.rx-xl { width: 132px; height: 132px; font-size: 40px; border: 4px solid #fff; box-shadow: 0 8px 24px rgba(18, 28, 45, .18); }

.rx-back { display: inline-block; margin-bottom: 12px; font-size: 13px; color: var(--ink-dim); text-decoration: none; }
.rx-back:hover { color: var(--accent); }
.rx-profile { display: grid; gap: 16px; }
.rx-loading { display: grid; justify-items: start; gap: 10px; padding: 24px; }
.rx-ghost { background: var(--line-soft); }
.rx-line { width: 260px; height: 16px; border-radius: 6px; background: var(--line-soft); }
.rx-line.short { width: 160px; }

.rx-hero {
  position: relative; border-radius: 16px; overflow: hidden; background: var(--panel); border: 1px solid var(--line);
  padding: 150px 28px 22px;
}
.rx-hero::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 190px;
  background: linear-gradient(180deg, rgba(18, 28, 45, .05), rgba(18, 28, 45, .55)), var(--rx-cover, linear-gradient(120deg, #0263e0, #6aa5f5));
  background-size: cover; background-position: center;
}
.rx-hero > * { position: relative; }
.rx-hero-top { position: absolute; top: 16px; left: 20px; right: 20px; display: flex; justify-content: space-between; align-items: center; }
.rx-kind {
  padding: 4px 10px; border-radius: 999px; font-size: 11.5px; font-weight: 650; letter-spacing: .04em; text-transform: uppercase;
  background: rgba(255, 255, 255, .9); color: var(--ink);
}
.rx-edit { background: #fff; color: var(--ink); border: 1px solid rgba(255, 255, 255, .6); text-decoration: none; }
.rx-ident { display: flex; align-items: flex-end; gap: 22px; }
.rx-words { padding-bottom: 6px; min-width: 0; }
.rx-words h1 { margin: 0; font-size: 28px; line-height: 1.15; letter-spacing: -0.015em; }
.rx-subtitle { margin-top: 4px; color: var(--ink-dim); font-size: 14px; }
.rx-belongs { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; align-items: center; }
.rx-chip {
  display: inline-flex; align-items: center; gap: 7px; padding: 4px 11px 4px 5px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--panel); color: var(--ink); text-decoration: none; font-size: 13px; font-weight: 550;
}
.rx-chip:hover { border-color: var(--accent); color: var(--accent); }
.rx-reach { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 20px; }
.visual-action, .rx-action {
  display: inline-flex; align-items: center; gap: 9px; padding: 8px 13px; border-radius: 10px;
  border: 1px solid var(--line); background: var(--panel); color: var(--ink); text-decoration: none; font-size: 13.5px; font-weight: 550;
}
.rx-action svg { width: 17px; height: 17px; flex: none; }
.rx-action span { display: grid; line-height: 1.25; }
.rx-action small { font-size: 11px; font-weight: 500; color: var(--ink-faint); }
.rx-action.rx-phone svg { color: var(--ok); }
.rx-action.rx-email svg { color: var(--accent); }
.rx-action.rx-link svg { color: var(--ink-dim); }
.visual-action:hover, .rx-action:hover { border-color: var(--accent); background: var(--accent-soft); }
.rx-note { font-size: 12.5px; color: var(--ink-faint); margin-top: -8px; }

.rx-split { display: grid; grid-template-columns: 3fr 2fr; gap: 16px; }
.rx-card > h2 .sub { margin-left: 8px; font-size: 13px; font-weight: 500; color: var(--ink-faint); }
.rx-bars { display: grid; gap: 9px; padding: 4px 20px 18px; }
.rx-barrow { display: grid; grid-template-columns: minmax(90px, 160px) 1fr 44px; gap: 10px; align-items: center; font-size: 13px; }
.rx-barlabel { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rx-bartrack { height: 10px; border-radius: 5px; background: var(--line-soft); overflow: hidden; }
.rx-barfill { display: block; height: 100%; border-radius: 5px; background: linear-gradient(90deg, #0263e0, #4f94ef); }
.rx-barvalue { text-align: right; font-variant-numeric: tabular-nums; color: var(--ink-dim); }
.rx-bars > .muted { padding: 6px 0; }

.rx-people { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; padding: 4px 16px 18px; }
.rx-person {
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: 6px; padding: 14px 8px;
  border-radius: 12px; color: var(--ink); text-decoration: none; min-width: 0;
}
.rx-person:hover { background: var(--accent-soft); }
.rx-person-name { font-size: 13.5px; font-weight: 600; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rx-person-sub { font-size: 12px; color: var(--ink-faint); }

.rx-card > .tabs { padding: 0 20px; }
.rx-listings { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 16px; padding: 16px 20px 20px; }
.rx-listing { display: block; color: var(--ink); text-decoration: none; min-width: 0; }
.rx-listing-pic {
  position: relative; aspect-ratio: 4 / 3; border-radius: 10px; overflow: hidden;
  background: linear-gradient(135deg, #e7ecf5, #f3f5fa);
}
.rx-listing-pic img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .25s; }
a.rx-listing:hover .rx-listing-pic img { transform: scale(1.04); }
.rx-status { position: absolute; top: 8px; left: 8px; box-shadow: 0 1px 4px rgba(0, 0, 0, .12); }
.rx-listing-pic .pill2:not(.ok):not(.warn):not(.unknown) { background: #fff; color: var(--ink); }
.rx-listing-pic .pill2.unknown { background: #fff; }
.rx-listing-price { margin-top: 8px; font-weight: 650; font-size: 15px; }
.rx-listing-address { font-size: 13px; color: var(--ink-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rx-listing-facts { font-size: 12px; color: var(--ink-faint); margin-top: 2px; }

/* Eric, 2026-10-23: Listings as a section of the Directory, in its style. */
.rx-filter {
  padding: 9px 12px; font: inherit; font-size: 14px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--panel); color: var(--ink);
}
.rx-grid.rx-listings { grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); padding: 0; gap: 14px; }
.rx-grid .rx-listing {
  padding: 10px 10px 14px; background: var(--panel); border: 1px solid var(--line); border-radius: 14px;
  transition: border-color .15s, box-shadow .15s, transform .15s;
}
.rx-grid .rx-listing:hover { border-color: var(--accent); box-shadow: 0 6px 20px rgba(18, 28, 45, .08); transform: translateY(-1px); }
.rx-listing .rx-tile-brand { margin-top: 8px; }
.rx-hero-listing .rx-pic { border-radius: 14px; }
.rx-price { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; font-size: 20px; font-weight: 700; }
.rx-photos { display: flex; gap: 10px; overflow-x: auto; padding: 4px 20px 20px; scroll-snap-type: x mandatory; }
.rx-photo { flex: none; width: 260px; aspect-ratio: 4 / 3; border-radius: 10px; overflow: hidden; background: var(--line-soft); scroll-snap-align: start; }
.rx-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rx-card > .rx-tags { padding: 0 20px; margin: 0 0 10px; }
.rx-description { padding: 6px 20px 20px; white-space: pre-line; font-size: 14px; line-height: 1.6; color: var(--ink-dim); }
.rx-description.rx-clamped { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 8; overflow: hidden; padding-bottom: 0; margin-bottom: 12px; }
.rx-more { margin: 0 20px 20px; }

@media (max-width: 900px) {
  .rx-split { grid-template-columns: 1fr; }
  .rx-grid.rx-listings, .rx-card .rx-listings { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .rx-card .rx-listings { padding: 12px 14px 16px; }
  .rx-listing-price { font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .rx-grid .rx-listing { padding: 6px 6px 10px; }
  .rx-grid .rx-listing-price { font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .rx-photo { width: 78vw; }
  .rx-bar { flex-wrap: wrap; }
  .rx-search { max-width: none; min-width: 0; }
  .rx-hero { padding: 120px 18px 18px; }
  .rx-hero::before { height: 160px; }
  .rx-ident { flex-direction: column; align-items: flex-start; gap: 12px; }
  .rx-xl { width: 104px; height: 104px; }
  .rx-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
}
.rx-ident { align-items: flex-start; }
.rx-words { padding: 52px 0 0; }
.rx-profile .kpis { grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); }
@media (max-width: 900px) { .rx-words { padding-top: 0; } }

.rx-place svg { width: 46%; height: 46%; }

/* Profile — one card per section, a switch per channel. */
.profile-page { display: grid; gap: 16px; max-width: 760px; }
.profile-page > .card { margin: 0; }
.profile-page .settings-form { max-width: none; }
.settings-form.profile-who { display: flex; align-items: center; gap: 20px; }
.profile-who .profile-avatar-wrap { width: 96px; margin: 0; flex: 0 0 auto; }
.profile-who .profile-avatar { width: 96px; height: 96px; font-size: 32px; padding: 3px; }
.settings-form.profile-who .profile-photo-edit { width: 32px; height: 32px; font-size: 18px; bottom: 0; right: -4px; }
.profile-fields { display: grid; gap: 8px; flex: 1; min-width: 0; }
.profile-email { color: var(--muted); font-size: 13px; overflow-wrap: anywhere; }
.notify-table { border: 1px solid var(--line); border-radius: 8px; border-collapse: separate; border-spacing: 0; overflow: hidden; table-layout: fixed; }
.notify-table th, .notify-table td { padding: 10px 12px; text-align: left; }
.notify-table th:not(:first-child), .notify-table td.cell-center { text-align: center; width: 84px; }
.notify-table th .pill2 { display: block; width: max-content; margin: 4px auto 0; font-weight: 500; font-size: 10.5px; }
.notify-table tbody tr + tr td { border-top: 1px solid var(--line); }
.settings-form .cell-switch { position: relative; display: inline-flex !important; justify-content: center; margin: 0; }
.cell-switch .toggle-track { margin-left: 0; }
.profile-link-actions { display: flex; gap: 10px; align-items: end; flex-wrap: wrap; }
.profile-link-actions label { flex: 1; min-width: 200px; }
.profile-foot { display: flex !important; gap: 12px; align-items: center; flex-wrap: wrap; }
@media (max-width: 600px) {
  .settings-form.profile-who { flex-direction: column; align-items: stretch; }
  .profile-who .profile-avatar-wrap { margin: 0 auto; }
  .notify-table th:not(:first-child), .notify-table td.cell-center { width: 64px; padding: 10px 4px; }
  .notify-table th:first-child, .notify-table td:first-child { padding-right: 4px; overflow-wrap: anywhere; }
}

/* Saved searches on Listings: a chip each, a bell for alerts. */
.rx-save { cursor: pointer; white-space: nowrap; font-weight: 550; }
.rx-save:hover { border-color: var(--accent); color: var(--accent); }
.rx-saved { display: flex; flex-wrap: wrap; gap: 8px; margin: -6px 0 16px; }
.rx-saved-chip { display: inline-flex; align-items: center; border: 1px solid var(--line); border-radius: 999px; background: var(--panel); overflow: hidden; }
.rx-saved-chip.on { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }
.rx-saved-chip button { border: 0; background: none; color: var(--ink); font: inherit; font-size: 13px; cursor: pointer; padding: 6px 8px; display: inline-flex; align-items: center; gap: 6px; }
.rx-saved-chip button:disabled { cursor: default; opacity: .5; }
.rx-saved-name { padding-left: 12px !important; font-weight: 550; }
.rx-saved-new { background: var(--accent); color: white; border-radius: 999px; padding: 1px 7px; font-size: 11px; font-weight: 650; }
.rx-saved-bell svg { width: 15px; height: 15px; color: var(--ink-faint); }
.rx-saved-bell.on svg { color: var(--accent); }
.rx-saved-x { color: var(--ink-faint) !important; padding-right: 10px !important; font-size: 16px !important; }
.rx-listing-pic .rx-new { position: absolute; top: 8px; right: 8px; }
.rx-dialog { border: 1px solid var(--line); border-radius: 12px; padding: 20px; width: min(440px, calc(100vw - 32px)); box-sizing: border-box; background: var(--panel); color: var(--ink); }
.rx-dialog[open] { display: grid; gap: 12px; }
.rx-dialog h2 { margin: 0; font-size: 17px; }
.rx-dialog .drawer-x { position: absolute; top: 10px; right: 12px; }
.rx-dialog-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.rx-dialog::backdrop { background: rgba(10, 16, 28, .35); }
@media (max-width: 600px) { .rx-bar { flex-wrap: wrap; } .rx-bar .rx-search { flex-basis: 100%; max-width: none; } }
.notify-table td { white-space: normal; }
.cell-switch input { inset: 0; width: 100% !important; height: 100% !important; margin: 0; cursor: pointer; z-index: 1; }

/* Inbox: one conversation per person, WhatsApp-style (Eric 2026-10-24). */
.chat { display: grid; grid-template-columns: minmax(260px, 340px) 1fr; height: calc(100vh - 190px); min-height: 460px; margin-top: 16px; background: var(--panel); border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.chat-list { display: flex; flex-direction: column; min-height: 0; border-right: 1px solid var(--line); }
.chat-search { margin: 10px; padding: 8px 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--rail); font: inherit; font-size: 14px; }
.chat-rows { overflow-y: auto; flex: 1; }
.chat-row { display: flex; gap: 10px; align-items: center; width: 100%; padding: 10px 12px; border: 0; border-bottom: 1px solid var(--line-soft); background: none; text-align: left; font: inherit; color: inherit; cursor: pointer; }
.chat-row:hover { background: var(--rail); }
.chat-row.on { background: var(--accent-soft); }
.chat-avatar { flex: none; display: inline-grid; place-items: center; width: 40px; height: 40px; border-radius: 50%; background: var(--unknown-soft); color: var(--ink-dim); font-size: 14px; font-weight: 600; }
.chat-row-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.chat-row-top, .chat-row-bottom { display: flex; align-items: center; gap: 8px; min-width: 0; }
.chat-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-row-top .chat-name { flex: 1; }
.chat-time { flex: none; font-size: 12px; color: var(--ink-faint); }
.chat-last { flex: 1; min-width: 0; font-size: 13px; color: var(--ink-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-you { color: var(--ink-faint); }
.chat-dot { flex: none; width: 10px; height: 10px; border-radius: 50%; background: var(--ok); }
.chat-empty, .chat-none { padding: 24px; text-align: center; }
.chat-none { margin: auto; }
.chat-pane { display: flex; flex-direction: column; min-height: 0; min-width: 0; background: #efeae2; }
.chat-head { display: flex; align-items: center; gap: 10px; padding: 8px 14px; background: var(--panel); border-bottom: 1px solid var(--line); }
.chat-head-who { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; }
.chat-head-who > span:last-child { display: flex; flex-direction: column; min-width: 0; }
.chat-sub { font-size: 12px; color: var(--ink-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-back { display: none; border: 0; background: none; font-size: 26px; line-height: 1; padding: 0 6px 0 0; color: var(--accent); cursor: pointer; }
.chat-kind { flex: none; }
.chat-log { flex: 1; overflow-y: auto; padding: 14px 6%; display: flex; flex-direction: column; gap: 4px; }
.chat-daymark { text-align: center; margin: 10px 0 6px; }
.chat-daymark span { display: inline-block; padding: 3px 10px; border-radius: 8px; background: var(--panel); color: var(--ink-dim); font-size: 12px; box-shadow: 0 1px 1px rgba(0,0,0,.06); }
.chat-line { display: flex; }
.chat-line.out { justify-content: flex-end; }
.chat-bubble { max-width: min(560px, 78%); padding: 6px 10px 4px; border-radius: 10px; background: var(--panel); box-shadow: 0 1px 1px rgba(0,0,0,.08); font-size: 14px; overflow-wrap: anywhere; }
.chat-line.in .chat-bubble { border-top-left-radius: 2px; }
.chat-line.out .chat-bubble { border-top-right-radius: 2px; background: #d9fdd3; }
.chat-subject { font-weight: 600; margin-bottom: 2px; }
.chat-text { white-space: pre-line; }
.chat-note { margin-top: 4px; padding-top: 4px; border-top: 1px solid var(--line-soft); font-size: 12px; color: var(--ink-dim); }
.chat-meta { text-align: right; font-size: 11px; color: var(--ink-faint); margin-top: 2px; }
.chat-foot { display: flex; justify-content: flex-end; padding: 10px 14px; background: var(--rail); border-top: 1px solid var(--line); }
.chat-reply { text-decoration: none; }
@media (max-width: 760px) {
  .chat { grid-template-columns: 1fr; height: calc(100dvh - 230px); }
  .chat .chat-pane { display: none; }
  .chat.chat-open .chat-list { display: none; }
  .chat.chat-open .chat-pane { display: flex; }
  .chat-back { display: inline-block; }
  .chat-log { padding: 12px 10px; }
  .chat-bubble { max-width: 86%; }
}

.chat-image { display: block; width: 100%; height: 240px; max-width: 100%; max-height: 480px; object-fit: contain; border-radius: 8px; margin: 8px 0; }
.mail-progress { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 0 12px; }

/* Keep sync with search; reserve the rest of the phone viewport for mail. */
.mail-toolbar { padding: 10px; border-bottom: 1px solid var(--line); }
.mail-toolbar .chat-search { width: 100%; margin: 0; min-width: 0; }
.mail-toolbar .mail-progress { padding: 6px 0 0; font-size: 11px; gap: 6px; }
.mail-progress .linkbtn { flex: none; }
@media (max-width: 760px) {
  .column:has(.mail-view) { height: 100dvh; display: flex; flex-direction: column; min-height: 0; }
  .column:has(.mail-view) .topbar { flex: none; }
  main:has(.mail-view) { flex: 1; min-height: 0; padding: 8px 8px max(8px, env(safe-area-inset-bottom)); display: flex; }
  .mail-view { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
  .mail-view .chat { flex: 1; min-height: 0; height: auto; margin-top: 8px; }
}

/* A gesture in mail stays in its own scroll area, including at either edge. */
.chat-log, .chat-rows { overscroll-behavior-y: contain; }

/* Keep the inbox tabs at their full height; only sideways scrolling is useful. */
.mail-view > .tabs { flex: none; margin-top: 0; overflow-y: hidden; overscroll-behavior: contain; }
.mail-view > .tabs .tab { flex: none; margin-bottom: 0; }

/* Inbox actions remain dismissible without deleting their source email. */
.mail-action { display: flex; align-items: center; min-width: 0; }
.mail-action .chat-row { flex: 1; min-width: 0; }
.mail-hide { flex: 0 0 40px; font-size: 24px; }
.mail-overview-caption { padding: 0 12px; font-size: 12px; }
.mail-view .mail-unread, .mail-view .mail-unread:hover { background: #b42318; color: #fff; border-color: #b42318; }
.mail-unread[aria-pressed="true"] { outline: 2px solid #f97066; outline-offset: 2px; }

.mail-compose { width: min(580px, calc(100vw - 32px)); max-height: calc(100dvh - 32px); overflow-y: auto; }
.mail-compose textarea { width: 100%; resize: vertical; min-height: 160px; }
.mail-compose .muted { overflow-wrap: anywhere; }

.mail-progress .mail-notice { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 10px; }

/* Source tabs share the remaining mobile inbox height. */
.inbox-source[hidden] { display: none !important; }
.inbox-sources { flex: none; min-width: 0; }
.inbox-sources > .tabs { margin-top: 0; overflow-y: hidden; }
@media (max-width: 760px) {
  main:has(.inbox-sources) { flex-direction: column; }
  .inbox-source:has(.mail-view) { display: flex; flex: 1; min-height: 0; min-width: 0; }
  .inbox-source:not(:has(.mail-view)) { overflow-y: auto; }
}


/* Shared form-dialog standard. See MODALS.md. Media viewer keeps its full-screen canvas. */
dialog.app-modal {
  --modal-width: 480px;
  box-sizing: border-box; position: fixed; inset: 0; margin: auto;
  width: min(var(--modal-width), calc(100vw - 32px));
  height: fit-content; max-height: calc(100dvh - 32px);
  padding: 24px; overflow: auto; overscroll-behavior: contain;
  border: 1px solid var(--line); border-radius: 16px;
  background: var(--panel); color: var(--ink);
  box-shadow: 0 16px 64px #0003;
  font: 14px/1.5 var(--sans);
}
dialog.app-modal[open] { display: grid; gap: 16px; align-content: start; align-items: start; }
dialog.app-modal:not([open]) { display: none; }
dialog.app-modal::backdrop { background: rgb(10 16 28 / .48); }
dialog.app-modal > :is(h2, h3) {
  margin: 0; padding: 4px 48px 4px 0; min-height: 36px;
  text-align: left; font-size: 20px; line-height: 1.4; font-weight: 650;
}
dialog.app-modal > :is(.image-key-close, .drawer-x) {
  position: absolute; inset: 16px 16px auto auto;
  display: grid; place-items: center; width: 44px; height: 44px; min-height: 44px;
  padding: 0; margin: 0; border: 0; border-radius: 8px;
  background: transparent; color: var(--ink-dim); font: 24px/1 var(--sans);
}
dialog.app-modal > :is(.image-key-close, .drawer-x):hover { background: var(--line-soft); }
dialog.app-modal :is(input:not([type=checkbox]):not([type=radio]):not([type=file]), select, textarea) {
  box-sizing: border-box; width: 100%; min-width: 0; padding: 10px 12px;
  border: 1px solid var(--line); border-radius: 8px; background: var(--panel); color: var(--ink);
  font: 16px/1.5 var(--sans);
}
dialog.app-modal :is(label, .formfield) { min-width: 0; margin: 0; }
dialog.app-modal :is(p, dl) { margin: 0; }
dialog.app-modal .cstatus:empty, dialog.app-modal [role=status]:empty:not(.key-spinner) { display: none; }
dialog.app-modal button { min-height: 44px; box-sizing: border-box; }
dialog.app-modal > button:not(.drawer-x):not(.image-key-close),
dialog.app-modal .modal-actions > button {
  height: 44px; padding: 10px 16px; border: 1px solid var(--line); border-radius: 8px;
  font: 600 14px/1.3 var(--sans); cursor: pointer;
}
dialog.app-modal button.primary { color: #fff; background: var(--accent); border-color: var(--accent); }
dialog.app-modal button:disabled { opacity: .55; cursor: default; }
dialog.app-modal :is(button, input, select, textarea):focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
dialog.app-modal .modal-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 10px; }
dialog.app-modal .modal-actions .action-generate { margin: 0; }
dialog.app-modal.mail-compose { --modal-width: 580px; }
dialog.app-modal .modal-routing { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 4px 12px; font-size: 13px; }
dialog.app-modal .modal-routing dt { color: var(--ink-dim); }
dialog.app-modal .modal-routing dd { margin: 0; overflow-wrap: anywhere; color: var(--ink); }
dialog.app-modal.mail-compose textarea { min-height: 140px; height: 180px; max-height: 40dvh; resize: vertical; }
@media (max-width: 600px) {
  dialog.app-modal { padding: 20px; }
  dialog.app-modal > :is(.image-key-close, .drawer-x) { top: 12px; right: 12px; }
}

.mail-link-badge { font-size: .75em; overflow-wrap: anywhere; margin-right: .4em; }
.mail-link-badge.official { color: var(--muted); }
.mail-link-badge.unverified, .chat-text a[aria-disabled="true"] { color: var(--muted); }
.chat-text a[aria-disabled="true"] { cursor: default; text-decoration: none; }

/* Client messages use the same typography and rows as the other Inbox sources. */
.client-messages .body { padding: 0; }
.client-messages .catcount, .client-messages .pager, .client-messages .body > .muted { padding: 12px 16px; margin: 0; }
.client-message-list .chat-row { padding: 16px; text-decoration: none; }
.client-message-list .chat-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.client-message-list .chat-subject, .client-message-list .detail { overflow-wrap: anywhere; }
.client-message-meta { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 8px 16px; margin: 0; padding: 16px 20px; border-bottom: 1px solid var(--line); font-size: 13px; }
.client-message-meta dt { color: var(--ink-dim); }
.client-message-meta dd { margin: 0; overflow-wrap: anywhere; }
.client-message-body { padding: 24px 20px; white-space: pre-wrap; overflow-wrap: anywhere; font: 14px/1.7 var(--sans); }
@media (max-width: 760px) {
  .client-message-list .chat-row-top { flex-wrap: wrap; }
  .client-message-list .chat-name { flex-basis: 100%; }
  .client-message-list .chat-time { font-size: 11px; }
}

/* Company social planner. */
.social-page { display: grid; gap: 24px; }
.social-heading, .social-toolbar, .social-actions, .social-post-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; }
.social-heading { justify-content: space-between; }
.social-heading h1, .social-heading p, .social-account h2, .social-account p { margin: 0; }
.social-heading p { margin-top: 8px; }
.social-accounts { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
.social-post { background: var(--panel); border: 1px solid var(--line); border-radius: 14px; padding: 20px; min-width: 0; }
.social-account { gap: 10px; padding: 24px 18px 18px; }
.social-account .social-actions { justify-content: center; margin-top: auto; padding-top: 12px; }
.social-account p { overflow-wrap: anywhere; max-width: 100%; }
.social-account .social-connection { font-size: 12.5px; color: var(--ink-dim); }
.social-account h2 { font-size: 18px; }
.social-mark { display: grid; place-items: center; width: 72px; height: 72px; border-radius: 18px; color: white; font-size: 26px; font-weight: 700; }
.social-toolbar h2 { margin-right: auto; }
.social-filter, .social-field { display: grid; gap: 6px; font-size: 13px; }
.social-toolbar input, .social-toolbar select { max-width: 100%; padding: 10px; border: 1px solid var(--line, #ddd); border-radius: 8px; background: transparent; color: inherit; font: inherit; }
.social-posts { display: grid; gap: 16px; }
.social-post-meta { color: var(--ink-dim); font-size: 13px; }
.social-status { white-space: normal; }
.social-copy { white-space: pre-wrap; overflow-wrap: anywhere; max-height: 280px; overflow-y: auto; }
.social-post h3 { overflow-wrap: anywhere; }
.social-post .social-actions { margin-top: 16px; }
.social-empty { padding: 40px 24px; border: 1px dashed var(--line, #ddd); border-radius: 12px; text-align: center; }
.social-page button { min-height: 44px; font-family: inherit; cursor: pointer; }
.social-page .social-actions a { min-height: 44px; }
.social-page button.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.social-page button:disabled { opacity: .55; cursor: default; }
.social-page button:hover:not(:disabled) { filter: brightness(.97); }
.social-page button:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.social-modal { --modal-width: 620px; }
.social-setup-steps { padding-left: 24px; }
.social-setup-steps li { margin: 12px 0; line-height: 1.5; }
.social-setup-scopes, .social-modal details { overflow-wrap: anywhere; }
.social-modal > .social-field { margin: 16px 0 8px; }
.social-modal form { display: grid; gap: 16px; }
.social-modal textarea { min-height: 100px; resize: vertical; }
.social-channels { display: flex; flex-wrap: wrap; gap: 12px; border: 1px solid var(--line, #ddd); border-radius: 8px; padding: 12px; }
.social-channels label { display: flex; align-items: center; gap: 8px; }
.social-modal .social-channels input { width: 18px; min-height: 18px; height: 18px; }
@media (max-width: 1000px) { .social-accounts { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .social-accounts { grid-template-columns: 1fr; } .social-toolbar { align-items: stretch; } .social-toolbar h2 { width: 100%; } .social-filter { flex: 1; } }
.calendar-greeting textarea, .calendar-setup textarea { width: 100%; box-sizing: border-box; font: inherit; padding: 10px 12px; border: 1px solid var(--line, #d9dde3); border-radius: 8px; resize: vertical; margin-bottom: 10px; }

/* RenoSprints Projects and Scrapers (public/reno.js) */
.rp-cell { display: inline-flex; align-items: center; gap: 10px; min-width: 0; }
.rp-thumb { width: 36px; height: 28px; border-radius: 4px; object-fit: cover; flex: none; background: var(--line); }
.rp-thumb-empty { display: inline-block; }
.rp-name { display: block; font-weight: 600; }
.rp-sub { display: block; font-size: 12px; }
.rp-map img { display: block; width: 100%; aspect-ratio: 16 / 10; object-fit: cover; border-radius: 8px; background: var(--line); }
.rp-desc { white-space: pre-wrap; margin: 0; line-height: 1.5; }
.rp-photos { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.rp-photos img { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 6px; }
.rp-bar { display: inline-block; width: 64px; height: 6px; border-radius: 3px; background: var(--line); vertical-align: middle; overflow: hidden; }
.rp-bar > span { display: block; height: 100%; background: var(--ok); }
.rp-pct { margin-left: 8px; font-variant-numeric: tabular-nums; }

/* RenoSprints on a phone (Eric 2026-10-28: "can use an update on mobile").
 * A `wide` column is shown in the row's drawer, so a phone keeps the columns
 * that identify a row and reads the rest under it. */
.rp-ghost { background: var(--panel); color: var(--ink); border: 1px solid var(--line); border-radius: 7px; padding: 9px 14px; font: 600 13.5px/1 var(--sans); cursor: pointer; }
.rp-ghost:hover { border-color: var(--accent); color: var(--accent); }
.rp-cell-text { display: grid; min-width: 0; }
.rp-phone { display: none; }
.rp-nowrap { white-space: nowrap; }
.drawer-sub { flex-wrap: wrap; row-gap: 2px; }
@media (max-width: 760px) {
  .dt .dt-wide { display: none; }
  .rp-phone { display: block; }
  .rp-cell { align-items: flex-start; }
  .rp-thumb { width: 52px; height: 40px; }
  .phead-actions .btn, .phead-actions .rp-ghost { padding: 8px 11px; font-size: 13px; }
  .drawer-head { padding: 14px 16px 12px; }
  .drawer-head h2 { font-size: 17px; }
  .drawer-sec { padding: 14px 16px; }
  .drawer dl.fields { grid-template-columns: minmax(96px, 36%) minmax(0, 1fr); column-gap: 12px; row-gap: 8px; font-size: 13.5px; }
  .drawer dl.fields dd { margin-bottom: 0; }
  .rp-cell-text .cell-clip { max-width: 62vw; white-space: nowrap; }
  .dt .rp-name, .dt .rp-sub { max-width: 42vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .rp-photos { grid-template-columns: repeat(2, 1fr); }
}
.rx-export-head { font-size: 13px; font-weight: 600; color: var(--ink-dim); }
.rx-export-checks { display: flex; flex-wrap: wrap; gap: 4px 18px; }
.rx-export-checks .settings-check { margin: 0; }
.rx-export-cols { display: grid; grid-template-columns: 1fr 1fr; max-height: 240px; overflow-y: auto; }
.rx-dialog [hidden] { display: none !important; }

/* Team */
.team-field { display: grid; gap: 6px; }
.team-field > span { font-size: 13px; font-weight: 600; color: var(--ink-dim); }
.team-field input, .team-field select { width: 100%; box-sizing: border-box; padding: 8px 10px; font: 14px var(--sans);
  border: 1px solid var(--line); border-radius: 8px; background: var(--panel); color: var(--ink); }
.team-form { display: grid; gap: 14px; }
.team-form .cstatus:empty { display: none; }
.team-foot { display: flex; flex-wrap: wrap; gap: 8px; }
.team-foot button.danger { border-radius: 8px; padding: 8px 14px; }
.dt-actions button.primary { border: 0; border-radius: 8px; padding: 8px 14px; background: var(--accent); color: #fff;
  font: 600 13.5px/1.2 var(--sans); cursor: pointer; white-space: nowrap; }
.dt-actions button.primary:hover { filter: brightness(1.08); }
.team-grid { display: grid; }
.team-grid-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 7px 0;
  font-size: 13.5px; border-top: 1px solid var(--line-soft); }
.team-seg { display: inline-flex; flex: 0 0 auto; padding: 2px; gap: 2px; background: var(--bg); border-radius: 8px; }
.team-form > .team-seg { display: flex; }
.team-form > .team-seg label { flex: 1; text-align: center; }
.team-seg label { position: relative; cursor: pointer; }
.team-seg input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: inherit; }
.team-seg span { display: block; min-width: 44px; padding: 4px 10px; box-sizing: border-box; text-align: center; border-radius: 6px;
  font-size: 12.5px; font-weight: 550; color: var(--ink-dim); }
.team-seg input:checked + span { background: var(--panel); color: var(--ink); box-shadow: 0 1px 2px rgba(18, 28, 45, 0.14); }
.team-seg input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 1px; }
.team-seg input:disabled { cursor: default; }
.team-seg input:disabled + span { color: var(--ink-faint); }
.team-seg input:disabled:checked + span { color: var(--ink-dim); }
.invite-body { min-height: 100vh; display: grid; place-items: center; padding: 24px 16px; }
.invite-page { width: 100%; max-width: 400px; }
.accountbtn.invite-brand { margin-bottom: 20px; min-height: 54px; cursor: default; }
.accountbtn.invite-brand:hover:not([disabled]) { border-color: var(--line); }
.invite-brand .account-name { grid-row: 1 / span 2; }
.invite-brand[hidden] { display: grid; visibility: hidden; }
.invite-card { background: var(--panel); border: 1px solid var(--line); border-radius: 12px; padding: 24px; }
.invite-card h1 { margin: 0 0 18px; font-size: 20px; line-height: 1.3; font-weight: 650; overflow-wrap: anywhere; }
.invite-facts { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 8px 16px; margin: 0 0 20px; padding: 12px 0; border-block: 1px solid var(--line-soft); font-size: 14px; }
.invite-facts[hidden], .invite-foot[hidden], .invite-page .team-field[hidden] { display: none; }
.invite-facts dt { color: var(--ink-dim); }
.invite-facts dd { margin: 0; text-align: right; overflow-wrap: anywhere; }
.invite-page .team-field { margin-bottom: 16px; }
/* Account social calendar: local dates, seven columns, usable on a phone. */
.social-page { min-width: 0; }
.social-month { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.social-weekday { padding: 8px 3px; text-align: center; color: var(--ink-dim); font-size: 12px; }
.social-day { min-height: 110px; padding: 6px; border-top: 1px solid var(--line); border-right: 1px solid var(--line); background: var(--panel); min-width: 0; }
.social-day > span { font-size: 12px; color: var(--ink-dim); }
.social-day.outside { background: transparent; }
.social-day-post.visual-action { display: block; width: 100%; min-height: 44px; padding: 4px; margin-top: 4px; text-align: left; font-size: 12px; white-space: normal; overflow-wrap: anywhere; background: var(--accent-soft); }
.social-calendar .social-toolbar { justify-content: space-between; }
@media (max-width: 600px) {
  .social-day { padding: 2px; min-height: 80px; }
  .social-day-post.visual-action { font-size: 10px; padding: 2px; }
  .social-calendar .social-toolbar h2 { order: -1; width: 100%; }
}
.social-page .social-filter select { min-height: 44px; padding: 8px 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel); color: var(--ink); font: inherit; max-width: 100%; }
.invite-page .team-field input { font-family: var(--mono); letter-spacing: 0.04em; text-transform: uppercase; }
.invite-page .cstatus { margin: 0 0 12px; }
.invite-page .cstatus:empty { display: none; }
.invite-join { width: 100%; min-height: 44px; border: 0; border-radius: 8px; background: var(--accent); color: #fff; font: inherit; font-weight: 600; cursor: pointer; }
.invite-join:hover:not(:disabled) { filter: brightness(1.08); }
.invite-join:disabled { opacity: 0.5; cursor: default; }
.invite-foot { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 4px 16px; margin-top: 14px; font-size: 13px; color: var(--ink-dim); }
.invite-foot span { overflow-wrap: anywhere; }
.invite-foot a { color: var(--accent); text-decoration: none; }
.invite-foot a:hover { text-decoration: underline; }
.invite-foot form { margin: 0; }
.invite-foot form button { color: var(--accent); background: none; border: 0; padding: 0; font: inherit; cursor: pointer; }
.invite-foot form button:hover { text-decoration: underline; }
.whomenu .signout-form { margin: 0; }
.signin-card .body { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }

/* Add email: Gmail or IMAP (2026-11-03). */
.mail-choices { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin: 12px 0; }
.mail-choice { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 18px 12px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel, #fff); cursor: pointer; font: inherit; color: inherit; }
.mail-choice:hover { border-color: var(--ink, #111); }
.mail-choice .app-icon { width: 48px; height: 48px; border-radius: 12px; }
.mail-choice .app-icon img { width: 26px; height: 26px; }
.mail-imap { background: #475569; color: #fff; font-size: 22px; font-weight: 600; }
.mail-connect { max-width: 420px; margin: 48px auto; text-align: center; }
.mail-connect h2 { margin: 0 0 8px; font-size: 18px; }
.mail-add { font-size: 16px; line-height: 1; padding-inline: 8px; }
.bag-screen .bag-bar .formfield:has([aria-label="Theme"]), .bag-screen .bag-bar .formfield:has([aria-label="Accent"]) { width: 120px; }
.bag-screen .bag-bar input[type="color"] { width: 100%; height: 36px; padding: 2px; border: 1px solid var(--line); border-radius: 8px; background: #fff; cursor: pointer; }
.bag-screen .snippet { max-width: 720px; margin: 8px auto 0; }

/* Approve / decline in the Identification table (Jose via Eric, 2026-11-08). */
.identification-decide { display: inline-flex; gap: 8px; }
.identification-act { display: inline-grid; place-items: center; width: 30px; height: 30px; padding: 0; border-radius: 50%; border: 1px solid; background: var(--panel); cursor: pointer; }
.identification-act svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.identification-act.ok { color: var(--ok); border-color: var(--ok); }
.identification-act.ok:hover:not(:disabled) { background: var(--ok); color: #fff; }
.identification-act.bad { color: var(--bad); border-color: var(--bad); }
.identification-act.bad:hover:not(:disabled) { background: var(--bad); color: #fff; }
.identification-act:disabled { opacity: .35; cursor: default; }
.identification-decline .identification-correction { margin-top: 4px; }

/* Keep Business Profile tables and reporting controls inside narrow screens. */
.social-page > *, .social-page details { min-width: 0; }
.social-page .phead-actions { flex-wrap: wrap; }
.social-page pre { max-width: 100%; }

/* Google Business Profile — one project's listing (2026-11-09). */
.gbp { display: grid; gap: 18px; min-width: 0; }
.gbp-loading, .gbp-empty { margin: 0; color: var(--ink-faint); font-size: 13.5px; }
.gbp-card { min-width: 0; }
.gbp-body { padding: 16px 20px 20px; display: grid; gap: 14px; min-width: 0; }
.gbp-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr)); gap: 18px; min-width: 0; }
.gbp-grid-wide { grid-template-columns: minmax(0, 1.7fr) minmax(min(100%, 300px), 1fr); }
@media (max-width: 900px) { .gbp-grid-wide { grid-template-columns: minmax(0, 1fr); } }
.gbp-hero { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 18px; align-items: center; padding: 20px; }
.gbp-mark { width: 64px; height: 64px; border-radius: 14px; background: var(--accent-soft); color: var(--accent); display: grid; place-items: center; font: 700 26px/1 var(--sans); overflow: hidden; }
.gbp-mark img { width: 100%; height: 100%; object-fit: cover; }
.gbp-who { display: grid; gap: 6px; min-width: 0; }
.gbp-name { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.gbp-name h2 { margin: 0; font-size: 21px; font-weight: 700; letter-spacing: -0.01em; overflow-wrap: anywhere; }
.gbp-where { margin: 0; color: var(--ink-dim); font-size: 13.5px; overflow-wrap: anywhere; }
.gbp-facts { display: flex; flex-wrap: wrap; gap: 6px 18px; align-items: center; font-size: 13.5px; }
.gbp-link { color: var(--accent); text-decoration: none; overflow-wrap: anywhere; }
.gbp-link:hover { text-decoration: underline; }
.gbp-rate { display: inline-flex; align-items: center; gap: 6px; color: var(--ink-dim); }
.gbp-rate strong { color: var(--ink); font-size: 15px; }
.gbp-stars { position: relative; display: inline-block; font-size: 15px; line-height: 1; letter-spacing: 1px; color: var(--line); }
.gbp-stars.sm { font-size: 12px; }
.gbp-stars-fill { position: absolute; inset: 0 auto 0 0; overflow: hidden; white-space: nowrap; color: #e8a10c; }
.gbp-controls { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; align-items: center; }
.gbp-controls select, .gbp-controls input { min-height: 40px; padding: 0 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel); color: inherit; font: inherit; font-size: 13.5px; max-width: 100%; }
@media (max-width: 760px) { .gbp-hero { grid-template-columns: auto minmax(0, 1fr); } .gbp-controls { grid-column: 1 / -1; justify-content: flex-start; } }
.gbp-sub { margin: 4px 0 0; font-size: 12.5px; font-weight: 600; color: var(--ink-dim); }
.gbp-chart { position: relative; }
.gbp-chart svg { display: block; width: 100%; height: auto; overflow: visible; }
.gbp-bar { fill: var(--accent); opacity: .85; }
.gbp-bar.on { opacity: 1; }
.gbp-hit { fill: transparent; cursor: default; }
.gbp-gridline { stroke: var(--line-soft); stroke-width: 1; }
.gbp-axis { stroke: var(--line); stroke-width: 1; }
.gbp-tick { fill: var(--ink-faint); font: 11px var(--sans); font-variant-numeric: tabular-nums; }
.gbp-tip { position: absolute; transform: translate(-50%, calc(-100% - 8px)); background: var(--ink); color: #fff; font-size: 12px; padding: 5px 8px; border-radius: 6px; white-space: nowrap; pointer-events: none; }
.gbp-tip strong { font-variant-numeric: tabular-nums; }
.gbp-bars { display: grid; gap: 8px; }
.gbp-barrow { display: grid; grid-template-columns: minmax(84px, 38%) minmax(40px, 1fr) auto; gap: 10px; align-items: center; font-size: 13px; background: none; border: 0; padding: 0; text-align: left; color: inherit; font-family: inherit; }
.gbp-barlabel { color: var(--ink-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gbp-track { height: 8px; background: var(--line-soft); border-radius: 4px; overflow: hidden; }
.gbp-fill { display: block; height: 100%; background: var(--accent); border-radius: 4px; }
.gbp-barvalue { font-variant-numeric: tabular-nums; font-weight: 600; min-width: 36px; text-align: right; }
.gbp-flag { margin: 0; font-size: 13px; color: var(--warn); }
.gbp-reviews { display: grid; gap: 0; border-top: 1px solid var(--line-soft); }
.gbp-review { display: grid; gap: 6px; justify-items: start; padding: 12px 0; border: 0; border-bottom: 1px solid var(--line-soft); background: none; text-align: left; color: inherit; font: inherit; cursor: pointer; min-width: 0; width: 100%; }
.gbp-review:hover { background: var(--rail); }
.gbp-review-head { display: flex; align-items: center; gap: 8px; width: 100%; min-width: 0; font-size: 13.5px; }
.gbp-review-head strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gbp-when { margin-left: auto; color: var(--ink-faint); font-size: 12px; white-space: nowrap; }
.gbp-avatar { width: 26px; height: 26px; flex: none; border-radius: 50%; background: var(--accent-soft); color: var(--accent); display: grid; place-items: center; font-size: 12px; font-weight: 700; overflow: hidden; }
.gbp-avatar img { width: 100%; height: 100%; object-fit: cover; }
.gbp-quote { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--ink); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
.gbp-desc { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--ink-dim); overflow-wrap: anywhere; }
.gbp-hours { display: grid; grid-template-columns: 48px 1fr; gap: 4px 12px; margin: 0; font-size: 13.5px; font-variant-numeric: tabular-nums; }
.gbp-hours dt { color: var(--ink-faint); }
.gbp-hours dd { margin: 0; }
.gbp-hours .on { font-weight: 650; color: var(--ink); }
.gbp-fields { margin: 0; }
.gbp-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.gbp-photos { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 6px; }
.gbp-photo { position: relative; display: block; aspect-ratio: 1; border-radius: 8px; overflow: hidden; background: var(--line-soft); }
.gbp-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gbp-badge { position: absolute; left: 6px; bottom: 6px; font-size: 10.5px; font-weight: 600; background: rgba(18, 28, 45, .72); color: #fff; padding: 2px 6px; border-radius: 4px; }
.gbp-failed { font-size: 13px; color: var(--ink-dim); }
.gbp-failed summary { cursor: pointer; }
.gbp-failed dl { margin-top: 10px; }
.gbp-choose { display: grid; gap: 8px; }
.gbp-choice { display: flex; gap: 12px; align-items: flex-start; padding: 12px 14px; border: 1px solid var(--line); border-radius: 10px; cursor: pointer; }
.gbp-choice:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }
.gbp-choice input { margin-top: 3px; width: 16px; height: 16px; }
.gbp-choice span { display: grid; gap: 2px; font-size: 13.5px; }
.gbp-choice span span { color: var(--ink-dim); font-size: 12.5px; }
.gbp .visual-action { min-height: 40px; }
.gbp-bars.compact .gbp-barrow { grid-template-columns: 40px minmax(40px, 1fr) auto; }

/* Mailbox access: projects it is bound to, people it is shared with. */
.mail-access { flex-basis: 100%; margin-top: 8px; }
.mail-access-form { display: grid; gap: 8px; }
.mail-access-projects { display: flex; flex-wrap: wrap; gap: 4px 14px; }
.mail-access-person { display: flex; align-items: center; gap: 12px; font-size: 13px; }
.mail-access-person > span { flex: 1; overflow: hidden; text-overflow: ellipsis; }
.identify-progress { font-size: 13px; color: var(--ink); }
.identify-failed { margin: 10px 0; padding: 0; list-style: none; max-height: 220px; overflow-y: auto; display: grid; gap: 4px; }
.identify-failed li { display: flex; justify-content: space-between; gap: 10px; font-size: 12.5px; }
.identify-failed small { color: var(--bad); text-align: right; }
.identify-queued-photo { margin: 0; }
.identify-queued-photo img { display: block; max-width: 100%; height: 160px; object-fit: contain; background: var(--bg); border: 1px solid var(--line-soft); border-radius: 6px; }
.species-photo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 8px; }
.species-photo-grid a { display: block; aspect-ratio: 4 / 3; border: 1px solid var(--line-soft); border-radius: 6px; overflow: hidden; background: var(--bg); }
.species-photo-grid img { width: 100%; height: 100%; object-fit: cover; display: block; }
.identify-retry[hidden] { display: none; }
/* An amount: the currency button joined to the figure. */
.money-input { display: flex; align-items: stretch; width: 100%; min-width: 0; }
.money-input button.currency-pick { border-radius: 6px 0 0 6px; border-right: 0; flex: none; }
.money-input input.money-figure[type="text"] { flex: 1 1 auto; width: auto; min-width: 0; border-radius: 0 6px 6px 0; }
.money-input input.money-figure[type="text"]:focus { position: relative; z-index: 1; }
button.currency-pick {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-height: 34px; padding: 0 9px;
  background: var(--line-soft); border: 1px solid var(--line); border-radius: 6px;
  color: var(--ink); font: 600 13.5px var(--sans); cursor: pointer;
}
button.currency-pick::after { content: ""; width: 5px; height: 5px; margin: -2px 1px 0 0; border: solid var(--ink-dim); border-width: 0 1.5px 1.5px 0; transform: rotate(45deg); }
button.currency-pick:hover { background: var(--accent-soft); }
button.currency-pick:focus-visible { outline: 2px solid var(--accent-soft); border-color: var(--accent); }
.currency-flag { display: block; width: 18px; height: 13.5px; border-radius: 2px; box-shadow: 0 0 0 1px rgba(18, 28, 45, 0.12); }
.currency-menu {
  position: fixed; inset: auto; margin: 0; min-width: 128px; padding: 4px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 9px;
  box-shadow: 0 10px 30px rgba(18, 28, 45, 0.13);
}
button.currency-option {
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 7px 9px;
  background: none; border: 0; border-radius: 6px; color: var(--ink); font: 13.5px var(--sans); text-align: left; cursor: pointer;
}
button.currency-option .currency-symbol { margin-left: auto; color: var(--ink-faint); }
button.currency-option:hover, button.currency-option:focus-visible { background: var(--accent-soft); color: var(--accent); outline: none; }
button.currency-option[aria-selected="true"] { font-weight: 600; }
.profile-currency { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }
