/* AutOn v1 — the components the design adds, and the ones it re-cuts.
 *
 * Loaded last, so it wins where it disagrees with app.css. Everything here is
 * a value read out of AutOn v1.dc.html.
 *
 * The idea running through all of it, and the thing the whole restyle is for:
 * SHOW THIN, OPEN ON DEMAND. A founder should be able to read a screen in four
 * seconds and still get to every number underneath it in one click. So the
 * default state of any detail in this system is closed, and `.disc` is the one
 * mechanism that opens it.
 */

/* ==========================================================================
   A · THE LABEL SYSTEM
   The design labels things three ways and never a fourth: an EYEBROW above a
   heading, a section LABEL inside a card header, and PROVENANCE in mono —
   which always names where a number came from. Provenance is the reason the
   product can be trusted, so it is a first-class type style, not a caption.
   ========================================================================== */
.eyebrow {
  display: block;
  font-size: var(--t-micro); font-weight: 600;
  letter-spacing: var(--tr-eyebrow); text-transform: uppercase;
  color: var(--quiet);
}
.eyebrow--ico { display: flex; align-items: center; gap: 7px; }
.eyebrow--ico svg { color: var(--accent); }
.label {
  display: flex; align-items: center; gap: 7px;
  font-size: var(--t-label); font-weight: 600;
  letter-spacing: var(--tr-label); text-transform: uppercase;
  color: var(--ink);
}
/* Provenance is TYPE, not a chip. The old system gave it a pill and a fill;
   the design sets it as plain mono at 10.5px, so the fill and the padding are
   cleared here or every source tag reads as a button that cannot be pressed. */
.prov {
  font-family: var(--font-mono); font-size: var(--t-prov); color: var(--quiet);
  background: none; padding: 0; border-radius: 0;
  overflow-wrap: anywhere;
}
/* It only refuses to wrap where it sits inline in a row that is already tight,
   and there it is always a short label. As a block line under a paragraph it is
   often a whole sentence, and nowrap ran those 127px past the card's edge. */
.card-h .prov, .loopcard-h .prov, .splitv-rf .prov, .splitv-rh .prov,
.artifact-h .prov, .disc-b .prov, .t .prov, .tile .prov {
  white-space: nowrap; overflow-wrap: normal;
}
a.prov:hover { color: var(--ink); }
.mono { font-family: var(--font-mono); font-size: var(--t-xs); color: var(--muted); }
.rule { flex: 1; height: 1px; background: var(--hairline); min-width: 12px; }
/* `.rule` collides: in the design it is the hairline that fills the rest of a
   card header, but app.css has owned `.rule` since before this repaint as an
   icon+text row — the "it may never send" lists, the guardrail bullets, the
   refusal lines, ~90 of them across 19 screens. The hairline is always EMPTY
   and the row never is, so the two are told apart by content rather than by
   renaming a class every screen in the product is already written against.
   Without this, every bullet row in the app draws a grey #EDECE6 bar behind
   its own text. */
.rule:not(:empty) { flex: 0 1 auto; height: auto; background: none; min-width: 0; }

/* ==========================================================================
   B · CARDS, BUTTONS, NUMBERS
   ========================================================================== */
.card {
  background: var(--surface);
  border: 1px solid var(--divider);
  border-radius: var(--r-card);
  box-shadow: var(--e1);
  overflow: hidden;
}
.card--lift { box-shadow: var(--e2); border-radius: var(--r-pane); }
.card--quiet { background: var(--surface-2); box-shadow: none; }
/* The one card on a screen that must be looked at: an ink hairline and real
   elevation. Used once per screen at most, or it stops meaning anything. */
.card--look { border-color: var(--ink); box-shadow: var(--e3); border-radius: var(--r-pane); }
/* The row you are reading is selected with INK. The old system drew it in
   terracotta, which under this palette is the amber that means a person must
   act — and "this is the one I clicked" is not a job. Amber is never spent on
   selection, hover or emphasis anywhere in v1. */
.segcard.is-on, .listrow.is-on, .doccard.is-on, .holdopt.is-on { border-color: var(--ink); }

/* Two more places app.css still spent amber on something that is not an act.
   v1.css loads last, so they are corrected here rather than in app.css, which
   other screens are still being written against.

   1. THE AVATAR. The design draws a person's initials in PALE GREEN — the Team
      screen sets `background:#E4E7E2; color:#4C7F5E` on the 36px circle. Those
      two values already ship as `--av-bg` / `--av-bd` in tokens.css and nothing
      was using them, while app.css drew every person in the product in
      `--terra-100/--terra-900`, i.e. in the colour that means "waiting on you".
      Six faces on #/team and two on #/measure/pages were reading as alarms.
   2. THE ASIDE ICON. `.why` and `.press` are neutral explanations — "here is
      the reasoning" — and their leading icon was amber for no reason. Quiet. */
.avatar { background: var(--av-bg); color: var(--accent-700); box-shadow: inset 0 0 0 1px var(--av-bd); }
.why svg, .press svg { color: var(--quiet); }
.card-h {
  display: flex; align-items: center; gap: 9px;
  padding: 13px var(--s5);
  border-bottom: 1px solid var(--hairline);
}
.card-t { font-size: var(--t-label); font-weight: 600; letter-spacing: var(--tr-label); text-transform: uppercase; color: var(--ink); }
.card-h svg { color: var(--accent); flex: none; }
.card-b { padding: var(--s5) var(--s6); }
.card-f {
  padding: 11px var(--s5);
  background: var(--surface-2); border-top: 1px solid var(--hairline);
  font-size: var(--t-xs); color: var(--muted);
}

.btn {
  display: inline-flex; align-items: center; gap: 6px;
  border-radius: var(--r-pill);
  border: 1px solid var(--divider); background: var(--surface); color: var(--ink);
  padding: 7px var(--s3);
  font-size: var(--t-xs); font-weight: 600; line-height: 1.2;
  cursor: pointer; white-space: nowrap;
  transition: background var(--fast), border-color var(--fast), color var(--fast);
}
.btn:hover { background: var(--ground); }
.btn--primary, .btn--dark { background: var(--ink); border-color: var(--ink); color: var(--on-dark); }
.btn--primary:hover, .btn--dark:hover { background: var(--ink-2); border-color: var(--ink-2); }
.btn--ghost { border-color: transparent; background: transparent; color: var(--muted); }
.btn--ghost:hover { background: var(--ground); color: var(--ink); }
.btn--danger { background: var(--stop); border-color: var(--stop); color: #fff; }
.btn--lg { padding: 10px var(--s6); font-size: var(--t-md); }
.btn--sm { padding: 5px 11px; font-size: var(--t-xs); }
.btn--icon { padding: 0; width: 30px; height: 30px; justify-content: center; }
.btn--block { width: 100%; justify-content: center; }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.pillbtn {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  border: 1px solid var(--divider); background: var(--surface); color: var(--ink);
  border-radius: var(--r-pill); padding: 5px 11px;
  font-size: var(--t-xs); font-weight: 600; white-space: nowrap; cursor: pointer;
}
.pillbtn:hover { background: var(--ground); }

/* The numbers are MONO at weight 500. This is the design's loudest signature
   and the easiest thing to lose to a heavy sans by accident. */
.stat-v, .num-xl, .num-lg, .num {
  font-family: var(--font-mono); font-weight: 500;
  letter-spacing: var(--tr-h1); font-variant-numeric: tabular-nums;
}
.stat-v { font-size: var(--t-num); }
.num { font-size: var(--t-num); }
.num-lg { font-size: var(--t-num-lg); }
.num-xl { font-size: var(--t-num-xl); letter-spacing: var(--tr-num); }
.stat-u { font-size: var(--t-base); color: var(--quiet); }

.tag, .chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--t-label); font-weight: 600;
  border-radius: var(--r-pill); padding: 3px 9px;
  background: var(--hover); color: var(--muted);
}
.tag--sage, .tag--good, .tag--g { background: var(--accent-50); color: var(--accent); }
.tag--terra, .tag--warn, .tag--held { background: var(--held-bg); color: var(--held-ink); }
.tag--ink { background: var(--ink); color: var(--on-dark); }

/* FILLS ARE GREEN. The design puts the accent on data and the amber on
   warnings: in the sibling design the olive is `background:` 13 times (progress
   bars, chart bars) while the terracotta is only ever `color:`, and the v1
   Objective head card draws a `#4C7F5E` fill on a `#EDECE6` track. app.css
   filled both `.bar` and `.pace` with --terra, which drew an amber bar under a
   card that said "on pace" — amber as decoration, which is the one thing it may
   never be. A bar turns amber only when it is told a person must act. */
.bar { background: var(--hairline); }
.bar > span, .bar--sage > span { background: var(--accent); }
.bar--held > span { background: var(--held); }
.pace { background: var(--hairline); }
.pace-fill { background: var(--accent); }
.pace--held .pace-fill { background: var(--held); }

/* The held block. Amber, and only ever used to say a person must act. */
.held {
  background: var(--held-bg); border: 1px solid var(--held-bd);
  border-radius: var(--r-chip); padding: 11px var(--s3);
}
.held-l { display: flex; align-items: center; gap: 7px; margin-bottom: 6px; font-size: var(--t-label); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--held-ink); }
.held-l svg { color: var(--held); }
.held-t { font-size: var(--t-base); color: var(--held-deep); line-height: var(--lh-body); }

/* ------------------------------------------------------------------ tables */
.t { width: 100%; border-collapse: collapse; font-size: var(--t-base); }
.t th {
  text-align: left; font-weight: 500; font-size: var(--t-label);
  letter-spacing: .04em; color: var(--quiet);
  padding: 10px var(--s6); border-bottom: 1px solid var(--hairline);
  white-space: nowrap;
}
.t td { padding: 12px var(--s6); border-bottom: 1px solid var(--hairline-2); }
.t tbody tr:last-child td { border-bottom: 0; }
/* `.num` above is the 27px display figure. A numeric TABLE cell is not that:
   it must stay at the table's own size, and without this it inherits 27px from
   `.num` because `.t td` never declares a size of its own. */
.t td.num, .t th.num { text-align: right; font-size: inherit; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.t tbody tr:hover { background: var(--surface-2); }
.tablewrap { overflow-x: auto; }
/* Seven stage columns at a 212px floor need ~1,556px and the page gives 1,082.
   A grid with 1fr tracks sizes itself to the wrapper and then overflows its own
   box instead of letting the wrapper scroll it. */
.tablewrap > .grid { min-width: max-content; }

/* The one line every draft is built on, set on ink. Read out of AutOn v1's
   Strategise screen: `background:#1C1B17; color:#FBFBF9; border-radius:16px;
   padding:22px`, an uppercase `#93C4A5` label over a 19px/1.5 weight-500 quote
   at 52ch, over a mono meta row in `#A9A69B` — which is exactly what the
   --accent-300 token is annotated for ("labels on ink"). */
.linecard {
  background: var(--ink); color: var(--on-dark);
  border-radius: var(--r-card); padding: var(--s7);
}
.linecard-l {
  font-size: var(--t-label); font-weight: 600; letter-spacing: var(--tr-label);
  text-transform: uppercase; color: var(--accent-300); margin-bottom: 14px;
}
.linecard-q {
  font-size: 19px; line-height: 1.5; font-weight: 500;
  max-width: 52ch; letter-spacing: var(--tr-tight);
}
.linecard-m {
  display: flex; gap: 16px; flex-wrap: wrap; margin-top: 18px;
  font-family: var(--font-mono); font-size: 11.5px; color: var(--n500);
}

/* ==========================================================================
   C · THE SPLIT VIEW  (.splitv)
   NB: `.split` was already taken — app.css has owned it since before this
   repaint as a main+aside two-column, and seventeen uses across twelve screens
   depend on it. The split VIEW is a different object and carries its own name.
   The design's own shape, and the answer to "show me" without losing the
   conversation: the thread keeps talking on the left while the REAL screen
   it is acting on stands on the right, filtered by what was said. The right
   pane is not a preview — it is the screen, which is why every route in the
   product can appear there without a bespoke layout.
   ========================================================================== */
/* 50/50, from `repeat(auto-fit, minmax(300px,1fr))` — the design builds the
   split out of the same grid it uses for any two-card row, which is why it
   collapses to a stack at narrow widths for free. */
.splitv {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: var(--s5);
  align-items: start;
  animation: aoRise .3s ease both;
  /* The thread's share. js/split.js writes a person's own choice over this as
     an inline variable; it is only READ in the wide rule below, so nothing
     inline can beat the narrow stack. */
  --split-l: 20%;
}
/* CARDS IN A ROW END TOGETHER. A grid stretches its cards to one height, but
   the body inside stops where its text does, so every button landed at a
   different height with blank beneath the shortest. A card that carries
   .card--pin is a column: its body grows, and the .pin-end row sits on the
   bottom edge. The rest of the body is wrapped in one block so paragraph
   margins still collapse the way they always did — a flex column would have
   doubled every p's 12px into 24. */
.card--pin { display: flex; flex-direction: column; }
.card--pin > .card-b { flex: 1; display: flex; flex-direction: column; }
.card--pin .pin-end { margin-top: auto; padding-top: var(--s4); }

/* THE GRAPH STAYS BESIDE ITS LIST. On the Brain the graph is 525px and the
   entity list 2,353px, and clicking an entity down the list lit a node that
   had scrolled away. It sits under the sticky tabs instead. */
@media (min-width: 861px) {
  .split--pin > :first-child { position: sticky; top: calc(var(--tabs-h) + var(--s3)); }
}

/* The divider is not there until there are two columns to divide. */
.splitv-h { display: none; }

/* 20 / 80, AND THE PERSON'S TO MOVE.
   The design's 50 / 50 stays the narrow behaviour above. From 761px the thread
   takes --split-l, never less than 260px (at 20% a 1280px laptop would give it
   about 235px, three words to a line) and never more than half. The divider IS
   the gutter — the same --s5 the gap was — so the panes have not moved apart. */
@media (min-width: 761px) {
  .splitv {
    grid-template-columns: clamp(260px, var(--split-l), 50%) var(--s5) minmax(0, 1fr);
    gap: 0;
    /* The thread is one window tall, less the top bar and a margin each side,
       so the composer is always on screen. */
    --thread-h: max(420px, calc(100dvh - var(--top-h) - 2 * var(--s4)));
  }
  /* THE THREAD STAYS IN VIEW. It was a fixed 640px box beside a live screen
     that runs to ~3,000px, so scrolling the screen left 2,000px of blank where
     the conversation had been. Sticky inside .stageview (the scroller), it
     stays beside whatever part of the screen is being read. */
  /* .splitv > .splitv-l, not .splitv-l: the base rule's fixed 640px sits
     later in this file and would win a tie. */
  .splitv > .splitv-l { position: sticky; top: var(--s4); height: var(--thread-h); }
  .splitv-h {
    display: flex; justify-content: center; align-self: stretch;
    cursor: col-resize; touch-action: none; outline: none;
  }
  /* The grip sits at the middle of the thread, which is a fixed 640px tall. */
  /* The grip follows the thread: the handle column runs the whole row, so the
     grip is sticky at the thread's middle rather than fixed at 298px. */
  .splitv-h span {
    position: sticky; top: calc(var(--s4) + var(--thread-h) / 2 - 22px);
    width: 4px; height: 44px; margin-top: calc(var(--thread-h) / 2 - 22px); border-radius: 4px;
    background: var(--n300); transition: background var(--d-micro) ease, height var(--d-micro) ease;
  }
  .splitv-h:hover span, .splitv.is-resizing .splitv-h span { background: var(--n600); }
  .splitv-h:focus-visible span { background: var(--ink); box-shadow: 0 0 0 3px var(--surface), 0 0 0 5px var(--ink); }
  /* While dragging nothing under the pointer should select, hover or scroll. */
  .splitv.is-resizing { cursor: col-resize; user-select: none; }
  .splitv.is-resizing .splitv-l, .splitv.is-resizing .splitv-r { pointer-events: none; }
}
.splitv-l, .splitv-r {
  background: var(--surface);
  border: 1px solid var(--divider);
  border-radius: var(--r-pane);
  box-shadow: var(--e2);
}
.splitv-l { display: flex; flex-direction: column; height: 640px; }
/* No fixed height on the right: it sizes to the screen inside it, which may be
   shorter or taller than the thread. `align-items:start` on the grid is what
   stops them dragging each other. */
.splitv-r { overflow: hidden; }

.splitv-lh {
  display: flex; align-items: center; gap: 9px;
  padding: 13px var(--s5); border-bottom: 1px solid var(--hairline);
}
.splitv-lh .label { font-size: var(--t-label); }
.splitv-acting { font-size: var(--t-label); color: var(--quiet); white-space: nowrap; }
.splitv-acting b { color: var(--ink); font-weight: 600; }
.splitv-lb { flex: 1; min-height: 0; overflow-y: auto; padding: var(--s5); display: flex; flex-direction: column; gap: var(--s4); scrollbar-width: thin; }
.splitv-lf { border-top: 1px solid var(--hairline); padding: var(--s3) var(--s4); }

.splitv-rh {
  padding: var(--s5) var(--s6);
  border-bottom: 1px solid var(--hairline);
  display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
}
.splitv-rh .grow { flex: 1; min-width: 180px; }
.splitv-rt { font-size: var(--t-2xl); font-weight: 700; letter-spacing: var(--tr-tight); }
.splitv-rt span { color: var(--faint); font-weight: 600; }
.splitv-rb { max-height: 720px; overflow-y: auto; }
/* The right pane holds a REAL screen, so the screen's own page padding and
   max-width have to be neutralised — it is a pane now, not a page. */
.splitv-rb .page { padding: var(--s4) 0 0; max-width: none; }
/* Two things the pane header has already said, so the screen must not say them
   again: its own page head, and its workspace-level summary tiles. The pane
   says "Waiting on you — 8 of 1,912"; repeating "1,912 in the book · ₹4.2Cr
   pipeline" above the eight rows is the exact overload this restyle exists to
   remove, and it pushes the answer below the fold. The rows are what was
   asked for, so the rows are what the pane opens on. */
.splitv-rb .page > .phead { display: none; }
.splitv-rb .page > .tiles { display: none; }
/* Leads opens with two more workspace-level blocks before its table: what the
   book holds back, and the filter bar. Both are the right first thing on the
   full page and the wrong first thing here — the thread asked "who is waiting
   on me", so the eight people are the answer and everything else is context
   that pushes the answer below the fold. The one-line "Showing only the rows…"
   note survives, so the filter is still explained, and the footer link opens
   the whole screen. Scoped by data-target so no other screen is trimmed. */
.splitv-rb[data-target="leads"] > .page > .mt5 { display: none; }

.splitv-full {
  display: inline-flex; align-items: center; gap: 5px; flex: none;
  font-weight: 600; color: var(--ink);
}
.splitv-full:hover { color: var(--accent); }
/* The borrowed screen arrives with the chrome it rendered inside — the loop
   card and the stage tabs. Those belong to the app, not to a pane, and the
   real ones are already on screen a few hundred pixels above this one. */
.splitv-rb > .loopwrap, .splitv-rb > .tabs { display: none; }
.splitv-rb .tablewrap, .splitv-rb .card { border-radius: 0; border-left: 0; border-right: 0; box-shadow: none; }
.splitv-rf {
  padding: 13px var(--s6); background: var(--surface-2);
  border-top: 1px solid var(--hairline);
  font-size: var(--t-xs); color: var(--muted);
  display: flex; gap: var(--s4); flex-wrap: wrap;
}
/* "Filtered by the thread" — the chip that says the right pane is not showing
   you everything, and why. Without it the split view is a lie. */
.bythread {
  display: flex; align-items: center; gap: 6px; flex: none;
  font-size: var(--t-xs); font-weight: 600;
  color: var(--accent); background: var(--accent-50);
  border-radius: var(--r-pill); padding: 5px 11px;
}

/* What the thread changed on the right, stated plainly. This block is the
   product's honesty: it always ends by naming what it did NOT do. */
.changed { background: var(--surface-2); border: 1px solid var(--hairline); border-radius: var(--r-chip); padding: 11px var(--s3); }
.changed .eyebrow { letter-spacing: .09em; margin-bottom: var(--s2); }
.changed-l { display: flex; flex-direction: column; gap: 6px; font-size: var(--t-sm); color: var(--ink); }
.changed-l i { font-style: normal; color: var(--muted); }

@media (max-width: 760px) { .splitv-l { height: 420px; } }

/* ==========================================================================
   D · DISCLOSURE — thin on the front, full on click
   One mechanism, used everywhere. The summary line always carries a mono
   count on the right so you know the size of what you are about to open.
   ========================================================================== */
.disc { background: var(--surface); border: 1px solid var(--divider); border-radius: var(--r-tile); padding: var(--s3) var(--s4); }
.disc--bare { border: 0; background: transparent; padding: 0; }
.disc--inset { background: var(--surface-2); }
.disc-b {
  display: flex; align-items: center; gap: var(--s2);
  width: 100%; border: 0; background: transparent; padding: 0;
  text-align: left; font-size: var(--t-sm); font-weight: 600; color: var(--muted);
  cursor: pointer;
}
.disc-b:hover { color: var(--ink); }
.disc-b > svg:first-child { flex: none; transition: transform var(--fast); }
.disc.is-open .disc-b > svg:first-child { transform: rotate(0deg); }
.disc:not(.is-open) .disc-b > svg:first-child { transform: rotate(-90deg); }
.disc-n { flex: none; font-family: var(--font-mono); font-size: var(--t-prov); color: var(--quiet); font-weight: 400; }
/* No margin, padding or border here: they sit outside the collapsed box and
   would hold it 25px tall when shut. They belong to the open state only. */
.disc-body { display: flex; flex-direction: column; gap: 9px; }
.disc.is-open .disc-body { margin-top: var(--s3); padding-top: var(--s3); border-top: 1px solid var(--hairline); }
.disc--bare.disc.is-open .disc-body { border-top: 0; padding-top: 0; }
/* a reasoning step inside a disclosure */
.disc-step { display: flex; gap: 10px; align-items: flex-start; }
.disc-step > .prov:first-child { padding-top: 2px; }
.disc-step-t { font-size: var(--t-base); color: var(--ink); line-height: var(--lh-snug); flex: 1; min-width: 0; }

/* ==========================================================================
   E · THE FRONT DOOR
   Chat is where the product starts. The assistant does not speak in a bubble —
   only the person does — because the assistant's turn carries DATA, and data
   in a speech bubble reads as a quote rather than as the screen it really is.
   ========================================================================== */
.thread { max-width: 860px; margin: 0 auto; display: flex; flex-direction: column; gap: var(--s6); animation: aoRise .3s ease both; }
.msg-you {
  align-self: flex-end; max-width: 70%;
  background: var(--ink); color: var(--on-dark);
  border-radius: var(--r-card) var(--r-card) 4px var(--r-card);
  padding: var(--s3) var(--s5);
  font-size: var(--t-lg); line-height: 1.55;
}
.splitv-lb .msg-you { max-width: 86%; border-radius: var(--r-tile) var(--r-tile) 4px var(--r-tile); padding: 10px 13px; font-size: var(--t-md); }
.msg-ai { display: flex; gap: var(--s3); }
.ai-mark {
  width: 30px; height: 30px; flex: 0 0 30px;
  border-radius: var(--r-item); background: var(--ink);
  display: grid; place-items: center;
}
.msg-ai-b { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--s3); }
.say { font-size: 14px; line-height: var(--lh-read); color: var(--ink); max-width: 64ch; }
.splitv-lb .say { font-size: var(--t-md); max-width: none; }
.splitv-lb .msg-ai { display: block; }          /* no avatar inside the pane */
.splitv-lb .ai-mark { display: none; }
.splitv-lb .msg-ai-b { gap: var(--s3); }

.suggest { display: flex; gap: var(--s2); flex-wrap: wrap; }
.suggest button {
  border: 1px solid var(--divider); background: var(--surface);
  border-radius: var(--r-pill); padding: 7px 13px;
  font-size: var(--t-sm); color: var(--ink); cursor: pointer;
  transition: border-color var(--fast);
}
.suggest button:hover { border-color: var(--ink); }

.composer {
  position: sticky; bottom: var(--s6);
  background: var(--surface); border: 1px solid var(--divider);
  border-radius: var(--r-pane); padding: var(--s4) var(--s5) 11px;
  box-shadow: var(--e-composer);
}
.composer-top { display: flex; align-items: flex-start; gap: 10px; }
.composer-top svg { color: var(--accent); margin-top: 2px; flex: none; }
.composer input {
  flex: 1; border: 0; outline: none; background: transparent;
  font-size: var(--t-lg); color: var(--ink); padding-top: 1px;
}
.composer input::placeholder { color: var(--quiet); }
.composer-bar { display: flex; align-items: center; gap: var(--s2); margin-top: var(--s3); flex-wrap: wrap; }
.composer-act { display: flex; align-items: center; gap: 6px; border: 0; background: transparent; color: var(--muted); font-size: var(--t-sm); padding: 4px 6px; border-radius: var(--s2); cursor: pointer; }
.composer-act:hover { background: var(--ground); }
.composer-note { font-size: var(--t-label); color: var(--quiet); }
.send-btn {
  width: 32px; height: 32px; flex: none;
  border-radius: var(--r-pill); border: 0;
  background: var(--ink); color: var(--on-dark);
  display: grid; place-items: center; cursor: pointer;
  transition: background var(--fast);
}
.send-btn:hover { background: var(--ink-2); }
.send-btn--sm { width: 28px; height: 28px; }
/* the composer inside the split's left pane is an inset bar, not a float */
.splitv-lf .composer-inset {
  display: flex; align-items: center; gap: 9px;
  background: var(--ground); border: 1px solid var(--hairline);
  border-radius: var(--r-chip); padding: 9px 11px;
}
.splitv-lf .composer-inset svg { color: var(--accent); flex: none; }
.splitv-lf .composer-inset input { flex: 1; min-width: 0; border: 0; outline: none; background: transparent; font-size: var(--t-md); text-overflow: ellipsis; }
/* At a fifth of the screen the prompt does not fit, and a sentence cut at
   "what to cl" reads as a bug. It ends in an ellipsis instead. */
.splitv-lf .composer-inset input::placeholder { text-overflow: ellipsis; }

/* The front-door tabs: thread / split / canvas */
.fronttabs {
  display: flex; align-items: center; gap: 4px; flex: none;
  background: var(--surface); border: 1px solid var(--divider);
  border-radius: var(--r-pill); padding: 4px; white-space: nowrap;
}
.fronttabs button {
  border: 0; border-radius: var(--r-pill); padding: 7px var(--s4);
  font-size: var(--t-sm); font-weight: 600;
  background: transparent; color: var(--muted); cursor: pointer;
  transition: background var(--fast), color var(--fast);
}
.fronttabs button:hover { color: var(--ink); }
/* The design fills the active tab with ink (#1C1B17 / #FBFBF9), not the hover
   tint — it is the one segmented control that reads as a chosen mode. */
.fronttabs button.is-on { background: var(--ink); color: var(--on-dark); }
.fronttabs button.is-on:hover { background: var(--ink-2); color: var(--on-dark); }

/* Only the top bar is chrome. The loop card and the tabs are page content and
   scroll away with it — the design's own behaviour, and worth ~90px on every
   screen. The tabs then pin themselves at the top of the scroller, so once the
   loop is gone you still know which face of the stage you are looking at. */
.tabs {
  position: sticky; top: 0; z-index: 12;
  background: var(--ground);
  padding-bottom: var(--s2);
}

/* ==========================================================================
   F · THE PAGE HEAD
   Two-tone headline: the fact in ink, the qualifier in --faint. Used on every
   screen, and it is what makes a heading read as a sentence rather than a
   label. Never accent-coloured — the accent is for data.
   ========================================================================== */
.phead { display: flex; align-items: flex-end; gap: var(--s5); flex-wrap: wrap; margin-bottom: var(--s6); }
.phead .grow { flex: 1; min-width: 260px; }
.ptitle {
  margin: 0; font-family: var(--font-display);
  font-size: var(--t-h1); line-height: var(--lh-tight);
  font-weight: 700; letter-spacing: var(--tr-h1); text-wrap: pretty;
}
.ptitle--lg { font-size: var(--t-h1-lg); }
.ptitle span, .ptitle .soft { color: var(--faint); font-weight: 600; }
.psub { margin: var(--s2) 0 0; font-size: var(--t-lg); color: var(--muted); line-height: var(--lh-body); max-width: 62ch; }
.phead-a { display: flex; align-items: center; gap: var(--s2); flex: none; }

/* ==========================================================================
   G · THE RUN, NARRATED
   The left pane talks; the right pane fills up. An artifact rises into place
   as its step finishes, which is the only motion in the product that is not
   answering a click — and it is earned, because it is showing work happening.
   ========================================================================== */
.narr { display: flex; flex-direction: column; gap: var(--s4); }
.narr-step { display: flex; gap: 10px; align-items: flex-start; animation: aoRise .3s ease both; }
.narr-dot {
  width: 7px; height: 7px; flex: none; margin-top: 7px;
  border-radius: var(--r-pill); background: var(--accent-100);
}
.narr-step.is-now .narr-dot { background: var(--ink); animation: aoPulse 2s ease-in-out infinite; }
.narr-step.is-next { opacity: .45; }
.narr-step.is-next .narr-dot { background: var(--hairline); }
.narr-b { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.narr-t { font-size: var(--t-md); line-height: var(--lh-read); color: var(--ink); }
.narr-step.is-next .narr-t { color: var(--muted); }
.narr-meta { display: flex; align-items: center; gap: var(--s2); }
/* On a real server a step's label is the way to open it on the right. */
.narr-go { background: none; border: 0; padding: 0; margin: 0; text-align: left; cursor: pointer; font-family: inherit; }
.narr-go:hover { text-decoration: underline; text-underline-offset: 3px; }
.narr-step.is-here .narr-go { font-weight: 700; }
/* A goal is a sentence, and the header it sits in is one line wide: it is cut
   with an ellipsis rather than running into the pane beside it. */
.splitv-lh .splitv-acting { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* A decision inside a live card, and the words a person types for it. */
.live-decide { border-top: 1px solid var(--hairline); padding-top: var(--s4); }
.live-waiting { border-top: 1px solid var(--held-bd); background: var(--held-bg); margin-inline: calc(-1 * var(--s5)); padding: var(--s4) var(--s5) var(--s3); }
.added-by-send { border-top: 1px dashed var(--hairline); padding-top: var(--s3); }
.say-form { display: grid; gap: var(--s3); width: min(460px, 100%); text-align: left; margin-top: var(--s4); }
.empty .say-form { margin-inline: auto; }

.artifacts { display: flex; flex-direction: column; gap: var(--s3); }
.artifact { animation: aoRise .34s ease both; }
.artifact-h { display: flex; align-items: center; gap: 9px; padding: 13px var(--s5); border-bottom: 1px solid var(--hairline); }
.artifact-b { padding: var(--s4) var(--s5); }
.artifact-wait {
  display: flex; align-items: center; gap: 10px;
  padding: var(--s4) var(--s5); background: var(--surface-2);
  border: 1px dashed var(--divider); border-radius: var(--r-card);
  font-size: var(--t-base); color: var(--muted);
}

/* ==========================================================================
   H · NARROW
   ========================================================================== */
/* The design carries no media queries at all — every breakpoint here is ours,
   and the app is desktop-first by brief. But sideways scroll is sloppy at any
   width, and twelve screens were doing it for four repeating structural
   reasons rather than twelve separate ones. These are those four. */
@media (max-width: 860px) {
  /* A card header is label + source + button in one nowrap row. At phone width
     that row is wider than the card, so it wraps instead. */
  .card-h { flex-wrap: wrap; row-gap: 6px; }
  .card-h .prov { white-space: normal; }
  /* A section label is text + a rule that eats the remaining width; the rule
     can collapse to nothing before the text has to shrink. */
  .slabel { flex-wrap: wrap; row-gap: 4px; }
  .slabel-rule { min-width: 0; }
  /* app.css's main+aside two-column keeps a fixed 360px rail that cannot fit
     beside anything at 430px. One column instead. */
  .split { grid-template-columns: minmax(0, 1fr); }
  /* Multi-column grids go to one column. Scoped to the declared column
     helpers rather than every .grid — a blanket rule collapsed the leads
     kanban and squeezed a card header down to 46px. */
  .grid.cols-2, .grid.cols-3, .grid.cols-4 { grid-template-columns: minmax(0, 1fr); }
  .stack > *, .row > * { min-width: 0; }
  /* The last few overflows are 8-14px of one unbroken token — an address, a
     domain, a credit id. Let long words break rather than push the page. */
  .page { overflow-wrap: anywhere; }
  .page .mono, .page .prov { overflow-wrap: anywhere; }
}

@media (max-width: 720px) {
  .crumbs span:first-child, .crumb-sep, .datechip { display: none; }
  .msg-you { max-width: 88%; }
  .page, .loopwrap, .topbar, .tabs { --pad-x: 14px; }
}

/* ==========================================================================
   BOOTING, AND FAILING TO BOOT
   The workspace arrives over the wire now, so both states are real screens
   rather than a spinner. Each says what it is doing in the founder's own
   terms — "Reading your workspace" tells you something; "Loading…" does not.
   ========================================================================== */
.boot {
  min-height: 100vh; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: var(--s2);
  padding: var(--s6); text-align: center; background: var(--ground);
}
.boot-mark {
  width: 46px; height: 46px; display: grid; place-items: center;
  border-radius: 14px; background: var(--ink); color: var(--on-dark);
  margin-bottom: var(--s3);
}
.boot-mark svg { animation: bootTurn 2.4s linear infinite; }
/* A failure is not a slower success, so it does not look like one: the mark
   goes amber, the card gets a ground, and nothing spins. */
.boot--failed .boot-t { color: var(--terra-900); }
.boot-mark--failed { background: var(--terra-100); color: var(--terra-800); }
.boot-mark--failed svg { animation: none; }
.boot-t { font-size: var(--t-xl); font-weight: 700; letter-spacing: var(--tr-tight); margin: 0; }
.boot-s { font-size: var(--t-md); color: var(--muted); margin: 0; max-width: 46ch; }

@keyframes bootTurn { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .boot-mark svg { animation: none; } }

/* Signing in: the boot panel, standing still, with a way in under it. */
.boot-mark--still svg { animation: none; }
.signin { gap: var(--s4); }
.signin .boot-mark, .signin .boot-t { margin-bottom: 0; }
.signin-why { color: var(--held-ink); background: var(--held-bg); border: 1px solid var(--held-bd); border-radius: var(--r-item); padding: var(--s3) var(--s4); text-align: left; }
.signin-invite { color: var(--ink-2); font-weight: 600; }
.signin-form { display: grid; gap: var(--s3); width: min(340px, 100%); text-align: left; }

/* ==========================================================================
   THE HERO, AND THE DISCIPLINE AROUND IT
   The reference this came from felt premium because of its product
   photography — one object shot with real care, everything else quiet. AutOn
   has no photography. Its objects are the figures, so this is where a figure
   is allowed to behave like one: on the paper, no border, and given room.

   The rule that makes it work is the restraint, not the size. One hero to a
   screen. If two things on a page are shouting, neither is.
   ========================================================================== */
.hero { display: flex; align-items: flex-end; gap: var(--s5); flex-wrap: wrap; padding: var(--s3) 0 var(--s6); }
.hero-fig {
  font-family: var(--font-mono); font-weight: 500; font-size: var(--t-hero);
  line-height: .92; letter-spacing: -.035em; font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.hero-of { font-size: var(--t-2xl); color: var(--quiet); font-weight: 500; margin-left: 2px; }
.hero-b { display: flex; flex-direction: column; gap: var(--s2); padding-bottom: 7px; min-width: 0; }
.hero-l { font-size: var(--t-lg); color: var(--ink); font-weight: 600; }
.hero-s { font-size: var(--t-base); color: var(--muted); max-width: 46ch; }

/* A BORDER MEANS "THIS IS A SEPARATE OBJECT".
   When every block has one the word stops meaning anything, which is what
   eleven identical cards on one screen had done. This is for content that is
   grouped but not separate — it gets the spacing of a card and none of the
   chrome. */
.card--bare {
  background: transparent; border: 0; box-shadow: none; border-radius: 0;
}
.card--bare > .card-h { padding-left: 0; padding-right: 0; border-bottom: 1px solid var(--hairline); }
.card--bare > .card-b { padding-left: 0; padding-right: 0; }

/* Secondary figures, side by side, separated by a hairline rather than boxed.
   Four bordered tiles read as four competing objects; this reads as one row of
   readings off one instrument, which is what they are. */
.figrow {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  border-top: 1px solid var(--hairline);
}
.figrow > * {
  padding: var(--s4) var(--s5) var(--s4) 0;
  border-right: 1px solid var(--hairline);
}
.figrow > *:last-child { border-right: 0; }
.fig-l { display: block; font-size: var(--t-xs); color: var(--muted); margin-bottom: var(--s2); }
.fig-v { font-family: var(--font-mono); font-weight: 500; font-size: var(--t-num); letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.fig-u { font-size: var(--t-sm); color: var(--quiet); margin-left: 5px; }
.fig-s { display: block; font-size: var(--t-xs); color: var(--muted); margin-top: var(--s2); }

@media (max-width: 720px) {
  .hero-fig { font-size: var(--t-num-xl); }
  .figrow > * { border-right: 0; border-bottom: 1px solid var(--hairline); }
}

/* When a hero figure carries the headline, the page title steps back to being
   what it actually is — the name of the thing, not an announcement. */
.ptitle--quiet {
  font-size: var(--t-2xl); font-weight: 600; color: var(--quiet);
  letter-spacing: -.015em;
}

/* ======================================================= THE STATES
   Loading, failed and denied, in the same window as the screen they stand
   in for. Three choices worth naming:

   The waiting state is a skeleton in the shape of rows, not a spinner. A
   spinner says "something is happening"; the outline says "a list is
   coming, about this wide" — and when the real rows land they replace it
   in place rather than pushing the page around.

   The failed state is amber, never red. Red is for a thing that went
   wrong and cannot be undone; amber, here and everywhere else in AutOn,
   means a person has to act. A read that failed is the second one: try
   again and it very likely works.

   Neither takes over the window. The dock, the top bar and the loop bar stay
   exactly where they are, because losing the whole product to a failed
   read of the lead book overstates how much is broken. */

.page-wait { padding: var(--s6) 0 var(--s9); }
.wait-l {
  font-size: var(--t-base);
  color: var(--quiet);
  margin-bottom: var(--s5);
}
.wait-rows { display: flex; flex-direction: column; }
.wait-row {
  display: flex;
  align-items: center;
  gap: var(--s4);
  padding: var(--s4) 0;
  border-bottom: 1px solid var(--hairline);
  /* Each row fades in a beat after the one above, so the list assembles
     downward the way a real list arrives rather than appearing at once. */
  opacity: 0;
  animation: waitIn .5s ease forwards;
}
.wait-row > :nth-child(2) { flex: 1; }

/* .skel is built for the inside of a card: its base is --n100 (#F5F5F1),
   which reads against --surface white and is INVISIBLE against --ground,
   because --ground is that same #F5F5F1. The class is not wrong — it is
   being asked to sit on a background it was never drawn for. On the paper
   it needs the divider tone to have a shape at all. */
.page-wait .skel {
  background: linear-gradient(90deg, var(--n300) 25%, var(--n400) 37%, var(--n300) 63%);
  background-size: 400% 100%;
}

@keyframes waitIn { to { opacity: 1; } }

/* The skeleton sweep and the stagger are both decoration on a wait. With
   reduced motion the outline still says what is coming, it just holds
   still while it says it. */
@media (prefers-reduced-motion: reduce) {
  .wait-row { animation: none; opacity: 1; }
  .page-wait .skel { animation: none; }
}

.empty--failed .empty-ico--failed,
.empty-ico--failed {
  background: var(--terra-50);
  color: var(--terra-700);
}
.empty--failed h3 { color: var(--ink); }
.empty--denied .empty-ico { background: var(--n100); color: var(--n500); }

/* ======================================== THE SPLIT PANES, RESPONSIVELY
   These two column widths used to be inline `style=` attributes on the
   markup. An inline style beats a stylesheet rule at ANY specificity,
   including inside a media query — so the `.split { grid-template-columns:
   minmax(0,1fr) }` written for narrow screens further up this file was
   dead the day it was written, and below ~420px the right pane (the draft,
   the checks, and the button that sends it) collapsed to zero width with
   no scroll to reach it.

   Declared here and only above the breakpoint, so the one-column rule is
   simply what applies below it. */
@media (min-width: 861px) {
  .split--queue { grid-template-columns: 400px minmax(0, 1fr); }
  .split--replies { grid-template-columns: 340px minmax(0, 1fr); }
}


/* ================================================== LEAD 360 · the record
   The relationship record for audience leads — investors, shareholders,
   journalists, analysts. Two columns that each flow top to bottom, not a
   grid of rows: a row stretches every card in it to the tallest one, so a
   short card became a box of empty space beside its neighbour. Here each
   card takes its own height, and a section with nothing to say is not
   rendered and the column closes up. */
.l360-crumb { font-size: var(--t-base); color: var(--muted); margin-bottom: var(--s3); }
.l360-crumb a { color: inherit; text-decoration: none; }
.l360-crumb a:hover { color: var(--ink); }
.l360-crumb b { color: var(--ink); font-weight: 600; }

.l360-hero {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--s6); align-items: center;
  background: var(--surface); border: 1px solid var(--divider); border-radius: var(--r-card);
  padding: var(--s5) var(--s6);
}
.l360-hero .avatar { box-shadow: 0 0 0 3px var(--surface); }
.l360-hero h1 { font-size: var(--t-3xl); line-height: 1.08; letter-spacing: -.015em; margin: 0; }
.l360-hero .l360-sub { font-size: var(--t-md); color: var(--muted); margin: var(--s1) 0 0; }
.l360-hero .l360-sub b { color: var(--ink); font-weight: 600; }
.l360-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--s3); }
.l360-side { display: flex; flex-direction: column; align-items: flex-end; gap: var(--s3); }
.l360-owner { display: flex; align-items: center; gap: var(--s2); font-size: var(--t-base); color: var(--quiet); }
.l360-owner b { color: var(--ink); font-weight: 600; }
.l360-owner select { height: 28px; font-size: var(--t-sm); }

.l360-cols { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: var(--s4); align-items: start; margin-top: var(--s4); }
.l360-col { display: flex; flex-direction: column; gap: var(--s4); min-width: 0; }

/* The read: a raised card, because it is the one sentence a person wants. */
.card.l360-read { border-color: var(--held-bd); box-shadow: var(--e2); }
.l360-read-t { font-size: var(--t-xl); font-weight: 500; line-height: 1.45; max-width: 62ch; margin: 0; }
.l360-wait { margin-top: var(--s4); padding: var(--s3) var(--s4); border-radius: var(--r-chip); background: var(--held-bg); color: var(--held-ink); font-size: var(--t-base); }
.l360-wait b { font-weight: 600; }
.l360-reasons { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s3); margin-top: var(--s4); }
.l360-reason { border-top: 1px solid var(--divider); padding-top: var(--s2); }
.l360-reason b { display: block; font-size: var(--t-base); font-weight: 600; }
.l360-reason p { margin: 2px 0 0; font-size: var(--t-sm); color: var(--muted); }
.l360-reason .tag { margin-top: var(--s2); }

/* Label/value rows. Empty values are dropped by the caller; this never dashes. */
.l360-kv { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s2) var(--s4); font-size: var(--t-base); margin: 0; }
.l360-kv dt { color: var(--quiet); white-space: nowrap; }
.l360-kv dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }

/* Five bars, filled to the rating. */
.rating { display: inline-flex; align-items: flex-end; gap: 2px; vertical-align: middle; }
.rating i { display: block; width: 5px; height: 12px; border-radius: 2px; background: var(--n300); }
.rating i.on { background: var(--held); }
.l360-hist { display: flex; align-items: flex-end; gap: 6px; height: 44px; margin-top: var(--s1); }
.l360-hist > div { display: flex; flex-direction: column; align-items: center; gap: 3px; width: 34px; }
.l360-hist i { display: block; width: 100%; border-radius: 3px 3px 0 0; background: var(--n300); }
.l360-hist i.mine { background: var(--held); }
.l360-hist span { font-family: var(--font-mono); font-size: 10px; color: var(--quiet); }

/* Career: every role on one time axis. At most eight year labels, on a
   1/2/5/10 step, so a long career does not print over itself. */
.l360-career { display: grid; grid-template-columns: 36% minmax(0, 1fr); column-gap: var(--s4); }
.l360-axis { position: relative; height: 18px; font-family: var(--font-mono); font-size: 10.5px; color: var(--quiet); }
.l360-axis span { position: absolute; top: 2px; transform: translateX(-50%); }
.l360-axis span.first { transform: none; }
.l360-role { min-width: 0; border-top: 1px solid var(--divider); padding: 7px 0; }
.l360-role b { display: block; font-size: var(--t-base); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.l360-role span { font-size: var(--t-sm); color: var(--quiet); }
.l360-track { position: relative; border-top: 1px solid var(--divider); background-image: linear-gradient(to right, var(--divider) 1px, transparent 1px); }
.l360-track i { position: absolute; top: 50%; height: 12px; transform: translateY(-50%); border-radius: 999px; background: var(--n400); }
.l360-track i.now { background: var(--held); }
.l360-track i.side { background: transparent; border: 1.5px dashed var(--accent); }
.l360-past { margin-top: var(--s3); padding: 9px var(--s3); border-radius: var(--r-chip); background: var(--accent-50); color: var(--accent); font-size: var(--t-base); }
.l360-past a { color: inherit; }

/* Company: facts hidden when empty, never dashed. */
.l360-facts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s3); margin-top: var(--s3); }
.l360-fact { border-top: 1px solid var(--divider); padding-top: 7px; }
.l360-fact .micro { display: block; }
.l360-fact b { display: block; margin-top: 2px; font-size: var(--t-md); font-weight: 600; font-variant-numeric: tabular-nums; }
.l360-growth { display: grid; grid-template-columns: 50px minmax(0, 1fr) 54px; align-items: center; gap: 6px var(--s3); font-size: var(--t-sm); margin-top: var(--s2); }
.l360-growth .bar { height: 10px; }
.l360-growth .neg > span { background: var(--terra-300); }
.l360-growth .num { text-align: right; font-family: var(--font-mono); font-size: var(--t-sm); }

/* Campaign: each email with its projected day. */
.l360-steps { list-style: none; margin: var(--s3) 0 0; padding: 0; }
.l360-step { display: grid; grid-template-columns: 18px minmax(0, 1fr) auto; align-items: center; gap: var(--s3); padding: 4px 0; font-size: var(--t-base); }
.l360-step i { display: block; width: 12px; height: 12px; border-radius: 50%; border: 2px solid var(--held); background: var(--surface); margin: 0 auto; }
.l360-step i.done { background: var(--held); }
.l360-step .l360-wait-row { display: block; width: 2px; height: 18px; background: var(--divider); margin: 0 auto; }
.l360-step--wait { color: var(--quiet); font-size: var(--t-sm); }
.l360-checks { display: grid; gap: 6px; margin-top: var(--s3); padding-top: var(--s3); border-top: 1px solid var(--divider); font-size: var(--t-sm); color: var(--muted); }
.l360-check { display: flex; gap: 6px; align-items: flex-start; }
.l360-check b { flex: none; font-weight: 700; }
.l360-check b.ok { color: var(--accent); }
.l360-check b.no { color: var(--held-ink); }
.l360-strip { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s4); }

/* Timeline, newest first. */
.l360-tl { list-style: none; margin: 0; padding: 0; }
.l360-tl li { display: grid; grid-template-columns: 78px minmax(0, 1fr); gap: var(--s3); padding: 7px 0; font-size: var(--t-base); border-top: 1px solid var(--divider); }
.l360-tl li:first-child { border-top: 0; }
.l360-tl .when { font-family: var(--font-mono); font-size: 11px; line-height: 1.6; color: var(--quiet); }
.l360-tl .sub { display: block; font-size: var(--t-sm); color: var(--quiet); }

.l360-sources { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s4); margin-top: var(--s4); padding: 10px var(--s4); border: 1px solid var(--divider); border-radius: var(--r-card); background: var(--surface-2); font-size: var(--t-sm); color: var(--muted); }

/* THE FACTS FILL THEIR LAST ROW. Anything from one to seven, three to a row:
   six tracks, two each, and a short last row widens to fill — one left over
   takes the row, two share it — while four are two pairs, not 3 + 1. Wide
   screens only; under 1100px the facts are one column and none of this runs. */
@media (min-width: 1101px) {
  .l360-facts { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .l360-facts > * { grid-column: span 2; }
  .l360-facts > :last-child:nth-child(3n+1) { grid-column: 1 / -1; }
  .l360-facts > :nth-last-child(2):nth-child(3n+1), .l360-facts > :last-child:nth-child(3n+2) { grid-column: span 3; }
  .l360-facts:has(> :nth-child(4):last-child) > * { grid-column: span 3; }
}

@media (max-width: 1100px) {
  .l360-cols { grid-template-columns: minmax(0, 1fr); }
  .l360-hero { grid-template-columns: auto minmax(0, 1fr); }
  .l360-side { grid-column: 1 / -1; align-items: flex-start; }
  .l360-reasons, .l360-facts { grid-template-columns: minmax(0, 1fr); }
}

/* ====================================================== PAGES · the screen
   Totals, findings, one heatmap over one picture, a scroll survival curve,
   the region table and the sessions. The heatmap frame is a placeholder the
   chrome in js/replay.js paints over: the replayed page is an iframe and an
   iframe moved in the DOM reloads, so it lives outside #app and is placed
   over this box. */
.pg-controls { margin-top: var(--s4); }
.pg-tiles { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--s3); }
/* Five tiles two to a row end 2 + 2 + 1; the fifth takes its row instead. */
@media (max-width: 1100px) {
  .pg-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pg-tiles > :last-child:nth-child(odd) { grid-column: 1 / -1; }
}

.pg-find { border: 1px solid var(--divider); border-left: 3px solid var(--n400); border-radius: var(--r-chip); background: var(--surface); padding: var(--s3) var(--s4); }
.pg-find--high { border-left-color: var(--held); }
.pg-find--medium { border-left-color: var(--terra-300); }

.hm-frame { position: relative; min-height: 280px; max-height: 760px; border: 1px solid var(--divider); border-radius: var(--r-chip); background: #fff; overflow: hidden; }
.hm-holding { position: absolute; left: var(--s4); top: var(--s3); margin: 0; }
.hm-legend { display: inline-flex; align-items: center; gap: 6px; }
.hm-legend i { display: inline-block; width: 22px; height: 9px; border-radius: 2px; }
.hm-legend i:first-of-type { border-radius: 4px 2px 2px 4px; }
.hm-legend i:last-of-type { border-radius: 2px 4px 4px 2px; }
/* Sequential amber, five steps, one hue, monotonic lightness. Not a rainbow:
   a rainbow implies categories, and these cells differ only in magnitude.
   Green is reserved for "it is working" everywhere else in the product and
   would read as a different KIND of thing here. */
.hm-c1 { background: var(--terra-200); }
.hm-c2 { background: var(--terra-300); }
.hm-c3 { background: var(--terra); }
.hm-c4 { background: var(--terra-700); }
.hm-c5 { background: var(--terra-900); }

/* The portal the chrome paints: fixed over the frame, scrolls on its own. */
.hm-portal { position: fixed; overflow-y: auto; overflow-x: hidden; z-index: 5; background: #fff; }
.hm-inner { position: relative; }
.hm-stage { position: absolute; left: 0; top: 0; overflow: hidden; pointer-events: none; }
.hm-stage .replayer-wrapper { left: 0 !important; top: 0 !important; margin: 0 !important; transform-origin: top left; pointer-events: none; }
.hm-stage iframe { border: 0; pointer-events: none; }
.hm-layer { position: absolute; left: 0; top: 0; pointer-events: none; }
.hm-layer--cursor { filter: blur(7px); }
.hm-cell { position: absolute; border-radius: 3px; opacity: .55; mix-blend-mode: multiply; }
.hm-layer--cursor .hm-cell { opacity: .42; }
.hm-band { position: absolute; left: 0; width: 100%; opacity: .5; mix-blend-mode: multiply; }
.hm-band span { position: absolute; left: 6px; top: 4px; padding: 1px 6px; border-radius: 3px; background: rgb(255 255 255 / .85); font-family: var(--font-mono); font-size: 10px; font-weight: 600; color: var(--ink); mix-blend-mode: normal; }
.hm-portal .empty { padding: var(--s6); }

.sd-strip { display: flex; align-items: flex-end; gap: 3px; height: 96px; }
.sd-col { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 4px; }
.sd-pct, .sd-d { font-family: var(--font-mono); font-size: 9.5px; color: var(--quiet); font-variant-numeric: tabular-nums; }
.sd-bar { display: block; width: 100%; border-radius: 3px 3px 0 0; background: var(--terra-300); }
.sd-bar--cliff { background: var(--terra-900); }

/* The replay player, owned by the chrome. */
.rp-scrim { position: fixed; inset: 0; background: rgb(28 27 23 / .55); z-index: 82; }
.rp-panel { position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); width: min(1160px, calc(100vw - 48px)); max-height: calc(100vh - 48px); overflow: auto; background: var(--surface); border-radius: var(--r-app); box-shadow: var(--e3); z-index: 83; padding: var(--s5); }
.rp-head { display: flex; align-items: flex-start; gap: var(--s3); margin-bottom: var(--s3); }
.rp-head .grow { min-width: 0; }
.rp-state { margin: 0 0 var(--s3); }
.rp-host { min-height: 120px; }
.rp-host .rr-player { margin: 0 auto; }

.modal--wide { width: min(1160px, calc(100vw - var(--s6))); }
