/* Herald control site.
   Palette and type from the house visual system (CLAUDE_ONLINE_TRAINING.md):
   navy #1A365D · teal #237D81 · orange #EE7C22 · page #EEF1FB→#F8FAFF · card #FFF/#E3E7F0 */

:root {
  --navy: #1A365D;
  --teal: #237D81;
  --orange: #EE7C22;
  --green: #217346;
  --blue: #0F6CBD;
  --muted: #8A93A6;
  --card: #FFFFFF;
  --line: #E3E7F0;
  --ink: #1A365D;
  --shadow: 0 1px 2px rgba(26, 54, 93, .06), 0 8px 24px rgba(26, 54, 93, .06);
  --radius: 14px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  background: linear-gradient(180deg, #EEF1FB 0%, #F8FAFF 100%) fixed;
  color: var(--ink);
  font: 15px/1.6 'Segoe UI', -apple-system, BlinkMacSystemFont, Helvetica, Arial, sans-serif;
}

/* ── Top bar ─────────────────────────────────────────────────────────────── */
.topbar {
  background: var(--card);
  border-bottom: 1px solid var(--line);
  padding: .85rem 1.5rem;
}

.topbar-inner {
  width: min(1680px, 100% - 3rem);
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 1rem;
}

.logo { height: 26px; width: auto; display: block; flex: none; }

.topbar .spacer { flex: 1; }

.who {
  font-size: .82rem;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: .6rem;
}

.btn {
  font: inherit;
  font-size: .82rem;
  padding: .34rem .8rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: #fff;
  color: var(--navy);
  cursor: pointer;
}

.btn:hover { border-color: var(--teal); color: var(--teal); }

/* ── Masthead ────────────────────────────────────────────────────────────── */
header.masthead {
  width: min(1680px, 100% - 3rem);
  margin: 0 auto;
  padding: 2.2rem 0 1rem;
}

.eyebrow {
  font-size: .7rem;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--teal);
  margin-bottom: .45rem;
}

h1 {
  margin: 0;
  font-size: 2rem;
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--navy);
}

/* The trumpet sits on the baseline with the wordmark, sized in em so it tracks the
   heading rather than needing its own breakpoint. */
h1 { display: flex; align-items: center; gap: .55rem; }

.herald-mark {
  width: 1.15em;
  height: 1.15em;
  flex: none;
  color: var(--teal);          /* the trumpet itself, via currentColor */
  transform: translateY(-.02em);
}

/* The pennant picks up the accent, so the mark carries both house colours. */
.herald-pennant { fill: var(--orange); }

.sub { margin: .5rem 0 0; color: var(--muted); max-width: 60ch; }

/* ── Layout ──────────────────────────────────────────────────────────────── */
/* ── Page width ────────────────────────────────────────────────────────────────
   1120px was a column down the middle of a desktop monitor with the rest empty.
   `min()` keeps the comfortable margins on a laptop and uses the width on a big
   screen, without a breakpoint to maintain. */
main { width: min(1680px, 100% - 3rem); margin: 0 auto; padding: 1rem 0 4rem; }

.grid {
  display: grid;
  /* auto-FIT, not auto-fill: auto-fill keeps empty tracks, so three devices on a 1680px
     screen left a whole phantom column of dead space on the right.
     The 480px ceiling is deliberate — a card is a form, and a form stretched to 560px is
     harder to scan, not easier. So cards grow to a comfortable maximum and the grid
     centres, which reads as composed rather than as a page that failed to fill. */
  grid-template-columns: repeat(auto-fit, minmax(360px, 480px));
  justify-content: center;
  gap: 1.15rem;
  align-items: start;
}

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.15rem 1.25rem 1.25rem;
  /* Teal rail marks a live device; the offline state greys it out. */
  border-left: 4px solid var(--teal);
}

.card.offline { border-left-color: var(--line); }

.card-top {
  display: flex;
  align-items: center;
  gap: .6rem;
  margin-bottom: .1rem;
}

.name {
  font-weight: 700;
  font-size: 1.06rem;
  color: var(--navy);
  border: none;
  background: none;
  font-family: inherit;
  padding: 0;
  min-width: 0;
  flex: 1;
  border-bottom: 1px dashed transparent;
}

.name:hover { border-bottom-color: var(--line); }
.name:focus { outline: none; border-bottom: 1px solid var(--teal); }

.pill {
  flex: none;
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  padding: .16rem .55rem;
  border-radius: 999px;
  background: #E6F4EA;
  color: var(--green);
  border: 1px solid #BFE3CB;
}

.pill.off { background: #F2F4F8; color: var(--muted); border-color: var(--line); }

.mac {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .74rem;
  color: var(--muted);
  margin: .1rem 0 1rem;
}

.field { margin-bottom: .85rem; }

label {
  display: block;
  font-size: .68rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--teal);
  margin-bottom: .3rem;
}

select, input[type=text] {
  width: 100%;
  padding: .52rem .65rem;
  border-radius: 9px;
  border: 1px solid var(--line);
  background: #FBFCFE;
  color: var(--ink);
  font: inherit;
  font-size: .9rem;
}

select:focus, input:focus {
  outline: none;
  border-color: var(--teal);
  box-shadow: 0 0 0 3px rgba(35, 125, 129, .12);
  background: #fff;
}

.chip {
  display: inline-block;
  font-size: .68rem;
  padding: .12rem .5rem;
  border-radius: 999px;
  background: #E7F0FB;
  color: #0F5AAB;
  border: 1px solid #BBD3EC;
  margin-top: .35rem;
}

.hint { font-size: .75rem; color: var(--muted); margin: .3rem 0 0; }

/* Volume slider. The readout sits in the label so the number you are choosing is visible
   while you drag — a bare slider gives no way to say "put it back to 80". */
.vol-val {
  float: right;
  font-variant-numeric: tabular-nums;   /* stops the label reflowing as digits change */
  color: var(--ink);
  letter-spacing: normal;
}
input[type="range"] {
  width: 100%;
  accent-color: var(--teal);
  cursor: pointer;
}
.saved { color: var(--green); font-weight: 600; }

/* ── Empty state ─────────────────────────────────────────────────────────── */
.empty {
  background: var(--card);
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  padding: 2.5rem 2rem;
  text-align: center;
  color: var(--muted);
}

.empty strong { color: var(--navy); display: block; margin-bottom: .4rem; font-size: 1.05rem; }

footer {
  width: min(1680px, 100% - 3rem);
  margin: 0 auto;
  padding: 0 0 2.5rem;
  color: var(--muted);
  font-size: .78rem;
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
}

.dot-sep::before { content: "·"; margin-right: 1rem; }

@media (max-width: 560px) {
  h1 { font-size: 1.6rem; }
  .grid { grid-template-columns: 1fr; }
}

/* ── Device switcher ─────────────────────────────────────────────────────────
   Leads with the shell colour, because with several units on a shelf that is how
   a person actually picks one out. */
.switcher {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin: 0 0 1.4rem;
}

.chip-device {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: .42rem .85rem .42rem .6rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--navy);
  font: inherit;
  font-size: .85rem;
  cursor: pointer;
  box-shadow: var(--shadow);
}

.chip-device:hover { border-color: var(--teal); }

.chip-device[aria-pressed="true"] {
  border-color: var(--teal);
  box-shadow: 0 0 0 2px rgba(35, 125, 129, .18), var(--shadow);
}

/* The colour blob IS the device — sized to be readable at a glance. */
.blob {
  width: 14px; height: 14px;
  border-radius: 50%;
  flex: none;
  border: 1px solid rgba(26, 54, 93, .18);
}

.chip-device .off-dot { opacity: .4; }

/* ── Colour swatches ─────────────────────────────────────────────────────── */
.swatches { display: flex; gap: .45rem; flex-wrap: wrap; }

.swatch {
  width: 26px; height: 26px;
  border-radius: 50%;
  border: 2px solid transparent;
  box-shadow: 0 0 0 1px var(--line);
  cursor: pointer;
  padding: 0;
  background-clip: padding-box;
}

.swatch[aria-pressed="true"] {
  border-color: var(--card);
  box-shadow: 0 0 0 2px var(--teal);
}

/* Card rail takes the device's own colour, so the grid is scannable by colour. */
.card[data-color] { border-left-color: var(--device-color, var(--teal)); }

/* ── Fleet summary ───────────────────────────────────────────────────────── */
.summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: .8rem;
  margin-top: 1.4rem;
}

.stat {
  line-height: 1.2;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: .8rem .95rem;
  box-shadow: var(--shadow);
}
.stat b { display: block; font-size: 1.5rem; font-weight: 700; color: var(--navy); }
.stat span { font-size: .72rem; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); }
.stat.warn b { color: var(--orange); }

/* ── Add-device ──────────────────────────────────────────────────────────── */
.adder { margin: 0 0 1.4rem; }
.adder summary { cursor: pointer; color: var(--teal); font-size: .85rem; font-weight: 600; }
.adder form { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; margin-top: .7rem; }
.adder input { width: auto; flex: 1 1 190px; }
.adder .hint { flex-basis: 100%; margin: 0; }

/* Status pill variants — "never connected" is a different problem from "offline". */
.pill.never  { background: #FDECE3; color: #A9431A; border-color: #F5C9B2; }
.pill.dormant{ background: #FDF3D6; color: #8A6608; border-color: #EFDFA8; }
.pill.idle,
.pill.recent { background: #F2F4F8; color: var(--muted); border-color: var(--line); }

.usage { font-size: .74rem; color: var(--muted); margin: .1rem 0 .9rem; }

/* ── Save feedback ───────────────────────────────────────────────────────────
   Two levels, because "did that save?" is the question this page has to answer
   without being asked: a per-field tick right where you were typing, and a toast
   for confirmation you cannot miss. */

/* Field flashes green briefly, so the answer appears where your eyes already are. */
.field.just-saved input,
.field.just-saved select {
  border-color: var(--green);
  box-shadow: 0 0 0 3px rgba(33, 115, 70, .14);
  transition: border-color .2s, box-shadow .2s;
}

.field-status {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  font-size: .72rem;
  font-weight: 600;
  color: var(--green);
  margin-top: .3rem;
  opacity: 0;
  transition: opacity .18s;
}

.field-status.show { opacity: 1; }
.field-status.err { color: #C43E1C; }

/* Toast: bottom-centre, out of the way of the cards but impossible to miss. */
.toast-wrap {
  position: fixed;
  left: 50%;
  bottom: 1.5rem;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: .5rem;
  z-index: 50;
  pointer-events: none;
}

.toast {
  background: var(--navy);
  color: #fff;
  padding: .6rem 1.1rem;
  border-radius: 999px;
  font-size: .85rem;
  box-shadow: 0 6px 24px rgba(26, 54, 93, .28);
  display: flex;
  align-items: center;
  gap: .5rem;
  animation: toast-in .18s ease-out;
}

.toast.err { background: #C43E1C; }
.toast .tick { font-weight: 700; }

@keyframes toast-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

/* Unsaved edits: a dashed amber underline while a field differs from what's stored. */
.field.dirty input,
.field.dirty select { border-color: var(--orange); }

/* ── Tabs ─────────────────────────────────────────────────────────────────── */
/* Two sections, not a navigation hierarchy — so an underline rather than chrome. */
.tabs {
  display: flex;
  gap: .3rem;
  border-bottom: 1px solid var(--line);
  margin: 0 0 1.3rem;
}
.tab {
  font: inherit;
  font-size: .82rem;
  font-weight: 700;
  letter-spacing: .02em;
  padding: .55rem .95rem;
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  color: var(--muted);
  cursor: pointer;
  margin-bottom: -1px;
}
.tab:hover { color: var(--navy); }
.tab[aria-selected="true"] { color: var(--navy); border-bottom-color: var(--teal); }

.panel-intro { margin: 0 0 1.2rem; max-width: 62ch; }

/* ── Personas ─────────────────────────────────────────────────────────────── */
/* A stack of rows rather than a card grid: a persona is mostly prose, and prose wants
   full width and one-at-a-time attention. */
.persona-list { display: flex; flex-direction: column; gap: .55rem; }

.persona {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.persona > summary {
  cursor: pointer;
  padding: .8rem 1rem;
  display: flex;
  align-items: center;
  gap: .6rem;
  flex-wrap: wrap;
  list-style: none;
}
.persona > summary::-webkit-details-marker { display: none; }
.persona > summary::before {
  content: "▸";
  color: var(--muted);
  font-size: .8rem;
  transition: transform .12s ease;
}
.persona[open] > summary::before { transform: rotate(90deg); }
.persona[open] > summary { border-bottom: 1px solid var(--line); }

.p-name  { font-weight: 700; color: var(--navy); }
.p-brain {
  font-size: .7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--teal);
  background: #EAF4F4;
  border-radius: 999px;
  padding: .12rem .5rem;
}
.p-tag {
  font-size: .68rem;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: .1rem .45rem;
}
/* Pushed right: how many devices depend on this is the thing you scan the list for. */
.p-used { margin-left: auto; font-size: .74rem; color: var(--muted); }

.p-body { padding: 1rem; }
.p-body textarea {
  width: 100%;
  font: inherit;
  font-size: .85rem;
  line-height: 1.5;
  padding: .55rem .65rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  resize: vertical;
}
.p-actions { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; margin-top: 1rem; }
.p-actions .hint { margin: 0; flex: 1 1 16rem; }

/* An unsaved change has to be visible on the button you have not yet pressed. */
.btn.dirty { border-color: var(--orange); color: var(--orange); font-weight: 700; }
.btn.danger { color: #A9431A; border-color: #F5C9B2; }
.btn.danger:hover { border-color: #A9431A; color: #A9431A; background: #FDECE3; }

/* A brain that cannot work yet (missing key) should say so where it is chosen. */
.warn-hint { color: #A9431A; }

#persona-form { flex-direction: column; align-items: stretch; }
#persona-form textarea {
  font: inherit;
  font-size: .85rem;
  line-height: 1.5;
  padding: .55rem .65rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  resize: vertical;
}
#persona-form .btn { align-self: flex-start; }

/* ── Landing page (signed out) ─────────────────────────────────────────────────
   Shown to anyone who has not signed in. The link gets shared with people who
   have never heard of the project, so it explains itself before asking who they
   are — an instant bounce to a Google account chooser is a poor welcome. */
.landing-main { width: min(1680px, 100% - 3rem); margin: 0 auto; padding: 2.5rem 0 4rem; }

.hero {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  gap: 3rem;
  align-items: center;
  min-height: 62vh;
}

.hero-copy h1 { font-size: clamp(2.4rem, 5vw, 3.6rem); }

.hero-lede {
  font-size: clamp(1.05rem, 1.6vw, 1.35rem);
  line-height: 1.5;
  color: var(--ink);
  max-width: 34ch;
  margin: 1rem 0 0;
}

.hero-sub {
  color: var(--muted);
  max-width: 46ch;
  margin: 1rem 0 2rem;
  border-left: 3px solid var(--orange);
  padding-left: .9rem;
}

.btn-primary {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  background: var(--navy);
  color: #fff;
  text-decoration: none;
  font-weight: 600;
  font-size: .95rem;
  padding: .8rem 1.35rem;
  border-radius: 999px;
  box-shadow: var(--shadow);
  transition: transform .12s ease, background .12s ease;
}
.btn-primary:hover { background: #14294a; transform: translateY(-1px); }
.g-mark { width: 18px; height: 18px; background: #fff; border-radius: 50%; padding: 1px; }

.hero-note { font-size: .78rem; color: var(--muted); margin: .9rem 0 0; max-width: 40ch; }

/* The device, drawn. Sharp at any size, weighs nothing, and shows the same face the
   hardware actually wears — a photo would date the moment the case changes. */
.hero-art { display: flex; justify-content: center; }

.device {
  width: min(320px, 60vw);
  background: linear-gradient(160deg, #24456f, #16294a);
  border-radius: 28px;
  padding: 26px 26px 0;
  box-shadow: 0 24px 60px rgba(26, 54, 93, .28);
}

.device-screen {
  aspect-ratio: 1;
  background: #0b1526;
  border-radius: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.face { display: grid; grid-template-columns: repeat(2, auto); gap: 14px 30px; justify-items: center; }

.eye {
  width: 34px; height: 42px;
  background: var(--teal);
  border-radius: 999px;
  animation: blink 5.2s infinite;
}
.eye:nth-child(2) { animation-delay: .04s; }

/* The mouth spans both eye columns and moves, the way the real one does when it speaks. */
.mouth {
  grid-column: 1 / -1;
  width: 84px;
  background: var(--teal);
  border-radius: 999px;
  animation: talk 2.6s infinite ease-in-out;
}

@keyframes blink {
  0%, 92%, 100% { height: 42px; }
  95% { height: 5px; }
}
@keyframes talk {
  0%, 100% { height: 8px; }
  30% { height: 26px; }
  55% { height: 12px; }
  75% { height: 30px; }
}

/* Anyone who has asked not to see motion gets a still face. */
@media (prefers-reduced-motion: reduce) {
  .eye, .mouth { animation: none; }
}

.device-chin { height: 26px; }

.pillars {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1.15rem;
  margin-top: 3rem;
}

.pillars article {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.4rem 1.5rem;
  border-top: 3px solid var(--teal);
}
.pillars h2 { margin: 0 0 .5rem; font-size: 1.05rem; color: var(--navy); }
.pillars p { margin: 0; color: var(--muted); font-size: .92rem; line-height: 1.6; }

.landing-footer {
  width: min(1680px, 100% - 3rem);
  margin: 0 auto;
  padding: 0 0 2.5rem;
  color: var(--muted);
  font-size: .78rem;
}

@media (max-width: 860px) {
  .hero { grid-template-columns: 1fr; gap: 2rem; min-height: 0; }
  .hero-art { order: -1; }
}
