/* iTripz Agent Console.

   Re-skinned on 2026-09-16 (docs/superpowers/specs/2026-09-16-console-reskin-design.md)
   after the team found the old "paper" look dull: cream on beige, grain, muted
   teal, typewriter capitals. The console now wears the iTripz brand: white and
   bright in light mode, deep navy in dark mode, the logo's cyan, navy and orange
   for colour, soft filled status pills, and one clean typeface.

   Rules that stay:
   - Tokens only. No raw hex below the token block.
   - Dark is the default, light is the stored choice (see the script in admin.html).
   - State colours mean something: green live, amber waiting, grey paused, red
     sent back. The brand orange is for counts that need someone.
   - No em dashes, anywhere. */

/* ── fonts, self-hosted ─────────────────────────────────────────────────── */
/* Plus Jakarta Sans (SIL Open Font License), one variable file for every weight.
   Self-hosted because the console's CSP only allows fonts from the console. Plex
   Mono stays for keys and code. */
@font-face { font-family: "Plus Jakarta Sans Variable"; src: url("/admin/fonts/jakarta.woff2") format("woff2"); font-weight: 200 800; font-display: swap; }
@font-face { font-family: "IBM Plex Mono"; src: url("/admin/fonts/plex-mono-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "IBM Plex Mono"; src: url("/admin/fonts/plex-mono-500.woff2") format("woff2"); font-weight: 500; font-display: swap; }

/* ── tokens ─────────────────────────────────────────────────────────────── */
:root {
  /* The brand, the same in both themes. */
  --brand-cyan: #00c3f4;
  --brand-navy: #0f4d7e;
  --attention: #fc901b;
  --on-attention: #2a1600;

  /* Ground, sheet, raised. The ground is the desk the white sheet sits on. */
  --paper-deep: #f2f5f9;
  --paper: #ffffff;
  --surface: #f4f7fb;
  --rule: #e1e7ef;
  --rule-soft: #edf1f6;

  --ink: #0f1f2e;
  --ink-soft: #3c4e60;
  --ink-muted: #5b6d80;

  /* Ocean blue: the brand between cyan and navy, dark enough for white text (5.8:1)
     and for blue text on its own pale wash (5.2:1). */
  --accent: #006aa6;
  --accent-bright: #00c3f4;
  --accent-wash: #e5f5fc;
  --on-accent: #ffffff;
  /* the chat: wallpaper, incoming and outgoing bubbles */
  --thread-bg: #edf2f7; --bubble-in: #ffffff; --bubble-out: #d8f1fb;

  --panel: #f7fafd;
  --panel-line: #dae3ed;
  --panel-ink: #0f1f2e;
  --panel-accent: #006aa6;

  /* Channel identity, close to each app's own colour. */
  --ch-wa: #1da851;
  --ch-ig: #d62976;
  --ch-fb: #1877f2;

  /* Semantic state. Separate from the accent; these mean something. */
  --ok: #15803d;
  --ok-wash: #e6f6ec;
  --warn: #b45309;
  --warn-wash: #fff1de;
  --bad: #c0362c;
  --bad-wash: #fdeceb;
  --quiet-wash: #edf1f5;
  --knob: #ffffff;
  --tone-0: #dff3fb; --tone-0-ink: #035f8c;
  --tone-1: #ffefda; --tone-1-ink: #9a4b08;
  --tone-2: #e1f4e7; --tone-2-ink: #166534;
  --tone-3: #fbe4ef; --tone-3-ink: #9d1f5a;
  --tone-4: #ebe7fb; --tone-4-ink: #5536b0;
  --tone-5: #e2eaf3; --tone-5-ink: #0f4d7e;

  --sheet-edge: var(--rule);
  --shadow-sm: 0 1px 2px rgba(15, 31, 46, 0.06);
  --shadow: 0 1px 2px rgba(15, 31, 46, 0.05), 0 12px 32px -18px rgba(15, 31, 46, 0.18);
  --radius: 0.8rem;

  /* The sign-in page is night in both themes: a photograph and a dark form. */
  --night: #06101b;
  --night-2: #0a1726;
  --night-line: #1c2f45;
  --night-ink: #eef4fa;
  --night-bad: #ff9d92;
  --night-3: #0f2135;
  --night-muted: #93a7bb;
  --cyan-soft: #9be6ff;
  --cyan-hi: #45dbff;
  --cyan-lo: #0093d1;

  --font-display: "Plus Jakarta Sans Variable", ui-sans-serif, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-sans: "Plus Jakarta Sans Variable", ui-sans-serif, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

:root[data-theme="dark"] {
  /* Deep navy in layers: the ground, the sheet, then anything raised, selected or
     hovered, which lifts in both themes. */
  --paper-deep: #060e18;
  --paper: #0c1826;
  --surface: #13243a;
  --rule: #22364d;
  --rule-soft: #182a3f;
  --ink: #e9f0f7;
  --ink-soft: #b3c3d4;
  --ink-muted: #7d91a7;
  --accent: #22c7f5;
  --accent-bright: #6ad9ff;
  --accent-wash: #0d2d44;
  --on-accent: #04121f;
  --thread-bg: #081320; --bubble-in: #15263a; --bubble-out: #0b4462;
  --panel: #0a1522;
  --panel-line: #213449;
  --panel-ink: #e6eef6;
  --panel-accent: #22c7f5;
  --ch-wa: #4ade80;
  --ch-ig: #f472b6;
  --ch-fb: #60a5fa;
  --ok: #4ade80;
  --ok-wash: #0f2d22;
  --warn: #fbb05c;
  --warn-wash: #33240f;
  --bad: #f7968b;
  --bad-wash: #3a1b18;
  --quiet-wash: #1a2b3e;
  --knob: #cfdae6;
  --tone-0: #0d3247; --tone-0-ink: #7fd9f7;
  --tone-1: #3a2610; --tone-1-ink: #fdba74;
  --tone-2: #11321f; --tone-2-ink: #86efac;
  --tone-3: #3a1729; --tone-3-ink: #f9a8d4;
  --tone-4: #26204a; --tone-4-ink: #c4b5fd;
  --tone-5: #172a40; --tone-5-ink: #93c5fd;
  --sheet-edge: var(--rule-soft);
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.35);
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 16px 40px -20px rgba(0, 0, 0, 0.7);
}

/* ── base ───────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--paper-deep);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.55;
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}
::selection { background: var(--accent); color: var(--on-accent); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
button { font: inherit; cursor: pointer; }
input[type="checkbox"], input[type="radio"], progress { accent-color: var(--accent); }
a { color: inherit; }
.hidden { display: none !important; }
/* The `hidden` attribute must beat the display rules further down. Author CSS
   outranks the browser's own [hidden] rule, so `.login .other { display: block }`
   was showing the local-test link on the production sign-in page. */
[hidden] { display: none !important; }

/* Display type: bold and tight. Labels: small sans capitals with light tracking.
   No other small text style is invented. */
.display { font-family: var(--font-display); font-weight: 800; letter-spacing: -0.02em; word-spacing: 0.04em; line-height: 1.05; }
.display-sm { font-family: var(--font-display); font-weight: 700; letter-spacing: -0.02em; line-height: 1.2; }
h1, h2, h3, h4 { letter-spacing: -0.01em; word-spacing: 0.03em; }
.label {
  font-family: var(--font-sans); font-size: 0.68rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.07em; color: var(--ink-muted);
}
.tnum { font-variant-numeric: tabular-nums; }
/* Times and dates: tabular figures in the text face, not a typewriter. */
.mono { font-family: var(--font-sans); font-size: 0.78rem; font-variant-numeric: tabular-nums; }

/* The sheet: a white card on the ground, lifted by a hairline and a soft shadow. */
.sheet {
  position: relative;
  background: var(--paper);
  border: 1px solid var(--sheet-edge);
  box-shadow: var(--shadow);
}

/* The instrument: the part you operate. Follows the theme; see the header. */
.instrument {
  background: var(--panel);
  color: var(--panel-ink);
  border: 1px solid var(--panel-line);
}
.instrument .label { color: var(--panel-accent); }

/* ── controls ───────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; gap: 0.5rem;
  border: 1px solid var(--accent); background: var(--accent); color: var(--on-accent);
  border-radius: 0.6rem; padding: 0.5rem 0.95rem;
  font-size: 0.85rem; font-weight: 600; white-space: nowrap;
  box-shadow: var(--shadow-sm); transition: background 0.16s, border-color 0.16s, color 0.16s;
}
.btn:hover:not(:disabled) { background: color-mix(in oklab, var(--accent) 88%, var(--ink)); border-color: color-mix(in oklab, var(--accent) 88%, var(--ink)); }
.btn:disabled { opacity: 0.55; cursor: progress; }
a.btn { text-decoration: none; }
.btn.quiet { background: var(--paper); color: var(--ink-soft); border-color: var(--rule); font-weight: 500; }
.btn.quiet:hover:not(:disabled) { background: var(--surface); border-color: var(--rule); color: var(--ink); }
.instrument .btn { border-color: var(--panel-accent); background: var(--panel-accent); color: var(--on-accent); }
.instrument .btn.quiet { background: transparent; color: var(--panel-ink); border-color: var(--panel-line); }

.input {
  width: 100%; padding: 0.6rem 0.75rem;
  border: 1px solid var(--rule); border-radius: 0.6rem;
  background: var(--paper); color: var(--ink); font: inherit;
  transition: border-color 0.16s, box-shadow 0.16s;
}
.input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-wash); }
select.input { appearance: auto; }
.instrument textarea.input {
  background: color-mix(in oklab, var(--panel) 70%, var(--panel-line));
  color: var(--panel-ink); border-color: var(--panel-line); resize: vertical; min-height: 5.5rem;
}

/* The switch. One control, unmistakable state. */
.switch {
  display: inline-flex; align-items: center; gap: 0.7rem;
  padding: 0.35rem 0.4rem 0.35rem 0.9rem; border-radius: 999px;
}
.switch .state { font-size: 0.85rem; white-space: nowrap; }
.switch .state b { font-weight: 700; }
.knob {
  width: 2.9rem; height: 1.6rem; border-radius: 999px; border: 0; padding: 0; position: relative; flex: none;
  background: var(--panel-line); transition: background 0.16s;
}
.knob::after {
  content: ""; position: absolute; top: 0.2rem; left: 0.2rem; width: 1.2rem; height: 1.2rem;
  border-radius: 50%; background: var(--knob); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25); transition: transform 0.16s;
}
.knob[aria-pressed="true"] { background: var(--panel-accent); }
.knob[aria-pressed="true"]::after { transform: translateX(1.3rem); background: var(--on-accent); }


.dot { display: inline-block; width: 0.45rem; height: 0.45rem; border-radius: 50%; background: var(--ink-muted); vertical-align: middle; }
.dot.ok { background: var(--ok); }
.dot.warn { background: var(--warn); }
.dot.bad { background: var(--bad); }

/* ── sign in ────────────────────────────────────────────────────────────── */
/* Sign in is a split screen; its rules live in the sign-in section below. */
.err { color: var(--bad); font-size: 0.85rem; min-height: 1.2rem; margin-top: 0.5rem; }

/* ── shell ──────────────────────────────────────────────────────────────── */
.shell { display: grid; grid-template-columns: 13rem 1fr; min-height: 100vh; }
.rail {
  background: var(--paper); border-right: 1px solid var(--rule);
  padding: 1.1rem 0.7rem; display: flex; flex-direction: column; gap: 0.15rem;
}
.rail .brand { padding: 0.2rem 0.6rem 1rem; display: flex; flex-direction: column; align-items: flex-start; gap: 0.5rem; }
.logo { display: block; border-radius: 0.4rem; object-fit: contain; }
.conv .subject, .thread .subject { font-size: 0.78rem; color: var(--accent); margin-top: 0.1rem; }
.thread .who a { color: var(--accent); text-decoration: none; }
.thread .who a:hover { text-decoration: underline; }
.rail .brand .name { font-size: 1rem; }
.rail .brand .label { display: block; margin-top: 0.25rem; }
.rail a {
  display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
  padding: 0.5rem 0.6rem; border-radius: 0.45rem; text-decoration: none;
  color: var(--ink-soft); font-size: 0.9rem; cursor: pointer;
}
.rail a:hover { background: var(--surface); }
.rail a[aria-current="page"] { background: var(--accent-wash); color: var(--ink); font-weight: 600; }
.rail .count { font-size: 0.68rem; background: var(--attention); color: var(--on-attention); border-radius: 999px; padding: 0.05rem 0.45rem; font-weight: 700; }
.rail .foot { margin-top: auto; padding: 0.6rem; display: flex; flex-direction: column; gap: 0.5rem; }
.rail .menu-btn { display: none; width: 2.4rem; height: 2.4rem; border-radius: 0.5rem; border: 1px solid var(--rule); background: var(--surface); color: var(--ink); place-items: center; flex: none; cursor: pointer; }
.rail .menu-btn .glyph { width: 1.2rem; height: 1.2rem; }
.rail .who { font-size: 0.8rem; color: var(--ink-muted); }
.rail .who b { color: var(--ink); font-weight: 600; }

main { padding: 1.4rem 1.6rem 3rem; min-width: 0; background: var(--paper-deep); }
.topbar { display: flex; align-items: center; gap: 0.8rem; flex-wrap: wrap; margin-bottom: 1.1rem; }
.topbar h2 { margin: 0; font-size: 1.3rem; }
.grow { flex: 1; }
.pill {
  display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.74rem; font-weight: 500;
  font-variant-numeric: tabular-nums; background: var(--surface); border: 1px solid var(--rule-soft);
  padding: 0.3rem 0.7rem; border-radius: 999px; color: var(--ink-soft); white-space: nowrap;
}

/* ── cards and tables (settings pages) ──────────────────────────────────── */
.card { padding: 1.1rem 1.2rem; margin-bottom: 1rem; border-radius: var(--radius); }
.card h3 { margin: 0 0 0.2rem; font-size: 0.98rem; }
.card .sub { margin: 0 0 0.9rem; color: var(--ink-muted); font-size: 0.85rem; max-width: 46rem; }
.row { display: flex; align-items: center; gap: 0.8rem; flex-wrap: wrap; }
table { width: 100%; border-collapse: collapse; font-size: 0.88rem; }
th { text-align: left; padding: 0 0.75rem 0.5rem 0; border-bottom: 1px solid var(--rule); }
td { padding: 0.55rem 0.75rem 0.55rem 0; border-bottom: 1px solid var(--rule-soft); color: var(--ink-soft); vertical-align: top; }
tr:last-child td { border-bottom: 0; }
td b { color: var(--ink); font-weight: 600; }
.scroll { overflow-x: auto; }
.none { color: var(--ink-muted); font-style: italic; }
ul.plain { margin: 0; padding-left: 1.1rem; } ul.plain li { margin: 0.25rem 0; color: var(--ink-soft); }
.empty { color: var(--ink-muted); padding: 1.4rem; text-align: center; font-size: 0.9rem; }

/* ── inbox ──────────────────────────────────────────────────────────────── */
.inbox { display: grid; grid-template-columns: 21rem 1fr; border-radius: var(--radius); overflow: hidden; min-height: 34rem; }
.convs { border-right: 1px solid var(--rule); overflow-y: auto; min-height: 0; }
.convs .head { border-bottom: 1px solid var(--rule-soft); position: sticky; top: 0; background: var(--paper); z-index: 1; }
.conv {
  display: block; width: 100%; text-align: left; background: none; border: 0;
  border-bottom: 1px solid var(--rule-soft); padding: 0.75rem 0.9rem; color: inherit;
}
.conv:hover { background: var(--surface); }
.conv[aria-current="true"] { background: var(--accent-wash); }
.convs .more { display: block; width: 100%; padding: 0.7rem; background: none; border: 0; color: var(--accent); font-size: 0.85rem; }

/* The chat reads like the app the team already lives in: a wallpaper with a
   faint line drawing (our own travel doodles, not theirs), flat bubbles with a
   tail on the first of a run, the time tucked inside. */
.thread { display: flex; flex-direction: column; min-width: 0; min-height: 0; position: relative; background: var(--thread-bg); }
/* The wallpaper lives on the scrolling region only, so the head and the bar
   stay plain, and it holds still while the messages move over it. Mid-grey
   lines at a fixed low opacity read as faint on both the dark and the cream
   ground. Icons are rotated and scattered so the tile does not read as a grid. */
.msgs { background-color: var(--thread-bg); background-size: 150px 150px; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='150' height='150' fill='none' stroke='%23808080' stroke-opacity='.11' stroke-width='1.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cg transform='rotate(-18 30 34)'%3E%3Cpath d='M14 40l26-12-6 10 8 6-12-2-7 5z'/%3E%3C/g%3E%3Cg transform='translate(112 20) rotate(12)'%3E%3Ccircle r='6'/%3E%3Cpath d='M0-11v3M0 8v3M-11 0h3M8 0h3M-8-8l2 2M6 6l2 2M-8 8l2-2M6-6l2-2'/%3E%3C/g%3E%3Cg transform='translate(70 118) rotate(-8)'%3E%3Cpath d='M0 26q3-22 8-34M8-8q-12-8-22-2M8-8q12-10 24-3M8-8q-3-13 5-20M8-8q5-13-5-20'/%3E%3C/g%3E%3Cg transform='translate(28 98) rotate(22)'%3E%3Ccircle r='9'/%3E%3Cpath d='M0-8l3 8-3 8-3-8z'/%3E%3C/g%3E%3Cg transform='translate(92 70) rotate(-6)'%3E%3Cpath d='M0 0a7 7 0 0 1 7-7 9 9 0 0 1 17-2 6 6 0 0 1 6 9z'/%3E%3C/g%3E%3Cg transform='translate(118 112) rotate(9)'%3E%3Crect x='-11' y='-7' width='22' height='16' rx='2.5'/%3E%3Cpath d='M-4-7v-4h8v4M-11 0h22'/%3E%3C/g%3E%3Cpath d='M8 138q6-6 12 0t12 0t12 0'/%3E%3Cg transform='translate(60 30) rotate(14)'%3E%3Crect x='-10' y='-7' width='20' height='14' rx='2.5'/%3E%3Ccircle r='3.5'/%3E%3C/g%3E%3Cg transform='translate(138 70) rotate(-20)'%3E%3Cpath d='M0-6l1.6 4 4 .4-3 2.8.8 4L0 3.2-3.4 5.2l.8-4-3-2.8 4-.4z'/%3E%3C/g%3E%3Cg transform='translate(130 140) rotate(-30)'%3E%3Cpath d='M-6 0h12M6 0l-3-3M6 0l-3 3'/%3E%3C/g%3E%3C/svg%3E"); }
.thread > * { position: relative; z-index: 1; }
.thread .head { padding: 0.8rem 1.1rem; border-bottom: 1px solid var(--rule-soft); display: flex; align-items: center; gap: 0.9rem; flex-wrap: wrap; }
.thread .who b { display: block; font-size: 0.98rem; }
.thread .who small { font-size: 0.74rem; font-variant-numeric: tabular-nums; color: var(--ink-muted); }
.thread .switch { margin-left: auto; }

.msgs { flex: 1; overflow-y: auto; padding: 0.9rem 1.4rem 1rem; display: flex; flex-direction: column; gap: 0.15rem; min-height: 0; }
.msg { position: relative; max-width: 68%; padding: 0.42rem 0.6rem 0.4rem 0.7rem; border-radius: 0.55rem; font-size: 0.9rem; line-height: 1.45; white-space: pre-wrap; word-break: break-word; box-shadow: 0 1px 1px rgba(0, 0, 0, 0.08); }
.msg::after { content: ""; display: block; clear: both; }
.msg.first { margin-top: 0.55rem; }
.msg.customer { background: var(--bubble-in); align-self: flex-start; }
.msg.business { background: var(--bubble-out); align-self: flex-end; }
.msg.customer.first { border-top-left-radius: 0; }
.msg.business.first { border-top-right-radius: 0; }
/* The tail: a triangle hanging off the top outer corner of the first bubble. */
.msg.first::before { content: ""; position: absolute; top: 0; width: 0; height: 0; border-top: 0.6rem solid var(--bubble-in); }
.msg.customer.first::before { left: -0.5rem; border-left: 0.5rem solid transparent; }
.msg.business.first::before { right: -0.5rem; border-top-color: var(--bubble-out); border-right: 0.5rem solid transparent; }
.notice { align-self: center; text-align: center; max-width: 34rem; }
/* The time sits inside, after the last line, the way a chat app does it. */
.msg .stamp { float: right; margin: 0.45rem 0 -0.1rem 0.7rem; font-size: 0.66rem; font-variant-numeric: tabular-nums; line-height: 1; color: color-mix(in oklab, var(--ink) 52%, transparent); }
.msg .by { display: block; font-size: 0.72rem; font-weight: 600; color: var(--accent); margin-bottom: 0.12rem; }

/* The composer: the instrument, and the only thing on the page you operate.
   One field, one decision (who answers next), one send. No eyebrow, no hint:
   the dark panel already says "this is where you act", and the decision is
   shown as the two marks that already appear on every row. */
/* A chat bar: one rounded line that grows with the text, and a round send
   button. What Send does is said by the placeholder, not by a line of its own;
   the switch in the head already shows who is answering. */
.composer { border-top: 1px solid var(--panel-line); padding: 0.5rem 0.8rem 0.55rem; }
.composer .bar { display: flex; align-items: flex-end; gap: 0.55rem; }
.composer textarea.input { min-height: 2.6rem; max-height: 11rem; resize: none; border-radius: 1.3rem; padding: 0.66rem 1rem; line-height: 1.4; overflow-y: auto; }
.composer .send { flex: none; width: 2.6rem; height: 2.6rem; border-radius: 50%; border: 0; background: var(--panel-accent); color: var(--on-accent); box-shadow: var(--shadow-sm); display: grid; place-items: center; cursor: pointer; }
.composer .send .glyph { width: 1.15rem; height: 1.15rem; }
.composer .send:disabled { opacity: 0.55; cursor: progress; }

/* The one case that needs words: the platform will not deliver. A struck clock
   and a single line, above the field so it is read before typing. */
.closed-note { display: flex; align-items: center; gap: 0.5rem; color: var(--warn); font-size: 0.8rem; margin-bottom: 0.55rem; }
.closed-note .glyph { flex: none; }
.closed-note.paused { color: var(--ink-muted); }
.composer.blocked .input { opacity: 0.55; }

/* Activity table state tags */
.tag { font-size: 0.7rem; font-weight: 600; padding: 0.12rem 0.55rem; border-radius: 999px; background: var(--quiet-wash); color: var(--ink-soft); white-space: nowrap; }
.tag.replied, .tag.assistant_on { background: var(--ok-wash); color: var(--ok); }
.tag.silent, .tag.stood_down, .tag.assistant_off, .tag.own_echo { background: var(--warn-wash); color: var(--warn); }
.tag.staff_reply { background: var(--accent-wash); color: var(--accent); }
.tag.error { background: var(--bad-wash); color: var(--bad); }

.toast {
  position: fixed; right: 1.1rem; bottom: 1.1rem; z-index: 10;
  padding: 0.7rem 1rem; border-radius: 0.6rem; font-size: 0.88rem;
  box-shadow: 0 12px 32px -12px rgba(0, 0, 0, 0.35);
}
.toast.bad { border-color: var(--bad); background: var(--bad-wash); color: var(--bad); }

/* ── the page is one sheet, not a stack of cards ────────────────────────── */
main { padding: 1.4rem 1.6rem 3rem; min-width: 0; background: var(--paper-deep); }
.page { padding: 1.4rem 1.6rem 2rem; border-radius: 1rem; min-height: calc(100vh - 4.4rem); }
.eyebrow { font-size: 0.7rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent); margin: 0 0 0.35rem; }
.lede { color: var(--ink-soft); font-size: 1rem; line-height: 1.55; margin: 0.4rem 0 1.4rem; max-width: 34rem; }
.measure { max-width: 46rem; }
.topbar { display: flex; align-items: flex-end; gap: 1rem; margin-bottom: 1.2rem; }
.topbar h2 { margin: 0; font-size: 1.65rem; font-weight: 800; letter-spacing: -0.012em; word-spacing: 0.06em; }

/* A section is a heading, a hairline that runs to the edge, and content. The
   rule is the divider; there are no boxes. */
.block { margin: 0 0 2rem; }
.rule { display: flex; align-items: center; gap: 0.9rem; margin-bottom: 0.7rem; }
.rule h3 { margin: 0; font-size: 1.15rem; white-space: nowrap; }
.rule .line { height: 1px; flex: 1; background: var(--rule); }
.faq dt { font-weight: 600; margin-top: 0.8rem; }
.faq dd { margin: 0.15rem 0 0; color: var(--ink-muted); max-width: 46rem; }
ul.cols { columns: 2; column-gap: 2.5rem; max-width: 46rem; }
.nowrap { white-space: nowrap; }
.bad { color: var(--bad); }

/* The figures a manager reads first. Large numerals, small captions, a hairline
   between each. State colour only where the figure is a state. */
.strip { display: grid; grid-template-columns: repeat(6, 1fr); border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule); margin: 0 0 1.2rem; }
.figure { padding: 0.9rem 1rem 0.8rem 0; border-right: 1px solid var(--rule-soft); }
.strip.three { grid-template-columns: repeat(3, 1fr); }
.figure + .figure { padding-left: 1rem; }
.figure:last-child { border-right: 0; }
.figure .num { font-size: 2rem; font-weight: 750; font-variant-numeric: tabular-nums; line-height: 1; margin-bottom: 0.35rem; }
.figure.warn .num { color: var(--warn); }
.figure.bad .num { color: var(--bad); }

/* Sign-in: the mark drawn large and faint behind the headline, bleeding off the
   corner of the sheet. Masked on every edge so nothing clips hard. */
/* ── sign in: a split screen ─────────────────────────────────────────────
   Left is the business: a real photograph from the tour catalogue, the brand,
   and three figures. Right is the work: the same two steps as before, password
   then a name. Deliberately dark in BOTH themes, unlike the console: this is a
   full-bleed night photograph, and a cream form over it reads as an accident,
   not a choice. The theme picks up again the moment you are inside. */
.login { min-height: 100vh; display: grid; grid-template-columns: 1.15fr 1fr; background: var(--night); color: var(--night-ink); }

.login-art { position: relative; overflow: hidden; }
.login-art > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; filter: saturate(1.05) contrast(1.05); }
/* Darkened toward the seam so the photo hands off to the form without an edge. */
.login-art::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(100deg, rgba(6,16,27,0.3) 0%, rgba(6,16,27,0.1) 40%, rgba(6,16,27,0.92) 100%),
    linear-gradient(to top, rgba(6,16,27,0.95) 0%, rgba(6,16,27,0.1) 45%),
    radial-gradient(120% 80% at 20% 90%, rgba(0,195,244,0.22), transparent 60%);
}
.art-layer { position: relative; z-index: 2; height: 100%; display: flex; flex-direction: column; justify-content: space-between; padding: 2.6rem 2.8rem; }
.art-brand { display: flex; align-items: center; gap: 0.9rem; }
/* The real wordmark already says the name, so it replaces the icon+text lockup.
   Source is 160x70; shown at 44px it is still ~2x, so it stays crisp. It is
   drawn for a white background (the "itri" is navy and disappears on dark), so
   it sits on a light chip rather than being recoloured, which would wreck the
   orange. Swap for a light-on-dark version the day the brand supplies one. */
.art-logo { height: 46px; width: auto; display: block; }
.art-brand .label { border-left: 1px solid rgba(255,255,255,0.2); padding-left: 0.9rem; }
.art-brand b { display: block; font-family: var(--font-display); font-weight: 700; font-size: 1.05rem; letter-spacing: -0.02em; line-height: 1.1; }
.art-brand .label { display: block; color: rgba(255,255,255,0.55); }
.art-title { font-size: 3.1rem; margin: 0 0 0.8rem; max-width: 11ch; }
.art-title em { font-style: normal; color: var(--brand-cyan); }
.art-lede { margin: 0; color: rgba(255,255,255,0.75); font-size: 1rem; line-height: 1.6; max-width: 34ch; }
.art-stats { display: flex; gap: 2.2rem; margin-top: 2rem; padding-top: 1.4rem; border-top: 1px solid rgba(255,255,255,0.1); }
.art-stats b { display: block; font-size: 1.35rem; line-height: 1; }
.art-stats .label { display: block; margin-top: 0.35rem; color: rgba(255,255,255,0.5); }

/* The working half: a glass card on a lit navy ground. A cyan glow from above and
   a warm hint of the brand orange low down give it depth; a faint dot grid fades
   toward the edges. Everything the person operates sits inside the card. */
.login-side { position: relative; display: grid; place-items: center; padding: 2.5rem 1.5rem; background: var(--night-2); overflow: hidden; isolation: isolate; }
.login-side::before {
  content: ""; position: absolute; inset: -20%; z-index: -1; pointer-events: none;
  background:
    radial-gradient(45% 40% at 72% 12%, rgba(0, 195, 244, 0.24), transparent 70%),
    radial-gradient(40% 35% at 12% 96%, rgba(252, 144, 27, 0.13), transparent 70%);
  animation: login-drift 18s ease-in-out infinite alternate;
}
.login-side::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-image: radial-gradient(rgba(255, 255, 255, 0.08) 1px, transparent 1px); background-size: 22px 22px;
  -webkit-mask-image: radial-gradient(70% 60% at 50% 45%, black, transparent);
          mask-image: radial-gradient(70% 60% at 50% 45%, black, transparent);
}
@keyframes login-drift { to { transform: translate3d(-3%, 2%, 0) scale(1.05); } }

.login-shell { width: 100%; max-width: 27rem; display: flex; flex-direction: column; gap: 1.3rem; }
#loginForm.login-card {
  position: relative; display: flex; flex-direction: column;
  padding: 2.4rem 2.2rem 2.1rem; border-radius: 1.5rem;
  background: linear-gradient(180deg, rgba(22, 43, 66, 0.72), rgba(10, 23, 38, 0.82));
  -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 0 0 1px rgba(255, 255, 255, 0.06), 0 40px 90px -40px rgba(0, 0, 0, 0.9);
  animation: login-rise 0.5s cubic-bezier(0.2, 0.7, 0.2, 1) both;
}
/* A hairline of light along the edge: cyan at the top corner, a touch of orange at the bottom one. */
#loginForm.login-card::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1px; pointer-events: none;
  background: linear-gradient(140deg, rgba(0, 195, 244, 0.6), rgba(0, 195, 244, 0) 38%, rgba(255, 255, 255, 0) 70%, rgba(252, 144, 27, 0.3));
  -webkit-mask: linear-gradient(black 0 0) content-box, linear-gradient(black 0 0); -webkit-mask-composite: xor;
          mask: linear-gradient(black 0 0) content-box, linear-gradient(black 0 0); mask-composite: exclude;
}
@keyframes login-rise { from { opacity: 0; transform: translateY(12px); } }

.login-chip { display: inline-flex; align-self: flex-start; align-items: center; gap: 0.5rem; margin: 0 0 1.1rem; padding: 0.32rem 0.8rem 0.32rem 0.6rem; border-radius: 999px; background: rgba(0, 195, 244, 0.1); border: 1px solid rgba(0, 195, 244, 0.22); color: var(--cyan-soft); font-size: 0.66rem; letter-spacing: 0.08em; }
.login-chip .live-dot { width: 0.42rem; height: 0.42rem; border-radius: 50%; background: var(--brand-cyan); box-shadow: 0 0 0 3px rgba(0, 195, 244, 0.2), 0 0 10px rgba(0, 195, 244, 0.8); }
#loginForm h1 { margin: 0 0 0.45rem; font-size: 2.15rem; font-weight: 800; letter-spacing: -0.02em; background: linear-gradient(180deg, var(--night-ink) 35%, var(--cyan-soft)); -webkit-background-clip: text; background-clip: text; color: transparent; }
#loginForm .lede { color: var(--night-muted); font-size: 0.95rem; line-height: 1.55; margin: 0 0 1.8rem; }

.login .field { margin-bottom: 0.9rem; }
.login .field .label { display: block; margin-bottom: 0.5rem; color: var(--night-muted); }
.input-wrap { position: relative; display: flex; align-items: center; }
.input-wrap .lead { position: absolute; left: 1rem; width: 1.15rem; height: 1.15rem; color: var(--night-muted); pointer-events: none; transition: color 0.16s; }
.input-wrap:focus-within .lead { color: var(--brand-cyan); }
/* The form sits on its own dark ground, so it cannot inherit the paper tokens. */
.login .input { height: 3.4rem; padding: 0 1rem 0 2.9rem; border-radius: 0.9rem; font-size: 1rem; background: rgba(255, 255, 255, 0.04); border: 1px solid rgba(255, 255, 255, 0.1); color: var(--night-ink); transition: border-color 0.16s, box-shadow 0.16s, background 0.16s; }
.login .input.has-reveal { padding-right: 3.2rem; }
.login .who-other .input { padding-left: 1rem; }
.login .input:hover { border-color: rgba(255, 255, 255, 0.2); }
.login .input:focus, .login .input:focus-visible { outline: none; background: rgba(0, 195, 244, 0.05); border-color: var(--brand-cyan); box-shadow: 0 0 0 4px rgba(0, 195, 244, 0.15); }
.login .input::placeholder { color: rgba(255, 255, 255, 0.3); }
/* The browser's autofill would paint the field white; keep it on the card. */
.login .input:-webkit-autofill, .login .input:-webkit-autofill:hover, .login .input:-webkit-autofill:focus { -webkit-text-fill-color: var(--night-ink); caret-color: var(--night-ink); box-shadow: 0 0 0 1000px var(--night-3) inset; transition: background-color 9999s; }
.reveal { position: absolute; right: 0.45rem; width: 2.5rem; height: 2.5rem; border: 0; border-radius: 0.65rem; background: transparent; color: var(--night-muted); display: grid; place-items: center; padding: 0; }
.reveal:hover { color: var(--night-ink); background: rgba(255, 255, 255, 0.06); }
.reveal[aria-pressed="true"] { color: var(--brand-cyan); }
.reveal:focus-visible { outline: 2px solid var(--brand-cyan); outline-offset: 1px; }
.reveal .glyph { width: 1.15rem; height: 1.15rem; }

.btn.wide { width: 100%; justify-content: center; margin-top: 0.4rem; }
.login .btn.wide {
  height: 3.4rem; margin-top: 0.6rem; gap: 0.6rem; padding: 0 1rem; border: 0; border-radius: 0.9rem;
  font-size: 1rem; font-weight: 700; color: var(--night);
  background: linear-gradient(135deg, var(--cyan-hi), var(--brand-cyan) 45%, var(--cyan-lo));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35), 0 14px 32px -14px rgba(0, 195, 244, 0.7);
  transition: transform 0.16s, box-shadow 0.16s, filter 0.16s;
}
.login .btn.wide:hover:not(:disabled) { transform: translateY(-1px); filter: brightness(1.06); background: linear-gradient(135deg, var(--cyan-hi), var(--brand-cyan) 45%, var(--cyan-lo)); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 20px 42px -14px rgba(0, 195, 244, 0.85); }
.login .btn.wide:active:not(:disabled) { transform: none; filter: brightness(0.97); }
.login .btn.wide:focus-visible { outline: 2px solid var(--brand-cyan); outline-offset: 3px; }
.login .btn.wide .arrow { width: 1.1rem; height: 1.1rem; stroke-width: 2; transition: transform 0.2s; }
.login .btn.wide:hover .arrow { transform: translateX(3px); }
/* Waiting on the server: the arrow turns into a spinner. */
.login .btn.wide:disabled { opacity: 1; cursor: progress; filter: saturate(0.85); }
.login .btn.wide:disabled .arrow { display: none; }
.login .btn.wide:disabled::after { content: ""; width: 1.05rem; height: 1.05rem; border-radius: 50%; border: 2px solid rgba(4, 18, 31, 0.25); border-top-color: var(--night); animation: login-spin 0.7s linear infinite; }
@keyframes login-spin { to { transform: rotate(360deg); } }

.login .err:empty { display: none; }
.login .err { display: block; margin: 0.3rem 0 0.2rem; padding: 0.65rem 0.85rem; border-radius: 0.75rem; background: rgba(247, 150, 139, 0.1); border: 1px solid rgba(247, 150, 139, 0.25); color: var(--night-bad); font-size: 0.88rem; line-height: 1.45; min-height: 0; }

/* The other way in: under an "or", as a quiet full-width button. */
.alt-row { display: flex; flex-direction: column; gap: 0.7rem; margin-top: 1.4rem; }
.alt-row .or { display: flex; align-items: center; gap: 0.8rem; color: var(--night-muted); font-size: 0.7rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; }
.alt-row .or::before, .alt-row .or::after { content: ""; flex: 1; height: 1px; background: rgba(255, 255, 255, 0.1); }
.alt-btn { display: inline-flex; align-items: center; justify-content: center; gap: 0.55rem; width: 100%; height: 3rem; border-radius: 0.9rem; border: 1px solid rgba(255, 255, 255, 0.14); background: rgba(255, 255, 255, 0.03); color: var(--night-ink); font-size: 0.92rem; font-weight: 600; transition: background 0.16s, border-color 0.16s; }
.alt-btn:hover { background: rgba(255, 255, 255, 0.07); border-color: rgba(255, 255, 255, 0.26); }
.alt-btn:focus-visible { outline: 2px solid var(--brand-cyan); outline-offset: 2px; }
.alt-btn .glyph { width: 1.05rem; height: 1.05rem; color: var(--brand-cyan); }

/* The link is on its way. */
.login .sent { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 0.35rem; margin: 0.2rem 0 0.2rem; }
.sent-icon { width: 4rem; height: 4rem; border-radius: 50%; display: grid; place-items: center; margin-bottom: 0.6rem; color: var(--cyan-soft); background: radial-gradient(circle at 30% 30%, rgba(0, 195, 244, 0.35), rgba(0, 195, 244, 0.08)); box-shadow: 0 0 0 1px rgba(0, 195, 244, 0.3), 0 0 44px -6px rgba(0, 195, 244, 0.6); }
.sent-icon .glyph { width: 1.7rem; height: 1.7rem; stroke-width: 1.6; }
.sent-title { margin: 0; font-size: 1.25rem; font-weight: 800; color: var(--night-ink); }
.login .sent p { margin: 0 0 1rem; color: var(--night-muted); line-height: 1.55; font-size: 0.95rem; max-width: 30ch; }
.login .sent .alt-btn { margin-top: 0.2rem; }

/* Who is signing in, after the team password: the team as cards with initials. */
.login .who-head { display: block; margin-bottom: 0.6rem; color: var(--night-muted); }
.login .people { display: flex; flex-direction: column; gap: 0.5rem; }
.person { display: flex; align-items: center; gap: 0.8rem; width: 100%; text-align: left; padding: 0.65rem 0.8rem; border-radius: 0.9rem; border: 1px solid rgba(255, 255, 255, 0.08); background: rgba(255, 255, 255, 0.03); color: var(--night-ink); font-size: 0.95rem; font-weight: 600; letter-spacing: -0.005em; transition: background 0.16s, border-color 0.16s; }
.person:hover { background: rgba(0, 195, 244, 0.08); border-color: rgba(0, 195, 244, 0.35); }
.person .p-ini { width: 2.2rem; height: 2.2rem; border-radius: 50%; display: grid; place-items: center; flex: none; background: rgba(0, 195, 244, 0.14); color: var(--cyan-soft); font-size: 0.8rem; font-weight: 700; }
.person .p-ini .glyph { width: 1rem; height: 1rem; }
.person .p-name { flex: 1; min-width: 0; }
.person .chev { width: 1rem; height: 1rem; color: var(--night-muted); transition: transform 0.16s, color 0.16s; }
.person:hover .chev { color: var(--brand-cyan); transform: translateX(2px); }
.login .other { display: block; background: none; border: 0; padding: 0.7rem 0.4rem 0.1rem; color: var(--brand-cyan); font-size: 0.85rem; text-decoration: none; }
.login .other:hover { text-decoration: underline; }
.login .who-loading { display: block; padding: 0.8rem 0.4rem; color: var(--night-muted); }
.login .who-note { display: block; margin: 0.5rem 0 0.7rem; line-height: 1.7; color: var(--night-muted); }
.login .who-other { margin-top: 0.6rem; }

.login-foot { display: flex; flex-direction: column; align-items: center; gap: 0.3rem; margin: 0; text-align: center; font-size: 0.8rem; color: var(--night-muted); }
.login-foot .secure { display: inline-flex; align-items: center; gap: 0.45rem; }
.login-foot .glyph { width: 1rem; height: 1rem; color: var(--brand-cyan); flex: none; }
.login-foot small { font-size: 0.72rem; opacity: 0.7; letter-spacing: 0.02em; }
.side-brand { display: none; justify-content: center; }
/* The supplied wordmark is drawn for white. On any dark ground it sits on a
   light chip; on the light theme the paper already suits it, so no chip. */
.brand-logo { display: block; width: auto; }
.side-brand .brand-logo { height: 52px; }
.rail .brand .brand-logo { height: 44px; }
/* The rail follows the theme, so it shows whichever artwork suits the ground:
   the white-ink version on the dark rail, the original navy one on paper. */
.rail .brand .on-light { display: none; }
:root:not([data-theme="dark"]) .rail .brand .on-dark { display: none; }
:root:not([data-theme="dark"]) .rail .brand .on-light { display: block; }

/* Narrow: the photograph steps aside and the form takes the screen. */
@media (max-width: 60rem) {
  .login { grid-template-columns: 1fr; }
  .login-art { display: none; }
  .side-brand { display: flex; }
  /* Without the photo panel, the photograph returns as a dim wash behind the card. */
  .login-side { min-height: 100vh; background: linear-gradient(180deg, rgba(10, 23, 38, 0.6) 0%, var(--night-2) 60%), url("/admin/img/hero.jpg") center top / cover no-repeat; }
}
@media (max-width: 30rem) {
  .login-side { padding: 1.5rem 1rem; }
  #loginForm.login-card { padding: 2rem 1.35rem 1.7rem; border-radius: 1.25rem; }
  #loginForm h1 { font-size: 1.85rem; }
}
@media (prefers-reduced-motion: reduce) {
  .login-side::before, #loginForm.login-card, .login .btn.wide:disabled::after { animation: none; }
}

.rail .foot .pill { justify-content: center; margin-bottom: 0.2rem; }

/* The rail: a real sidebar. Sections, counts, a footer. */
.rail { padding: 1.1rem 0.7rem 0.9rem; }
.rail .brand { padding: 0.4rem 0.6rem 1.1rem; margin-bottom: 0.3rem; display: flex; align-items: center; gap: 0.5rem; border-bottom: 1px solid var(--rule-soft); }
.rail .brand .label { color: var(--accent); letter-spacing: 0.12em; }
.rail .brand-name { font-size: 1.05rem; line-height: 1; }
.rail .mark { display: block; }
.rail nav .section { display: block; padding: 1.4rem 0.65rem 0.55rem; }
.rail a { display: flex; align-items: center; gap: 0.7rem; padding: 0.62rem 0.7rem; border-radius: 0.55rem; text-decoration: none; color: var(--ink-soft); font-size: 0.92rem; cursor: pointer; margin-bottom: 0.15rem; }
.rail a > span:first-of-type { flex: 1; }
.rail a .nav-ico { width: 1.05rem; height: 1.05rem; flex: none; color: var(--ink-muted); }
.rail a[aria-current="page"] .nav-ico { color: var(--accent); }
.rail a:hover .nav-ico { color: var(--ink-soft); }
.rail a:hover { background: var(--surface); color: var(--ink); }
.rail a[aria-current="page"] { background: var(--accent-wash); color: var(--ink); font-weight: 650; }
.rail .count { font-size: 0.68rem; background: var(--attention); color: var(--on-attention); border-radius: 999px; padding: 0.05rem 0.45rem; font-weight: 700; }
.rail .count:empty { display: none; }
.rail .count.muted { background: transparent; color: var(--ink-muted); font-weight: 500; }
.rail .foot { margin-top: auto; padding: 0.9rem 0.6rem 0; border-top: 1px solid var(--rule-soft); display: flex; flex-direction: column; gap: 0.6rem; }
:root[data-theme="dark"] .rail { position: relative; overflow: hidden; }
:root[data-theme="dark"] .rail::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 42%; z-index: 0; pointer-events: none;
  background: url("/admin/img/hero.jpg") 22% 35% / cover no-repeat; opacity: 0.16;
  -webkit-mask-image: linear-gradient(to top, black 30%, transparent);
          mask-image: linear-gradient(to top, black 30%, transparent);
}
:root[data-theme="dark"] .rail > * { position: relative; z-index: 1; }
.rail .who b { display: block; color: var(--ink); font-weight: 600; margin-top: 0.1rem; }
.row.tight { gap: 0.4rem; }
/* The name and, beside it, a way to change it that does not end the session. */
.rail .who .me { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 0.5rem; }
.rail .notyou { background: none; border: 0; padding: 0; color: var(--ink-muted); font-size: 0.72rem; text-decoration: underline; text-underline-offset: 2px; }
.rail .notyou:hover { color: var(--accent); }

/* Inbox: the list and the thread share the sheet, divided by a hairline. */
.inbox { display: grid; grid-template-columns: 21rem 1fr; border: 1px solid var(--rule); border-radius: var(--radius); overflow: hidden; min-height: 32rem; box-shadow: var(--shadow-sm); }
.conv .subject { font-size: 0.78rem; color: var(--accent); margin-top: 0.1rem; }
.thread .who b { display: block; font-size: 1.05rem; }
.thread .who .subject { font-size: 0.82rem; color: var(--accent); margin-top: 0.15rem; }
.empty.tall { margin: auto; width: min(26rem, 100%); }
/* Shimmering grey bars while something loads. */
.skeleton { display: flex; flex-direction: column; gap: 0.7rem; padding: 1rem 0; width: 100%; }
.skeleton span { display: block; height: 0.8rem; border-radius: 999px; background: linear-gradient(90deg, color-mix(in oklab, var(--ink) 7%, transparent) 0%, color-mix(in oklab, var(--ink) 14%, transparent) 40%, color-mix(in oklab, var(--ink) 7%, transparent) 80%); background-size: 200% 100%; animation: shimmer 1.3s linear infinite; }
.skeleton span:nth-child(3n+1) { width: 92%; }
.skeleton span:nth-child(3n+2) { width: 74%; }
.skeleton span:nth-child(3n) { width: 58%; }
@keyframes shimmer { from { background-position: 200% 0; } to { background-position: 0 0; } }
.empty-pane .skeleton { width: min(30rem, 100%); }
/* An empty screen: an icon in a soft circle, a line that says what is missing, a line that says what to do. */
.empty-state { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 0.35rem; padding: 2.4rem 1.2rem; color: var(--ink-muted); }
.empty-state > .glyph { width: 1.5rem; height: 1.5rem; padding: 0.8rem; box-sizing: content-box; border-radius: 50%; background: var(--accent-wash); color: var(--accent); margin-bottom: 0.4rem; }
.empty-state b { color: var(--ink); font-size: 0.98rem; font-weight: 700; }
.empty-state p { margin: 0; max-width: 24rem; font-size: 0.85rem; line-height: 1.5; }

/* ── marks: hairline glyphs, one stroke, currentColor ───────────────────── */
/* Six hand-drawn marks in the kit's stroke, so a channel, a state and a person
   all read as one hand. Colour is the only thing that changes between them,
   and only where the fact is a state that must be noticed. */
.glyph { width: 1rem; height: 1rem; fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; display: block; }
.marks { display: flex; flex-direction: column; align-items: center; gap: 0.35rem; padding-top: 0.15rem; color: var(--ink-muted); flex: none; }
.mark-ch { color: var(--ink-soft); }
.mark-ch.big .glyph { width: 1.4rem; height: 1.4rem; }
.mark-ch[data-ch="WhatsApp"] { color: var(--ch-wa); }
.mark-ch[data-ch="Instagram"] { color: var(--ch-ig); }
.mark-ch[data-ch="Facebook / Instagram"] { color: var(--ch-fb); }
.mark-ch[data-ch="Website chat"] { color: var(--accent); }
.mark-ai { color: var(--accent); }
.mark-closed { color: var(--bad); }
.mark-who.glyph-who { background: transparent; color: var(--ink-soft); }
.mark-who { width: 1.2rem; height: 1.2rem; border-radius: 50%; background: var(--accent); color: var(--on-accent); font-size: 0.62rem; font-weight: 700; display: grid; place-items: center; }

/* An avatar: initials in one of six colours, the same colour for the same person,
   and the channel as a badge on the corner. A person glyph when there is no name. */
.avatar { position: relative; flex: none; width: 2.5rem; height: 2.5rem; border-radius: 50%; display: grid; place-items: center; font-size: 0.85rem; font-weight: 700; letter-spacing: 0.01em; background: var(--tone-5); color: var(--tone-5-ink); }
.avatar[data-tone="0"] { background: var(--tone-0); color: var(--tone-0-ink); }
.avatar[data-tone="1"] { background: var(--tone-1); color: var(--tone-1-ink); }
.avatar[data-tone="2"] { background: var(--tone-2); color: var(--tone-2-ink); }
.avatar[data-tone="3"] { background: var(--tone-3); color: var(--tone-3-ink); }
.avatar[data-tone="4"] { background: var(--tone-4); color: var(--tone-4-ink); }
.avatar > .glyph { width: 1.15rem; height: 1.15rem; }
.avatar.big { width: 2.9rem; height: 2.9rem; font-size: 1rem; }
.ch-badge { position: absolute; right: -0.2rem; bottom: -0.2rem; width: 1.15rem; height: 1.15rem; border-radius: 50%; display: grid; place-items: center; background: var(--paper); box-shadow: 0 0 0 2px var(--paper); color: var(--ink-soft); }
.ch-badge .glyph { width: 0.75rem; height: 0.75rem; stroke-width: 1.8; }
.ch-badge[data-ch="WhatsApp"] { color: var(--ch-wa); }
.ch-badge[data-ch="Instagram"] { color: var(--ch-ig); }
.ch-badge[data-ch="Facebook / Instagram"] { color: var(--ch-fb); }
.ch-badge[data-ch="Website chat"] { color: var(--accent); }
.conv[aria-current="true"] .ch-badge { background: var(--accent-wash); box-shadow: 0 0 0 2px var(--accent-wash); }
.thread .head .ch-badge { background: var(--paper); box-shadow: 0 0 0 2px var(--paper); }

/* A row is three columns: marks, the person and their subject, the time. No
   chips, no last-message preview. What a consultant needs, and nothing that
   makes it look like a chat app. */
.conv { display: grid; grid-template-columns: 2.5rem minmax(0, 1fr) auto; gap: 0.75rem; align-items: center; width: 100%; text-align: left; background: none; border: 0; border-bottom: 1px solid var(--rule-soft); padding: 0.75rem 0.9rem; color: inherit; }
.conv .side { display: flex; flex-direction: column; align-items: flex-end; gap: 0.35rem; align-self: start; padding-top: 0.1rem; }
.conv .side .marks { flex-direction: row; gap: 0.3rem; padding: 0; }
.conv .side .marks:empty { display: none; }
.conv:hover { background: var(--surface); }
.conv[aria-current="true"] { background: var(--accent-wash); }
.conv .body { min-width: 0; display: flex; flex-direction: column; gap: 0.1rem; }
.conv .name { font-weight: 600; font-size: 0.9rem; letter-spacing: -0.005em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.conv .subject { font-size: 0.8rem; color: var(--ink-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.conv .when { font-size: 0.72rem; color: var(--ink-muted); }
/* Waiting too long: the time column turns amber and the row gets a hairline
   marker at its left edge. Position and colour carry it, not a word. */
.conv.waiting { box-shadow: inset 3px 0 0 var(--warn); }
.conv.waiting .when { color: var(--warn); font-weight: 600; font-size: 0.74rem; }

.thread .head .who { display: flex; align-items: center; gap: 0.7rem; min-width: 0; }
.thread .head .who b { display: block; font-size: 1.05rem; line-height: 1.15; }

/* Informative, not a headline: the same six figures in one quiet line. The
   big-numeral form stays for the knowledge page tiles (.strip.three). */
/* The Activity figures as a row of cards: the number large, what it counts under it,
   and a state colour only when the figure is a problem. */
.strip.compact { display: grid; grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr)); gap: 0.75rem; padding: 0; margin: 0 0 1.6rem; border: 0; }
.strip.compact .figure { display: flex; flex-direction: column; gap: 0.35rem; padding: 0.95rem 1rem; border: 1px solid var(--rule); border-radius: var(--radius); background: var(--paper); box-shadow: var(--shadow-sm); }
.strip.compact .figure + .figure { padding-left: 1rem; }
.strip.compact .figure:last-child, .strip.compact .figure:nth-child(3n) { border-right: 1px solid var(--rule); }
.strip.compact .figure .num { font-size: 1.75rem; margin-bottom: 0; color: var(--ink); }
.strip.compact .figure .label { font-size: 0.66rem; line-height: 1.35; }
.strip.compact .figure.warn { background: var(--warn-wash); border-color: transparent; }
.strip.compact .figure.warn:nth-child(3n), .strip.compact .figure.warn:last-child { border-right-color: transparent; }
.strip.compact .figure.warn .num { color: var(--warn); }
.strip.compact .figure.bad { background: var(--bad-wash); border-color: transparent; }
.strip.compact .figure.bad:nth-child(3n), .strip.compact .figure.bad:last-child { border-right-color: transparent; }
.strip.compact .figure.bad .num { color: var(--bad); }

/* ── search and filters, in the list header ─────────────────────────────── */
/* A rounded search field and a row of filter pills that match the marks on the
   rows. */
.convs .head { display: flex; flex-direction: column; gap: 0.5rem; padding: 0.7rem 0.9rem 0.6rem; }
/* Two rows, no more: search beside the channel icons, then status with the count. */
.search-row { display: flex; align-items: center; gap: 0.6rem; }
.search-row .search { flex: 1; min-width: 0; }
.filters-row { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.filters-row .filters { flex-wrap: nowrap; }
.search { display: flex; align-items: center; gap: 0.5rem; border: 1px solid var(--rule-soft); background: var(--surface); border-radius: 999px; padding: 0.35rem 0.75rem; color: var(--ink-muted); }
.search:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-wash); }
.search .glyph { flex: none; }
.search input { flex: 1; border: 0; background: transparent; color: var(--ink); font: inherit; font-size: 0.85rem; padding: 0.05rem 0; outline: none; min-width: 0; }
.search input::placeholder { color: var(--ink-muted); }
.filters { display: flex; gap: 0.3rem; flex-wrap: wrap; }
.filters button { font-size: 0.7rem; font-weight: 500; text-transform: capitalize; padding: 0.2rem 0.5rem; border-radius: 999px; border: 1px solid var(--rule); background: var(--paper); color: var(--ink-soft); transition: background 0.16s, color 0.16s; }
.filters button:hover { color: var(--ink); background: var(--surface); }
.filters button[aria-pressed="true"] { border-color: transparent; color: var(--accent); background: var(--accent-wash); font-weight: 600; }
.filters button.warn[aria-pressed="true"] { border-color: transparent; color: var(--warn); background: var(--warn-wash); }
/* Channel filters: the same glyphs the rows wear, lit in the channel's colour
   when pressed. A second press clears the filter. */
.filters.chans button { display: inline-flex; align-items: center; padding: 0.25rem 0.45rem; }
.filters.chans .glyph { width: 0.85rem; height: 0.85rem; }
.filters.chans button[aria-pressed="true"] { background: var(--surface); border-color: currentColor; }
.filters.chans button { padding: 0.28rem 0.5rem; }
.filters.chans [data-ch="WhatsApp"][aria-pressed="true"] { color: var(--ch-wa); }
.filters.chans [data-ch="Facebook / Instagram"][aria-pressed="true"] { color: var(--ch-fb); }
.filters.chans [data-ch="Instagram"][aria-pressed="true"] { color: var(--ch-ig); }
.filters.chans [data-ch="Website chat"][aria-pressed="true"] { color: var(--accent); }

/* Unread: a filled accent dot beside the name and the name in full ink. Read
   rows are quieter. State by weight and a mark, not by a word. */
.conv .name::before { content: ""; display: none; width: 0.45rem; height: 0.45rem; border-radius: 50%; background: var(--accent); margin-right: 0.4rem; vertical-align: 0.1rem; }
.conv.unread .name::before { display: inline-block; }
.conv.unread .name { color: var(--ink); font-weight: 700; }
.conv:not(.unread) .name { color: var(--ink-soft); font-weight: 600; }

/* ── smoothness: only what changed moves ─────────────────────────────────── */
/* The list and the thread are stable regions updated in place. A row that
   changes cross-fades; the thread swaps with one short fade; the selected row
   slides its wash rather than blinking. Nothing else animates. */
.conv { transition: background 0.16s, box-shadow 0.16s; }
.conv .when { transition: color 0.16s; }
.thread { position: relative; }
.thread .fade { animation: fade 0.18s ease-out; }
@keyframes fade { from { opacity: 0; transform: translateY(3px); } to { opacity: 1; transform: none; } }
.msgs { scroll-behavior: smooth; overscroll-behavior: contain; }
.convs { overscroll-behavior: contain; }
.toast { animation: fade 0.18s ease-out; }

/* ── signal chips in the header ──────────────────────────────────────────── */
.pulse { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; justify-content: flex-end; }
.chip { font-size: 0.74rem; font-weight: 600; padding: 0.3rem 0.75rem; border-radius: 999px; border: 1px solid var(--rule-soft); color: var(--ink-soft); background: var(--surface); white-space: nowrap; }
.chip.warn { border-color: transparent; color: var(--warn); background: var(--warn-wash); }
.chip.bad { border-color: transparent; color: var(--bad); background: var(--bad-wash); }
.chip.quiet { color: var(--ink-muted); }

/* ── theme toggle, top right ─────────────────────────────────────────────── */
.theme { display: grid; place-items: center; width: 2.1rem; height: 2.1rem; border: 1px solid var(--rule); border-radius: 999px; background: var(--paper); color: var(--ink-soft); padding: 0; box-shadow: var(--shadow-sm); }
.theme:hover { color: var(--ink); border-color: var(--ink-muted); }
.theme .glyph { grid-area: 1 / 1; width: 1rem; height: 1rem; transition: opacity 0.16s, transform 0.16s; }
.theme .sun { opacity: 0; transform: rotate(-30deg) scale(0.8); }
.theme .moon { opacity: 1; }
:root[data-theme="dark"] .theme .sun { opacity: 1; transform: none; }
:root[data-theme="dark"] .theme .moon { opacity: 0; transform: rotate(30deg) scale(0.8); }

/* ── what it knows ────────────────────────────────────────────────────────── */
/* Two panels on the sheet: the kinds on the left, the chosen kind's list on
   the right as one bordered pane with its own head (title, what it is for,
   the New button). The editor is a drawer over everything, so the list
   never has to shrink to make room for it. */
.config { display: grid; grid-template-columns: 13rem minmax(0, 1fr); gap: 1.2rem; align-items: start; }
.sections { display: flex; flex-direction: column; gap: 0.15rem; padding: 0.4rem; border: 1px solid var(--rule); border-radius: var(--radius); background: var(--paper); box-shadow: var(--shadow-sm); }
.sections [role="tab"] { display: flex; align-items: center; gap: 0.6rem; border: 0; background: transparent; text-align: left; padding: 0.55rem 0.65rem; border-radius: 0.45rem; color: var(--ink-soft); font-size: 0.9rem; }
.sections [role="tab"] .nav-ico { width: 1rem; height: 1rem; color: var(--ink-muted); flex: none; }
.sections .tlabel { flex: 1; min-width: 0; }
.sections [role="tab"]:hover { background: var(--surface); color: var(--ink); }
.sections [role="tab"][aria-selected="true"] { background: var(--accent-wash); color: var(--ink); font-weight: 600; }
.sections [role="tab"][aria-selected="true"] .nav-ico { color: var(--accent); }
.sections .rule-note { margin: 0.6rem 0.65rem 0.3rem; font-size: 0.76rem; line-height: 1.45; }
.scount { font-size: 0.72rem; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--ink-muted); display: inline-flex; align-items: center; gap: 0.35rem; }
.ddot { width: 0.45rem; height: 0.45rem; border-radius: 50%; background: var(--attention); display: inline-block; }
.pane { border: 1px solid var(--rule); border-radius: var(--radius); background: var(--paper); overflow: hidden; box-shadow: var(--shadow-sm); }
.pane-head { display: flex; align-items: center; gap: 0.9rem; padding: 0.95rem 1.1rem; border-bottom: 1px solid var(--rule-soft); }
.pane-head > div { flex: 1; min-width: 0; }
.pane-head h3 { margin: 0; font-size: 1.05rem; font-weight: 700; }
.pane-head .sub { display: block; margin: 0.1rem 0 0; font-size: 0.8rem; }
.pane-head .label { white-space: nowrap; }
/* The list groups by status; an approver's queue reads first. A group head is a
   quiet title, never a bar across the pane: a dot in the status colour, the name,
   and the count as a small pill. data-st carries the status (notes and documents). */
.group-head { display: flex; align-items: center; gap: 0.5rem; padding: 1rem 1.1rem 0.45rem; background: transparent; border-bottom: 1px solid var(--rule-soft); color: var(--ink-soft); text-transform: none; letter-spacing: 0; font-size: 0.8rem; font-weight: 700; }
.group-head::before { content: ""; width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--ink-muted); flex: none; }
.group-head[data-st="draft"]::before { background: var(--attention); }
.group-head[data-st="live"]::before { background: var(--ok); }
.group-head[data-st="paused"]::before { background: var(--ink-muted); }
.group-head[data-st="returned"]::before { background: var(--bad); }
.group-head[data-st="ended"]::before { background: var(--rule); }
.group-head b { font-weight: 600; font-size: 0.7rem; color: var(--ink-muted); background: var(--quiet-wash); border-radius: 999px; padding: 0.02rem 0.45rem; margin-left: 0; }
.notes-list { overflow: hidden; }
.empty-pane { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 0.7rem; padding: 2.6rem 1.5rem; color: var(--ink-soft); }
.empty-pane .glyph { width: 1.7rem; height: 1.7rem; color: var(--ink-muted); }
.empty-pane p { margin: 0; max-width: 32rem; font-size: 0.9rem; line-height: 1.5; }
.send-row { display: flex; align-items: center; gap: 0.6rem; margin-top: 0.6rem; }
/* A fixed first column, not auto: the four status words are different lengths
   and an auto column left the note titles on four different margins. */
.note { display: grid; grid-template-columns: 6.2rem minmax(0, 1fr) auto; gap: 0.8rem; align-items: start; width: 100%; text-align: left; background: none; border: 0; border-bottom: 1px solid var(--rule-soft); padding: 0.8rem 1.1rem; color: inherit; transition: background 0.16s; }
.note:last-child { border-bottom: 0; }
.note .marks { align-items: flex-start; }
.note:hover { background: var(--surface); }
.note .body { min-width: 0; display: flex; flex-direction: column; gap: 0.1rem; }
.note .name { font-weight: 650; font-size: 0.92rem; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.note .subject { font-size: 0.85rem; color: var(--ink-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.note .when { font-size: 0.76rem; color: var(--ink-muted); padding-top: 0.2rem; }
.note.ended { opacity: 0.55; }
.note .why { font-size: 0.78rem; color: var(--warn); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.note.returned .why { color: var(--bad); }
.note.paused .why { color: var(--ink-muted); }
.notes-list .more { display: block; width: 100%; border: 0; border-top: 1px solid var(--rule-soft); background: transparent; color: var(--ink-soft); font-size: 0.8rem; padding: 0.6rem; cursor: pointer; }
.notes-list .more:hover { color: var(--ink); background: var(--surface); }
/* Status in words. A glyph plus a title attribute is invisible on a scan and
   on a touch screen, and status is the only thing this screen is about. */
.nstat {
  display: inline-flex; align-items: center; gap: 0.35rem;
  font-size: 0.72rem; font-weight: 600; white-space: nowrap;
  padding: 0.16rem 0.6rem 0.16rem 0.5rem; border-radius: 999px; background: var(--quiet-wash); color: var(--ink-soft);
}
.nstat::before { content: ""; width: 0.4rem; height: 0.4rem; border-radius: 50%; background: currentColor; flex: none; }
.nstat.live { color: var(--ok); background: var(--ok-wash); }
.nstat.draft { color: var(--warn); background: var(--warn-wash); }
.nstat.paused { color: var(--ink-soft); background: var(--quiet-wash); }
.nstat.returned { color: var(--bad); background: var(--bad-wash); }
.nstat.ended { color: var(--ink-muted); background: var(--quiet-wash); }
/* The drawer: fixed to the right edge, the page dimmed behind it. */
.drawer-back { position: fixed; inset: 0; z-index: 39; background: rgba(6, 16, 27, 0.45); backdrop-filter: blur(2px); }
.note-editor { position: fixed; top: 0; right: 0; bottom: 0; width: min(36rem, 100%); z-index: 40; overflow-y: auto; padding: 1.1rem 1.4rem 1.3rem; border-radius: 0; box-shadow: -24px 0 60px -24px rgba(0, 0, 0, 0.45); animation: slide-in 0.18s ease-out; }
@keyframes slide-in { from { transform: translateX(1.5rem); opacity: 0; } }
.note-editor .send-row { position: sticky; bottom: -1.3rem; background: var(--panel); padding: 0.8rem 0 1.3rem; margin-top: 1rem; border-top: 1px solid var(--panel-line); }
.note-editor .label { display: block; margin: 0.7rem 0 0.3rem; }
.note-editor .label:first-of-type { margin-top: 0; }
.note-editor .input { background: color-mix(in oklab, var(--panel) 70%, var(--panel-line)); color: var(--panel-ink); border-color: var(--panel-line); }
/* A live note is read, not edited: its fields go quiet and dashed. [readonly]
   rather than :read-only, which would also match every select, always. */
.note-editor .input[readonly], .note-editor .input:disabled { opacity: 0.6; border-style: dashed; cursor: default; }
/* minmax(0, 1fr): a bare 1fr cannot shrink below a date input's intrinsic width, and two of them push the sheet off a phone. */
.note-editor .two { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0.7rem; }
.editor-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.8rem; margin-bottom: 0.8rem; padding-bottom: 0.8rem; border-bottom: 1px solid var(--panel-line); }
.editor-head h3 { margin: 0.2rem 0 0; font-size: 1.15rem; color: var(--panel-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.editor-head > div { min-width: 0; }
.checks { display: flex; gap: 0.9rem; flex-wrap: wrap; font-size: 0.85rem; }
.checks label { display: inline-flex; gap: 0.35rem; align-items: center; }

/* ── settings: office hours ─────────────────────────────────────────────── */
/* One setting, drawn as one: what is in force at the top, the version waiting
   for a decision under it, then the week. A day row is three columns (the day,
   open or closed, the two hours) and folds to two rows on a phone, so seven
   pairs of dropdowns never push the page sideways. */
.hours .sub { color: var(--ink-muted); font-size: 0.8rem; }
.hours-now { padding: 0.9rem 1rem; border-bottom: 1px solid var(--rule-soft); }
.hours-now .now { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.2rem 0.5rem; margin: 0; font-size: 0.95rem; }
.hours-now .now .dot { align-self: center; }
.hours-now .source { margin: 0.3rem 0 0; font-size: 0.85rem; color: var(--ink-soft); max-width: 46rem; }
/* Clock-in, drawn only when the server reads it: one quiet line and the people,
   under the hours it may narrow. A dashed rule, because it qualifies the lines
   above rather than starting a new section. */
.clockin { margin-top: 0.55rem; padding-top: 0.5rem; border-top: 1px dashed var(--rule); }
.clockin p { margin: 0; font-size: 0.82rem; color: var(--ink-soft); max-width: 46rem; }
.clockin .label { margin-right: 0.35rem; }
.clock-people { list-style: none; margin: 0.3rem 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.2rem 1.1rem; font-size: 0.82rem; color: var(--ink-muted); }
.clock-people b { color: var(--ink); font-weight: 600; }
.clock-people [data-st="OPENED"] span { color: var(--ok); }
.hours-state { padding: 0.8rem 1rem 0.7rem; border-bottom: 1px solid var(--rule-soft); background: var(--warn-wash); }
.hours-state.back { background: var(--bad-wash); }
.hours-state > .label { color: var(--warn); }
.hours-state.back > .label { color: var(--bad); }
.hours-state p { margin: 0.25rem 0 0; font-size: 0.9rem; max-width: 46rem; }
.hours-state .send-row { flex-wrap: wrap; margin-top: 0.55rem; }
.hours-state .older { margin-top: 0.7rem; padding-top: 0.5rem; border-top: 1px solid var(--rule); }
.older-row { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; font-size: 0.85rem; padding: 0.25rem 0; }
.hours-form { padding: 0.1rem 1rem 1.1rem; }
.hours-sec { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.2rem 0.7rem; margin: 1.1rem 0 0.45rem; }
.hours-sec .btn { margin-left: auto; }
.day-row { display: grid; grid-template-columns: 6.5rem auto minmax(0, 1fr); align-items: center; gap: 0.35rem 0.9rem; padding: 0.45rem 0; border-bottom: 1px solid var(--rule-soft); }
.day-rows { border-top: 1px solid var(--rule-soft); }
.day-row .day { font-weight: 600; font-size: 0.9rem; }
/* Open or closed: two real radio buttons drawn as one pill, so the keyboard
   and a screen reader get a proper choice and the eye gets one control. */
.seg { display: inline-flex; padding: 0.15rem; border: 1px solid var(--rule-soft); border-radius: 999px; background: var(--surface); }
.seg label { position: relative; }
.seg input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
.seg span { display: block; padding: 0.22rem 0.75rem; border-radius: 999px; font-size: 0.8rem; color: var(--ink-muted); cursor: pointer; }
.seg input:checked + span { background: var(--paper); color: var(--accent); font-weight: 600; box-shadow: var(--shadow-sm); }
.seg input[value="closed"]:checked + span { color: var(--ink); }
.seg input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 1px; }
.times { display: flex; align-items: center; flex-wrap: wrap; gap: 0.35rem 1rem; }
.times label { display: inline-flex; align-items: center; gap: 0.45rem; }
.times .input { width: auto; padding: 0.35rem 0.5rem; font-size: 0.85rem; }
.times-off { font-size: 0.85rem; }
.day-row.faulty .input { border-color: var(--bad); }
.day-notes { grid-column: 1 / -1; }
.day-notes:empty { display: none; }
.hnote { margin: 0.2rem 0 0; font-size: 0.8rem; line-height: 1.45; max-width: 46rem; }
.hnote.fault { color: var(--bad); }
/* A warning is something the person may not expect, not a mistake: quiet ink
   and an amber hairline, never the fault red. */
.hnote.warning { color: var(--ink-soft); padding-left: 0.55rem; border-left: 2px solid var(--warn); }
.closed-rows { display: flex; flex-direction: column; gap: 0.45rem; margin-bottom: 0.5rem; }
.closed-rows > .sub { margin: 0; }
/* minmax(0, ...) for the same reason as the drawer: a date input's intrinsic width would otherwise push a phone sideways. */
.closed-row { display: grid; grid-template-columns: 11rem minmax(0, 1fr) auto; gap: 0.5rem; align-items: center; }
.closed-row .input { min-width: 0; padding: 0.4rem 0.6rem; }
.hours-form > .input { max-width: 36rem; }
.hours-say { margin-top: 1.2rem; padding: 0.8rem 1rem; border: 1px solid transparent; border-radius: 0.6rem; background: var(--accent-wash); }
.hours-say p { margin: 0.25rem 0 0; font-size: 0.92rem; }
.hours-form .send-row { flex-wrap: wrap; margin-top: 0.9rem; }
@media (max-width: 40rem) {
  .day-row { grid-template-columns: minmax(0, 1fr) auto; }
  .times { grid-column: 1 / -1; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0.5rem; }
  .times label { flex-direction: column; align-items: stretch; gap: 0.2rem; min-width: 0; }
  .times .input { width: 100%; min-width: 0; }
  /* The pill already says Closed; a second line saying it again costs a row per day. */
  .times-off { display: none; }
  .closed-row { grid-template-columns: minmax(0, 1fr) auto; }
  .closed-row .lbl { grid-column: 1 / -1; grid-row: 2; }
  .hours-sec .btn { margin-left: 0; }
}

@media (max-width: 56rem) {
  .config { grid-template-columns: 1fr; }
  .sections { flex-direction: row; overflow-x: auto; }
  .sections [role="tab"] { flex: none; }
  .sections .rule-note { display: none; }
  .pane-head { flex-wrap: wrap; gap: 0.6rem 0.8rem; }
  .pane-head > div { flex: 1 1 100%; }
  .pane-head .label { margin-right: auto; }
  .kcards { grid-template-columns: 1fr; }
}

/* Built-in knowledge as three cards: the figure, one line on what it is and
   where a change really happens, and the list disclosed inside the card. */
.kcards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.9rem; margin-top: 1rem; }
.kcard { border: 1px solid var(--rule); border-radius: var(--radius); background: var(--paper); padding: 1rem 1.15rem 1.05rem; color: inherit; font: inherit; text-align: left; box-shadow: var(--shadow-sm); transition: border-color 0.16s; }
.kcard:hover { border-color: var(--accent); }
.kcard summary, .kcard.link { list-style: none; cursor: pointer; display: flex; flex-direction: column; align-items: flex-start; gap: 0.15rem; }
.kcard summary::-webkit-details-marker { display: none; }
.kcard .num { font-size: 1.9rem; line-height: 1; margin: 0.2rem 0 0.25rem; color: var(--accent); }
.kcard .sub { font-size: 0.8rem; line-height: 1.45; margin: 0; }
.kcard .more-link { margin-top: 0.55rem; font-size: 0.8rem; font-weight: 600; color: var(--accent); }
.kcard summary:hover .more-link, .kcard.link:hover .more-link { text-decoration: underline; }
.kcard[open] .more-link { display: none; }
.kcard ul.cols, .kcard .faq { margin: 0.9rem 0 0; padding-top: 0.9rem; border-top: 1px solid var(--rule-soft); columns: 1; font-size: 0.85rem; }
.kcard.link { width: 100%; }

/* ── the inbox as an app frame ──────────────────────────────────────────── */
/* The workspace owns the viewport: one frame, only inner regions scroll. The
   other pages stay documents on a sheet. The class is set by render(). */
/* Cap the single grid row to the viewport (the phone rule already does this
   for its two-row layout). Without it, a tall thread grows the row past 100vh,
   the whole page scrolls, and the composer is dragged off the bottom, which
   reads as "there is no reply box". overflow:hidden keeps the page itself from
   scrolling; only .msgs scrolls, and the composer stays pinned. */
body.view-inbox .shell { height: 100vh; grid-template-rows: minmax(0, 1fr); overflow: hidden; }
body.view-inbox main { display: flex; min-width: 0; min-height: 0; padding-bottom: 1.4rem; }
body.view-inbox .page { flex: 1; display: flex; flex-direction: column; min-height: 0; }
body.view-inbox #view { flex: 1; display: flex; flex-direction: column; min-height: 0; }
body.view-inbox .inbox { flex: 1; min-height: 0; grid-template-rows: minmax(0, 1fr); }
body.view-inbox .strip { margin-bottom: 1rem; }

/* A day separator: a thread that spans weeks must not read as one evening. */
.day-sep { display: flex; align-items: center; gap: 0.8rem; margin: 0.4rem 0; }
.day-sep::before, .day-sep::after { content: ""; height: 1px; flex: 1; background: var(--rule-soft); }

/* Back to the list; exists only on the one-pane phone layout. */
.thread .back { display: none; align-items: center; gap: 0.3rem; border: 0; background: transparent; color: var(--accent); font-size: 0.85rem; padding: 0.2rem 0.4rem 0.2rem 0; flex: none; }

/* ── tours: the photo and the facts the assistant grounds on ────────────── */
.thumb { width: 3.4rem; height: 2.3rem; object-fit: cover; border-radius: 0.35rem; display: block; border: 1px solid var(--rule-soft); }
.tour-row { cursor: pointer; }
.tour-row:hover td { background: var(--surface); }
.tour-cat { font-size: 0.75rem; color: var(--ink-muted); margin-top: 0.1rem; }
.tour-card { position: fixed; z-index: 30; width: 21rem; border-radius: var(--radius); overflow: hidden; pointer-events: none; }
.tour-card img { width: 100%; height: 9.5rem; object-fit: cover; display: block; }
.tour-card .pad { padding: 0.8rem 0.95rem 0.9rem; }
.tour-card h4 { margin: 0 0 0.15rem; font-size: 0.95rem; }
.tour-card .meta { font-size: 0.74rem; font-weight: 600; color: var(--accent); margin-bottom: 0.45rem; }
.tour-card p { margin: 0 0 0.45rem; font-size: 0.8rem; color: var(--ink-soft); line-height: 1.5; }
.tour-card ul { margin: 0; padding-left: 1rem; font-size: 0.78rem; color: var(--ink-soft); }
.tour-card li { margin: 0.15rem 0; }
.tour-detail td { background: var(--surface); }
.tour-detail .wrap { display: flex; gap: 0.9rem; padding: 0.4rem 0; align-items: flex-start; }
.tour-detail img { width: 8rem; height: 5.4rem; object-fit: cover; border-radius: 0.45rem; flex: none; }
.tour-detail p { margin: 0 0 0.4rem; font-size: 0.82rem; color: var(--ink-soft); line-height: 1.5; }
.tour-detail ul { margin: 0; padding-left: 1rem; font-size: 0.78rem; color: var(--ink-soft); }

/* ── phone ──────────────────────────────────────────────────────────────── */
@media (max-width: 56rem) {
  .shell { grid-template-columns: 1fr; }
  /* On a phone the rail is one short bar: the logo and a menu button. The
     nav and the footer unfold under it only while the menu is open, so the
     page itself starts near the top of the screen. */
  .rail { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 0.3rem 0.6rem; padding: 0.55rem 0.8rem; border-right: 0; border-bottom: 1px solid var(--rule); }
  .rail .brand { flex: 1; flex-direction: row; align-items: center; gap: 0.6rem; padding: 0; margin: 0; border-bottom: 0; }
  .rail .brand .brand-logo { width: 70px; height: auto; }
  .rail .brand .label { margin: 0; }
  .rail .menu-btn { display: inline-grid; }
  .rail nav, .rail .foot { display: none; width: 100%; }
  .rail.open nav { display: flex; flex-direction: column; gap: 0.15rem; margin-top: 0.4rem; padding-top: 0.5rem; border-top: 1px solid var(--rule-soft); }
  .rail.open .foot { display: flex; flex-direction: row; align-items: center; justify-content: space-between; margin: 0; padding: 0.6rem 0 0.2rem; }
  .rail .foot .pill { display: none; }
  /* One pane at a time: the list, or the thread with a way back. */
  .inbox { grid-template-columns: 1fr; }
  /* The figures give way to the conversation on a phone: three across when
     browsing, gone entirely once a thread is open. */
  .strip { grid-template-columns: repeat(3, 1fr); }
  .figure .num { font-size: 1.4rem; }
  #view:has(.inbox.open) .strip { display: none; }
  .inbox:not(.open) .thread { display: none; }
  .inbox.open .convs { display: none; }
  .thread .back { display: inline-flex; }
  body.view-inbox .shell { grid-template-rows: auto minmax(0, 1fr); }
  /* The header signal takes its own row under the title; the theme button
     stays beside the title instead of orphaned on a third line. Pills wrap. */
  .pulse { order: 5; flex-basis: 100%; justify-content: flex-start; }
  .filters-row { flex-wrap: wrap; }
  .filters-row .filters { flex-wrap: wrap; }
  .filters-row #convCount { display: none; }
  /* With a thread open the screen belongs to the chat: no header chips, a
     compact head (no subject line), the switch on its own slim row. */
  body.view-inbox:has(.inbox.open) .pulse { display: none; }
  .thread .head { padding: 0.5rem 0.75rem; gap: 0.4rem 0.6rem; }
  .thread .head .subject { display: none; }
  .thread .head .who b { font-size: 0.98rem; }
  .thread .switch { flex: 1 1 100%; margin-left: 0; justify-content: space-between; }
  /* The skyline atmosphere is for the tall rail. On the phone the rail is a
     short top bar, the fade compresses, and the picture lands behind the
     footer text. Off, here. */
  :root[data-theme="dark"] .rail::before { display: none; }
  main { padding: 1rem; }
  .inbox { grid-template-columns: 1fr; }
  .strip { grid-template-columns: repeat(3, 1fr); }
  .figure:nth-child(3n) { border-right: 0; }
  .header-art { display: none; }
  ul.cols { columns: 1; }
  /* One pane at a time fills the frame; the old 16rem and 20rem caps came from
     when the list and the thread were stacked on one screen. */
  .convs { border-right: 0; }
  .msg { max-width: 88%; }
  /* The built-in cards stack. This rule has to come after the base .kcards rule. */
  .kcards { grid-template-columns: 1fr; }
}
@media (max-width: 40rem) {
  /* A note row on a phone: the status pill on its own line, then the title with
     the end date beside it, so titles are not cut to a word. */
  .note { grid-template-columns: minmax(0, 1fr) auto; gap: 0.35rem 0.6rem; padding: 0.75rem 0.9rem; }
  .note .marks { grid-column: 1 / -1; flex-direction: row; }
  /* Two figure cards a row on a phone; one a row wastes the screen. */
  .strip.compact { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.6rem; }
  .strip.compact .figure { padding: 0.8rem 0.85rem; }
  .strip.compact .figure .num { font-size: 1.45rem; }
}
@media (prefers-reduced-motion: reduce) { * { transition: none !important; } }
@media print { body { background: white; } .sheet { border: 0; box-shadow: none; } }

/* ── uploaded documents (document plan, phase 6) ── */
/* Rows reuse the notes' row, pill and group styles; only what is new lives here. */
.note.doc { cursor: default; }
/* A failure reason cut to "Claude could not …" tells nobody anything; let it wrap. */
.note.doc .subject { white-space: normal; }
.note .why.quiet { color: var(--ink-muted); }
.doc-budget { margin: 0; padding: 0.6rem 0.9rem; border-top: 1px solid var(--rule-soft); font-size: 0.8rem; }
.drop-zone { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.35rem; margin: 1rem 0 0.6rem; padding: 2rem 1rem; border: 1.5px dashed var(--panel-line); border-radius: var(--radius); text-align: center; cursor: pointer; }
.drop-zone:hover, .drop-zone.over { border-color: var(--accent); background: var(--accent-wash); }
.drop-zone .drop-title { font-weight: 600; overflow-wrap: anywhere; }
.upload-bar { width: 100%; height: 0.55rem; accent-color: var(--accent); }
.upload-error { color: var(--bad); }
.doc-steps { margin: 0.9rem 0 0.4rem; padding-left: 1.2rem; line-height: 1.55; font-size: 0.9rem; }

/* ── the review sheet (document plan, phase 6, stage 2) ── */
/* A full view: the kinds rail, the pane head, the lede and Built in step aside. */
body.doc-review .lede, body.doc-review .sections, body.doc-review .pane-head, body.doc-review .built-in { display: none; }
body.doc-review .config { grid-template-columns: minmax(0, 1fr); }
button.note.doc { cursor: pointer; }
.note.doc .doc-acts { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.45rem; }
.review { display: grid; grid-template-columns: minmax(15rem, 19rem) minmax(0, 1fr); align-items: start; }
.rv-head { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem 0.9rem; padding: 0.8rem 1rem; border-bottom: 1px solid var(--rule-soft); }
.rv-title { flex: 1; min-width: 12rem; }
.rv-title h3 { margin: 0; font-size: 1.05rem; overflow-wrap: anywhere; }
.rv-title .sub { display: block; margin-top: 0.1rem; font-size: 0.8rem; }
.rv-list { min-width: 0; border-right: 1px solid var(--rule-soft); }
.rv-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 0.55rem; padding: 0.55rem 0.8rem; border-bottom: 1px solid var(--rule-soft); }
.rv-row.sel { background: var(--accent-wash); }
.rv-row input { margin: 0; }
.rv-pick { display: flex; flex-direction: column; gap: 0.08rem; min-width: 0; padding: 0; border: 0; background: none; color: inherit; font: inherit; text-align: left; cursor: pointer; }
.rv-kind { font-size: 0.7rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-muted); }
.rv-t { overflow: hidden; font-size: 0.88rem; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.rv-why { font-size: 0.76rem; color: var(--warn); }
.rv-why.quiet { color: var(--ink-muted); }
/* Knowledge the staff may use and the customer may not see. Filled, not a word
   among other words: a reviewer scanning a list has to catch it without reading. */
.rv-internal {
  font-size: 0.7rem; font-weight: 600; white-space: nowrap;
  padding: 0.1rem 0.4rem; border-radius: 999px;
  background: var(--attention); color: var(--on-attention);
}
/* What the reading covered, and what it could not. */
/* .review is a two column grid, so EVERY direct child of it must span both columns
   or it takes a single cell and shifts the list and the form around it. That is not
   theoretical: these two lines were added without it, and the sheet looked right only
   while both happened to render. The day a reading had nothing missing, one cell was
   filled instead of two and the form fell below the list (2026-10-20). */
.rv-coverage { grid-column: 1 / -1; margin: 0 0 0.5rem; font-size: 0.82rem; color: var(--ink-muted); }
.rv-missing {
  grid-column: 1 / -1;
  margin: 0 0 0.75rem; font-size: 0.82rem; color: var(--ink);
  background: var(--warn-wash); border-left: 3px solid var(--warn);
  border-radius: var(--radius); padding: 0.5rem 0.7rem;
}
.rv-n { font-size: 0.76rem; font-weight: 600; white-space: nowrap; }
.rv-n.stop { color: var(--bad); }
.rv-n.check { color: var(--warn); }
.rv-foot { display: flex; flex-direction: column; gap: 0.55rem; padding: 0.8rem; }
.rv-foot .sub { margin: 0; font-size: 0.8rem; }
.rv-form { min-width: 0; padding: 0.9rem 1.2rem 1.2rem; }
.rv-form .label { display: block; margin: 0.95rem 0 0.3rem; }
.rv-form .input { width: 100%; }
.rv-form textarea.input { resize: vertical; }
.rv-form .send-row { flex-wrap: wrap; margin-top: 1.2rem; padding-top: 0.8rem; border-top: 1px solid var(--rule-soft); }
.rv-ptitle { margin: 0.35rem 0 0; font-size: 1.05rem; }
.rv-state { margin: 0.7rem 0; }
.rv-block { font-size: 0.8rem; color: var(--bad); }
.rv-to-list { display: none; }
.src { margin: 0.3rem 0 0; font-size: 0.8rem; color: var(--ink-muted); }
/* No vertical padding: the clamp cuts at the padding edge, and padding showed half a fourth line. */
.src-quote { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; margin: 0.45rem 0 0.2rem; padding: 0 0.6rem; border-left: 2px solid var(--rule); color: var(--ink-soft); white-space: pre-line; cursor: pointer; }
.src-quote.open { display: block; }
.src-open { margin-left: 0.35rem; color: var(--accent); font-weight: 600; }
.src details summary { margin-top: 0.3rem; cursor: pointer; }
/* The whole page block, behind the sentence that was actually cited. */
.src-block summary { font-size: 0.78rem; color: var(--ink-muted); }
.src-block .src-quote { margin-top: 0.3rem; }
.src.typed { font-style: italic; }
.src-confirmed { display: block; margin-top: 0.3rem; color: var(--accent); }
.flag { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.35rem 0.5rem; margin: 0.4rem 0 0; padding: 0.45rem 0.6rem; border-radius: 0.4rem; font-size: 0.82rem; line-height: 1.45; }
.flag > b { flex: none; }
.flag > span { flex: 1; min-width: 10rem; }
.flag.stop { color: var(--bad); background: color-mix(in oklab, var(--bad) 10%, transparent); }
.flag.check { color: var(--warn); background: color-mix(in oklab, var(--warn) 10%, transparent); }
/* ── where a note came from (stage 3) ── */
/* "From an uploaded d…" names nothing; the origin line wraps like a failure reason. */
.note .why.origin { white-space: normal; }
.note-editor .from-doc { margin: 0 0 0.4rem; font-size: 0.8rem; color: var(--accent); }
.note-sources { margin-top: 1.2rem; padding-top: 0.9rem; border-top: 1px solid var(--panel-line); }
.note-sources > .sub { margin: 0.2rem 0; font-size: 0.8rem; }
.src-field { margin-top: 0.8rem; }
.note-editor .src-field .label { margin: 0 0 0.15rem; }
.note-editor .src, .note-editor .src-quote { color: color-mix(in oklab, var(--panel-ink) 72%, transparent); }
.note-editor .src-quote { border-left-color: var(--panel-line); }
/* ── settings: document reading (stage 3) ── */
.pane.doc-reading { margin-top: 1.2rem; }
.doc-reading-body { padding: 0.3rem 1rem 0.9rem; overflow-x: auto; }
.doc-reading-body table { width: 100%; }
.doc-reading-body td { padding: 0.5rem 0.8rem 0.5rem 0; border-bottom: 1px solid var(--rule-soft); vertical-align: top; }
.doc-reading-body td.label { width: 40%; white-space: normal; }
.doc-reading-off { margin: 0.6rem 0; }
/* Phone: two steps, the proposals and then the one tapped, full width. */
@media (max-width: 40rem) {
  .review { grid-template-columns: minmax(0, 1fr); }
  .rv-list { border-right: 0; }
  .review[data-step="list"] .rv-form, .review[data-step="form"] .rv-list { display: none; }
  .rv-to-list { display: inline-flex; margin-bottom: 0.5rem; }
  .rv-form { padding: 0.8rem; }
  .src-open { display: inline-flex; align-items: center; min-height: 44px; }
}

/* ── Settings tabs (settings-and-keys design) ── */
.tabbar { display: flex; gap: 0.4rem; margin: 0 0 1.1rem; overflow-x: auto; scrollbar-width: none; }
.tabbar::-webkit-scrollbar { display: none; }
.tabbar [role="tab"] { flex: none; padding: 0.45rem 1rem; border: 1px solid var(--rule); border-radius: 999px; background: var(--paper); color: var(--ink-soft); font: inherit; font-size: 0.88rem; cursor: pointer; transition: background 0.16s, color 0.16s; }
.tabbar [role="tab"]:hover { color: var(--ink); background: var(--surface); }
.tabbar [role="tab"][aria-selected="true"] { border-color: var(--accent); background: var(--accent); color: var(--on-accent); font-weight: 600; }
.tabbar [role="tab"]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.stab-panel > .pane + .pane { margin-top: 1.2rem; }
.clockin-body { padding: 0.8rem 1rem 1rem; }
.clockin-body .clockin { margin-top: 0; padding-top: 0; border-top: 0; }
.clock-off { margin: 0; font-size: 0.88rem; color: var(--ink-soft); }

/* ── Services and keys (settings-and-keys design) ── */
.keys { display: grid; gap: 1.2rem; }
.key-card .pane-head { align-items: baseline; }
.key-body { padding: 0.8rem 1rem 1rem; }
.key-body p { margin: 0 0 0.4rem; font-size: 0.9rem; max-width: 46rem; }
.key-body code { font-family: var(--font-mono); font-size: 0.85em; }
.kstat { font-size: 0.72rem; font-weight: 600; padding: 0.14rem 0.6rem; border-radius: 999px; background: var(--quiet-wash); color: var(--ink-soft); white-space: nowrap; }
.kstat.ok { color: var(--ok); background: var(--ok-wash); }
.kstat.bad { color: var(--bad); background: var(--bad-wash); }
.key-form { margin-top: 0.7rem; }
.key-form .label { display: block; margin-bottom: 0.3rem; }
.key-form .input { width: 100%; max-width: 32rem; font-family: var(--font-mono); }
.key-acts { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.7rem; }
