/* Client portal.
 *
 * The look is meant to read as expensive by being quiet, not by being decorated.
 * Three rules hold it together:
 *
 *   1. ONE cue per idea. A card was carrying a tint, a border AND a shadow to
 *      say "card" once. Now the page is the tint, the card is white, the border
 *      is a hairline, and the shadow is almost nothing.
 *   2. Ink leads, colour follows. The primary button is near-black, not brand
 *      blue. Blue is reserved for the three places it means something: links,
 *      the selected thing, and data.
 *   3. Space is the luxury. Padding and line-height are generous enough that
 *      nothing needs a divider to feel separate.
 *
 * Light lives on the bare :root; dark is redefined under both the OS media query
 * and an explicit [data-theme] stamp so a toggle wins in either direction.
 */

:root {
  color-scheme: light;

  /* Page is a soft neutral; cards are pure white. The contrast between the two
     is what makes a card read as raised without a shadow doing the work. */
  --bg:            #f4f4f2;
  --surface-1:     #ffffff;
  --surface-2:     #f7f7f5;
  --surface-3:     #efefec;
  --border:        #e7e6e1;
  --border-strong: #d2d0c9;

  --text-primary:   #14140f;
  --text-secondary: #57564f;
  --text-muted:     #8b897f;

  /* The action colour. Near-black rather than the brand hue: a page where the
     only saturated thing is the data reads calmer, and the one button that
     matters still wins on contrast alone. */
  --ink:        #1a1a17;
  --ink-hover:  #34332e;
  --ink-text:   #ffffff;

  /* Series colours are the validated categorical pair and are NOT design
     surface — they are data. Do not restyle them to match a mood; re-run
     scripts/validate_palette.js if a surface underneath them ever changes. */
  --series-1: #2a78d6;   /* pageviews */
  --series-2: #eb6834;   /* visitors  */

  --good:     #1baf7a;
  --warning:  #eda100;
  --critical: #e34948;

  --accent: var(--series-1);

  --r-sm: 6px;
  --r-md: 10px;
  --r-lg: 14px;
  --radius: var(--r-md);

  /* A whisper. On white cards the hairline does the separating; the shadow only
     stops them looking painted onto the page. */
  --shadow:    0 1px 2px rgba(20, 20, 15, .04);
  --shadow-lg: 0 1px 2px rgba(20, 20, 15, .05), 0 8px 24px rgba(20, 20, 15, .06);

  --ring: 0 0 0 3px color-mix(in srgb, var(--accent) 26%, transparent);
  --ease: 130ms cubic-bezier(.4, 0, .2, 1);

  --font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --bg:            #0e0e0d;
    --surface-1:     #171716;
    --surface-2:     #1f1f1d;
    --surface-3:     #272725;
    --border:        #2c2c28;
    --border-strong: #403f39;

    --text-primary:   #f6f5f1;
    --text-secondary: #b6b4aa;
    --text-muted:     #86847c;

    /* Inverted: on a dark page the confident action is the light one. */
    --ink:       #f3f2ee;
    --ink-hover: #ffffff;
    --ink-text:  #14140f;

    --series-1: #3987e5;
    --series-2: #d95926;

    --good:     #199e70;
    --warning:  #c98500;
    --critical: #e66767;

    --shadow:    0 1px 2px rgba(0, 0, 0, .5);
    --shadow-lg: 0 1px 2px rgba(0, 0, 0, .5), 0 8px 24px rgba(0, 0, 0, .38);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --bg:            #0e0e0d;
  --surface-1:     #171716;
  --surface-2:     #1f1f1d;
  --surface-3:     #272725;
  --border:        #2c2c28;
  --border-strong: #403f39;

  --text-primary:   #f6f5f1;
  --text-secondary: #b6b4aa;
  --text-muted:     #86847c;

  --ink:       #f3f2ee;
  --ink-hover: #ffffff;
  --ink-text:  #14140f;

  --series-1: #3987e5;
  --series-2: #d95926;

  --good:     #199e70;
  --warning:  #c98500;
  --critical: #e66767;

  --shadow:    0 1px 2px rgba(0, 0, 0, .5);
  --shadow-lg: 0 1px 2px rgba(0, 0, 0, .5), 0 8px 24px rgba(0, 0, 0, .38);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text-primary);
  font: 14.5px/1.55 var(--font);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: 'kern' 1;
}

a { color: var(--accent); text-underline-offset: 2px; }

::selection { background: color-mix(in srgb, var(--accent) 22%, transparent); }

/* One focus treatment everywhere, and only for keyboards. A mouse click should
   not leave a ring sitting on the thing it just pressed. */
:focus { outline: none; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ------------------------------------------------------------------ chrome */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 16px 32px;
  background: var(--surface-1);
  border-bottom: 1px solid var(--border);

  /* Same column as .shell, so the masthead sits over the rail rather than
     drifting left of it on a wide screen. */
  max-width: 1360px;
  margin: 0 auto;
  width: 100%;
}

.topbar h1 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -.014em;
}

.topbar .who {
  color: var(--text-muted);
  font-size: 12.5px;
  margin-top: 2px;
}

/* The client's own logo, top right, with the platform credit beneath it. */
.brandmark {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 5px;
  flex-shrink: 0;
}

.brandmark img {
  display: block;
  max-height: 38px;
  max-width: 190px;
  object-fit: contain;
}

.brandmark .fallback {
  font-size: 15.5px;
  font-weight: 620;
  letter-spacing: -.014em;
}

.brandmark .powered {
  font-size: 10px;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--text-muted);
  white-space: nowrap;
}

/* Navigation lives in a left rail, not across the top. */
.shell {
  position: relative;
  display: grid;
  grid-template-columns: 232px minmax(0, 1fr);
  max-width: 1360px;
  margin: 0 auto;
}

.shell::before {
  content: '';
  position: absolute;
  left: 232px;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--border);
  pointer-events: none;
}

.sidenav {
  position: sticky;
  top: 0;
  height: fit-content;
  max-height: 100vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 24px 14px;
  scrollbar-width: none;
}

.sidenav::-webkit-scrollbar { display: none; }

.sidenav button {
  appearance: none;
  border: 0;
  background: none;
  font: inherit;
  font-size: 13.5px;
  color: var(--text-secondary);
  text-align: left;
  padding: 9px 12px;
  border-radius: var(--r-sm);
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  transition: background var(--ease), color var(--ease);
}

.sidenav button:hover { background: var(--surface-3); color: var(--text-primary); }

/* The selected item is a filled pill rather than a rule down its edge: one
   shape, no marginalia. */
.sidenav button[aria-selected="true"] {
  background: var(--surface-3);
  color: var(--text-primary);
  font-weight: 570;
}

.sidenav .count {
  margin-left: auto;
  min-width: 18px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--critical);
  color: #fff;
  font-size: 10.5px;
  font-weight: 620;
  line-height: 18px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* Under tablet the rail would eat the page, so it lays flat above the content. */
@media (max-width: 760px) {
  .shell { grid-template-columns: 1fr; }

  .shell::before { display: none; }

  .sidenav {
    position: static;
    flex-direction: row;
    gap: 4px;
    height: auto;
    max-height: none;
    overflow-x: auto;
    overflow-y: visible;
    padding: 10px 16px;
    border-bottom: 1px solid var(--border);
  }

  .sidenav button { width: auto; white-space: nowrap; }
  .topbar { padding: 14px 18px; }
  main { padding: 20px 18px 56px; }
}

main {
  min-width: 0;
  padding: 28px 32px 72px;
}

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

.card {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  padding: 24px;
  margin-bottom: 18px;
}

.card h2 {
  margin: 0 0 3px;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.013em;
}

.card .sub {
  margin: 0 0 18px;
  color: var(--text-muted);
  font-size: 13px;
  line-height: 1.5;
  max-width: 68ch;
}

.row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
  flex-wrap: wrap;
}

/* -------------------------------------------------------------- stat tiles */

.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 14px;
  margin-bottom: 18px;
}

.tile {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  padding: 20px 22px;
}

.tile .label {
  font-size: 11px;
  font-weight: 560;
  color: var(--text-muted);
  letter-spacing: .07em;
  text-transform: uppercase;
}

/* The number is the point of a tile, so it is allowed to be big. Tabular
   figures keep a column of them aligned as the data changes. */
.tile .value {
  font-size: 34px;
  font-weight: 600;
  letter-spacing: -.03em;
  line-height: 1.1;
  margin-top: 8px;
  font-variant-numeric: tabular-nums;
}

.tile .swatch {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  margin-right: 7px;
  vertical-align: baseline;
}

/* ------------------------------------------------------------------- chart */

.chart-wrap { position: relative; }

svg.chart { display: block; width: 100%; height: auto; overflow: visible; }

svg.chart .grid  { stroke: var(--border); stroke-width: 1; }
svg.chart .axis  { fill: var(--text-muted); font-size: 11px; }
svg.chart .line  { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
svg.chart .dot   { stroke: var(--surface-1); stroke-width: 2; }
svg.chart .cross { stroke: var(--border-strong); stroke-width: 1; stroke-dasharray: 3 3; }

.legend {
  display: flex;
  gap: 20px;
  align-items: center;
  font-size: 12.5px;
  color: var(--text-secondary);
}

.legend span.key { display: inline-flex; align-items: center; gap: 7px; }

.legend i {
  width: 11px;
  height: 3px;
  border-radius: 2px;
  display: inline-block;
}

.tooltip {
  position: absolute;
  pointer-events: none;
  background: var(--surface-1);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  padding: 9px 11px;
  font-size: 12.5px;
  box-shadow: var(--shadow-lg);
  white-space: nowrap;
  opacity: 0;
  transition: opacity .1s;
  z-index: 5;
}

.tooltip.on { opacity: 1; }
.tooltip b { display: block; margin-bottom: 5px; font-weight: 600; font-size: 12px; }
.tooltip .k { display: flex; align-items: center; gap: 7px; }
.tooltip .k i { width: 8px; height: 8px; border-radius: 2px; }
.tooltip .k .n { margin-left: auto; padding-left: 16px; font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------------ tables */

table { width: 100%; border-collapse: collapse; font-size: 13.5px; }

th {
  text-align: left;
  font-weight: 560;
  font-size: 10.5px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 0 12px 10px 0;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

td {
  padding: 12px 12px 12px 0;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
  color: var(--text-secondary);
}

td:first-child { color: var(--text-primary); }
tr:last-child td { border-bottom: 0; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; padding-right: 0; }

/* A quiet magnitude cue behind the label — the number stays authoritative. */
td .bar {
  position: relative;
  display: block;
  padding: 4px 7px;
  border-radius: var(--r-sm);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

td .bar::before {
  content: '';
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--pct, 0%);
  background: color-mix(in srgb, var(--series-1) 13%, transparent);
  border-radius: var(--r-sm);
}

td .bar span { position: relative; }

.two-col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
}

@media (max-width: 760px) { .two-col { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------------- forms */

label.field { display: block; margin-bottom: 18px; }

label.field .lab {
  display: block;
  font-size: 12.5px;
  font-weight: 570;
  margin-bottom: 7px;
  letter-spacing: -.005em;
}

label.field .hint {
  font-weight: 400;
  color: var(--text-muted);
  margin-left: 8px;
}

input[type="text"], input[type="url"], input[type="email"],
input[type="search"], input[type="password"], textarea {
  width: 100%;
  padding: 10px 12px;
  font: inherit;
  font-size: 14px;
  color: var(--text-primary);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  resize: vertical;
  transition: border-color var(--ease), box-shadow var(--ease), background var(--ease);
}

input::placeholder, textarea::placeholder { color: var(--text-muted); }

input[type="text"]:hover, input[type="url"]:hover, input[type="email"]:hover,
input[type="search"]:hover, input[type="password"]:hover, textarea:hover {
  border-color: var(--border-strong);
}

input:focus, textarea:focus {
  outline: none;
  background: var(--surface-1);
  border-color: var(--accent);
  box-shadow: var(--ring);
}

.listitem {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 14px 16px;
  margin-bottom: 10px;
  background: var(--surface-2);
}

.listitem .idx {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--text-muted);
  margin-bottom: 9px;
}

/* ----------------------------------------------------------------- buttons */

button.btn, a.btn {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  font: inherit;
  font-size: 13.5px;
  font-weight: 550;
  line-height: 1.2;
  padding: 9px 15px;
  border-radius: var(--r-sm);
  border: 1px solid var(--border-strong);
  background: var(--surface-1);
  color: var(--text-primary);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--ease), border-color var(--ease), color var(--ease);
}

button.btn:hover:not(:disabled), a.btn:hover {
  background: var(--surface-2);
  border-color: var(--text-muted);
}

button.btn:disabled { opacity: .45; cursor: not-allowed; }

/* Ink, not brand blue. There is one of these on a screen and it should read as
   the obvious next move without shouting a colour. */
button.btn.primary, a.btn.primary {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--ink-text);
}

button.btn.primary:hover:not(:disabled), a.btn.primary:hover {
  background: var(--ink-hover);
  border-color: var(--ink-hover);
}

.actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }

.seg {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  padding: 2px;
  gap: 2px;
}

.seg button {
  appearance: none;
  border: 0;
  background: none;
  font: inherit;
  font-size: 12.5px;
  font-weight: 520;
  color: var(--text-muted);
  padding: 5px 12px;
  border-radius: 4px;
  cursor: pointer;
  transition: background var(--ease), color var(--ease);
}

.seg button:hover { color: var(--text-primary); }

/* The pressed segment is a raised chip inside the track, which is legible at a
   glance in a way a background swap is not. */
.seg button[aria-pressed="true"] {
  background: var(--surface-1);
  color: var(--text-primary);
  font-weight: 570;
  box-shadow: var(--shadow);
}

/* ------------------------------------------------------------------ pieces */

.pill {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 570;
  letter-spacing: .01em;
  border: 1px solid transparent;
}

.pill.pending  { background: color-mix(in srgb, var(--warning) 14%, transparent);  color: var(--warning); }
.pill.approved { background: color-mix(in srgb, var(--good) 14%, transparent);     color: var(--good); }
.pill.rejected { background: color-mix(in srgb, var(--critical) 13%, transparent); color: var(--critical); }
.pill.sent     { background: color-mix(in srgb, var(--series-1) 13%, transparent); color: var(--series-1); }

pre.snippet {
  margin: 0;
  padding: 14px 16px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  font: 12.5px/1.65 var(--mono);
  overflow-x: auto;
  white-space: pre;
  color: var(--text-secondary);
}

.note {
  padding: 11px 14px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  font-size: 13px;
  color: var(--text-secondary);
}

.note.warn {
  border-color: color-mix(in srgb, var(--warning) 45%, var(--border));
  background: color-mix(in srgb, var(--warning) 9%, var(--surface-2));
}

.note.bad {
  border-color: color-mix(in srgb, var(--critical) 45%, var(--border));
  background: color-mix(in srgb, var(--critical) 9%, var(--surface-2));
  color: var(--text-primary);
}

/* Something finished cleanly — the counterpart to .note.bad, not a warning. */
.note.good {
  border-color: color-mix(in srgb, var(--good) 45%, var(--border));
  background: color-mix(in srgb, var(--good) 9%, var(--surface-2));
  color: var(--text-primary);
}

/* Sits over the page rather than replacing it: the whole point is that the
   work underneath is still there. */
.lapsed {
  position: fixed;
  left: 50%;
  bottom: 22px;
  transform: translateX(-50%);
  z-index: 60;
  width: min(680px, calc(100vw - 32px));
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px;
  border-radius: 10px;
  border: 1px solid color-mix(in srgb, var(--critical) 45%, var(--border));
  background: color-mix(in srgb, var(--critical) 10%, var(--surface-1));
  color: var(--text-primary);
  font-size: 13.5px;
  box-shadow: 0 10px 30px rgb(0 0 0 / 18%);
}

.lapsed .actions { margin: 0; flex: 0 0 auto; }

.empty { color: var(--text-muted); font-size: 13.5px; padding: 18px 0; text-align: center; }

.spinner { color: var(--text-muted); font-size: 13.5px; padding: 28px 0; text-align: center; }

/* ------------------------------------------------------------------- login */

.login-wrap {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 24px;
}

.login-card {
  width: 100%;
  max-width: 360px;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow);
  padding: 28px;
}

.login-card h1 { margin: 0 0 4px; font-size: 19px; letter-spacing: -.015em; }
.login-card p.sub { margin: 0 0 22px; color: var(--text-muted); font-size: 13.5px; }
.login-card button { width: 100%; margin-top: 6px; }

.login-foot {
  margin-top: 20px;
  text-align: center;
  font-size: 10.5px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.pill.awaiting_platform {
  background: color-mix(in srgb, var(--series-1) 15%, transparent);
  color: var(--series-1);
}

/* Owner-only client switcher, pinned to the bottom of the rail. */
.switcher {
  margin-top: auto;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}

.account {
  padding-top: 14px;
  margin-top: 14px;
  border-top: 1px solid var(--border);
}

.account-who {
  font-size: 12.5px;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 0 12px;
}

.account-role {
  font-size: 11.5px;
  color: var(--text-muted);
  padding: 1px 12px 10px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

button.btn.signout {
  width: 100%;
  font-size: 13.5px;
  padding: 7px 12px;
}

.switcher-label {
  display: block;
  font-size: 11px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 0 0 6px 12px;
}

.client-select {
  width: 100%;
  padding: 8px 10px;
  font: inherit;
  font-size: 13.5px;
  color: var(--text-primary);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 7px;
}

.client-select:focus { outline: 2px solid var(--accent); outline-offset: -1px; }

@media (max-width: 760px) {
  .switcher {
    margin: 0 0 0 auto;
    padding: 0 0 0 12px;
    border-top: 0;
    border-left: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: 8px;
  }
  .switcher-label { display: none; }
  .client-select { width: auto; }
}

/* On phones the rail is a horizontal strip; the account block folds into it. */
@media (max-width: 760px) {
  .account {
    margin: 0 0 0 12px;
    padding: 0 0 0 12px;
    border-top: 0;
    border-left: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: 10px;
  }
  .account-who, .account-role { padding: 0; max-width: 140px; }
  button.btn.signout { width: auto; }
}

/* Local-only sign-in shortcuts on the login page. */
.devbox {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px dashed var(--border-strong);
}

.devbox h2 {
  margin: 0 0 3px;
  font-size: 11px;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--warning);
}

.devbox p {
  margin: 0 0 12px;
  font-size: 12px;
  color: var(--text-muted);
}

.devbox button {
  display: block;
  width: 100%;
  text-align: left;
  margin-bottom: 7px;
  padding: 9px 12px;
  font: inherit;
  font-size: 13.5px;
  color: var(--text-primary);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 7px;
  cursor: pointer;
}

.devbox button:hover { border-color: var(--text-muted); }
.devbox button .r { display: block; font-size: 11.5px; color: var(--text-muted); margin-top: 1px; }

/* CityPress wire */

/* ---------------------------------------------------- client access (owner) */

/* One row per feature: the switch, then what it does and where the current
   answer came from. */
.feat {
  display: grid;
  grid-template-columns: 44px 1fr;
  gap: 14px;
  align-items: start;
  padding: 14px 0;
  border-top: 1px solid var(--border);
}

.feat:first-of-type { border-top: 0; padding-top: 0; }

.feat-name {
  font-size: 14px;
  font-weight: 560;
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 3px;
}

.feat .sub { margin: 0 0 2px; }
.feat .actions { margin-top: 8px; }
.feat-status { color: var(--text-muted); }
.feat-caution { margin-top: 9px; }

/* A checkbox wearing a switch: the input keeps focus, keyboard and screen
   reader behaviour, and only the paint is ours. */
.switch { display: inline-block; position: relative; line-height: 0; }

.switch input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.switch .track {
  display: block;
  width: 40px;
  height: 23px;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  transition: background .15s ease, border-color .15s ease;
}

.switch .track::after {
  content: '';
  display: block;
  width: 17px;
  height: 17px;
  margin: 2px;
  border-radius: 50%;
  background: var(--text-muted);
  transition: transform .15s ease, background .15s ease;
}

.switch input:checked + .track {
  background: var(--accent);
  border-color: var(--accent);
}

.switch input:checked + .track::after {
  background: #fff;
  transform: translateX(17px);
}

.switch input:focus-visible + .track {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

button.btn.linkish, a.btn.linkish {
  padding: 5px 10px;
  font-size: 12.5px;
  font-weight: 520;
  color: var(--text-secondary);
  background: none;
  border-color: transparent;
}

button.btn.linkish:hover:not(:disabled), a.btn.linkish:hover {
  background: var(--surface-2);
  border-color: transparent;
  color: var(--text-primary);
}

details.desk {
  margin-top: 6px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

details.desk > summary {
  cursor: pointer;
  font-size: 13px;
  font-weight: 560;
  color: var(--text-secondary);
  margin-bottom: 12px;
}

details.desk p.sub { margin-bottom: 14px; }

.readiness { margin-top: 8px; }

.check-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 16px 0 6px;
  font-size: 13px;
}

table.checks td { vertical-align: top; }
table.checks .sub { margin: 2px 0 0; }

/* Standing caveats read as quiet context; a live problem gets a .note box. */
.feat .caveat { color: var(--text-muted); font-size: 12.5px; margin-top: 4px; }

/* ------------------------------------------------------- citypress: the wire */

.wire-card {
  display: flex;
  flex-direction: column;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
  margin-bottom: 16px;
}

@media (min-width: 760px) { .wire-card { flex-direction: row; } }

.wire-thumb {
  flex: 0 0 auto;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  height: 190px;
}

@media (min-width: 760px) {
  .wire-thumb { width: 240px; height: auto; border-bottom: 0; border-right: 1px solid var(--border); }
}

.wire-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

.wire-thumb.empty {
  display: grid;
  place-items: center;
  font: 700 40px/1 var(--font);
  color: color-mix(in srgb, var(--accent) 22%, transparent);
}

.wire-body { flex: 1 1 auto; min-width: 0; padding: 18px 20px; }

.wire-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 7px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-muted);
}

.wire-meta .dot { color: var(--border-strong); }

h2.wire-title {
  margin: 10px 0 0;
  font-size: 20px;
  font-weight: 640;
  line-height: 1.2;
  letter-spacing: -.015em;
}

.wire-excerpt {
  margin: 9px 0 0;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--text-secondary);
  /* The full post is one click away; the card stays scannable. */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.wire-full { margin-top: 12px; border-top: 1px solid var(--border); padding-top: 10px; }

.wire-full > summary {
  cursor: pointer;
  font-size: 11.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--accent);
}

.wire-full-text {
  margin-top: 10px;
  white-space: pre-wrap;
  font-size: 13px;
  line-height: 1.65;
  color: var(--text-secondary);
}

.wire-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 16px;
}

/* --------------------------------------------------- citypress: the desk line */

.cp-source-title {
  margin: 10px 0 0;
  font-size: 23px;
  font-weight: 640;
  line-height: 1.18;
  letter-spacing: -.02em;
}

.cp-step { border-top: 1px solid var(--border); padding: 14px 0; }
.cp-step:first-of-type { border-top: 0; padding-top: 0; }

.cp-step-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.cp-step-title { display: flex; align-items: center; gap: 10px; font-size: 14px; font-weight: 600; }

.cp-step-index {
  display: inline-grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  font: 600 11px/1 var(--mono);
  border: 1px solid var(--border-strong);
  color: var(--text-secondary);
}

.cp-step.done .cp-step-index {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

/* A locked step is visibly not yet available, rather than a button that fails. */
.cp-step.locked .cp-step-title { color: var(--text-muted); }
.cp-step.locked .cp-step-index { opacity: .45; }

.cp-step-hint { margin: 7px 0 0 30px; font-size: 12.5px; color: var(--text-muted); }
.cp-step-body { margin: 11px 0 0 30px; }

.cp-chosen { margin: 0; font-size: 14.5px; font-weight: 600; line-height: 1.35; }

.cp-candidates { list-style: none; margin: 10px 0 0; padding: 0; }
.cp-candidates li + li { margin-top: 4px; }

.cp-candidates button {
  appearance: none;
  width: 100%;
  text-align: left;
  font: inherit;
  font-size: 13.5px;
  line-height: 1.45;
  padding: 8px 11px;
  border: 1px solid transparent;
  border-radius: 7px;
  background: transparent;
  color: var(--text-primary);
  cursor: pointer;
}

.cp-candidates button:hover { background: var(--surface-2); }

.cp-candidates button.current {
  background: var(--surface-2);
  border-color: var(--border-strong);
  font-weight: 600;
}

.cp-embed {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--text-muted);
  cursor: pointer;
}

.cp-embed input { accent-color: var(--accent); }

/* The article arrives as assembled HTML — bold summary, h2, quoted source. */
.cp-article { font-size: 13.5px; line-height: 1.65; color: var(--text-secondary); }
.cp-article p { margin: 0 0 10px; }
.cp-article strong { color: var(--text-primary); font-weight: 600; }
.cp-article h2 { margin: 16px 0 8px; font-size: 15.5px; font-weight: 640; color: var(--text-primary); }
.cp-article a { color: var(--accent); }

.cp-article blockquote {
  margin: 0;
  padding-left: 13px;
  border-left: 2px solid var(--border-strong);
  color: var(--text-muted);
}

.cp-article figure { margin: 16px 0 0; }
.cp-article figcaption { margin-top: 6px; font-size: 11.5px; color: var(--text-muted); }
.cp-article .cp-source-url { font-size: 12px; word-break: break-all; }

.cp-thumb {
  height: 110px;
  width: auto;
  border: 1px solid var(--border);
  border-radius: 6px;
  object-fit: cover;
}

.cp-read { margin: 0; font-size: 13.5px; line-height: 1.7; }

/* Say what the picture should show. It shares the action row with Upload
   and Generate, so it may not take the full width the base input rule
   gives every other box. */
.cp-img-prompt {
  flex: 1 1 240px;
  min-width: 180px;
  width: auto;
}

.cp-saved-thumb {
  width: 100%;
  height: 170px;
  object-fit: cover;
  border-radius: 8px;
  border: 1px solid var(--border);
  margin-bottom: 14px;
}

.cp-saved-read { margin-top: 16px; border-top: 1px solid var(--border); padding-top: 12px; }

/* CityPress desk */
.cp-article {
  margin-top: 16px;
  padding: 16px 18px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 14.5px;
  line-height: 1.6;
}

.cp-article p { margin: 0 0 12px; }
.cp-article h2 { margin: 18px 0 10px; font-size: 16px; font-weight: 620; }
.cp-article p.cp-source-url { font-size: 12.5px; color: var(--text-muted); }

.cp-thumb {
  display: block;
  margin-top: 14px;
  max-width: 340px;
  width: 100%;
  border-radius: 8px;
  border: 1px solid var(--border);
}

/* CityPress: the chosen headline candidate, and the file-upload button. */
.wire-item.cp-chosen { background: var(--surface-2); border-radius: 8px; padding-left: 10px; }
.cp-file { display: none; }

/* CityPress: the feed image on offer before one is chosen. */
.cp-thumb-offer { margin: 12px 0 0; }
.cp-thumb-offer figcaption { margin-top: 6px; }

/* A Facebook post embedded at the foot of an article. */
/* The end of the line: leave for WordPress, or come back for the next story.
   Wraps rather than squeezing, because these are the two verbs that matter. */
.cp-handoff {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.cp-fb-embed { margin: 18px 0; }
.cp-fb-embed iframe { max-width: 100%; border: 0; }

/* ------------------------------------------------------- email builder */

.wp-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

/* A scroll box rather than a growing page: twenty posts is a list to skim,
   not a page to lose the Send button behind. */
.wp-picker {
  margin-top: 12px;
  max-height: 420px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}

.wp-post {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  width: 100%;
  padding: 10px 12px;
  text-align: left;
  background: none;
  border: 0;
  border-top: 1px solid var(--border);
  cursor: pointer;
  color: inherit;
  font: inherit;
}

.wp-post:first-child { border-top: 0; }
.wp-post { transition: background var(--ease); }
.wp-post:hover:not(:disabled) { background: var(--surface-2); }
.wp-post:disabled { opacity: 0.5; cursor: default; }

.wp-post img,
.wp-post-noimg {
  width: 84px;
  height: 56px;
  flex: 0 0 84px;
  object-fit: cover;
  border-radius: 5px;
  background: var(--surface-2);
}

.wp-post-noimg {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  font-size: 13px;
}

.wp-post-text { min-width: 0; }

.wp-post-title {
  font-size: 13.5px;
  font-weight: 560;
  color: var(--text-primary);
  margin-bottom: 3px;
}

/* Two lines of teaser, then stop — the rows have to stay scannable. */
.wp-post-text .sub {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}


/* ------------------------------------------------------- email builder */

/* Blocks left, the email right. Below 1000px the preview drops under the
   blocks rather than shrinking to a column neither pane can use. */
.builder {
  display: grid;
  grid-template-columns: minmax(0, 380px) minmax(0, 1fr);
  gap: 16px;
  align-items: start;
}

@media (max-width: 1000px) {
  .builder { grid-template-columns: minmax(0, 1fr); }
}

.blocks { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }

.blk {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-2);
  transition: border-color var(--ease), background var(--ease);
}

.blk:hover:not(.pinned) { border-color: var(--border-strong); }

.blk.open {
  border-color: var(--border-strong);
  background: var(--surface-1);
  box-shadow: var(--shadow);
}
.blk.off .blk-name { color: var(--text-muted); text-decoration: line-through; }
.blk.dragging { opacity: 0.4; }

/* The drop target, marked on its top edge — the block being dragged lands
   where the line is, not on top of what is already there. */
.blk.dropinto { box-shadow: inset 0 3px 0 0 var(--accent); }

.blk.pinned { background: var(--surface-2); border-style: dashed; }
.blk.pinned .blk-head { cursor: default; }

.blk-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 13px;
  cursor: pointer;
  user-select: none;
}

.blk-grip {
  color: var(--text-muted);
  font-size: 14px;
  cursor: grab;
  width: 12px;
}

.blk-name { flex: 1; font-size: 13.5px; font-weight: 560; color: var(--text-primary); }

.blk-lock { font-size: 11.5px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; }

.blk-toggle {
  font-size: 11px;
  font-weight: 570;
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface-1);
  color: var(--text-muted);
  cursor: pointer;
  transition: background var(--ease), color var(--ease), border-color var(--ease);
}

.blk-toggle[aria-pressed="true"] {
  border-color: color-mix(in srgb, var(--good) 45%, var(--border));
  background: color-mix(in srgb, var(--good) 14%, transparent);
  color: var(--good);
}

.blk-body { padding: 2px 13px 14px; border-top: 1px solid var(--border); }

.blk-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 9px;
  margin: 12px 0 14px;
}

/* The preview follows the page down — the blocks column is the long one. */
.preview-card { position: sticky; top: 16px; }

.preview-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}

.mailframe-wrap {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  overflow: hidden;
  background: #fafafa;
  transition: max-width 0.15s ease;
}

/* Phone width: the email's own media queries take over at 620px, so 380
   shows the stacked layout a reader on a handset actually gets. */
.mailframe-wrap.narrow { max-width: 380px; margin: 0 auto; }

.mailframe {
  display: block;
  width: 100%;
  height: 760px;
  border: 0;
  background: #fafafa;
}


/* ------------------------------------------------------ audience picker */

.aud-list {
  margin-top: 14px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  overflow: hidden;
}

.aud-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  width: 100%;
  padding: 11px 14px;
  text-align: left;
  background: none;
  border: 0;
  border-top: 1px solid var(--border);
  cursor: pointer;
  color: inherit;
  font: inherit;
}

.aud-row:first-child { border-top: 0; }
.aud-row { transition: background var(--ease); }
.aud-row:hover { background: var(--surface-2); }

.aud-row.on {
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  box-shadow: inset 3px 0 0 0 var(--accent);
}

/* ------------------------------------------- Find News Clipper instructions */

.howto { margin: 8px 0 4px; padding-left: 22px; display: grid; gap: 10px; }
.howto li { padding-left: 4px; }
.howto li::marker { font-weight: 600; color: var(--accent); }
.howto .sub { margin-top: 2px; }
.howto code {
  padding: 1px 5px;
  border-radius: 4px;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  font-size: 0.92em;
}

/* ------------------------------------------------ GetAlerts source picker */

.src-picker { position: relative; }
.src-picker .src-input { width: 100%; }

/* A dropdown over the page rather than a list that shoves the feeds table
   down on every keystroke. */
.src-list {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 4px);
  z-index: 40;
  max-height: 340px;
  overflow-y: auto;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: 0 12px 32px rgb(0 0 0 / 14%);
}

.src-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  width: 100%;
  padding: 10px 14px;
  text-align: left;
  background: none;
  border: 0;
  border-top: 1px solid var(--border);
  cursor: pointer;
  color: inherit;
  font: inherit;
}
.src-row:first-child { border-top: 0; }
.src-row[aria-selected="true"] {
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  box-shadow: inset 3px 0 0 0 var(--accent);
}
.src-row[aria-disabled="true"] { cursor: default; }
.src-row[aria-disabled="true"] .src-name { color: var(--text-muted); }

.src-name { font-weight: 560; }
.src-name mark { background: none; color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.src-row .wire-meta { margin-top: 3px; }
.src-act { flex: 0 0 auto; font-size: 12.5px; color: var(--text-muted); }
.src-row[aria-selected="true"] .src-act { color: var(--accent); }
.src-empty { padding: 12px 14px; color: var(--text-muted); font-size: 13px; }
.src-hint { margin: 6px 0 0; }

/* Sits in the uppercase meta line, so it wears the line's type rather than a
   button's — a quiet word, not a control shouting from every card. */
.wire-meta .wire-hide {
  padding: 0;
  font-size: 11px;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.aud-name { font-size: 13.5px; font-weight: 560; color: var(--text-primary); }
.aud-count { font-size: 12.5px; color: var(--text-muted); white-space: nowrap; }

/* Sending is the one irreversible thing on this page; it should not look like
   the button next to it. */
.btn.danger {
  background: var(--critical);
  border-color: var(--critical);
  color: #fff;
  font-weight: 570;
}

.btn.danger:hover:not(:disabled) {
  background: color-mix(in srgb, var(--critical) 86%, #000);
  border-color: color-mix(in srgb, var(--critical) 86%, #000);
}

.btn.danger:disabled { opacity: 0.45; }

/* ------------------------------------------------- email performance card */

/* The second line on a stat tile: what the number is measured over. A tile
   without it invites the reader to assume a window that isn't the real one. */
.tile-note {
  margin-top: 6px;
  font-size: 11.5px;
  color: var(--text-muted);
  line-height: 1.4;
}

svg.chart .bar {
  fill: var(--series-1);
  transition: fill var(--ease);
}

/* A send that is still being opened is not comparable to the settled ones, so
   it is drawn as an outline rather than a solid: the shape still shows where it
   has got to, and the emptiness says it is not finished. Colour alone would not
   carry that — the difference is fill, which reads in greyscale and for a
   colour-blind reader too. */
svg.chart .bar.landing {
  fill: color-mix(in srgb, var(--series-1) 18%, transparent);
  stroke: var(--series-1);
  stroke-width: 1.5;
  stroke-dasharray: 3 2.5;
}

/* The median line: recessive, because it is a reference and not a measurement. */
svg.chart .typical {
  stroke: var(--text-muted);
  stroke-width: 1;
  stroke-dasharray: 4 4;
}

svg.chart .typical-label { font-size: 10.5px; }

.tooltip .k span:first-child { color: var(--text-muted); }
.tooltip .landing-note {
  margin-top: 5px;
  padding-top: 5px;
  border-top: 1px solid var(--border);
  color: var(--warning);
  font-size: 11.5px;
}

/* --------------------------------------------------------------- icons */

/* Optical alignment: a 17px glyph next to 13.5px text sits a shade low if it
   is baselined, so it is centred against the line box instead. */
.ico {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
  color: var(--text-muted);
  transition: color var(--ease);
}

.sidenav button:hover .ico { color: var(--text-secondary); }

/* The selected rail item is the one place an icon carries the accent — it is
   the "you are here", and the label alone was doing that work. */
.sidenav button[aria-selected="true"] .ico { color: var(--accent); }

.btn .ico { color: inherit; opacity: .8; }

/* --------------------------------------------------------- page titles */

.pagehead {
  display: flex;
  align-items: center;
  gap: 11px;
  margin: 2px 0 22px;
}

.pagehead .ico { color: var(--text-secondary); }
.pagehead .ico svg { width: 20px; height: 20px; }

/* Bigger than a card heading and lighter in weight than the stat numbers, so
   the hierarchy reads page > section > figure without anything shouting. */
.pagehead h1 {
  margin: 0;
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -.022em;
  color: var(--text-primary);
}

.pagehead-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 10px;
}

@media (max-width: 560px) {
  .pagehead { flex-wrap: wrap; }
  .pagehead-actions { margin-left: 0; width: 100%; }
}


/* ------------------------------------------------------ google sign-in */

/* A labelled rule, so the two ways in read as alternatives rather than as a
   form with a stray button under it. */
.or {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 20px 0 14px;
  color: var(--text-muted);
  font-size: 12px;
}

.or::before, .or::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* Google's brand guidance wants their mark on a neutral surface with the
   wordmark intact — so this one keeps a white face in both themes rather than
   inverting with everything else. */
.btn.google {
  width: 100%;
  background: #ffffff;
  border-color: var(--border-strong);
  color: #1f1f1f;
  font-weight: 540;
}

.btn.google:hover { background: #f6f6f5; border-color: var(--text-muted); }
.btn.google svg { flex: 0 0 auto; }

/* --------------------------------------------------------------- selects */

/* Inputs are styled by element selector, which never covered <select> — so a
   dropdown beside a text field looked like a different design system. This
   matches them, and matches .client-select which had solved it locally. */
select.inp {
  width: 100%;
  padding: 10px 12px;
  font: inherit;
  font-size: 14px;
  color: var(--text-primary);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  transition: border-color var(--ease), box-shadow var(--ease), background var(--ease);
}

select.inp:hover { border-color: var(--border-strong); }

select.inp:focus {
  outline: none;
  background: var(--surface-1);
  border-color: var(--accent);
  box-shadow: var(--ring);
}

/* The desk's headline style picker sits inline beside Generate, so it takes
   select.inp's look at its natural width and the action row's button height. */
select.cp-style {
  padding: 7px 10px;
  font: inherit;
  font-size: 13.5px;
  color: var(--text-primary);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  transition: border-color var(--ease), box-shadow var(--ease), background var(--ease);
}

select.cp-style:hover { border-color: var(--border-strong); }

select.cp-style:focus {
  outline: none;
  background: var(--surface-1);
  border-color: var(--accent);
  box-shadow: var(--ring);
}

/* A one-time password wants to be unmistakably copyable. */
.note code {
  font: 13px/1.4 var(--mono);
  padding: 2px 7px;
  border-radius: 5px;
  background: var(--surface-1);
  border: 1px solid var(--border-strong);
  user-select: all;
}


/* ------------------------------------------------ dashboard assignment */

.assign {
  padding: 16px 0 6px;
  border-top: 1px dashed var(--border);
}

/* Wraps into columns rather than one long list — twenty brands should not
   push the Save button off the bottom of the card. */
.assign-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 6px 18px;
}

.assign-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 5px 0;
  font-size: 13.5px;
  cursor: pointer;
}

.assign-item input { accent-color: var(--accent); width: 15px; height: 15px; }
.assign-item:hover span { color: var(--text-primary); }
.assign-item span { color: var(--text-secondary); }


/* ------------------------------------------------------------ jail desk */

.jail-charges { margin: 14px 0 0; padding-left: 20px; }
.jail-charges li { margin-bottom: 6px; font-size: 13.5px; color: var(--text-secondary); }

.jail-case {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-2);
  padding: 16px 18px;
  margin-top: 14px;
}

.jail-case-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
}

.jail-case-id { font-size: 13.5px; font-weight: 570; color: var(--text-primary); }

/* The line that has to survive a redesign. */
.jail-caveat, p.jail-caveat { color: var(--text-muted); font-size: 13px; }

/* The booking photo on the write card. Deliberately modest: it is evidence an
   editor should look at, not a hero image. The fixed aspect keeps a wire of
   portrait mugshots from shoving the story fields down the page. */
.jail-shot {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  padding: 14px;
  margin-bottom: 16px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-2);
}

.jail-shot img {
  width: 96px;
  height: 120px;
  object-fit: cover;
  border-radius: var(--r-sm);
  background: var(--border);
  flex: none;
}

/* The transcribed filing, and the photo as it appears in a story. Both are
   evidence blocks: quiet, bounded, clearly not the paper's own voice. */
.jail-filing {
  border-left: 3px solid var(--border);
  padding: 4px 0 4px 16px;
  margin: 14px 0;
  color: var(--text-secondary);
  font-size: 14px;
}

.jail-filing p { margin: 0 0 10px; }
.jail-filing p:last-child { margin-bottom: 0; }

.jail-photo { margin: 0 0 18px; }
.jail-photo img { max-width: 100%; height: auto; border-radius: var(--r-sm); }
.jail-photo figcaption {
  margin-top: 8px;
  font-size: 13px;
  color: var(--text-muted);
}

/* ------------------------------------------------- the story editor */

/* A contenteditable, styled to look like the story rather than like a form
   field — the point of replacing the markup textarea was that an editor should
   see what they are writing. */
.rt {
  border: 1px solid var(--border);
  border-radius: 0 0 var(--r-md) var(--r-md);
  border-top: 0;
  background: var(--surface-1);
  padding: 18px 20px;
  min-height: 320px;
  max-height: 620px;
  overflow-y: auto;
  font-size: 15px;
  line-height: 1.65;
  color: var(--text-primary);
  outline: 0;
  transition: box-shadow var(--ease);
}

.rt:focus-within, .rt:focus { box-shadow: var(--ring); }

.rt > :first-child { margin-top: 0; }
.rt > :last-child { margin-bottom: 0; }
.rt h2 { font-size: 17px; font-weight: 600; margin: 22px 0 8px; }
.rt p { margin: 0 0 14px; }
.rt ul { margin: 0 0 14px; padding-left: 22px; }
.rt li { margin-bottom: 5px; }
.rt a { color: var(--ink); }
.rt img { max-width: 100%; height: auto; border-radius: var(--r-sm); }
.rt figure { margin: 0 0 18px; }
.rt figcaption { font-size: 13px; color: var(--text-muted); margin-top: 8px; }
.rt blockquote {
  margin: 0 0 14px;
  padding-left: 16px;
  border-left: 3px solid var(--border);
  color: var(--text-secondary);
}
/* The two lines that must survive an edit, marked so they look load-bearing. */
.rt .jail-caveat, .rt .jail-source { font-size: 13px; color: var(--text-muted); }

.rt-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 7px 8px;
  border: 1px solid var(--border);
  border-radius: var(--r-md) var(--r-md) 0 0;
  background: var(--surface-2);
}

.rt-tool {
  min-width: 30px;
  height: 28px;
  padding: 0 8px;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--text-secondary);
  font-size: 13px;
  cursor: pointer;
  transition: background var(--ease), color var(--ease);
}

.rt-tool:hover { background: var(--surface-1); color: var(--text-primary); border-color: var(--border); }

/* --------------------------------------------- click-to-insert & headlines */

.ins { margin: 14px 0; }

.ins-btn {
  display: block;
  width: 100%;
  text-align: left;
  margin-bottom: 6px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text-secondary);
  font-size: 13.5px;
  line-height: 1.5;
  cursor: pointer;
  transition: border-color var(--ease), background var(--ease);
}

.ins-btn:hover { border-color: var(--ink); background: var(--surface-1); }
.ins-label { display: block; font-weight: 570; color: var(--text-primary); }
.ins-btn .sub { display: block; margin-top: 2px; }

.heads-row { margin: -6px 0 16px; }
.heads { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }

.head-pick {
  text-align: left;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text-primary);
  font-size: 14px;
  cursor: pointer;
  transition: border-color var(--ease), background var(--ease);
}

.head-pick:hover { border-color: var(--ink); background: var(--surface-1); }

/* ------------------------------------------------------------- poll results */

/* A poll is a shape before it is a number, so the bar leads and the count
   follows it — with the raw count beside the share, because a percentage with
   no denominator is how a poll of nine people gets published as 78%. */
.tally { margin: 18px 0 0; }
.tally + .tally { padding-top: 18px; border-top: 1px solid var(--border); }

.tally-row {
  display: grid;
  grid-template-columns: minmax(70px, 130px) 1fr minmax(96px, auto);
  align-items: center;
  gap: 12px;
  margin-bottom: 8px;
}

.tally-label { font-size: 13.5px; color: var(--text-primary); }

.tally-bar {
  height: 10px;
  border-radius: 999px;
  background: var(--surface-2);
  overflow: hidden;
}

.tally-fill {
  height: 100%;
  border-radius: 999px;
  background: var(--ink);
  transition: width var(--ease);
}

.tally-count {
  font-size: 13px;
  color: var(--text-secondary);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------- wire mugshots */

/* A face beside a name, so two people with the same charge are telling apart
   at a glance. Small and square on purpose — this is identification, not
   display, and a row of large mugshots reads as a gallery. */
.wire-face {
  width: 44px;
  height: 44px;
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--surface-2);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
}

.wire-face img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* No photo on file: the initial, quietly. Better than an empty frame, which
   reads as a failure rather than as an absence. */
.wire-face.is-empty {
  color: var(--text-muted);
  font-size: 15px;
  font-weight: 560;
  border: 1px solid var(--border);
}

/* ------------------------------------------------------------------ charts */

/* Two categorical slots from the house palette. Both modes were run through
   the validator before being written here — lightness band, chroma floor,
   colour-vision separation, normal-vision floor and contrast against the
   surface all pass, worst adjacent pair ΔE 24.7 under protanopia. */
:root {
  --series-1: #2a78d6;
  --series-2: #eb6834;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --series-1: #3987e5;
    --series-2: #d95926;
  }
}

:root[data-theme="dark"] {
  --series-1: #3987e5;
  --series-2: #d95926;
}

.chart-plot { position: relative; }
.chart { display: block; overflow: visible; }

/* Scaffolding, and it should look like it. */
.chart-grid { stroke: var(--border); stroke-width: 1; }
.chart-tick { fill: var(--text-muted); font-size: 11px; }
.chart-cross { stroke: var(--border); stroke-width: 1; }

/* Thin marks. A 2px line reads as data; a 6px one reads as decoration. */
.chart-line {
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.chart-dot { stroke: var(--surface-1); stroke-width: 2; }
.chart-bar { transition: opacity var(--ease); }
.chart-bar:hover { opacity: 0.85; }

.chart-tip {
  position: absolute;
  top: 4px;
  min-width: 120px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface-1);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.10);
  font-size: 12.5px;
  pointer-events: none;
  z-index: 2;
}

.chart-tip-head { font-weight: 570; margin-bottom: 5px; color: var(--text-primary); }
.chart-tip-row { display: flex; align-items: center; gap: 7px; color: var(--text-secondary); }
.chart-tip-row b { margin-left: auto; color: var(--text-primary); font-variant-numeric: tabular-nums; }

.chart-tip-dot { width: 8px; height: 8px; border-radius: 999px; flex: none; }

.chart-legend { display: flex; gap: 16px; margin-top: 12px; }
.chart-legend-item {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  color: var(--text-secondary);
}

.chart-table { margin-top: 12px; }
.chart-table summary { font-size: 13px; color: var(--text-muted); cursor: pointer; }
.chart-table table { margin-top: 10px; }
