/*
 * Brand palette applied; full visual design still to come.
 *
 * Colours and type are from the BossBestie brand identity style guides
 * (reference/Brandbook.pdf). The four semantic colours below are additions to
 * the brand four, approved for state only — never decorative, never marketing.
 *
 * The governing rule: no state is expressed by colour alone. Every one also
 * carries a form (filled, outlined, dashed, faded) and a word, so the screen
 * still works for someone who cannot separate the hues.
 */

:root {
  --space: 1rem;
  --measure: 34rem;
  --radius: 12px;
  --radius-pill: 100px;
  --tab-bar-height: 3.25rem;

  /* Brand */
  --color-plum: #3c1b27;
  --color-gold: #cfac7c;
  --color-tan: #dcc6ab;

  /* Semantic — state only */
  --color-sage: #5f7355;    /* handled: ready, done, delegated */
  --color-ochre: #b0742c;   /* a risk the user chose */
  --color-brick: #9e3f38;   /* a deadline that passed on its own */
  --color-stone: #8a7b76;   /* unavailable: blocked, waiting */

  /* Text tints of the above, darkened to clear 4.5:1 on their own grounds */
  --color-sage-ink: #4c5c44;
  --color-ochre-ink: #7d5f36;
  --color-brick-ink: #8c352f;
  --color-stone-ink: #6b5f5a;

  /* Neutrals, warmed toward the plum so they read as chosen */
  --color-text: #2a1219;
  --color-muted: #6d555c;
  --color-faint: #9a848a;
  --color-line: #e8ddd6;
  --color-surface: #fff;
  --color-bg: #fbf8f6;

  /* Tinted grounds for state pills */
  --tint-sage: #edf1eb;
  --tint-gold: #f8f1e8;
  --tint-stone: #f0ebe9;
  --tint-faint: #f4f0ee;

  --color-accent: var(--color-plum);
  --color-danger: var(--color-brick);
  --color-attention: var(--color-ochre);
  --color-ok: var(--color-sage);
}

body {
  font-family: "Outfit", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-weight: 300;
}

/* The wordmark is the real artwork now, extracted from the brandbook as vector
   outlines, so no font is involved and Cormorant Garamond is not loaded for
   the interface at all — which is what the brandbook asks for. */
.app__brand { display: inline-flex; align-items: center; }
.app__logo { display: block; height: 1.35rem; width: auto; }

* { box-sizing: border-box; }

/* Links had no colour at all, so every one in the product rendered in browser
   default blue — a colour that appears nowhere in the brand. */
a {
  color: var(--color-plum);
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}
a:hover { text-decoration-thickness: 2px; }

/* --- Keyboard and motion ---
 *
 * A visible focus ring is not decoration: without one, someone navigating by
 * keyboard cannot tell where they are. Applied to everything interactive
 * rather than per component, so a control added later inherits it.
 */

:where(a, button, input, textarea, select, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
  border-radius: 3px;
}

.skip-link {
  position: absolute;
  left: 0.5rem;
  top: -3rem;
  z-index: 10;
  padding: 0.55rem 0.9rem;
  background: var(--color-accent);
  color: #fff;
  border-radius: var(--radius);
  text-decoration: none;
  transition: top 120ms ease;
}
.skip-link:focus { top: 0.5rem; }

main:focus { outline: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

body.app {
  margin: 0;
  padding: 0;
  font: 16px/1.55 system-ui, -apple-system, "Segoe UI", sans-serif;
  color: var(--color-text);
  background: var(--color-bg);
}

/* --- Chrome --- */

/* The header carries the wordmark and nothing else. Inside the iOS app it sits
   below Hotwire Native's own bar, so it stays deliberately short. */
.app__header {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: calc(var(--space) * 0.85) var(--space);
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-line);
}

.app__brand { display: inline-flex; text-decoration: none; }

.app__main {
  max-width: var(--measure);
  margin: 0 auto;
  padding: calc(var(--space) * 1.5) var(--space);
}

/* Clear the tab bar, plus whatever the home indicator takes — only on screens
   that have one. Onboarding does not. */
.app__main--tabbed { padding-bottom: calc(var(--tab-bar-height) + var(--space) * 2); }

/* --- Tab bar ---
   Five destinations, thumb-reachable, and fixed so it survives scrolling. The
   header nav it replaces overflowed a 390pt screen by 64px: "Account" clipped,
   "Sign out" gone entirely. */
.tab-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 10;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  background: var(--color-surface);
  border-top: 1px solid var(--color-line);
  padding-bottom: env(safe-area-inset-bottom, 0);
}

.tab {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.2rem;
  /* A 44pt target is the smallest thing a finger reliably hits. */
  min-height: 3.25rem;
  padding: 0.5rem 0.25rem;
  text-decoration: none;
  color: var(--color-muted);
}

.tab__icon { width: 1.5rem; height: 1.5rem; flex: none; }
.tab__label { font-size: 0.6875rem; font-weight: 500; letter-spacing: 0.01em; }

/* The selected tab is plum and heavier. Colour alone would not say it. */
.tab--current { color: var(--color-plum); }
.tab--current .tab__label { font-weight: 700; }
.tab:focus-visible { outline-offset: -3px; }

/* --- Messaging --- */

.flash { margin-bottom: var(--space); }
.flash__message { margin: 0 0 0.5rem; padding: 0.7rem 0.9rem; border-radius: var(--radius); }
.flash__message--notice { background: #e8f3ed; color: var(--color-ok); }
.flash__message--alert { background: #fbeaea; color: var(--color-danger); }

.form-errors {
  margin-bottom: var(--space); padding: 0.8rem 1rem;
  background: #fbeaea; border-radius: var(--radius); color: var(--color-danger);
}
.form-errors__title { margin: 0 0 0.4rem; font-weight: 600; }
.form-errors__list { margin: 0; padding-left: 1.1rem; }

/* --- Forms --- */

.form__field { margin-bottom: var(--space); }
.form__label { display: block; margin-bottom: 0.3rem; font-size: 0.9rem; font-weight: 600; }
.form__input {
  width: 100%; padding: 0.6rem 0.7rem;
  border: 1px solid var(--color-line); border-radius: var(--radius);
  font: inherit; background: var(--color-surface);
}
.form__hint { margin: 0.3rem 0 0; font-size: 0.82rem; color: var(--color-muted); }

/* iOS sizes a native date or time control from its own internals and ignores
   `width` until the native appearance is switched off. Without this the two
   fields in a pair render at their intrinsic width, overflow their columns, and
   run off the right of the screen — which desktop Chrome never reproduces, so
   every specimen looked correct. */
input[type="time"],
input[type="date"],
input[type="datetime-local"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  min-width: 0;
  display: block;
  line-height: normal;
  /* iOS renders the chosen value in system blue. `-webkit-text-fill-color` as
     well as `color`, because Safari honours the former on these controls. */
  color: var(--color-text);
  -webkit-text-fill-color: var(--color-text);
}

/* A field that carries its own glyph. iOS draws nothing in an empty date or
   time input — no placeholder, no picker indicator — so the control reads as a
   blank box. The glyph is the only thing saying it does something. */
.field-with-icon { position: relative; }
.field-with-icon .form__input { padding-right: 2.6rem; }
.field-with-icon__glyph {
  position: absolute; top: 50%; right: 0.85rem;
  width: 1.15rem; height: 1.15rem;
  transform: translateY(-50%);
  color: var(--color-stone);
  pointer-events: none;
}

.button {
  display: inline-block; padding: 0.65rem 1.1rem;
  border: 0; border-radius: var(--radius);
  font: inherit; font-weight: 600; cursor: pointer;
}
.button--primary { background: var(--color-accent); color: #fff; }
.button--danger { background: var(--color-danger); color: #fff; }

/* --- Auth + account --- */

.auth__title, .account__title, .home__title, .schedule__title, .memory__title {
  margin: 0 0 calc(var(--space) * 1.25);
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
  text-wrap: balance;
}
.auth__aside { margin-top: var(--space); font-size: 0.9rem; color: var(--color-muted); }

.account__section { margin-top: calc(var(--space) * 2); padding-top: var(--space); border-top: 1px solid var(--color-line); }
.account__subtitle { margin: 0 0 0.5rem; font-size: 1.05rem; }
.account__warning { color: var(--color-muted); font-size: 0.9rem; }

/* --- Home (PRD 7.1: needs-you vs on-track) --- */

.home__section { margin-bottom: calc(var(--space) * 2); }
.home__heading {
  margin: 0 0 0.75rem; font-size: 0.8rem; font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-muted);
}
.home__empty { margin: 0; color: var(--color-muted); font-size: 0.92rem; }

/* --- First run ---
   Shown only when someone has never captured anything. Deliberately still: no
   float, no twinkle. An empty screen that moves reads as decoration; this one
   is an instruction. */
.first-run {
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; text-align: center;
  min-height: calc(100dvh - 14rem);
  padding: var(--space) 0;
}

.first-run__mark { position: relative; margin-bottom: calc(var(--space) * 1.5); }
.first-run__medallion {
  display: flex; align-items: center; justify-content: center;
  width: 7rem; height: 7rem;
  border: 1px solid var(--color-line); border-radius: 50%;
  background: var(--color-surface);
}
.first-run__icon { width: 3.25rem; height: 3.25rem; }

.first-run__sparkle { position: absolute; }
.first-run__sparkle--large { top: -0.15rem; right: -0.15rem; width: 1.35rem; height: 1.35rem; }
.first-run__sparkle--small { bottom: 0.4rem; left: -0.5rem; width: 0.9rem; height: 0.9rem; }

.first-run__title {
  margin: 0 0 0.5rem; font-size: 1.25rem; font-weight: 700;
  letter-spacing: -0.01em; color: var(--color-plum);
}
.first-run__lede {
  max-width: 19rem; margin: 0 0 calc(var(--space) * 2);
  font-size: 0.9375rem; line-height: 1.5; color: var(--color-muted);
}

.first-run__action {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
  width: 100%; max-width: 18rem; min-height: 3rem;
  text-decoration: none;
}
.first-run__plus { width: 1.05rem; height: 1.05rem; }

.obligation-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.75rem; }

.obligation {
  position: relative;
  padding: 1.1rem 1.15rem;
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-left-width: 3px;
  border-radius: var(--radius);
}
/* Five distinct states. needs-you is the only filled one on the screen, which
   is what makes it pull attention regardless of how many obligations there are
   — not a louder colour (PRD §7.1). */
.obligation--needs-you { border-left-color: var(--color-plum); }
.obligation--blocked   { border-left-color: var(--color-stone); }
.obligation--scheduled { border-left-color: var(--color-tan); }
.obligation--ready     { border-left-color: var(--color-sage); }
/* Home shows only upcoming obligations, so this does not currently render
   there — a completed obligation recedes by leaving the screen entirely. Kept
   because the state is real and does render on the obligation detail header. */
.obligation--complete  { border-left-color: var(--color-line); opacity: 0.62; }

.obligation__title { margin: 0 0 0.25rem; font-size: 1.15rem; font-weight: 700; letter-spacing: -0.01em; }
.obligation__when { margin: 0; font-size: 0.9rem; color: var(--color-muted); }

/* One pill vocabulary, shared by obligations and actions, so the two screens
   read as one product. Only `needs_you` is filled — that is what makes
   attention land in one place however many cards are on screen. */
.obligation__state, .action__state {
  display: inline-block;
  padding: 0.3rem 0.7rem;
  border-radius: var(--radius-pill);
  font-size: 0.6875rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.08em;
  white-space: nowrap;
}
.obligation__state { margin: 0.55rem 0 0; }
.obligation__state[data-readiness="needs_you"] { background: var(--color-plum); color: #fff; }
.obligation__state[data-readiness="blocked"]   { background: var(--tint-stone); color: var(--color-stone-ink); }
.obligation__state[data-readiness="scheduled"] { background: var(--tint-gold);  color: var(--color-ochre-ink); }
.obligation__state[data-readiness="ready"]     { background: var(--tint-sage);  color: var(--color-sage-ink); }
.obligation__state[data-readiness="complete"]  { background: var(--tint-faint); color: #7a646d; }
.obligation__next-action { margin: 0.45rem 0 0; font-size: 0.9rem; }
.obligation__next-action-label { font-weight: 600; }
.obligation__next-action-timing { color: var(--color-muted); }
/* Same severity, different authorship. past-safe-moment is a scheduling call
   the user made knowingly and the product respects; overdue is a deadline that
   slipped past on its own. Scolding someone for their own decision is the one
   tone this product cannot have (FR-10.2). */
.obligation__risk { margin: 0.35rem 0 0; font-size: 0.85rem; }
.obligation__risk[data-risk="past-safe-moment"] { color: var(--color-ochre-ink); }
.obligation__risk[data-risk="overdue"]          { color: var(--color-brick-ink); }

/* --- Onboarding (screen 2) --- */

/* One segment per step, so adding a question later does not make the copy lie.
   Filled segments are behind you; the last filled one is where you are. */
.progress { list-style: none; display: flex; gap: 0.5rem; margin: 0 0 calc(var(--space) * 2); padding: 0; }
.progress__segment { flex: 1; height: 4px; border-radius: var(--radius-pill); background: var(--color-line); }
.progress__segment[data-done="true"] { background: var(--color-plum); }

/* Fill the screen so Continue lands in the same place on every step, whatever
   each one asks. `dvh` rather than `vh` because mobile browser chrome moves.
   The subtraction is the header plus this screen's own padding. */
.onboarding { display: flex; flex-direction: column; min-height: calc(100dvh - 7rem); }
.onboarding__form { display: flex; flex-direction: column; flex: 1; }
.onboarding__title { margin: 0 0 0.6rem; font-size: 1.75rem; font-weight: 700; letter-spacing: -0.02em; line-height: 1.15; color: var(--color-plum); }
.onboarding__lede { margin: 0 0 calc(var(--space) * 2); color: var(--color-muted); line-height: 1.5; }

/* The action sits at the bottom of the screen rather than under the last
   field, because that is where the thumb already is. */
.onboarding__footer { margin-top: auto; padding-top: calc(var(--space) * 1.5); }
.onboarding__continue { display: block; width: 100%; height: 3rem; }

.onboarding__aside { margin-top: var(--space); text-align: center; font-size: 0.8125rem; color: var(--color-muted); }
.onboarding__aside .link-button { font-size: 1rem; font-weight: 600; color: var(--color-plum); }
.onboarding__reassurance { display: block; margin-top: 0.4rem; }

/* --- Grouped fields --- */

.field-group { margin: 0 0 calc(var(--space) * 2); padding: 0; border: 0; }
.field-group__legend {
  display: block; margin-bottom: 0.6rem; padding: 0;
  font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.01em; color: var(--color-text);
}
/* `min-width: 0` on the children, because a grid item defaults to `min-width:
   auto` and a native time input has an intrinsic minimum width it refuses to
   shrink below. Without it the two fields overflow their columns and eat the
   gap, so they touch. */
.field-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.field-pair > * { min-width: 0; }
.field-pair .form__input { width: 100%; min-width: 0; height: 3rem; }

/* --- Day toggles --- */

.day-toggles { display: flex; justify-content: space-between; gap: 0.35rem; }
.day-toggle { cursor: pointer; }
.day-toggle__initial {
  display: flex; align-items: center; justify-content: center;
  width: 2.5rem; height: 2.5rem;
  border: 1px solid var(--color-line); border-radius: 50%;
  background: var(--color-surface);
  font-size: 0.9375rem; font-weight: 600; color: var(--color-muted);
}
/* `:has` rather than a sibling selector, so the input can sit inside its own
   label and stay a real checkbox for the keyboard and for screen readers. */
.day-toggle:has(input:checked) .day-toggle__initial {
  background: var(--color-plum); border-color: var(--color-plum); color: #fff;
}
.day-toggle:has(input:focus-visible) .day-toggle__initial {
  outline: 2px solid var(--color-gold); outline-offset: 2px;
}

/* --- Chips ---
   One choice from a short list, where a dropdown would hide the options and a
   radio list would spend a line on each. */
.chips { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.chip { cursor: pointer; }
.chip__label {
  display: inline-flex; align-items: center;
  min-height: 2.5rem; padding: 0.55rem 1rem;
  border: 1px solid var(--color-line); border-radius: var(--radius-pill);
  background: var(--color-surface);
  font-size: 0.875rem; font-weight: 500; color: var(--color-text);
}
.chip:has(input:checked) .chip__label {
  background: var(--color-plum); border-color: var(--color-plum); color: #fff;
}
.chip:has(input:focus-visible) .chip__label {
  outline: 2px solid var(--color-gold); outline-offset: 2px;
}

.field-group__hint { margin: 0.6rem 0 0; font-size: 0.8125rem; color: var(--color-stone-ink); }

.form__fieldset { margin: 0 0 var(--space); padding: 0; border: 0; }
.form__legend { padding: 0; margin-bottom: 0.4rem; font-size: 0.9rem; font-weight: 600; }
.form__choices { display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; }
.form__choices--stacked { flex-direction: column; gap: 0.45rem; }
.settings__title { margin: 0 0 0.4rem; font-size: 1.5rem; }
.subscription { padding: 1rem 1.1rem; margin-bottom: var(--space); background: var(--color-surface);
  border: 1px solid var(--color-line); border-left-width: 3px; border-radius: var(--radius); }
.subscription[data-status="trialing"], .subscription[data-status="active"] { border-left-color: var(--color-ok); }
.subscription[data-status="past_due"] { border-left-color: var(--color-attention); }
.subscription[data-status="cancelled"], .subscription[data-status="expired"] { border-left-color: var(--color-danger); }
.subscription__state { margin: 0; font-size: 0.78rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; }
.subscription__remaining { margin: 0.3rem 0 0; font-size: 1.05rem; }
.subscription__lapsed { margin: 0.6rem 0 0; font-size: 0.9rem; color: var(--color-muted); }
.settings__lede { margin: 0 0 calc(var(--space) * 1.5); color: var(--color-muted); }
.form__choice { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.92rem; }

.button--quiet { background: var(--color-surface); color: var(--color-text); border: 1px solid var(--color-line); }
.link-button, .link-button button {
  display: inline; border: 0; background: none; padding: 0;
  font: inherit; color: var(--color-accent); text-decoration: underline; cursor: pointer;
}
.link-button--danger button { color: var(--color-danger); }

.setup-prompt {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 0.75rem; margin-bottom: calc(var(--space) * 1.5);
  padding: 0.85rem 1rem; background: var(--color-surface);
  border: 1px dashed var(--color-line); border-radius: var(--radius);
}
.setup-prompt__text { margin: 0; font-size: 0.92rem; }

/* --- Memory (screen 8) --- */

.memory__title { margin: 0 0 0.4rem; font-size: 1.5rem; }
.memory__lede, .memory__empty { margin: 0 0 calc(var(--space) * 1.5); color: var(--color-muted); font-size: 0.92rem; }

.memory-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.75rem; }
.memory-fact {
  padding: 0.9rem 1rem; background: var(--color-surface);
  border: 1px solid var(--color-line); border-radius: var(--radius);
}
.memory-fact__key { margin: 0 0 0.15rem; font-size: 1rem; }
.memory-fact__provenance { margin: 0 0 0.6rem; font-size: 0.82rem; color: var(--color-muted); }

/* Gold marks BossBestie's own reasoning wherever it appears. A user has to be
   able to tell at a glance which beliefs are theirs and which the product
   inferred, because the inferred ones are what they will want to correct
   (FR-9.3, FR-9.4). */
.memory-fact[data-provenance="inferred"] {
  border-left: 3px solid var(--color-gold); background: #fdfaf5;
}
.memory-fact[data-provenance="inferred"] .memory-fact__provenance { color: var(--color-ochre-ink); }
.memory-fact__form { display: flex; gap: 0.5rem; align-items: center; margin-bottom: 0.5rem; }
.memory-fact__form .form__input { flex: 1; }

/* --- Obligation detail: thread (screen 5) + plan (screen 6) --- */

.obligation-header { margin-bottom: calc(var(--space) * 1.5); padding-bottom: var(--space); border-bottom: 1px solid var(--color-line); }
.obligation-header__title { margin: 0 0 0.3rem; font-size: 1.75rem; font-weight: 700; letter-spacing: -0.02em; line-height: 1.15; }
.obligation-header__when { margin: 0; font-size: 0.95rem; color: var(--color-muted); }
.obligation-header__location::before { content: " · "; }

/* The same pill as the cards below it, so the obligation's state and its
   actions' states are visibly the same kind of thing. */
.obligation-header__state {
  display: inline-block;
  margin: 0.7rem 0 0;
  padding: 0.3rem 0.7rem;
  border-radius: var(--radius-pill);
  font-size: 0.6875rem; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
}
.obligation-header[data-readiness="needs_you"] .obligation-header__state { background: var(--color-plum);  color: #fff; }
.obligation-header[data-readiness="blocked"]   .obligation-header__state { background: var(--tint-stone); color: var(--color-stone-ink); }
.obligation-header[data-readiness="scheduled"] .obligation-header__state { background: var(--tint-gold);  color: var(--color-ochre-ink); }
.obligation-header[data-readiness="ready"]     .obligation-header__state { background: var(--tint-sage);  color: var(--color-sage-ink); }
.obligation-header[data-readiness="complete"]  .obligation-header__state { background: var(--tint-faint); color: #7a646d; }

.obligation-header__nav { display: flex; gap: var(--space); margin-top: var(--space); }
.tab { font-size: 0.9rem; color: var(--color-muted); text-decoration: none; padding-bottom: 0.2rem; }
.tab--current { color: var(--color-text); font-weight: 600; border-bottom: 2px solid var(--color-accent); }

.thread { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.6rem; }
.thread-message { padding: 0.7rem 0.9rem; background: var(--color-surface); border: 1px solid var(--color-line); border-radius: var(--radius); }
.thread-message--system { background: transparent; border-style: dashed; }
.thread-message__body { margin: 0; font-size: 0.94rem; }
.thread-message__at { margin: 0.25rem 0 0; font-size: 0.78rem; color: var(--color-muted); }
.thread__empty, .thread__pending, .action-list__empty { margin-top: var(--space); color: var(--color-muted); font-size: 0.9rem; }

.action-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.75rem; }

.action {
  padding: 1.1rem 1.15rem;
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius);
}

/* Blocked reads unavailable, not broken: a dashed edge and a sunk ground say
   "not yet", where a red one would say "wrong". */
.action[data-status="blocked"] {
  background: var(--tint-faint);
  border-style: dashed;
}
.action[data-status="blocked"] .action__title { color: var(--color-stone-ink); }

.action[data-status="done"] .action__title {
  color: var(--color-muted);
  text-decoration: line-through;
}

/* The critical path is not surfaced. The hook stays on the markup because the
   engine knows it and design may want it later, but a gold edge reads as a
   state the row does not have — and on a row that already carries a risk line
   it is noise. "Critical path" is project-management vocabulary anyway, which
   is the deeper reason this is still undecided. */

.action__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.45rem;
}
.action__title { margin: 0; font-size: 1.05rem; font-weight: 700; letter-spacing: -0.01em; }

/* Quiet. The obligation header carries the one filled pill on this screen —
   a second one in the top row would say the same thing twice, and the row that
   actually needs attention says so with its risk line. */
.action__state[data-status="pending"]   { background: var(--tint-faint); color: var(--color-muted); }
.action__state[data-status="scheduled"] { background: var(--tint-gold);   color: var(--color-ochre-ink); }
.action__state[data-status="delayed"]   { background: var(--tint-gold);   color: var(--color-ochre-ink); }
.action__state[data-status="blocked"]   { background: var(--tint-stone);  color: var(--color-stone-ink); }
.action__state[data-status="done"]      { background: var(--tint-sage);   color: var(--color-sage-ink); }
.action__state[data-status="delegated"] { background: var(--tint-sage);   color: var(--color-sage-ink); }

.action__timing, .action__scheduled, .action__delegate, .action__blocked-by, .action__completed {
  margin: 0.15rem 0 0; font-size: 0.9rem; color: var(--color-muted);
}
.action__delegate { color: var(--color-text); }

.action__risk { margin: 0.45rem 0 0; font-size: 0.9rem; font-weight: 500; }
.action__risk[data-risk="past-safe-moment"] { color: var(--color-ochre-ink); }
.action__risk[data-risk="overdue"]          { color: var(--color-brick-ink); }

/* Done stays one tap on the row; everything else is behind the overflow.
   A grid rather than a flex row so the panel opens beneath the toggle without
   the toggle moving — a control that jumps when you tap it is worse than a
   narrow panel. */
.action__controls {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: start;
  gap: 0.5rem;
  margin-top: 0.9rem;
}
.action__more { grid-column: 2; justify-self: stretch; }
.action__more-toggle { margin-left: auto; }

/* With no Mark Done — a blocked action — the overflow keeps its column. */
.action__controls > .action__more:only-child { grid-column: 1 / -1; }

.action__more-toggle {
  display: flex; align-items: center; justify-content: center;
  width: 2.75rem; height: 2.4rem;
  border-radius: var(--radius);
  color: var(--color-muted);
  font-size: 1.35rem; line-height: 1;
  cursor: pointer;
  list-style: none;
}
.action__more-toggle::-webkit-details-marker { display: none; }
.action__more-toggle:hover { background: var(--tint-faint); }
.action__more[open] .action__more-toggle { background: var(--tint-faint); color: var(--color-text); }

.action__more-panel {
  display: grid;
  gap: 0.75rem;
  margin-top: 0.75rem;
  padding-top: 0.85rem;
  border-top: 1px solid var(--color-line);
}
.action__control { display: grid; gap: 0.35rem; }
.action__control-label { font-size: 0.8rem; font-weight: 600; color: var(--color-muted); }

.form__input--inline { width: auto; padding: 0.35rem 0.5rem; font-size: 0.88rem; }

/* --- Questions in the thread (SL-3) --- */

.questions { display: grid; gap: 0.6rem; margin-bottom: calc(var(--space) * 1.25); }
.question {
  padding: 0.9rem 1rem; background: var(--color-surface);
  border: 1px solid var(--color-line); border-left: 3px solid var(--color-accent);
  border-radius: var(--radius);
}
.question[data-lead="true"] { box-shadow: 0 1px 3px rgb(0 0 0 / 0.06); }
.question__prompt { margin: 0 0 0.2rem; font-size: 0.98rem; font-weight: 600; }
.question__rationale { margin: 0 0 0.6rem; font-size: 0.85rem; color: var(--color-muted); }
.question__suggestion { margin: 0 0 0.5rem; font-size: 0.85rem; color: var(--color-muted); font-style: italic; }
.question__form { display: flex; gap: 0.5rem; align-items: center; margin-bottom: 0.4rem; }
.question__form .form__input { flex: 1; }

.thread-message--sloane { border-left: 3px solid var(--color-accent); }
.thread-message__answer { color: var(--color-muted); }

/* --- Capture (screen 4) --- */

.capture__title { margin: 0 0 0.4rem; font-size: 2rem; font-weight: 700; letter-spacing: -0.02em; line-height: 1.1; color: var(--color-plum); }
.capture__lede { margin: 0 0 calc(var(--space) * 1.5); font-size: 1.0625rem; line-height: 1.35; color: var(--color-plum); }
.capture__form { margin-bottom: calc(var(--space) * 2); }
.capture__empty { color: var(--color-muted); font-size: 0.9rem; }

/* The composer. A heavier border than the rest of the app's inputs, because on
   this screen it is the only thing that matters. */
.capture__body {
  width: 100%;
  padding: 0.9rem 1rem;
  border: 2px solid var(--color-plum);
  border-radius: 16px;
  background: var(--color-surface);
  font: inherit;
  font-size: 1.0625rem;
  resize: none;
}
.capture__status { margin: 0.4rem 0 0; font-size: 0.82rem; color: var(--color-muted); min-height: 1.1em; }

/* The global focus ring is 2px of --color-accent, which is plum — the same
   colour and weight as this box's own border. Drawn around it that reads as a
   doubled edge rather than as focus, and the composer is autofocused, so it is
   on screen the instant the page opens.
   A soft plum glow instead: still plainly a focus indicator, and it cannot be
   mistaken for the border it surrounds. */
.capture__body:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(60, 27, 39, 0.16);
}

/* Three controls, one row, all 48px tall. Capture and Speak share the space
   equally — Speak is not a secondary action. */
.capture__inputs { display: flex; align-items: stretch; gap: 0.75rem; margin-top: 0.75rem; }
.capture__action {
  /* `min-width: 0`, because a flex item will not shrink below its content and
     Speak carries an icon Capture does not — so the two came out different
     widths despite both being flex: 1. */
  flex: 1;
  min-width: 0;
  display: inline-flex; align-items: center; justify-content: center; gap: 0.45rem;
  height: 3rem; padding: 0 0.75rem;
  border-radius: var(--radius);
  font-weight: 700;
}
.capture__attach {
  flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 3rem; height: 3rem; padding: 0;
  border-radius: var(--radius);
  cursor: pointer;
}
.capture__icon { width: 1.15rem; height: 1.15rem; flex: none; }
.capture__attached { display: flex; align-items: center; gap: 0.75rem; margin: 0.85rem 0 0; font-size: 0.875rem; }
.capture__attached[hidden] { display: none; }
.capture__attached-image { width: 3.5rem; height: 3.5rem; object-fit: cover; border-radius: 0.5rem; flex: none; }
.capture__attached-text { flex: 1; }
.capture__note { margin: 0.85rem 0 0; font-size: 0.8125rem; line-height: 1.5; color: var(--color-muted); }
.capture__form[data-listening="true"] .capture__body { border-color: var(--color-gold); }

/* --- Recent captures --- */

.capture-list { list-style: none; margin: 0 0 calc(var(--space) * 2); padding: 0; display: grid; gap: 0.75rem; }

.capture-item {
  position: relative;
  overflow: hidden;
  display: grid;
  gap: 0.5rem;
  padding: 1rem;
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius);
}

/* Only a failed capture carries an edge, which is what makes it the one card
   that stands out. */
.capture-item[data-state="failed"]::before {
  content: "";
  position: absolute; left: 0; top: 0; bottom: 0;
  width: 3px; background: var(--color-brick);
}

.capture-item__state {
  /* Only the pill shrinks to its content. The grid used to do this for every
     child, which made the failed card's sentence wrap early and pushed its
     retry onto a line of its own. */
  justify-self: start;
  margin: 0;
  padding: 0.2rem 0.5rem;
  border-radius: var(--radius-pill);
  font-size: 0.6875rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.1em;
  background: var(--tint-faint); color: var(--color-muted);
}
.capture-item[data-state="pending"]    .capture-item__state { background: var(--tint-stone); color: var(--color-stone-ink); }
.capture-item[data-state="processing"] .capture-item__state { background: var(--tint-gold);  color: var(--color-ochre-ink); }
.capture-item[data-state="extracted"]  .capture-item__state { background: var(--tint-sage);  color: var(--color-sage-ink); }
.capture-item[data-state="failed"]     .capture-item__state { background: #f6e9e7; color: var(--color-brick-ink); }

.capture-item__body { margin: 0; font-size: 1rem; font-weight: 500; line-height: 1.3; }
.capture-item__kind { color: var(--color-muted); font-weight: 400; }
.capture-item__meta { margin: 0; font-size: 0.875rem; color: var(--color-muted); }
.capture-item__meta .link-button, .capture-item__link { font-weight: 600; color: var(--color-plum); }
/* `button_to` renders a form, which is a block and would drop "Try again" onto
   its own line — the failed card reads as one sentence, so it stays inline. */
.capture-item__meta form { display: inline; }

/* --- Forwarding address --- */

.forwarding { border-top: 1px solid var(--color-line); }
.forwarding__toggle {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space);
  padding: 1rem 0;
  font-size: 1rem; font-weight: 700; color: var(--color-plum);
  cursor: pointer; list-style: none;
}
.forwarding__toggle::-webkit-details-marker { display: none; }
.forwarding__chevron { width: 1.1rem; height: 1.1rem; color: var(--color-stone); transition: transform 0.15s ease; }
.forwarding[open] .forwarding__chevron { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) { .forwarding__chevron { transition: none; } }
.forwarding__panel { padding-bottom: var(--space); display: grid; gap: 0.6rem; }
.forwarding__lede, .forwarding__note { margin: 0; font-size: 0.875rem; color: var(--color-muted); }
.forwarding__address { margin: 0; }
.forwarding__address code { font-size: 0.875rem; word-break: break-all; }


.completed { margin-top: calc(var(--space) * 2); }
.completed__heading, .removed__heading {
  margin: 0 0 0.75rem; font-size: 0.8rem; font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-muted);
}

.removed { margin-top: calc(var(--space) * 2); padding-top: var(--space); border-top: 1px solid var(--color-line); }
.removed__heading { margin: 0 0 0.25rem; font-size: 0.8rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-muted); }
.removed__lede { margin: 0 0 0.75rem; font-size: 0.86rem; color: var(--color-muted); }
.removed-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.4rem; }
.removed-action { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; font-size: 0.9rem; color: var(--color-muted); }
.removed-action__title { text-decoration: line-through; }

.obligation__link { color: inherit; text-decoration: none; }
.obligation__link:hover { text-decoration: underline; }

/* --- Admin (FR-13.1) --- */

.admin__title { margin: 0 0 0.2rem; font-size: 1.5rem; }
.admin__lede { margin: 0 0 calc(var(--space) * 1.5); color: var(--color-muted); font-size: 0.9rem; }
.admin__section { margin-bottom: calc(var(--space) * 2); }
.admin__heading { margin: 0 0 0.6rem; font-size: 0.8rem; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--color-muted); }

.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr)); gap: 0.6rem; margin: 0; }
.stat { padding: 0.7rem 0.85rem; background: var(--color-surface); border: 1px solid var(--color-line);
  border-radius: var(--radius); }
.stat dt { margin: 0 0 0.15rem; font-size: 0.72rem; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--color-muted); }
.stat dd { margin: 0; font-size: 1.35rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.stat[data-state="failed"] dd { color: var(--color-danger); }
.stat[data-state="extracted"] dd { color: var(--color-ok); }

.admin-table { width: 100%; border-collapse: collapse; font-size: 0.92rem; }
.admin-table th { text-align: left; font-size: 0.7rem; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--color-muted); padding: 0.4rem 0.6rem; }
.admin-table td { padding: 0.4rem 0.6rem; border-top: 1px solid var(--color-line);
  font-variant-numeric: tabular-nums; }
.admin-table td:first-child { font-variant-numeric: normal; }
.admin-table__detail { display: block; font-size: 0.78rem; color: var(--color-muted); }
.admin-table tr[data-on-target="true"] td:nth-child(2) { color: var(--color-sage-ink); font-weight: 600; }
.admin-table tr[data-on-target="false"] td:nth-child(2) { color: var(--color-brick-ink); font-weight: 600; }
.admin__note { margin: 0 0 0.6rem; font-size: 0.85rem; color: var(--color-muted); }

.admin-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
.admin-item { padding: 0.7rem 0.85rem; background: var(--color-surface); border: 1px solid var(--color-line);
  border-left: 3px solid var(--color-danger); border-radius: var(--radius); }
.admin-item__body { margin: 0 0 0.2rem; font-size: 0.92rem; }
.admin-item__meta { margin: 0; font-size: 0.8rem; color: var(--color-muted); }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* --- Schedule (screen 7) ---
 *
 * The one screen where the ownership boundary is visible. What BossBestie set
 * aside and what it merely read sit side by side, and must never be mistaken
 * for each other: ours is solid and openable, theirs is quiet and inert
 * (FR-7.3).
 */

.schedule__title { margin: 0 0 0.3rem; font-size: 1.5rem; }
.schedule__lede { margin: 0 0 calc(var(--space) * 1.5); color: var(--color-muted); }
.schedule__empty { margin: 0; color: var(--color-muted); font-size: 0.92rem; }

.schedule__days { list-style: none; margin: 0; padding: 0; display: grid; gap: calc(var(--space) * 1.5); }

.schedule-day__date {
  margin: 0 0 0.6rem; font-size: 0.8rem; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-muted);
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem;
}
.schedule-day__note { font-weight: 400; letter-spacing: 0; text-transform: none; color: var(--color-faint); }
.schedule-day[data-working="false"] .schedule-day__date { color: var(--color-faint); }

.schedule-entries { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }

.schedule-entry {
  padding: 0.75rem 0.9rem; background: var(--color-surface);
  border: 1px solid var(--color-line); border-left-width: 3px; border-radius: var(--radius);
}

/* Ours: plum edge, title links through to the plan it belongs to. */
.schedule-entry[data-owner="ours"] { border-left-color: var(--color-plum); }

/* Theirs: read-only, so it is deliberately quieter and nothing in it is a
   link. Tinted rather than faded — it is not less important to the user, it is
   simply not ours to change. */
.schedule-entry[data-owner="theirs"] {
  background: var(--tint-stone); border-left-color: var(--color-stone); border-style: dashed;
}

.schedule-entry__time {
  margin: 0; font-size: 0.8rem; color: var(--color-muted);
  display: flex; gap: 0.5rem; align-items: baseline;
}
.schedule-entry__duration { color: var(--color-faint); }
.schedule-entry__title { margin: 0.1rem 0 0; font-size: 1rem; font-weight: 500; }
.schedule-entry__for, .schedule-entry__source { margin: 0.15rem 0 0; font-size: 0.85rem; color: var(--color-muted); }
.schedule-entry__source { color: var(--color-faint); }

/* --- Signed-out header ---
 *
 * The only place the tagline appears in the product. Everywhere else the
 * wordmark alone carries it, per the brandbook's own hierarchy.
 */

.auth-header {
  display: flex;
  justify-content: center;
  padding: calc(var(--space) * 2.5) var(--space) calc(var(--space) * 1.5);
}
.auth-header__logo { display: block; width: 100%; max-width: 15rem; height: auto; }
