/* Site-wide layout container.
 *
 * A separate stylesheet rather than a Tailwind utility: static/base.css
 * is a frozen compiled bundle (see base.html), so a class it
 * never emitted renders as nothing at all.
 *
 * One width for the whole site. The tool at /ratio/ runs to 1600px, and while
 * the marketing pages stayed at Tailwind's max-w-7xl (1280px) the site read as
 * two different products bolted together — on a 1512px display the front page
 * sat in a narrow column with 232px of dead margin at each edge.
 *
 * The padding steps match Tailwind's px-4 / sm:px-6 / lg:px-8 so replacing those
 * utilities with this class changes the maximum width and nothing else.
 */
.ls-container {
  max-width: 1600px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 1rem;
  padding-right: 1rem;
}

@media (min-width: 640px) {
  .ls-container { padding-left: 1.5rem; padding-right: 1.5rem; }
}

@media (min-width: 1024px) {
  .ls-container { padding-left: 2rem; padding-right: 2rem; }
}

/* ---------- header ------------------------------------------------------ */

/* Brand and nav as one left-hand group.
 *
 * With the nav as a middle child of a justify-between row, its position depended
 * on whether the page happened to carry a Subscribe button — centred on the
 * marketing pages, hard right on the tool, which read as two different headers.
 * Grouped, the nav starts at the same x on every page and the actions stay right.
 */
.ls-brandnav {
  display: flex;
  align-items: center;
  gap: 2rem;
  min-width: 0;
}

@media (max-width: 767px) {
  .ls-brandnav { gap: 0; }
}

/* ---------- the two products -------------------------------------------- */

/* One column until there is room for two honest ones. Not a Tailwind grid: the
 * compiled sheet is frozen and never emitted lg:grid-cols-2, so that class would
 * have rendered as nothing and stacked the cards on every screen.
 */
.ls-products {
  display: grid;
  gap: 1.5rem;
  margin-top: 3.5rem;
  align-items: stretch;
}

/* Two live products side by side, the one that has not opened spanning beneath
   them.
 *
 * Three equal columns looked tidy and did not work: at 1200px each card was
 * 357px, which left the search field 187px of usable width — too narrow for the
 * placeholder to finish a sentence, let alone for a real query to be readable
 * while typing. A card containing a working input needs width the way a card
 * containing a paragraph does not, so the two that take input get the row.
 */
@media (min-width: 1000px) {
  .ls-products { grid-template-columns: 1fr 1fr; gap: 2rem; }
  .ls-product--soon { grid-column: 1 / -1; }
}

/* Equal weight, deliberately. One card styled as primary would answer a question
 * the visitor has not been asked yet — which product they came for.
 */
.ls-product {
  display: flex;
  flex-direction: column;
  padding: 2rem;
  background: var(--color-white, #fff);
  border: 1px solid var(--color-surface-300, #e3dfd9);
  border-radius: 14px;
  box-shadow: 0 1px 2px rgb(31 29 26 / 0.05);
}

@media (min-width: 900px) { .ls-product { padding: 2.5rem; } }

.ls-product-kicker {
  margin: 0;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--color-brand-600, #486581);
}

.ls-product-name {
  margin: 0.625rem 0 0;
  font-family: var(--font-serif, Georgia, serif);
  font-size: 1.875rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--color-surface-900, #1f1d1a);
}

.ls-product-lede {
  margin: 0.875rem 0 0;
  font-size: 1rem;
  line-height: 1.65;
  color: var(--color-surface-600, #7d7870);
  /* Held near a readable measure; the card is wider than the prose wants. */
  max-width: 34rem;
}

/* Pushed to the bottom so both cards' actions line up however long the copy is. */
.ls-product-form {
  display: flex;
  gap: 0.625rem;
  margin-top: auto;
  padding-top: 1.75rem;
  flex-wrap: wrap;
}

.ls-field {
  flex: 1 1 12rem;
  min-width: 0;
  padding: 0.75rem 1rem;
  font: inherit;
  font-size: 0.9375rem;
  color: var(--color-surface-800, #3d3a35);
  background: var(--color-white, #fff);
  border: 1px solid var(--color-surface-300, #e3dfd9);
  border-radius: 10px;
}

.ls-field::placeholder { color: var(--color-surface-500, #a39e96); }

.ls-field:focus {
  outline: none;
  border-color: var(--color-brand-600, #486581);
  box-shadow: 0 0 0 3px rgb(72 101 129 / 0.15);
}

.ls-btn {
  flex: 0 0 auto;
  padding: 0.75rem 1.375rem;
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--color-white, #fff);
  background: var(--color-brand-900, #1b2a4a);
  border: 0;
  border-radius: 10px;
  cursor: pointer;
  transition: background 0.15s;
}

/* Square, and the same height as the text button beside it in the next card,
   so the two forms still read as a pair. */
.ls-btn--icon {
  padding: 0;
  width: 2.875rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.ls-btn--icon svg { width: 1.125rem; height: 1.125rem; }

.ls-btn:hover { background: var(--color-brand-800, #243b53); }
.ls-btn:focus-visible { outline: 2px solid var(--color-brand-900, #1b2a4a); outline-offset: 2px; }

.ls-product-foot {
  margin: 0.875rem 0 0;
  font-size: 0.8125rem;
  color: var(--color-surface-500, #a39e96);
}

.ls-product-foot a {
  color: var(--color-brand-700, #334e68);
  font-weight: 500;
}

/* The product that has not opened. Quieter ground and no action, so it reads as
   an announcement beside two working things rather than a third door that
   sticks when pushed. */
.ls-product--soon {
  background: var(--color-surface-100, #faf7f2);
  border-style: dashed;
  box-shadow: none;
}

.ls-product--soon .ls-product-kicker { color: var(--color-surface-500, #a39e96); }
.ls-product--soon .ls-product-foot { margin-top: auto; padding-top: 1.25rem; }

/* Spanning the row, it is short and wide rather than tall and thin: the copy
   sits beside the link instead of leaving a column of empty card beneath it. */
@media (min-width: 1000px) {
  /* Three columns, and every child is placed in one explicitly. Setting only
     grid-row on each put all four in the same cell, so the name printed on top
     of the description. */
  .ls-product--soon {
    display: grid;
    grid-template-columns: minmax(0, auto) minmax(0, 1fr) auto;
    column-gap: 2.5rem;
    row-gap: 0.25rem;
    padding-top: 1.75rem;
    padding-bottom: 1.75rem;
  }
  .ls-product--soon .ls-product-kicker { grid-column: 1; grid-row: 1; }
  .ls-product--soon .ls-product-name {
    grid-column: 1; grid-row: 2;
    margin: 0; font-size: 1.5rem; white-space: nowrap;
  }
  .ls-product--soon .ls-product-lede {
    grid-column: 2; grid-row: 1 / 3;
    align-self: center; margin: 0; max-width: none; font-size: 0.9375rem;
  }
  .ls-product--soon .ls-product-foot {
    grid-column: 3; grid-row: 1 / 3;
    align-self: center; margin: 0; padding: 0; white-space: nowrap;
  }
}

/* ---------- the coming-soon page ---------------------------------------- */

.ls-soon {
  margin-top: 2.5rem;
  padding: 1.75rem;
  background: var(--color-surface-100, #faf7f2);
  border: 1px solid var(--color-surface-300, #e3dfd9);
  border-radius: 14px;
}

.ls-soon-label {
  margin: 0 0 0.875rem;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--color-brand-600, #486581);
}

.ls-soon-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--color-surface-700, #5c5850);
}

.ls-soon-list li { padding-left: 1.25rem; position: relative; }

.ls-soon-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--color-brand-600, #486581);
}

.ls-soon-links {
  margin-top: 1.5rem;
  display: grid;
  gap: 1rem;
}

@media (min-width: 640px) { .ls-soon-links { grid-template-columns: 1fr 1fr; } }

.ls-soon-links a {
  display: block;
  padding: 1.25rem;
  background: var(--color-white, #fff);
  border: 1px solid var(--color-surface-300, #e3dfd9);
  border-radius: 12px;
  text-decoration: none;
  transition: border-color 0.15s;
}

.ls-soon-links a:hover { border-color: var(--color-brand-600, #486581); }

.ls-soon-links b {
  display: block;
  font-family: var(--font-serif, Georgia, serif);
  font-size: 1.125rem;
  color: var(--color-surface-900, #1f1d1a);
}

.ls-soon-links span {
  display: block;
  margin-top: 0.375rem;
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--color-surface-600, #7d7870);
}

/* The hero headline.
 *
 * "For Indian lawyers who argue for a living" ran to about 960px of type in a
 * 672px column, so it always broke, and it broke badly — "a living" orphaned on
 * its own line. Shorter copy is the fix; balance is the guard, so that at any
 * width where it does wrap the lines come out even rather than leaving one word
 * stranded.
 */
.ls-hero {
  text-wrap: balance;
  max-width: 20ch;
  margin-left: auto;
  margin-right: auto;
}

/* ---------- account ------------------------------------------------------ */

/* Sits where a header action belongs, quiet enough that it is not competing
   with the nav. It answers a question the reader asks once — am I signed in,
   and how much is left — and should not keep asking for attention after that.
 */
.ls-account {
  display: inline-flex;
  align-items: baseline;
  gap: 0.5rem;
  font-size: 0.8125rem;
  color: var(--color-surface-500, #a39e96);
  max-width: 16rem;
  white-space: nowrap;
}

.ls-account a,
.ls-account-in {
  color: var(--color-brand-700, #334e68);
  font-weight: 500;
  text-decoration: none;
}

.ls-account a:hover,
.ls-account-in:hover { color: var(--color-brand-900, #1b2a4a); }

.ls-account-in { font-size: 0.875rem; }

/* The count used to live here and be hidden on phones because the header is
   already logo and hamburger. It now sits on Ratio's search bar instead, so
   there is nothing left to hide -- and it is visible on a phone again, which
   is where knowing the balance before spending one matters most. */

/* ---------- ILB hero form ------------------------------------------------ */

.ls-hero-form {
  display: flex;
  gap: 0.625rem;
  margin-top: 2rem;
  flex-wrap: wrap;
  max-width: 30rem;
}

.ls-hero-note {
  margin: 0.875rem 0 0;
  font-size: 0.8125rem;
  color: var(--color-surface-500, #a39e96);
}

/* ---------- beta ---------------------------------------------------------- */

/* Says the product is early without shouting it. Set beside the name rather
   than in the copy, because someone deciding whether to rely on this should
   see it in the same glance as the name — not two paragraphs later.
 */
.ls-beta {
  display: inline-block;
  vertical-align: 0.28em;
  margin-left: 0.4375rem;
  padding: 0.0625rem 0.4375rem;
  border-radius: 999px;
  background: var(--color-brand-100, #d9e2ec);
  color: var(--color-brand-800, #243b53);
  font-family: var(--font-sans, system-ui, sans-serif);
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1.6;
}

.ls-beta--lg { vertical-align: 0.5em; font-size: 0.6875rem; }

/* ---------- social ------------------------------------------------------- */

/* Wellknown is the agent-to-agent discovery network — where a service is found
   by an AI, not a person. The footer links our listing there the way it would
   a LinkedIn or an X profile: an identity link, sat with the rest of the
   footer's identity. Colour comes from the footer's own utility classes so it
   matches the legal links exactly; this only handles the icon + label layout. */
.ls-social {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  transition: color 0.15s;
}
.ls-social svg { width: 0.9375rem; height: 0.9375rem; flex: none; }

/* ---------- the case record, signed out and signed in --------------------- */

/* One case, two pages: the teaser a search engine and a shared link land on,
   and the full record behind sign-in. They were styled separately and drifted
   — the citation was a grey chip on one and muted text on the other, the
   cited-by count was a sentence on one and absent from the rail on the other.
   Defined once here so they cannot drift again, and matched to the result
   rail in icnc/tool.css (.icnc-neutral / .icnc-scr / .icnc-auth) so a case
   looks the same in the results as it does on its own page. The literal
   colours are tool.css's own values; neither of these pages loads that sheet. */

/* The identifiers get their own line under the title, each under a label
   saying what it is. The labels are the point, not decoration: a judgment
   has TWO citations and most readers do not know why. The neutral citation
   is assigned by the court itself and the S.C.R. one by the reporter, and
   naming them teaches that distinction without a paragraph explaining it.
   Neutral citations are recent in India, so this is genuinely new to people
   arriving from a web search. */
.case-meta {
  display: flex; flex-wrap: wrap; align-items: flex-start;
  gap: 0.5rem 1.6rem; margin: 0 0 0.7rem;
}
.case-field { display: flex; flex-direction: column; gap: 0.1rem; }
.case-field-label {
  font-size: 0.625rem; letter-spacing: 0.09em; text-transform: uppercase;
  color: #a39e96; white-space: nowrap;
}
/* Marked as explicable, because "neutral citation" is the term a reader is
   most likely not to know. Dotted rather than solid so it reads as a
   definition, not a link. */
.case-field-label abbr {
  text-decoration: none; border-bottom: 1px dotted #c9bfae; cursor: help;
}

/* The neutral citation — the court's own identifier, so it reads darkest, and
   the string most often wanted from this page: it goes into a filing. So it
   carries a copy affordance you can SEE. Styled as text until hovered was too
   quiet — nothing said it could be clicked, and a control nobody knows is a
   control is not a feature. The glyph sits at low contrast and comes up on
   hover: present enough to invite, quiet enough not to compete with the
   actions below. */
.case-cite {
  display: inline-flex; align-items: center; gap: 0.3rem;
  font-family: inherit; font-size: 0.6875rem; font-weight: 600;
  color: #3d3a35; font-variant-numeric: tabular-nums; letter-spacing: 0.02em;
  white-space: nowrap; background: none; border: 1px solid transparent;
  border-radius: 999px; padding: 0.125rem 0.4rem; margin-left: -0.4rem;
}
.case-cite svg { width: 0.72rem; height: 0.72rem; flex: none; opacity: 0.4; }
/* "How to cite", for a judgment the Court gave no neutral citation. This one
   is a sentence rather than an identifier — parties, court, diary number and
   date — so it takes its own row and wraps. Without this it inherits the
   nowrap above and pushes the meta row past the column. */
.case-field--cite { flex-basis: 100%; }
.case-field--cite .case-cite {
  white-space: normal; text-align: left; align-items: flex-start;
  font-weight: 500; line-height: 1.45;
}
.case-field--cite .case-cite svg { margin-top: 0.2rem; }
button.case-cite { cursor: pointer; }
button.case-cite:hover { background: #fffbf5; border-color: #e3dfd9; }
button.case-cite:hover svg { opacity: 0.85; }
button.case-cite:focus-visible { outline: 2px solid #1b2a4a; outline-offset: 1px; }
button.case-cite.is-copied {
  color: #2f5d3a; background: #e8efe9; border-color: transparent;
}
button.case-cite.is-copied svg { opacity: 1; }

/* The reporter's citation, quieter: the neutral one leads. */
.case-scr {
  font-size: 0.75rem; color: #7d7870;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* Bench and date, as labelled fields rather than a bare line. "K. Vinod
   Chandran and J.B. Pardiwala JJ." with nothing above it told a reader
   nothing about what they were looking at -- a row of names is only obviously
   a bench to somebody who already knew. Wraps, unlike the citation beside it:
   a five-judge bench does not fit one line and must not force the row wide. */
.case-bench {
  font-size: 0.75rem; color: #7d7870; line-height: 1.5;
}

/* Authority — the one number on the row worth a glance, so the figure is
   emphasised and the noun beside it stays quiet.

   Deliberately NOT a filled navy pill. Solid #1b2a4a is this site's
   call-to-action fill — "Share this case" wears it — so a static count in the
   same colour, at the same pill radius, read as a button and invited a press
   that does nothing. Navy as TEXT is the colour every heading on the page
   already uses, so the figure keeps its weight without claiming to be a
   control. Matches .case-bench above it: the two values on this row are the
   same kind of thing and should look it. */
.case-auth {
  font-size: 0.75rem; color: #7d7870; line-height: 1.5; white-space: nowrap;
}
.case-auth b {
  font-weight: 600; color: #1b2a4a; font-variant-numeric: tabular-nums;
}

/* Status — good law, doubted, limited — reads the same on both pages. */
.case-flag {
  display: inline-block; font-size: 0.75rem; border-radius: 999px;
  padding: 0.15rem 0.6rem; background: #f7efd9; color: #8a6d1a;
}
.case-flag--doubted { color: #8c2f21; background: #f7e8e5; }
.case-flag--limited { color: #6a5a1e; background: #f5efdd; }

/* Breadcrumb bar under the header — gives the Ratio sub-products (Space Law,
   a case reader) a visible "you are here" trail back up. Lives here, not in a
   base.html <style> block: an inline block there is counted by tests that grep
   the served HTML and shifts the "first <style>" other pages rely on. */
.ls-crumbs { border-bottom: 1px solid rgba(0,0,0,.06); background: rgba(255,255,255,.4); }
.ls-crumbs ol { display: flex; flex-wrap: wrap; align-items: center;
  list-style: none; margin: 0; padding: 0.55rem 0; font-size: 0.82rem; }
.ls-crumbs li { display: inline-flex; align-items: center; }
.ls-crumbs a { color: #0e6e63; text-decoration: none; font-weight: 500; padding: 0.1rem; }
.ls-crumbs a:hover { text-decoration: underline; }
.ls-crumbs .sep { color: #b7b0a4; margin: 0 0.5rem; user-select: none; }
.ls-crumbs [aria-current] { color: #55504a; font-weight: 600; }
@media print { .ls-crumbs { display: none; } }

/* Chat — a two-pane research view: the conversation on the left, the source
   it is citing on the right. The utilities this needs (min-h-0 for a flex
   child that must scroll, whitespace-pre-wrap, resize-none) are not in the
   frozen base.css, and there is no build step to add them, so the layout
   lives here rather than as classes that would silently do nothing. */
/* ---- Chat ------------------------------------------------------------
   Painted from the site's own tokens rather than hand-picked greys: navy
   brand on warm cream, with the teal kept for one job only -- marking what
   came from the record (citations, ratio, sources). Declared once here so a
   colour cannot drift between the two panes. */
.ls-chat {
  --ink: #1b2a4a;          /* brand-900 */
  --ink-2: #243b53;        /* brand-800 */
  --ink-3: #486581;        /* brand-600 */
  --mute: #7d7870;         /* surface-600 */
  --faint: #a39e96;        /* surface-500 */
  --line: #e3dfd9;         /* surface-300 */
  --panel: #fffbf5;        /* surface-50  */
  --panel-2: #faf7f2;      /* surface-100 */
  --wash: #f0ede8;         /* surface-200 */
  --record: #0e6e63;       /* the site's accent: evidence, not chrome */
  --warn: #9a6b1f;
  --bad: #8a2020;
  --bad-wash: #fdeaea;
  display: grid; gap: 1rem; align-items: stretch;
  /* One height for every column, so the three read as one instrument rather
     than three boxes that happen to be adjacent. Fills the viewport instead
     of a fixed 72vh, which was cramped on a short laptop and left a band of
     dead cream on a tall monitor. */
  --pane-h: clamp(24rem, calc(100vh - 15rem), 52rem);
  /* Set here rather than left to a utility class on the wrapper: the gap
     measured zero, so the panes started flush against the sentence
     describing them and the page had no breath in it. */
  margin-top: 1.6rem;
}

/* Three zones, and they are deliberately NOT equal. The conversation is the
   product; the record supports it; the list of conversations is furniture.
   Equal halves gave the sources pane the same billing as the answer and left
   the prose far wider than anyone can comfortably read. */
@media (min-width: 1200px) {
    /* Both side columns scale with the window and stop at sensible bounds; the
     conversation takes what is left. Fixed rem for all three squeezed the
     middle badly between 1200 and 1400, where the two fixed columns ate most
     of a narrow container. The middle can afford to give: its text is held at
     38rem however wide the pane is, so width past that is margin. */
  .ls-chat { grid-template-columns:
      clamp(15rem, 18vw, 18rem) minmax(0, 1fr) clamp(20rem, 25vw, 30rem); }
}
/* No room for the rail as a column: it becomes a band above, still the same
   markup, laid out sideways. */
@media (min-width: 820px) and (max-width: 1199px) {
  .ls-chat { grid-template-columns: minmax(0, 1fr) clamp(20rem, 30vw, 24rem); }
  .ls-rail { grid-column: 1 / -1; }
}
@media (max-width: 819px) {
  /* Stacked, so the two panes cannot both be full height or the record sits a
     screen and a half below the answer that cites it. The conversation keeps
     the room; the record gets enough to show a card and scroll. */
  .ls-chat-pane--talk { height: clamp(26rem, 68vh, 40rem); }
  .ls-chat-pane--src { height: 22rem; }
}

/* ---- folding the record away ------------------------------------------
   The reader's choice, remembered. Collapsed it keeps a strip carrying its
   name and the number of authorities in the current answer -- folded away it
   is the only sign there is anything to come back to. */
@media (min-width: 1200px) {
  .ls-chat.is-src-collapsed { grid-template-columns: clamp(15rem, 18vw, 18rem) minmax(0, 1fr) 2.6rem; }
}
@media (min-width: 820px) and (max-width: 1199px) {
  .ls-chat.is-src-collapsed { grid-template-columns: minmax(0, 1fr) 2.6rem; }
}
.ls-chat.is-src-collapsed .ls-art { display: none; }
@media (min-width: 820px) {
  .ls-chat.is-src-collapsed .ls-chat-head--src {
    flex-direction: column; height: 100%; border-bottom: 0;
    padding: 0.6rem 0.25rem; gap: 0.5rem; }
  .ls-chat.is-src-collapsed .ls-src-title { writing-mode: vertical-rl; }
  .ls-chat.is-src-collapsed .ls-src-count { margin: 0; }
  .ls-chat.is-src-collapsed .ls-src-toggle { margin: auto 0 0; padding: 0.2rem; }
}
/* Stacked, there is no column to narrow -- it becomes a bar you can open. */
@media (max-width: 819px) {
  .ls-chat.is-src-collapsed .ls-chat-pane--src { height: auto; }
}

.ls-chat-head--src { display: flex; align-items: center; gap: 0.45rem; }
.ls-src-title { flex: none; }
.ls-src-count { font-size: 0.62rem; font-weight: 600; letter-spacing: 0;
  color: var(--record); background: rgba(14,110,99,.09);
  border-radius: 999px; padding: 0 0.32rem; opacity: 0; }
.ls-src-count.is-on { opacity: 1; }
.ls-src-toggle { margin-left: auto; font: inherit; font-size: 0.66rem;
  text-transform: none; letter-spacing: 0; cursor: pointer; color: var(--mute);
  background: none; border: 0; padding: 0.1rem 0.2rem;
  text-decoration: underline; text-decoration-color: transparent; }
.ls-src-toggle:hover { color: var(--ink-2); text-decoration-color: currentColor; }

.ls-chat-pane { display: flex; flex-direction: column; min-height: 0;
  height: var(--pane-h); background: var(--panel);
  border: 1px solid var(--line); border-radius: 0.8rem; overflow: hidden; }
.ls-chat-head { padding: 0.6rem 0.9rem; border-bottom: 1px solid var(--line);
  background: var(--panel-2); font-size: 0.72rem; font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase; color: var(--mute); }

/* The state line: beacon, what is happening, how long it has been happening.
   Top-left of the conversation, where the eye already is. */
.ls-chat-head--state { display: flex; align-items: center; gap: .45rem; }
.ls-state { color: var(--ink-2); letter-spacing: .04em; text-transform: none;
  font-size: .78rem; }
.ls-state-t { margin-left: auto; color: var(--faint); font-size: .72rem;
  font-variant-numeric: tabular-nums; text-transform: none; letter-spacing: 0; }

/* One dot, six meanings. Colour carries the state and the halo carries
   "still going", so it reads at a glance without being read. */
.ls-beacon { width: .55rem; height: .55rem; border-radius: 50%; flex: none;
  background: var(--faint); box-shadow: 0 0 0 0 transparent; }
.ls-beacon[data-state="starting"] { background: var(--warn); animation: ls-pulse 1.5s ease-out infinite; }
.ls-beacon[data-state="connected"] { background: var(--record); }
.ls-beacon[data-state="thinking"]  { background: var(--ink-3); animation: ls-pulse 1.5s ease-out infinite; }
.ls-beacon[data-state="tool"]      { background: var(--record); animation: ls-pulse 1.1s ease-out infinite; }
.ls-beacon[data-state="writing"]   { background: var(--ink); animation: ls-pulse 1.8s ease-out infinite; }
.ls-beacon[data-state="offline"]   { background: var(--faint); }
.ls-beacon[data-state="error"]     { background: var(--bad); }
@keyframes ls-pulse {
  0%   { box-shadow: 0 0 0 0 currentColor; }
  70%  { box-shadow: 0 0 0 .42rem transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}
.ls-beacon[data-state="starting"] { color: rgba(154,107,31,.45); }
.ls-beacon[data-state="thinking"] { color: rgba(72,101,129,.45); }
.ls-beacon[data-state="tool"]     { color: rgba(14,110,99,.45); }
.ls-beacon[data-state="writing"]  { color: rgba(27,42,74,.35); }

/* ---- the rail: which conversation you are in ---------------------------
   One list, two shapes. As a column where there is room it scales to any
   number of conversations, and folders become real headings; as a band on a
   narrower screen it falls back to a scrolling strip. Same DOM either way. */
.ls-rail { display: flex; flex-direction: column; min-height: 0;
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 0.8rem; overflow: hidden; }
.ls-rail-top { display: flex; gap: 0.4rem; align-items: center; flex: none;
  padding: 0.6rem; border-bottom: 1px solid var(--line); }
.ls-rail-new { flex: 1 1 auto; font: inherit; font-size: 0.78rem; font-weight: 600;
  cursor: pointer; color: #fff; background: var(--ink); border: 0;
  border-radius: 0.45rem; padding: 0.34rem 0.6rem; }
.ls-rail-new:hover { background: var(--ink-2); }
.ls-rail-foot { flex: none; display: flex; align-items: center; gap: 0.4rem;
  padding: 0.5rem 0.6rem; border-top: 1px solid var(--line); }

/* Quiet on purpose. A destructive control with the same weight as a folder
   picker is one somebody eventually hits by accident. */
.ls-linkbtn { font: inherit; font-size: 0.7rem; cursor: pointer; background: none;
  border: 0; padding: 0.1rem 0.2rem; color: var(--mute); text-decoration: underline;
  text-decoration-color: transparent; margin-left: auto; }
.ls-linkbtn:hover { text-decoration-color: currentColor; }
.ls-linkbtn--danger:hover { color: var(--bad); }
.ls-linkbtn--danger.is-armed { color: var(--bad); font-weight: 600;
  text-decoration-color: currentColor; }

.ls-tabs { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden;
  display: flex; flex-direction: column; gap: 0.2rem; padding: 0.5rem; }
.ls-tabgroup { display: flex; flex-direction: column; gap: 0.1rem; }
.ls-tabgroup + .ls-tabgroup { margin-top: 0.5rem; padding-top: 0.5rem;
  border-top: 1px solid var(--line); }
.ls-tabgroup-label { font-size: 0.6rem; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--faint); cursor: text;
  padding: 0.1rem 0.4rem 0.15rem; }
/* Two lines, not one. A conversation is named after the question that started
   it, so one line clips nearly every one of them; two shows enough to tell
   them apart, and the full name is on the tooltip either way. */
.ls-tab { text-align: left; font-size: 0.78rem; line-height: 1.35; color: var(--mute);
  cursor: pointer; padding: 0.42rem 0.55rem; border-radius: 0.4rem;
  border: 1px solid transparent; overflow: hidden;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.ls-tab:hover { background: var(--wash); color: var(--ink-2); }
/* The current one reads as selected by weight and ground, not by a tab shape
   -- there is no strip for it to be a tab of any more. */
.ls-tab.is-on { background: var(--panel); color: var(--ink); font-weight: 600;
  border-color: var(--line); }
.ls-tab-edit { font: inherit; font-size: 0.78rem; width: 100%; min-width: 0;
  padding: 0.26rem 0.42rem; border: 1px solid var(--ink-3);
  border-radius: 0.4rem; background: #fff; color: var(--ink); }

.ls-mini { font: inherit; font-size: 0.7rem; cursor: pointer; color: var(--ink-2);
  background: #fff; border: 1px solid var(--line); border-radius: 0.4rem;
  padding: 0.24rem 0.5rem; white-space: nowrap; }
.ls-mini:hover { border-color: var(--ink-3); }
.ls-mini-label { font-size: 0.62rem; text-transform: uppercase;
  letter-spacing: 0.07em; color: var(--faint); }
.ls-mini-select { font: inherit; font-size: 0.7rem; color: var(--ink-2);
  background: #fff; border: 1px solid var(--line); border-radius: 0.4rem;
  padding: 0.18rem 0.3rem; min-width: 0; flex: 1 1 auto; }

/* No column to be: lay the same list out sideways. */
@media (max-width: 1199px) {
  .ls-rail { height: auto; }
  .ls-tabs { flex-direction: row; overflow-x: auto; overflow-y: hidden;
    align-items: center; gap: 0.75rem; }
  .ls-tabgroup { flex-direction: row; align-items: center; gap: 0.25rem; }
  .ls-tabgroup + .ls-tabgroup { margin-top: 0; padding-top: 0;
    border-top: 0; border-left: 1px solid var(--line); padding-left: 0.75rem; }
  .ls-tab { flex: none; max-width: 14rem; -webkit-line-clamp: 1;
    white-space: nowrap; text-overflow: ellipsis; }
  .ls-tab-edit { width: 10rem; }
}
@media (min-width: 1200px) { .ls-rail { height: var(--pane-h); } }

/* The pane is wide; prose is not. The column is held to a readable measure and
   centred in what is left, so a large monitor buys margin rather than longer
   lines. 38rem is roughly 78 characters at this size -- 46rem was about 100,
   which is past the point where the eye loses the start of the next line. */
.ls-chat { --measure: 38rem; }
.ls-chat-log { flex: 1 1 auto; min-height: 0; overflow-y: auto;
  /* More at the top than the sides: the first thing said sits under a status
     bar, and jammed against it the conversation reads as though it started
     mid-sentence. */
  padding: 1.5rem max(0.9rem, (100% - var(--measure)) / 2) 1.1rem;
  display: flex; flex-direction: column; gap: 0.85rem; }
.ls-chat-form { padding-left: max(0.7rem, (100% - var(--measure)) / 2);
  padding-right: max(0.7rem, (100% - var(--measure)) / 2); }
.ls-chat-msg { white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.55;
  font-size: 0.92rem; border-radius: 0.7rem; padding: 0.6rem 0.8rem; max-width: 92%; }
.ls-chat-msg--you { align-self: flex-end; background: var(--ink); color: #fff; }
.ls-chat-msg--bot { align-self: flex-start; background: var(--wash); color: var(--ink-2); }
.ls-chat-msg--err { align-self: flex-start; background: var(--bad-wash); color: var(--bad); }
.ls-chat-tools { font-size: 0.72rem; color: var(--mute); align-self: flex-start; }

/* The cold start, explained. ~30s of a container booting reads as a hung page
   unless it is named, so it is named -- and the sentence says the wait does
   not repeat, which is the part that decides whether someone waits. */
.ls-chat-boot { display: flex; align-items: flex-start; gap: .55rem;
  font-size: .8rem; line-height: 1.5; color: var(--mute);
  background: var(--panel-2); border: 1px dashed var(--line);
  border-radius: .7rem; padding: .6rem .75rem; }
.ls-boot-text { flex: 1 1 auto; }
.ls-spin { width: .8rem; height: .8rem; flex: none; margin-top: .15rem;
  border: 2px solid var(--line); border-top-color: var(--ink-3);
  border-radius: 50%; animation: ls-spin .8s linear infinite; }
@keyframes ls-spin { to { transform: rotate(360deg); } }

/* The opening of an empty conversation. Sits in the flow rather than centred
   in the void: the first answer will appear directly beneath it, so the eye
   starts where the reading will continue. */
.ls-chat-empty { display: flex; flex-direction: column; gap: 0.7rem;
  align-items: flex-start; max-width: 100%; padding-top: 0.5rem; }
.ls-chat-empty-lede { font-size: 0.92rem; line-height: 1.6; color: var(--mute); }
.ls-chat-openers { display: flex; flex-direction: column; gap: 0.4rem; width: 100%; }
/* Real questions, and clickable. A first-time reader learns what this answers
   and how to phrase it from the same three lines. */
.ls-opener { font-size: 0.86rem; line-height: 1.45; color: var(--ink-2);
  background: #fff; border: 1px solid var(--line); border-radius: 0.6rem;
  padding: 0.55rem 0.7rem; cursor: pointer; }
.ls-opener:hover { border-color: var(--ink-3); background: var(--panel-2); }
.ls-opener:focus-visible { outline: 2px solid var(--ink-3); outline-offset: 1px; }

/* A turn in progress: what it looked up, what it is thinking, what it has
   said so far -- in the order those happen. */
.ls-chat-turn { display: flex; flex-direction: column; gap: 0.4rem; align-items: flex-start; }
.ls-chat-activity { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.ls-chat-tool { display: inline-flex; align-items: center; gap: .28rem;
  font-size: 0.7rem; color: var(--record); background: rgba(14,110,99,.07);
  border: 1px solid rgba(14,110,99,.2); border-radius: 999px;
  padding: 0.14rem 0.5rem 0.14rem 0.42rem; }
.ls-chat-tool svg { flex: none; opacity: .85; }
/* Hidden until there is reasoning to show, and gone once the answer starts:
   a permanently empty panel reads as something broken. */
.ls-chat-think { display: none; max-width: 92%; font-size: 0.78rem; line-height: 1.5;
  color: var(--mute); border-left: 2px solid var(--line); padding: 0.15rem 0 0.15rem 0.6rem; }
.ls-chat-think.is-on { display: block; }
.ls-chat-think-label { font-size: 0.64rem; text-transform: uppercase; letter-spacing: .08em;
  color: var(--faint); margin-bottom: 0.15rem; }
.ls-chat-think-text { white-space: pre-wrap; overflow-wrap: anywhere; }
.ls-chat-msg--live::after { content: "▋"; margin-left: 1px; color: var(--faint);
  animation: ls-blink 1.1s steps(2, start) infinite; }
@keyframes ls-blink { to { visibility: hidden; } }
@media (prefers-reduced-motion: reduce) {
  .ls-chat-msg--live::after, .ls-spin, .ls-beacon { animation: none !important; }
}

/* Bottom-aligned: as the box grows the button stays on the composer's base
   line rather than drifting down the middle of it. */
.ls-chat-form { display: flex; gap: 0.5rem; align-items: flex-end;
  padding: 0.85rem 0.7rem;
  border-top: 1px solid var(--line); background: var(--panel-2); }
.ls-chat-form textarea { flex: 1 1 auto; resize: none; font: inherit;
  font-size: 0.92rem; padding: 0.55rem 0.7rem; border-radius: 0.6rem;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
  min-height: 4.6rem; max-height: 13.75rem; line-height: 1.5; }
.ls-chat-form textarea:focus { outline: 2px solid var(--ink-3); outline-offset: 1px; }
.ls-chat-form textarea[disabled] { background: var(--wash); }
.ls-chat-form button { border-radius: 0.6rem; background: var(--ink); color: #fff;
  border: 0; padding: 0 1.1rem; height: 2.6rem; font-weight: 600; font-size: 0.9rem;
  cursor: pointer; flex: none; }
.ls-chat-form button:hover:not([disabled]) { background: var(--ink-2); }
.ls-chat-form button[disabled] { opacity: .45; cursor: default; }

/* Markdown as rendered inside an answer. */
.ls-chat-msg--bot strong { font-weight: 700; color: var(--ink); }
.ls-chat-msg--bot em { font-style: italic; }
.ls-chat-msg--bot code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .85em; background: rgba(27,42,74,.06); padding: .05rem .3rem; border-radius: .25rem; }
.ls-chat-msg--bot .ls-h { display: block; margin: .35rem 0 .1rem; }
.ls-chat-msg--bot .ls-q { display: block; border-left: 3px solid rgba(14,110,99,.45);
  padding: .1rem 0 .1rem .6rem; margin: .2rem 0; color: var(--mute); }
.ls-chat-msg--bot .ls-hr { border: 0; border-top: 1px solid var(--line); margin: .5rem 0; }
.ls-chat-msg--bot a[target="_blank"] { color: var(--record); text-decoration: underline; }

/* A citation inside the answer: a reference in running prose, not a button. */
.ls-cite { color: var(--record); text-decoration: underline;
  text-decoration-color: rgba(14,110,99,.4); text-underline-offset: 2px;
  cursor: pointer; font-weight: 600; }
.ls-cite:hover { text-decoration-color: var(--record); background: rgba(14,110,99,.07); }

/* ---- the source pane ---- */
.ls-art { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 0.9rem;
  font-size: 0.9rem; color: var(--ink-2); }
.ls-art-empty { color: var(--mute); font-size: 0.86rem; line-height: 1.55; }
.ls-art-count { font-size: .7rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--faint); margin-bottom: .6rem; }
.ls-art-card { padding: .7rem .8rem; margin-bottom: .7rem; border-radius: .6rem;
  border: 1px solid var(--line); background: #fff;
  scroll-margin-top: .5rem; transition: border-color .2s, box-shadow .2s; }
.ls-art-card.is-sel { border-color: var(--record); box-shadow: 0 0 0 2px rgba(14,110,99,.15); }
@media (prefers-reduced-motion: reduce) { .ls-art-card { transition: none; } }
.ls-art h3 { font-size: 1rem; font-weight: 700; color: var(--ink); margin: 0 0 .2rem; }
.ls-art .cite { font-size: .8rem; color: var(--mute); margin-bottom: .7rem; }
.ls-art .row { margin: .5rem 0; }
.ls-art .label { font-size: .7rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--faint); display: block; margin-bottom: .15rem; }
.ls-art .clamp { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden; }
.ls-art blockquote { margin: .4rem 0; padding: .5rem .7rem; border-left: 3px solid var(--record);
  background: rgba(14,110,99,.05); font-size: .88rem; }
.ls-art blockquote a.pin { font-size: .75rem; color: var(--record); white-space: nowrap; }
.ls-art a.pdf { display: inline-block; margin-top: .6rem; padding: .45rem .8rem;
  border-radius: .55rem; background: var(--ink); color: #fff; text-decoration: none;
  font-weight: 600; font-size: .85rem; }
.ls-art a.pdf:hover { background: var(--ink-2); }

/* Cited by the answer, absent from the index. The one thing this pane must
   never hide. */
.ls-art-missing { margin-top: .8rem; padding: .6rem .8rem; border-radius: .6rem;
  background: var(--bad-wash); color: var(--bad); font-size: .85rem; }
.ls-art-missing .label { color: var(--bad); }
.ls-art-missing p { margin-top: .35rem; font-size: .78rem; }

/* ---------- credits: buying them ----------------------------------------
   Same tokens as the chat panes; this is the same product taking money. */
.ls-credits { --ink: #1b2a4a; --ink-2: #243b53; --mute: #7d7870; --faint: #a39e96;
  --line: #e3dfd9; --panel: #fffbf5; --panel-2: #faf7f2; --record: #0e6e63;
  --bad: #8a2020; max-width: 56rem; }
.ls-credits-head { margin-bottom: 1.6rem; }
.ls-credits-head h1 { font-size: 1.5rem; font-weight: 600; color: var(--ink); margin: 0; }
.ls-credits-balance { font-size: 0.95rem; color: var(--mute); margin: 0.25rem 0 0; }
.ls-credits-balance strong { color: var(--ink); font-size: 1.15rem; }
.ls-credits-lede { font-size: 0.9rem; line-height: 1.6; color: var(--mute);
  margin: 0.6rem 0 0; max-width: 42rem; }
.ls-credits-grid { display: grid; gap: 1rem; align-items: start; }
@media (min-width: 820px) { .ls-credits-grid { grid-template-columns: 1fr 1fr; } }
.ls-card { background: var(--panel); border: 1px solid var(--line);
  border-radius: 0.8rem; padding: 1.1rem 1.2rem; }
.ls-card--wide { margin-top: 1rem; }
.ls-card h2 { font-size: 0.72rem; font-weight: 600; letter-spacing: .07em;
  text-transform: uppercase; color: var(--mute); margin: 0 0 0.9rem; }

/* One price, three quantities. Not a discount ladder -- the packs are the same
   rate, so none of them is dressed up as a saving it does not make. */
.ls-packs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem; }
.ls-pack { display: flex; flex-direction: column; align-items: center; gap: 0.1rem;
  cursor: pointer; font: inherit; padding: 0.7rem 0.4rem; border-radius: 0.6rem;
  border: 1px solid var(--line); background: #fff; }
.ls-pack:hover { border-color: var(--ink-2); }
.ls-pack.is-on { border-color: var(--ink); box-shadow: 0 0 0 1px var(--ink); }
.ls-pack-n { font-size: 1.1rem; font-weight: 700; color: var(--ink);
  font-variant-numeric: tabular-nums; }
.ls-pack-u { font-size: 0.62rem; text-transform: uppercase; letter-spacing: .07em;
  color: var(--faint); }
.ls-pack-p { font-size: 0.82rem; color: var(--mute); margin-top: 0.15rem; }

.ls-credits-custom { display: flex; flex-direction: column; gap: 0.3rem;
  margin: 0.9rem 0; font-size: 0.78rem; color: var(--mute); }
.ls-credits-custom input, .ls-credits-custom select { font: inherit; font-size: 0.9rem;
  padding: 0.45rem 0.6rem; border: 1px solid var(--line); border-radius: 0.5rem;
  background: #fff; color: var(--ink-2); }
.ls-credits-total { font-size: 0.95rem; font-weight: 600; color: var(--ink);
  margin: 0 0 0.8rem; font-variant-numeric: tabular-nums; }
.ls-credits-note { font-size: 0.75rem; color: var(--faint); margin: 0.6rem 0 0;
  line-height: 1.5; }
.ls-credits-note.is-bad { color: var(--bad); }
.ls-credits-on { font-size: 0.9rem; line-height: 1.6; color: var(--ink-2); margin: 0; }
.ls-credits-on strong { color: var(--ink); }

.ls-credits-history { list-style: none; margin: 0; padding: 0;
  font-size: 0.85rem; color: var(--mute); }
.ls-credits-history li { display: flex; gap: 1rem; padding: 0.35rem 0;
  border-bottom: 1px solid var(--line); font-variant-numeric: tabular-nums; }
.ls-credits-history li:last-child { border-bottom: 0; }
.ls-credits-history li span:first-child { flex: 1 1 auto; }
.ls-chat-msg--err a { color: inherit; font-weight: 600; text-decoration: underline; }
/* Only ever visible while the keys are test keys. */
.ls-testnote { font-size: 0.82rem; line-height: 1.6; color: #6b5720;
  background: #fdf6e3; border: 1px solid #e8d9a8; border-radius: 0.6rem;
  padding: 0.7rem 0.9rem; margin-bottom: 1rem; max-width: 56rem; }
.ls-testnote code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.85em; background: rgba(0,0,0,.06); padding: 0.05rem 0.3rem;
  border-radius: 0.25rem; }

/* The balance beside the Credits tab. Quiet: it is a number you glance at, and
   it is the reason anyone clicks the tab -- knowing you are low. */
.ls-navbal { font-size: 0.72rem; font-variant-numeric: tabular-nums;
  color: #7d7870; background: #f0ede8; border-radius: 999px;
  padding: 0.05rem 0.4rem; margin-left: 0.15rem; }

/* ---------- the Ratio lockup -------------------------------------------
   The mark, then the mode. The red full stop IS the period in "Ratio.", so
   "Ratio. Chat" reads without a period set in type -- and because the mark
   carries the product name on every surface Ratio owns, the site nav needs
   only "Search" and "Chat".

   Centred, not baseline-aligned. The wordmark's artboard carries about 23% of
   its height as padding below the baseline (descender room the glyphs here do
   not use), so an inline image -- whose baseline is its bottom edge -- hangs
   the wordmark that far above the word beside it. Centring works because the
   padding is symmetric: the box's middle is the wordmark's middle.

   Literal hex, not the --ink tokens: those are declared on .ls-chat, and this
   lockup is also used in the footer and on the tool, outside that scope.

   Both are outside base.css on purpose -- it is a frozen bundle with no build
   step, so a utility class it never emitted renders as nothing at all. */
/* The artboard is padded a uniform 663 units (about 9% of its width) on all
   four sides, so the gap set here is not the gap you see -- roughly 6px of
   air comes free at header size before this one is added. */
.ls-mark { display: flex; align-items: center; gap: 0.25rem; margin: 0; }
.ls-mark img { height: 1.55rem; width: auto; display: block; }
.ls-mark span { font-family: "Source Serif 4", Georgia, serif;
  font-size: 1.5rem; font-weight: 400; line-height: 1.1; color: #1b2a4a; }
.ls-mark--hero img { height: 2.1rem; }
.ls-mark--hero span { font-size: 1.7rem; }

/* The sitewide credit under the LegalStreet mark in the footer. */
/* Nearly closed for the same reason as .ls-mark: the artboard's own padding
   is already about a word space at this size. */
.ls-poweredby { display: inline-flex; align-items: center; gap: 0.1rem;
  font-size: 0.75rem; color: #a39e96; text-decoration: none;
  transition: color 0.15s ease; }
.ls-poweredby img { height: 1.05rem; width: auto; display: block;
  opacity: 0.8; transition: opacity 0.15s ease; }
.ls-poweredby:hover { color: #1b2a4a; }
.ls-poweredby:hover img { opacity: 1; }
