/* Hermes Outreach web tier — one hand-written stylesheet (decision A3).
   No framework, no build step, no CDN: the CSP is `default-src 'self'`, so every
   asset here is local. The two faces are self-hosted under /static/fonts/ with
   @font-face (see docs/DESIGN-SYSTEM.md for provenance and the shipped OFL text).

   Design: "Pocket Agent" — replicated values from the reference mockup
   (design/pocket-agent-ui/). The mockup's markup and its vendored React runtime
   are NOT part of the design; only its values are, and they live in the single
   token block below. Nothing outside that block may contain a raw hex colour
   (enforced by tests/test_design_tokens.py).                                        */

/* ===========================================================================
   TOKENS — the ONE place a literal colour value is allowed.
   Everything below this block refers to these custom properties by name.
   =========================================================================== */
/* TOKENS:BEGIN */
:root {
  /* --- palette (verbatim from design/pocket-agent-ui/TOKENS-extracted.md) --- */
  --ink: #1B1340;           /* text and outlines */
  --ground: #F5F1FF;        /* screens (page background) */
  --card: #FFFFFF;          /* cards */
  --lime: #B6F03C;          /* approve, done */
  --tangerine: #FF7A1A;     /* needs attention */
  --pink: #FF5C8A;          /* people, email */
  --sky: #4CC9F0;           /* research, working */

  /* --- derived tints (computed once, here, so no rule needs a literal) ------ */
  --ink-soft: #5A5480;      /* muted/meta text: 6.27:1 on ground, 6.97:1 on card */
  --rule: #D9D2F0;          /* 1px table rules */
  --wash: #EDE7FF;          /* hover / table head fill */

  /* --- type ---------------------------------------------------------------- */
  --font-display: "Bricolage Grotesque", "Figtree", "Segoe UI", system-ui, sans-serif;
  --font-body: "Figtree", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
               Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --fs-meta: 13px;          /* the mockup's 13 */
  --fs-label: 14px;         /* the mockup's 14 */
  --fs-body: 16px;          /* body copy, Figtree 500 */
  --fs-h3: 18px;
  --fs-h2: 20px;
  --fs-title: 26px;
  --fs-hero: 44px;
  --fs-hero-lg: 52px;
  --w-body: 500;
  --w-label: 700;
  --w-display: 800;

  /* --- shape --------------------------------------------------------------- */
  --r-card: 24px;
  --r-btn: 16px;
  --r-chip: 999px;
  --outline: 3px;
  --elev-btn: 4px;          /* 0 4px 0 ink */
  --elev-card: 6px;         /* 0 6px 0 ink — no blur, ever */

  /* --- motion (CSS only; an enhancement, never a requirement) -------------- */
  --press-ms: 180ms;
  --press-ease: cubic-bezier(.2, 1.6, .4, 1);
  --press-shift: 4px;       /* pressing drops the card 4px */
  --confetti-ms: 900ms;

  /* --- space --------------------------------------------------------------- */
  --gap: 16px;
  --pad-card: 18px 20px;
}
/* TOKENS:END */

/* ---------------------------------------------------------------------------
   Faces — self-hosted woff2 (the mockup's Google Fonts <link> would be blocked
   by `default-src 'self'`; the CSP is NOT widened, the files are local).
   SIL Open Font License 1.1; the licence text ships beside the files.
   --------------------------------------------------------------------------- */
@font-face {
  font-family: "Figtree";
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url("/static/fonts/figtree-latin-500-700.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
    U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
    U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Figtree";
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url("/static/fonts/figtree-latin-ext-500-700.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Bricolage Grotesque";
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url("/static/fonts/bricolage-grotesque-latin-800.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
    U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
    U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Bricolage Grotesque";
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url("/static/fonts/bricolage-grotesque-latin-ext-800.woff2") format("woff2");
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1,
    U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329,
    U+1EA0-1EF9, U+20AB;
}

/* ---------------------------------------------------------------------------
   Base
   --------------------------------------------------------------------------- */
* { box-sizing: border-box; }

html { color-scheme: light; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: var(--w-body);
  line-height: 1.55;
}

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: var(--w-display);
  line-height: 1.15;
  margin: 0 0 10px;
}
h1 { font-size: var(--fs-title); letter-spacing: -.01em; }
h2 { font-size: var(--fs-h3); }
h3 { font-size: var(--fs-body); }
.hero { font-size: var(--fs-hero); }

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

a {
  color: var(--ink);
  font-weight: var(--w-label);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 2px;
}
a:hover { background: var(--wash); }

code, pre { font-family: var(--font-mono); }
code {
  background: var(--wash);
  border: 1px solid var(--rule);
  border-radius: 6px;
  padding: 0 5px;
  font-size: var(--fs-meta);
}
pre {
  background: var(--wash);
  border: 2px solid var(--ink);
  border-radius: var(--r-btn);
  padding: 10px 12px;
  overflow-x: auto;
  white-space: pre-wrap;
  word-break: break-word;
  font-size: var(--fs-meta);
  line-height: 1.45;
}

/* Focus is never invisible: a 3px ink ring, drawn with `outline` so it cannot
   change any box's size or reflow the page (constraint 5). */
:focus-visible {
  outline: var(--outline) solid var(--ink);
  outline-offset: 2px;
}
.skip {
  position: absolute;
  left: -9999px;
  top: auto;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 10px 14px;
}
.skip:focus {
  left: 8px;
  top: 8px;
  background: var(--card);
  border: var(--outline) solid var(--ink);
  border-radius: var(--r-btn);
  z-index: 30;
}

/* ---------------------------------------------------------------------------
   Frame: top bar, nav, main, footer
   --------------------------------------------------------------------------- */
.topbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  padding: 12px 20px;
  background: var(--card);
  border-bottom: var(--outline) solid var(--ink);
}
.brand {
  font-family: var(--font-display);
  font-weight: var(--w-display);
  font-size: var(--fs-h2);
  letter-spacing: -.01em;
}
.nav { display: flex; flex-wrap: wrap; gap: 6px; }
.nav a, .nav-off {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 4px 11px;
  border: 2px solid var(--ink);
  border-radius: var(--r-chip);
  background: var(--card);
  text-decoration: none;
  font-size: var(--fs-label);
  font-weight: var(--w-label);
}
.nav a:hover { background: var(--wash); }
.nav a[aria-current="page"] { background: var(--lime); text-decoration: underline; text-underline-offset: 5px; text-decoration-thickness: 2px; }
.nav-off {
  border-style: dashed;
  border-color: var(--ink-soft);
  background: var(--ground);
  color: var(--ink-soft);
  cursor: not-allowed;
}
.who { margin-left: auto; color: var(--ink-soft); font-size: var(--fs-meta); }

main { max-width: 1100px; margin: 0 auto; padding: 22px 20px; }

.foot {
  max-width: 1100px;
  margin: 0 auto;
  padding: 6px 20px 34px;
  color: var(--ink-soft);
  font-size: var(--fs-meta);
}

/* ---------------------------------------------------------------------------
   Card — 24px radius, 3px ink outline, solid offset shadow, no blur.
   Pressing drops it 4px (motion is the enhancement, the shape is the design).
   --------------------------------------------------------------------------- */
.card {
  background: var(--card);
  border: var(--outline) solid var(--ink);
  border-radius: var(--r-card);
  box-shadow: 0 var(--elev-card) 0 var(--ink);
  padding: var(--pad-card);
  margin: 0 0 22px;
  transition: transform var(--press-ms) var(--press-ease),
              box-shadow var(--press-ms) var(--press-ease);
}
.card.narrow { max-width: 620px; }
.card.pressable:active,
.card.pressable:focus-within {
  transform: translateY(var(--press-shift));
  box-shadow: 0 calc(var(--elev-card) - var(--press-shift)) 0 var(--ink);
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 22px;
}
.grid .card { margin: 0; }

/* ---------------------------------------------------------------------------
   Controls — buttons 16px radius, chips are pills. Text labels carry the
   meaning; colour is the second signal, never the only one.
   --------------------------------------------------------------------------- */
.btn, button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--card);
  color: var(--ink);
  border: var(--outline) solid var(--ink);
  border-radius: var(--r-btn);
  box-shadow: 0 var(--elev-btn) 0 var(--ink);
  min-height: 44px;
  padding: 8px 16px;
  font-family: var(--font-body);
  font-size: var(--fs-label);
  font-weight: var(--w-label);
  cursor: pointer;
  transition: transform var(--press-ms) var(--press-ease),
              box-shadow var(--press-ms) var(--press-ease);
}
.btn:hover, button:hover { background: var(--wash); }
.btn:active, button:active {
  transform: translateY(var(--press-shift));
  box-shadow: 0 calc(var(--elev-btn) - var(--press-shift)) 0 var(--ink);
}
.btn-approve { background: var(--lime); }
.btn-approve:hover { background: var(--lime); filter: brightness(1.06); }
.btn-deny { background: var(--tangerine); }
.btn-deny:hover { background: var(--tangerine); filter: brightness(1.06); }
.btn-quiet { background: var(--ground); }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 2px solid var(--ink);
  border-radius: var(--r-chip);
  background: var(--ground);
  color: var(--ink);
  padding: 1px 10px;
  font-size: var(--fs-meta);
  font-weight: var(--w-label);
  white-space: nowrap;
}
.chip-mark { font-family: var(--font-body); }
/* semantic fills — lime done, tangerine held, sky in flight, pink people/mail */
.chip-done { background: var(--lime); }
.chip-held { background: var(--tangerine); }
.chip-work { background: var(--sky); }
.chip-people, .chip-mail { background: var(--pink); }
.chip-plain { background: var(--ground); }

/* Standalone notices: same mapping, still paired with a word in the template. */
.notice {
  border: var(--outline) solid var(--ink);
  border-radius: var(--r-btn);
  box-shadow: 0 var(--elev-btn) 0 var(--ink);
  padding: 10px 14px;
  margin: 0 0 18px;
  background: var(--card);
}
.notice-done { background: var(--lime); }
.notice-held { background: var(--tangerine); }
.notice-work { background: var(--sky); }

/* ---------------------------------------------------------------------------
   Forms
   --------------------------------------------------------------------------- */
form.row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 8px 0;
}
label { color: var(--ink-soft); font-size: var(--fs-label); font-weight: var(--w-label); }

input[type="text"], input[type="number"], input[type="password"],
input[type="file"], input[type="date"], input[type="time"], input[type="datetime-local"],
textarea, select {
  background: var(--card);
  color: var(--ink);
  border: 2px solid var(--ink);
  border-radius: 10px;
  padding: 7px 9px;
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: var(--w-body);
  max-width: 100%;
}
input[type="number"] { width: 5.5em; }
textarea { width: 100%; }

/* ---------------------------------------------------------------------------
   Tables / lists
   --------------------------------------------------------------------------- */
table { width: 100%; border-collapse: collapse; font-size: var(--fs-body); }
th, td { text-align: left; padding: 6px 10px 6px 0; vertical-align: top; }
thead th, table tr:first-child th {
  color: var(--ink-soft);
  font-weight: var(--w-label);
  font-size: var(--fs-label);
}
tbody th, td { border-top: 1px solid var(--rule); }

/* ---------------------------------------------------------------------------
   Semantic text helpers.
   The literal words ("connected", "paused", "held until …") are already in the
   markup; the marks below add a non-colour signal for colour-blind readers and
   the fill makes the state scannable. This is the whole point of constraint 4.
   --------------------------------------------------------------------------- */
.muted { color: var(--ink-soft); }
.ok, .warn, .bad { color: var(--ink); font-weight: var(--w-label); }
.ok::before { content: "\2713  "; font-weight: var(--w-label); }
.warn::before { content: "\26A0  "; font-weight: var(--w-label); }
.bad::before { content: "\2715  "; font-weight: var(--w-label); }
.ok { background: var(--lime); border-radius: var(--r-chip); padding: 0 10px; }
.warn { background: var(--tangerine); border-radius: var(--r-chip); padding: 0 10px; }
.bad { background: var(--pink); border-radius: var(--r-chip); padding: 0 10px; }
/* inline spans inside a sentence must not grow a pill */
td .ok, td .warn, td .bad, .muted .ok, .muted .warn, .muted .bad {
  background: none;
  padding: 0;
}

/* ---------------------------------------------------------------------------
   Pills, pager, thread
   --------------------------------------------------------------------------- */
.pills { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0 2px; }
.pills a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 3px 12px;
  border: 2px solid var(--ink);
  border-radius: var(--r-chip);
  background: var(--card);
  text-decoration: none;
  font-size: var(--fs-label);
  font-weight: var(--w-label);
}
.pills a:hover { background: var(--wash); }
.pills a[aria-current="page"] { background: var(--ink); color: var(--ground); }

/* ---------------------------------------------------------------------------
   Connect-a-mailbox (t_76e4239d). The provider picker is the .pills component
   above — every pill is already a 44px tap target, on every width. What is here
   is the numbered instruction list and the server line, so a phone user reads one
   action per line at 16px without a horizontal scroll. No colour literal: the
   values come from the token block, which is the only place a hex may live.
   --------------------------------------------------------------------------- */
.steps { margin: 12px 0 6px; padding-left: 22px; }
.steps li { margin: 0 0 10px; }
.steps li::marker { color: var(--ink); font-weight: var(--w-label); }
.conn-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 10px 0 2px;
}
.conn-servers {
  border: 2px solid var(--ink);
  border-radius: var(--r-btn);
  background: var(--ground);
  padding: 8px 12px;
}
.conn-servers code { overflow-wrap: anywhere; }

.pager {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  padding: 10px 2px;
  color: var(--ink-soft);
  font-size: var(--fs-meta);
}
.pager a { text-decoration: none; }

/* Email lives on the pink surface (constraint 4: pink = people and mail). */
.msg {
  border: 2px solid var(--ink);
  border-left-width: 10px;
  border-radius: var(--r-btn);
  padding: 8px 14px;
  margin: 12px 0;
  background: var(--card);
}
.msg-in { border-left-color: var(--pink); }
.msg-out { border-left-color: var(--pink); background: var(--wash); }
.msg p { margin: 0 0 6px; }
.msg pre { margin: 0; background: var(--card); }
.note-body { max-height: 60vh; overflow-y: auto; }

/* ---------------------------------------------------------------------------
   Motion — 180ms springy press is the default; both the operating system's
   `prefers-reduced-motion` AND the operator's own /settings switch (rendered
   by the server as `data-motion="reduced"`) turn the bounce and the confetti
   off. Nothing here is required to use the app.
   --------------------------------------------------------------------------- */
.card.pressable, .btn, button, .msg { will-change: transform; }

.confetti {
  position: fixed;
  inset: 0 0 auto 0;
  height: 0;
  overflow: visible;
  pointer-events: none;
  z-index: 40;
}
.confetti::before {
  content: "";
  position: absolute;
  left: -10%;
  right: -10%;
  top: 0;
  height: 14px;
  background-image: repeating-linear-gradient(
    90deg,
    var(--lime) 0 14px,
    var(--tangerine) 14px 28px,
    var(--sky) 28px 42px,
    var(--pink) 42px 56px
  );
  border-bottom: 2px solid var(--ink);
  animation: confetti-fall var(--confetti-ms) var(--press-ease) 1 both;
}
@keyframes confetti-fall {
  from { transform: translateY(-140%); opacity: 0; }
  60%  { transform: translateY(0); opacity: 1; }
  to   { transform: translateY(0); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  :root { --press-ms: 0ms; --press-shift: 0px; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .confetti { display: none; }
}

/* The operator-level switch, applied server-side from a preference cookie. */
[data-motion="reduced"] { --press-ms: 0ms; --press-shift: 0px; }
[data-motion="reduced"] .confetti { display: none; }
[data-motion="reduced"] .card.pressable:active,
[data-motion="reduced"] .btn:active,
[data-motion="reduced"] button:active { transform: none; }

/* ---------------------------------------------------------------------------
   Folded "Advanced" card — the plumbing, one tap away and never in the way.
   Used by Today (the database report and the agent's own job queue), the emails
   page (the existing send gate) and Settings (what is switched on). P0-6 / P0-8.
   --------------------------------------------------------------------------- */
details.advanced { padding: 0; }
details.advanced > summary {
  cursor: pointer;
  padding: var(--pad-card);
  font-family: var(--font-display);
  font-weight: var(--w-display);
  font-size: var(--fs-h3);
  line-height: 1.2;
}
details.advanced[open] > summary { border-bottom: 2px solid var(--rule); }
details.advanced > section { padding: var(--pad-card); }
details.advanced > section:first-of-type { padding-top: 10px; }
details.advanced h2 { font-size: var(--fs-body); }

/* ---------------------------------------------------------------------------
   Phone (≤ 560px) — the measured fixes from the simplicity review (P0-2, P2-1).
   Two rules carry the whole table problem, and every control reaches the 44px
   thumb floor with 16px text.

   1. a wide table can never widen the PAGE: it scrolls inside its own card;
   2. a table marked `stack` needs no sideways motion at all — each row becomes a
      short labelled line, the label coming from each cell's own `data-label`.
   --------------------------------------------------------------------------- */
@media (max-width: 560px) {
  .who { margin-left: 0; }
  :root { --fs-hero: var(--fs-title); --fs-hero-lg: var(--fs-hero); }

  /* 0 — the nav becomes a bottom bar (UX review §4.3/§6.2: on a phone the nine nouns
     wrapped into a 350x113 block above the content and pushed the page down; four
     targets at the bottom are inside thumb reach and cost no vertical space). It is
     the same <nav> and the same links, so it is the same tab order and the same
     no-JavaScript behaviour. */
  body { padding-bottom: 82px; }
  .nav {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 20;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 4px;
    padding: 6px 6px calc(6px + env(safe-area-inset-bottom, 0px));
    background: var(--card);
    border-top: var(--outline) solid var(--ink);
  }
  .nav a, .nav-off {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 48px;
    padding: 6px 4px;
    border-radius: 12px;
    font-size: var(--fs-body);
    text-align: center;
  }

  /* 1 — contain every table (measured: dashboard 495, settings 528, /me 457, channels 605) */
  table { display: block; overflow-x: auto; max-width: 100%; }

  /* 2 — the stacked pattern */
  table.stack { display: table; overflow: visible; width: 100%; }
  table.stack tr:first-child {
    display: block;
    padding: 0;
    border-top: 0;
    height: 0;
    overflow: hidden;
  }
  table.stack tr {
    display: block;
    padding: 8px 0;
    border-top: 1px solid var(--rule);
  }
  table.stack td, table.stack th {
    display: block;
    border: 0;
    padding: 2px 0;
  }
  table.stack td::before, table.stack th::before {
    content: attr(data-label) " ";
    color: var(--ink-soft);
    font-weight: var(--w-label);
  }

  /* 3 — every control is thumb-sized, and one action per row is the obvious one.
         (The 44px floor is also in the base rules now, so it holds at every width.) */
  .btn, button { min-height: 44px; font-size: var(--fs-body); }
  form.row .btn, form.row button { flex: 1 1 100%; justify-content: center; }
  .pills a {
    min-height: 44px;
    padding: 8px 14px;
    font-size: var(--fs-body);
  }
  input[type="text"], input[type="number"], input[type="password"], input[type="file"],
  input[type="date"], input[type="time"], input[type="datetime-local"], textarea, select {
    min-height: 44px;
    font-size: var(--fs-body);
  }
  .skip:focus {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 10px 14px;
  }
  details.advanced > summary { min-height: 44px; font-size: var(--fs-body); }
  main a { display: inline-flex; align-items: center; min-height: 44px; }

  /* 4 — nothing is set below the 16px body floor (P2-1: 13px and 14px everywhere).
        The table-head selector repeats the earlier rule's specificity so it wins. */
  label, .muted, code, .chip, .pager, .foot, .who, td,
  table th, table tr:first-child th, thead th { font-size: var(--fs-body); }
}

