/* 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: 1240px;
  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: 1240px;
  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; }

/* Tags a post went out with. The archive size sits inside the chip because it
   is the reason the tag was worth applying, not a footnote to it. */
.cp-tags .cp-tag {
  display: inline-block;
  margin: 0 6px 6px 0;
  padding: 3px 9px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface-2, transparent);
  font-size: 12px;
  line-height: 1.6;
}
.cp-tags .cp-tag em {
  font-style: normal;
  opacity: 0.55;
  margin-left: 2px;
}

/* The poll as the reader will meet it: the question, then the answers. A
   preview, not a form — the words were written from the article, and the
   editor's decision is whether to keep them, not to type new ones. */
.cp-poll-preview {
  margin: 0;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface-2, transparent);
}
.cp-poll-preview .cp-poll-q {
  margin: 0 0 8px;
  font-weight: 600;
}
.cp-poll-preview .cp-poll-a {
  margin: 0;
  padding-left: 18px;
  color: var(--ink-2, inherit);
  font-size: 14px;
}
.cp-poll-preview .cp-poll-a li { margin: 2px 0; }

/* ---------------------------------------------------------------- chips
   A small, closed set of choices, all visible at once. A dropdown hides
   four of five and makes the editor remember what the others were; a row
   of chips is the question and its answers in one line. */
.cp-chips {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  align-items: center;
  margin: 0 0 12px;
}
.cp-chips-lab {
  width: 100%;
  font-size: 12.5px;
  color: var(--text-secondary);
  margin-bottom: 2px;
}
.cp-chip {
  appearance: none;
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.4;
  padding: 5px 13px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-primary);
  cursor: pointer;
}
.cp-chip:hover:not(:disabled) { border-color: var(--text-secondary); }
.cp-chip.on {
  background: var(--text-primary);
  border-color: var(--text-primary);
  color: var(--surface);
}
.cp-chip:disabled { opacity: 0.5; cursor: default; }

/* The headline candidates, as things to choose between rather than links to
   press. The mark carries the state, so the chosen one is visible in the list
   it came from. */
.cp-candidates button { display: flex; gap: 10px; align-items: flex-start; }
.cp-rad {
  flex: none;
  width: 14px;
  height: 14px;
  margin-top: 2px;
  border-radius: 50%;
  border: 2px solid var(--border-strong);
}
.cp-candidates button.current .cp-rad {
  border: 4px solid var(--accent);
}

/* "Or type your own headline." — the rarer way, kept as a sentence. */
.cp-or { margin: 10px 0 0; font-size: 13px; color: var(--text-secondary); }
.linkish-inline {
  appearance: none;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: var(--accent);
  font-weight: 600;
  cursor: pointer;
  text-decoration: underline;
}

/* The picture choices, under the picture they change. */
.cp-pic-choose { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); }

/* =====================================================================
   THE NEWSROOM SKIN
   ---------------------------------------------------------------------
   From citypress-simple-mockup: a local paper's desk rather than a SaaS
   dashboard. Red and navy on newsprint grey, serif headlines, square
   cards with a hairline rule, and one loud button per screen.

   It is applied by overriding the tokens above rather than by rewriting
   the rules that use them, so every tab moves at once and nothing has to
   be restyled twice.

   Light only, on purpose: the design is ink on paper and has no dark
   half. The values are repeated under the dark query so a machine set to
   dark gets the paper too - same specificity, later in the file, so
   these win.
   ===================================================================== */

:root {
  --bg:            #eeeeee;
  --surface-1:     #ffffff;
  --surface-2:     #f6f6f6;
  --surface-3:     #eeeeee;
  --border:        #dddddd;
  --border-strong: #bbbbbb;

  --text-primary:   #222222;
  --text-secondary: #5a5a5a;
  --text-muted:     #7c7c7c;

  /* The loud button is red now, not near-black. */
  --ink:       #cc1818;
  --ink-hover: #a51212;
  --ink-text:  #ffffff;

  --accent: #cc1818;
  --navy:   #1f3d7a;
  --paper-black: #111111;
  --pink:   #fff5f5;

  --good:     #1e7a3a;
  --warning:  #8a5a00;
  --critical: #cc1818;

  /* Newsprint has square corners. */
  --r-sm: 4px;
  --r-md: 0px;
  --r-lg: 0px;
  --radius: 0px;

  --shadow: none;
  --shadow-lg: none;

  --font: Lato, 'Helvetica Neue', Arial, sans-serif;
  --serif: Georgia, 'Times New Roman', serif;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: light;
    --bg:            #eeeeee;
    --surface-1:     #ffffff;
    --surface-2:     #f6f6f6;
    --surface-3:     #eeeeee;
    --border:        #dddddd;
    --border-strong: #bbbbbb;
    --text-primary:   #222222;
    --text-secondary: #5a5a5a;
    --text-muted:     #7c7c7c;
    --ink:       #cc1818;
    --ink-hover: #a51212;
    --ink-text:  #ffffff;
    --accent: #cc1818;
    --good:     #1e7a3a;
    --warning:  #8a5a00;
    --critical: #cc1818;
    --shadow: none;
    --shadow-lg: none;
  }
}

/* Headlines are set, not styled. */
h1, h2, h3, h4 { font-family: var(--serif); letter-spacing: 0; }

/* ------------------------------------------------------------ the ticker */
.ticker {
  background: var(--paper-black);
  color: #fff;
  font-size: 13px;
  display: flex;
  gap: 12px;
  align-items: center;
  padding: 7px 22px;
}
.ticker b {
  background: var(--accent);
  padding: 2px 9px;
  text-transform: uppercase;
  letter-spacing: .06em;
  font-size: 11px;
  font-weight: 800;
}
.ticker .t-items { color: #cfcfcf; }

/* ------------------------------------------------------------ the masthead */
header.topbar {
  background: #fff;
  border-bottom: 1px solid var(--border);
  align-items: center;
}
.wordmark {
  font: 700 30px/1 Oswald, 'Arial Narrow', Impact, sans-serif;
  text-transform: uppercase;
  letter-spacing: .01em;
}
.wordmark .r { color: var(--accent); }
.wordmark .n { color: var(--navy); border-bottom: 4px solid var(--navy); }
.wordmark-sub {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin-top: 8px;
  display: flex;
  gap: 6px;
  align-items: center;
}
.wordmark-sub i { width: 9px; height: 9px; background: var(--accent); display: inline-block; }
header.topbar h1 { font-size: 21px; }

/* ------------------------------------------------------------ the rail */
.sidenav { background: #fff; border-right: 1px solid var(--border); }
.nav-group {
  margin: 16px 20px 4px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .14em;
  color: var(--text-muted);
  text-transform: uppercase;
}
.nav-group:first-child { margin-top: 4px; }

.sidenav [role="tab"] {
  border-radius: 0;
  border-left: 4px solid transparent;
  padding-left: 18px;
  font-weight: 600;
  font-size: 14.5px;
}
.sidenav [role="tab"]:hover { background: var(--surface-2); }
.sidenav [role="tab"][aria-selected="true"] {
  background: var(--pink);
  border-left-color: var(--accent);
  color: var(--accent);
}
.sidenav [role="tab"][aria-selected="true"] svg { color: var(--accent); }
.sidenav .count { background: var(--accent); color: #fff; }

/* ------------------------------------------------------------ cards, rules */
.card, .cp-step, table {
  border-radius: 0;
  box-shadow: none;
  border: 1px solid var(--border);
}
h2 { font-size: 20px; }

/* A section rule: the newspaper's way of starting a column. */
.card > h2:first-child {
  border-bottom: 3px solid var(--paper-black);
  padding-bottom: 8px;
  margin-bottom: 14px;
  text-transform: uppercase;
  font-size: 18px;
  letter-spacing: .02em;
}

/* ------------------------------------------------------------ buttons */
.btn {
  border-radius: 4px;
  font-weight: 800;
  letter-spacing: .01em;
}
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.primary:hover:not(:disabled) { background: var(--ink-hover); border-color: var(--ink-hover); }
.btn.linkish { color: var(--text-secondary); font-weight: 700; }
.btn.linkish:hover:not(:disabled) { color: var(--accent); }

/* ------------------------------------------------------------ the steps */
.cp-step { margin-bottom: 14px; }
.cp-step-index {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font: 800 14px var(--font);
  background: var(--border);
  color: var(--text-secondary);
  flex: none;
}
.cp-step.done .cp-step-index { background: var(--good); color: #fff; }
.cp-step.ready .cp-step-index { background: var(--accent); color: #fff; }
.cp-step.ready { border-color: var(--accent); }
.cp-step-title { font-family: var(--serif); font-size: 19px; font-weight: 700; }

/* The chosen headline, set like a headline. */
.cp-chosen {
  font: 700 20px/1.3 var(--serif);
  border-left: 4px solid var(--accent);
  padding-left: 12px;
  margin: 0 0 12px;
}

/* Candidates read as headlines too, because that is what they are. */
.cp-candidates button {
  font: 600 16px/1.35 var(--serif);
  border: 2px solid var(--border);
  border-radius: 6px;
  padding: 11px 13px;
}
.cp-candidates li + li { margin-top: 8px; }
.cp-candidates button.current {
  border-color: var(--accent);
  background: var(--pink);
  font-weight: 700;
}
.cp-rad { width: 18px; height: 18px; border-width: 2px; border-color: #999; margin-top: 3px; }
.cp-candidates button.current .cp-rad { border: 5px solid var(--accent); }

/* Chips, in the paper's colours. */
.cp-chip { border-radius: 99px; font-weight: 800; border-width: 2px; }
.cp-chip.on { background: var(--paper-black); border-color: var(--paper-black); color: #fff; }

/* The poll, as the reader meets it. */
.cp-poll-preview { border-radius: 6px; border-width: 2px; }
.cp-poll-preview .cp-poll-q { font: 700 17px/1.35 var(--serif); }
.cp-poll-preview .cp-poll-a { list-style: none; padding: 0; }
.cp-poll-preview .cp-poll-a li {
  border: 2px solid var(--border);
  border-radius: 6px;
  padding: 8px 12px;
  margin: 6px 0 0;
  font-weight: 700;
  font-size: 14px;
}

/* The article, set to be read. */
.cp-article, .cp-article p { font-family: var(--serif); }

/* ------------------------------------------------------------ the footer */
.deskfoot {
  border-top: 1px solid var(--border);
  background: #fff;
  padding: 14px 24px;
  display: flex;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  font-size: 12.5px;
  color: var(--text-secondary);
}
.deskfoot b { color: var(--text-primary); }

/* Below 760 the rail becomes a horizontal strip of tabs. Headings make sense
   down a column and only clutter a row, so they step out of the way. */
@media (max-width: 760px) {
  .nav-group { display: none; }
  .ticker { padding: 6px 14px; font-size: 12px; }
  .wordmark { font-size: 24px; }
}

/* ------------------------------------------------------------------ home
   What to do now on the left, how it is going on the right. */
.home-hello {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-left: 5px solid var(--accent);
  padding: 16px 20px;
  margin-bottom: 22px;
}
.home-hello h1 { font-size: 25px; margin: 0; }
.home-hello p { margin: 4px 0 0; color: var(--text-secondary); font-size: 15px; }

.home-cols { display: grid; grid-template-columns: minmax(0, 1fr) 310px; gap: 22px; align-items: start; }
@media (max-width: 1000px) { .home-cols { grid-template-columns: 1fr; } }

.home-sec {
  font-size: 17px;
  text-transform: uppercase;
  letter-spacing: .02em;
  padding-bottom: 7px;
  border-bottom: 3px solid var(--paper-black);
  margin: 0 0 14px;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
}
.home-sec + section, section + section { margin-top: 26px; }

/* A story on the home page: the beat, the line, the way in. */
.home-story {
  display: grid;
  grid-template-columns: 96px minmax(0, 1fr);
  gap: 16px;
  align-items: start;
  padding: 14px 16px;
  margin-bottom: 10px;
}
.home-tile {
  height: 78px;
  display: grid;
  place-items: center;
  color: #fff;
  font: 700 13px/1 Oswald, 'Arial Narrow', sans-serif;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.home-tile.fire { background: var(--accent); }
.home-tile.police { background: var(--navy); }
.home-tile.sheriff { background: var(--paper-black); }
.home-tile.news { background: #6b6b6b; }
.home-story-h {
  font-size: 18px;
  line-height: 1.3;
  margin: 5px 0 10px;
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}
.home-story .actions { justify-content: flex-start; }

/* The rail. */
.home-rail-card h4 {
  margin: 0 0 12px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  border-left: 4px solid var(--accent);
  padding-left: 9px;
  font-family: var(--font);
  color: var(--text-primary);
}
.home-num { margin-bottom: 12px; }
.home-num .n { font: 700 32px/1.05 var(--serif); color: var(--accent); }
.home-num .l { color: var(--text-secondary); font-size: 13.5px; }
.home-num .note-sm { color: var(--text-muted); font-size: 12px; }

.home-top { border-top: 1px solid var(--border); padding-top: 10px; margin-top: 4px; }
.home-top-h {
  font-size: 11px; font-weight: 800; letter-spacing: .1em;
  text-transform: uppercase; color: var(--text-muted); margin-bottom: 6px;
}
.home-top-row { display: flex; justify-content: space-between; gap: 10px; font-size: 13px; padding: 3px 0; }
.home-top-row .p { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.home-top-row .v { color: var(--text-secondary); flex: none; }


.btn.wide { display: block; width: 100%; text-align: center; margin-top: 8px; }
.btn.dark { background: var(--paper-black); border-color: var(--paper-black); color: #fff; }
.btn.dark:hover:not(:disabled) { background: #000; border-color: #000; }

/* The two ways to begin, at the top where an editor arriving to write will
   reach for them, rather than a list of them further down the page. */
.home-go { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 16px; }
.btn.big { padding: 12px 22px; font-size: 15px; }
.btn.ghost {
  background: var(--surface-1);
  color: var(--text-primary);
  border: 2px solid var(--border-strong);
}
.btn.ghost:hover:not(:disabled) { border-color: var(--text-secondary); }

/* A story's own picture on the home page. Fixed box so five of them line up
   however different the source images are. */
.home-shot {
  height: 78px;
  overflow: hidden;
  background: var(--surface-3);
}
.home-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ------------------------------------------------------- a readable measure
   A dashboard wants width; prose does not. Stretched across the whole shell a
   wire card ran well past a hundred characters to the line, which is where the
   eye starts losing its place on the way back to the left. The desk, the
   Workshop and the library are capped; charts and tables keep their room. */
#view.reading { max-width: 880px; }

/* Belt and braces inside the cap: a card with no picture beside it still puts
   its text on a sane line, and the article on the story page reads like an
   article rather than a banner. */
.wire-excerpt,
.wire-full-text,
.cp-source-title + .sub,
.cp-article p { max-width: 68ch; }

/* An icon inside a button takes the button's colour, not the muted grey it
   wears in the rail — on the red primary it was a grey mark on white text. */
.btn .ico { color: inherit; }
.home-go .ico svg { width: 18px; height: 18px; }

/* ------------------------------------------------- the board editor
   Three columns in the order the work happens: pages → boards → the wire.
   Each column is its own scroller, so a hundred pages on the left never
   pushes the wire off the bottom of the screen.

   Nothing here uses colour alone to say anything. A card being carried is
   outlined AND says so in the bar above; a drop target under the pointer is
   filled AND dashed. */

.ga-editor { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--border); }
.ga-h { font-size: 15px; font-weight: 620; margin: 0 0 2px; }

.ga-bar:not(:empty) { margin: 10px 0 0; display: grid; gap: 8px; }
.ga-picked {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 12px; border: 1px solid var(--ink); border-radius: var(--r-sm);
  background: var(--surface-3); font-size: 13px;
}

.ga-cols {
  display: grid; gap: 12px; margin: 14px 0 4px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: start;
}
@media (max-width: 860px) { .ga-cols { grid-template-columns: 1fr; } }

.ga-col > h3 {
  font-size: 12px; font-weight: 640; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-muted); margin: 0 0 8px;
}
.ga-col .src-input { width: 100%; }
.ga-hint { margin: 6px 0 8px; font-size: 12px; }

.ga-list { display: grid; gap: 6px; max-height: 560px; overflow: auto; padding: 2px; }

/* One page. A button, so it is reachable by keyboard and by tap on a phone,
   where dragging does not exist. */
.ga-card {
  display: grid; gap: 1px; text-align: left; width: 100%; cursor: grab;
  padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--r-sm);
  background: var(--surface-1); font: inherit; font-size: 13px; color: var(--text-primary);
}
.ga-card:hover { border-color: var(--border-strong); background: var(--surface-2); }
.ga-card:active { cursor: grabbing; }
.ga-name { font-weight: 560; }
.ga-name mark { background: none; color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.ga-card .wire-meta { font-size: 11.5px; }
.ga-tag {
  justify-self: start; margin-top: 3px; padding: 1px 6px; border-radius: 3px;
  background: var(--surface-3); color: var(--text-secondary); font-size: 11px;
}
.ga-card.ga-on { opacity: .75; }
.ga-held { outline: 2px solid var(--ink); outline-offset: 1px; }
.ga-dragging { opacity: .4; }

/* A drop target with something over it. Dashed as well as filled: the fill
   alone is a colour change, and a colour change alone says nothing. */
.ga-over {
  border-style: dashed !important;
  border-color: var(--ink) !important;
  background: var(--surface-3) !important;
}

/* ----------------------------------------------------------- boards */

.ga-board {
  border: 1px solid var(--border); border-radius: var(--r-sm);
  background: var(--surface-1); padding: 8px 10px; display: grid; gap: 6px;
}
.ga-grip {
  display: block; width: 100%; text-align: left; cursor: grab;
  background: none; border: 0; padding: 0; font: inherit; color: inherit;
}
.ga-grip:active { cursor: grabbing; }
.ga-board-head { display: grid; gap: 1px; font-size: 13px; }
.ga-board-head .wire-meta { font-size: 11.5px; }
.ga-board-acts { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.ga-board-acts .btn { font-size: 12px; padding: 4px 9px; }

.ga-board-pages { border-top: 1px solid var(--border); padding-top: 6px; }
.ga-page {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 4px 6px; border-radius: 4px; font-size: 12.5px; cursor: grab;
}
.ga-page:hover { background: var(--surface-2); }
.ga-new .sub { margin: 0; font-size: 12px; }
.ga-new input { width: 100%; }
.ga-new .actions { display: grid; gap: 6px; }

.ga-put { width: 100%; justify-content: center; font-size: 12.5px; }

.ga-connect {
  border: 1px dashed var(--border-strong); border-radius: var(--r-sm);
  padding: 12px; background: var(--surface-2); font-size: 13px;
}
.ga-connect .sub { margin: 6px 0; font-size: 12px; }
.ga-connect code {
  display: block; overflow-x: auto; padding: 7px 9px; border-radius: 4px;
  background: var(--surface-3); font-family: var(--mono); font-size: 11.5px;
}
.ga-missing { font-size: 12px; margin: 0; }

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

.ga-wire {
  display: grid; gap: 6px; padding: 8px 10px;
  border: 1px solid var(--border); border-radius: var(--r-sm); background: var(--surface-1);
  font-size: 13px;
}
.ga-wire .wire-meta { font-size: 11.5px; word-break: break-word; }
.ga-wire.ga-muted { opacity: .6; }
.ga-wire-acts { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ga-mute { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-secondary); }
.ga-drop { font-size: 12px; }

.ga-manual { margin-top: 14px; }
.ga-manual > summary { cursor: pointer; font-size: 13px; font-weight: 560; }
.ga-manual .sub { margin: 6px 0 8px; font-size: 12px; }
.ga-manual .actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* The wire column has no border of its own, so it marks a hovering drop with
   an outline rather than the fill the bordered cards use. */
.ga-col.ga-over {
  outline: 2px dashed var(--ink); outline-offset: 6px;
  border-radius: var(--r-sm); background: none !important;
}

/* A board's RSS address is one long unbroken word, and it was pushing a
   horizontal scrollbar through the wire column and the Remove button off the
   end of it. Names wrap anywhere; the columns scroll down only. */
.ga-list { overflow-x: hidden; overflow-y: auto; }
.ga-name, .ga-wire .wire-meta { overflow-wrap: anywhere; }

/* Stacked on a phone, the columns are one above another and an inner scroller
   inside each one is a trap: you swipe the page and move a list instead. */
@media (max-width: 860px) { .ga-list { max-height: none; overflow: visible; } }
.ga-whose { margin: 0 0 8px; font-size: 12px; }
.ga-ask { display: grid; gap: 8px; align-items: stretch; }
.ga-ask .actions { display: flex; gap: 8px; align-items: center; }
.ga-ask input { flex: 1; min-width: 0; }

/* ----------------------------------------- Follow Sources, as its own page
   The three columns are one direction, so they are numbered. The number is
   the only decoration on the page that is not a control. */
.ga-step {
  display: inline-grid; place-items: center; width: 17px; height: 17px;
  margin-right: 6px; border-radius: 50%; background: var(--ink); color: var(--ink-text);
  font-size: 10.5px; font-weight: 700; letter-spacing: 0;
}

/* Pasting an address is the normal way to add a page, not the fallback, so it
   is the first thing in the first column and the search is under it. */
.ga-add {
  display: grid; gap: 6px; padding: 10px;
  border: 1px solid var(--border-strong); border-radius: var(--r-sm);
  background: var(--surface-2);
}
.ga-add h4 { margin: 0; font-size: 13px; font-weight: 640; }
.ga-add input { width: 100%; }
.ga-kind { margin: 0; font-size: 11.5px; }
.ga-add .btn { justify-content: center; }

.ga-or {
  margin: 14px 0 6px; font-size: 11.5px; font-weight: 600; letter-spacing: .03em;
  text-transform: uppercase; color: var(--text-muted);
}

/* --------------------------------------------------------- the Get Alerts mark
   The wire comes from Get Alerts, so the credit sits on the pages that are
   Get Alerts: large on Follow Sources, small on the desk, once in the footer.
   A link, because somebody who wants the boards themselves should be one click
   away from them. */
.ga-credit {
  display: inline-flex; align-items: center; gap: 7px;
  margin-top: 8px; text-decoration: none; color: var(--text-muted);
  font-size: 10.5px; letter-spacing: .09em; text-transform: uppercase;
  white-space: nowrap;
}
.ga-credit img { display: block; height: 30px; width: auto; }
.ga-credit:hover { color: var(--text-secondary); }
.ga-credit:hover img { opacity: .85; }

.ga-credit.big {
  margin-top: 12px; gap: 10px;
  font-size: 11.5px; letter-spacing: .07em;
  color: var(--text-secondary);
}
.ga-credit.big img { height: 47px; }

/* The footer puts the two credits side by side: Get Alerts supplies the news,
   MegaStack runs the rest of it, and they are two different sentences. */
.foot-credits { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
/* In the footer it sits beside "Powered by MegaStack", so it is set like it
   rather than like the small caps it wears inside a page. */
.foot-credits .ga-credit {
  margin-top: 0; font-size: 12.5px; letter-spacing: normal; text-transform: none;
  color: var(--text-secondary);
}
.foot-credits .ga-credit img { height: 26px; }
