/* ============================================================
   LineRelay — portal stylesheet.

   Same monochrome editorial system as linerelay.ai: paper background, near
   black ink, hairline rules, one accent blue used sparingly. Application
   surfaces are flat and bordered rather than shadowed and rounded, tables read
   like tables, and nothing here animates for its own sake.
   ============================================================ */

@import url("/assets/fonts/fonts.css");

:root {
  --ink: #111110;
  --black: #0c0c0b;
  --paper: #f7f6f2;
  --white: #fdfdfb;
  --grey: #575550;
  --grey-2: #b8b6af;
  --grey-soft: #77756e;
  --blue: #00a9fe;
  --blue-ink: #0070ab;
  --line: rgba(17, 17, 16, 0.16);
  --line-soft: rgba(17, 17, 16, 0.08);

  /* Status colours. Calm and desaturated — a phone system reporting an error
     should read as serious, not alarming. */
  --ok: #1f6f43;
  --ok-bg: rgba(31, 111, 67, 0.09);
  --warn: #8a5a00;
  --warn-bg: rgba(138, 90, 0, 0.10);
  --bad: #9a2c22;
  --bad-bg: rgba(154, 44, 34, 0.09);
  --info-bg: rgba(0, 169, 254, 0.10);

  --font: "Inter Tight Variable", "Noto Sans JP Variable", "Hiragino Kaku Gothic ProN", "Hiragino Sans", "Yu Gothic", system-ui, sans-serif;
  --pad: clamp(20px, 3.2vw, 44px);
  --sidebar: 236px;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.65;
  font-weight: 400;
  font-feature-settings: "palt" 1;
  -webkit-font-smoothing: antialiased;
}
:lang(ja) body, body:lang(ja) { letter-spacing: 0.02em; }

img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
a:hover { opacity: 0.72; }
a, button, input, select, textarea { font: inherit; }
:focus { outline: none; }
:focus-visible { outline: 2px solid var(--blue-ink); outline-offset: 2px; }
::selection { background: var(--ink); color: var(--white); }

/* An editorial scale rather than a flat one. The page title is the only large
   thing on a screen; everything under it steps down sharply so a dense table
   still reads as the subject of the page. Tracking tightens as size grows,
   which is what keeps a large Inter Tight heading from looking loose. */
h1, h2, h3, h4 { margin: 0; font-weight: 400; line-height: 1.3; letter-spacing: -0.005em; }
h1 { font-size: clamp(1.6rem, 2.5vw, 2.15rem); line-height: 1.1; letter-spacing: -0.028em; }
h2 { font-size: 1.125rem; letter-spacing: -0.014em; }
h3 { font-size: 0.95rem; letter-spacing: -0.008em; }
p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

.label {
  display: block;
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--grey-soft);
}
.muted { color: var(--grey); }
.small { font-size: 0.8125rem; line-height: 1.6; }
.mono { font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1; }
.nowrap { white-space: nowrap; }
.right { text-align: right; }
.stack > * + * { margin-top: var(--gap, 16px); }
.row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.row-tight { display: flex; align-items: center; gap: 8px; }
.spacer { flex: 1 1 auto; }
.hide { display: none !important; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: 12px; top: -60px; z-index: 200;
  background: var(--ink); color: var(--white); padding: 10px 16px;
  transition: top 0.15s var(--ease);
}
.skip-link:focus { top: 12px; }

/* ---------- shell ---------- */

.shell { display: flex; min-height: 100vh; }

.sidebar {
  width: var(--sidebar);
  flex: none;
  background: var(--white);
  border-right: 1px solid var(--line);
  padding: 22px 0 24px;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}
.sidebar-head { padding: 0 20px 20px; }
.brand-mark { height: 20px; width: auto; }
.org-switch {
  margin-top: 18px;
  width: 100%;
  padding: 8px 10px;
  background: var(--paper);
  border: 1px solid var(--line);
  color: var(--ink);
  font-size: 0.8125rem;
}
.nav { padding: 0 10px; }
.nav a {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 32px;
  padding: 6px 10px;
  font-size: 0.875rem;
  color: var(--grey);
  border-left: 2px solid transparent;
  transition: background 0.12s var(--ease), color 0.12s var(--ease);
}
.nav a:hover { color: var(--ink); opacity: 1; background: var(--paper); }
.nav a[aria-current="page"] {
  color: var(--ink);
  font-weight: 500;
  border-left-color: var(--ink);
  background: var(--paper);
}
.nav-group { margin-top: 20px; }
.nav-group > .label { padding: 0 12px 8px; }
.badge-count {
  margin-left: auto;
  min-width: 20px;
  padding: 1px 6px;
  text-align: center;
  background: var(--ink);
  color: var(--white);
  font-size: 0.6875rem;
  font-variant-numeric: tabular-nums;
  border-radius: 2px;
}
.sidebar-foot { margin-top: auto; padding: 16px 20px 0; border-top: 1px solid var(--line-soft); }

.main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.topbar {
  display: none;
  align-items: center;
  gap: 12px;
  padding: 12px var(--pad);
  background: var(--white);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 40;
}
.content { padding: clamp(24px, 3.5vw, 44px) var(--pad) 72px; max-width: 1320px; width: 100%; }

.page-head {
  margin-bottom: 28px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--line);
}
.page-head .eyebrow { display: block; margin-bottom: 10px; }
.page-head h1 { margin-bottom: 6px; }
.page-head .lede { color: var(--grey); max-width: 62ch; }
/* The actions sit on the title's baseline on a wide screen and wrap under it
   on a narrow one, rather than shrinking the title to make room. */
.page-head .row { align-items: flex-end; row-gap: 16px; }

/* A heading for a section inside a page — one step below the page title, with
   a rule that ties it to the panel beneath. */
.section-title {
  margin-bottom: 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line);
  font-size: 1.05rem;
  font-weight: 500;
  letter-spacing: -0.014em;
}

/* ---------- cards, panels ---------- */

.card {
  background: var(--white);
  border: 1px solid var(--line);
  padding: 20px 22px;
}
.card-head {
  display: flex; align-items: baseline; gap: 12px;
  margin-bottom: 14px;
}
.card-head h2 { font-size: 1rem; font-weight: 500; letter-spacing: -0.012em; }

.panel { background: var(--white); border: 1px solid var(--line); }
.panel-head {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 15px 20px; border-bottom: 1px solid var(--line);
}
.panel-head h2 { font-size: 1rem; font-weight: 500; letter-spacing: -0.012em; }
.panel-body { padding: 20px; }
.panel-foot { padding: 12px 18px; border-top: 1px solid var(--line); background: var(--paper); }

.grid { display: grid; gap: 16px; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid-form { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }

/* ---------- metrics ----------

   One bordered strip divided by hairlines rather than a row of separate
   floating cards. The numbers then sit on a shared baseline and read as one
   instrument panel, which is how somebody actually scans them: across, not
   card by card. */
/* The seams are grid gaps letting the container's own colour through, so they
   stay exactly one hairline wide however many columns fit and wherever the row
   wraps — no nth-child arithmetic that breaks at the next breakpoint. */
.metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}
.kpi { display: flex; flex-direction: column; background: var(--white); padding: 18px 20px 20px; min-width: 0; }
/* Two lines' worth of room whether or not the label needs it, so a metric with
   a long name does not push its number below the rest of the row. The point of
   the strip is that the numbers line up. */
.kpi .label { line-height: 1.2; min-height: 2.4em; margin-bottom: 10px; }
.kpi-value {
  font-size: clamp(1.5rem, 2.3vw, 2rem);
  font-weight: 300;
  line-height: 1;
  letter-spacing: -0.035em;
  font-variant-numeric: tabular-nums;
}
.kpi-sub { margin-top: 8px; font-size: 0.8125rem; color: var(--grey-soft); }


/* ---------- status ---------- */

.status {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 2px 8px;
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  border: 1px solid var(--line);
  background: var(--paper);
  color: var(--grey);
  white-space: nowrap;
}
.status::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; flex: none; }
.status--ok { color: var(--ok); background: var(--ok-bg); border-color: transparent; }
/* The one status worth a second of attention gets a halo on its dot. Nothing
   pulses — a phone system is not a notification feed. */
.status--ok::before { box-shadow: 0 0 0 3px var(--ok-bg); }
.status--warn::before { box-shadow: 0 0 0 3px var(--warn-bg); }
.status--bad::before { box-shadow: 0 0 0 3px var(--bad-bg); }
.status--warn { color: var(--warn); background: var(--warn-bg); border-color: transparent; }
.status--bad { color: var(--bad); background: var(--bad-bg); border-color: transparent; }
.status--info { color: var(--blue-ink); background: var(--info-bg); border-color: transparent; }
.status--plain::before { display: none; }

/* A count that belongs to a heading — "3 awaiting reply" — rather than a
   status. Amber because it is a nudge, not a fault. */
.chip {
  display: inline-flex; align-items: center;
  padding: 2px 7px;
  border: 1px solid rgba(138, 90, 0, 0.28);
  background: var(--warn-bg);
  color: var(--warn);
  font-size: 0.6875rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.chip--quiet { border-color: var(--line); background: var(--paper); color: var(--grey-soft); }

.dot-new {
  display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--blue); flex: none;
}

/* ---------- the status banner at the top of Overview ---------- */

.hero-status {
  position: relative;
  background: var(--white);
  border: 1px solid var(--line);
  padding: clamp(22px, 2.8vw, 30px);
  display: flex;
  gap: 28px;
  flex-wrap: wrap;
  align-items: flex-start;
}
/* One dark rule along the top edge. It gives the panel that answers "is my
   phone being answered?" more weight than the panels below it, without
   turning the whole block into a black slab.
   Ink is the normal state — working is not an event, and colouring it would
   spend the page's only accent on the thing nobody needs to look at. The rule
   turns amber only when setup is unfinished or the AI is paused. */
.hero-status::before {
  content: "";
  position: absolute;
  inset: -1px -1px auto -1px;
  height: 2px;
  background: var(--ink);
}
.hero-status--attention::before { background: var(--warn); }

/* A phone number is the thing people read aloud and copy down, so it is set
   larger than anything else on the page except the title. */
.number {
  font-size: clamp(1.4rem, 2.5vw, 1.95rem);
  font-weight: 300;
  line-height: 1.15;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}

/* Setup progress, shown while a number is still being provisioned. */
.progress { margin-top: 18px; max-width: 380px; }
.progress-head {
  display: flex; justify-content: space-between; gap: 12px;
  margin-bottom: 8px; font-size: 0.75rem; color: var(--grey-soft);
}
.progress-head strong { color: var(--ink); font-weight: 500; }
.progress-track { height: 3px; background: var(--line-soft); }
.progress-track > span { display: block; height: 100%; background: var(--ink); }

/* ---------- buttons ---------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 36px;
  padding: 8px 16px;
  /* A button label never wraps. In a narrow table cell — and Japanese labels
     are short enough to invite one — a wrapped "Edit" reads as two controls. */
  white-space: nowrap;
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--white);
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: opacity 0.2s var(--ease), background 0.2s var(--ease);
}
.btn:hover { opacity: 0.82; }
.btn:disabled { opacity: 0.4; cursor: not-allowed; }
.btn--ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.btn--ghost:hover { background: var(--white); opacity: 1; border-color: var(--ink); }
.btn--quiet { background: transparent; color: var(--grey); border-color: transparent; padding-left: 8px; padding-right: 8px; }
.btn--quiet:hover { color: var(--ink); background: var(--paper); opacity: 1; }
/* The locale you are already reading in. Themed rather than inlined, so it
   stays legible on a dark surface as well as on paper. */
.btn--quiet.is-current { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.btn--danger { background: transparent; color: var(--bad); border-color: rgba(154, 44, 34, 0.35); }
.btn--danger:hover { background: var(--bad-bg); opacity: 1; }
.btn--sm { min-height: 30px; padding: 5px 11px; font-size: 0.75rem; }
.btn--block { width: 100%; }

/* ---------- forms ---------- */

.field { display: block; margin-bottom: 18px; }
.field > .field-label {
  display: block;
  margin-bottom: 6px;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--ink);
}
.field-hint { margin-top: 6px; font-size: 0.78rem; color: var(--grey-soft); line-height: 1.55; }
.field-error { margin-top: 6px; font-size: 0.78rem; color: var(--bad); }

input[type="text"], input[type="email"], input[type="password"], input[type="tel"],
input[type="url"], input[type="number"], input[type="search"], input[type="date"],
input[type="time"], input[type="datetime-local"], select, textarea {
  width: 100%;
  padding: 9px 11px;
  background: var(--white);
  border: 1px solid var(--line);
  color: var(--ink);
  border-radius: 0;
  appearance: none;
}
select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%2377756e' fill='none' stroke-width='1.4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 11px center;
  padding-right: 30px;
}
textarea { min-height: 110px; resize: vertical; line-height: 1.6; }
input:focus, select:focus, textarea:focus { border-color: var(--ink); }
input[aria-invalid="true"], textarea[aria-invalid="true"], select[aria-invalid="true"] { border-color: var(--bad); }
input::placeholder, textarea::placeholder { color: var(--grey-2); }
input:disabled, select:disabled, textarea:disabled { background: var(--paper); color: var(--grey-soft); }

.check { display: flex; align-items: flex-start; gap: 9px; font-size: 0.875rem; }
.check input { width: 15px; height: 15px; margin-top: 3px; flex: none; accent-color: #111110; }

.choice {
  display: block;
  border: 1px solid var(--line);
  background: var(--white);
  padding: 16px 18px;
  cursor: pointer;
}
.choice:hover { border-color: var(--grey-2); }
.choice input { position: absolute; opacity: 0; }
.choice:has(input:checked) { border-color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
.choice:has(input:focus-visible) { outline: 2px solid var(--blue-ink); outline-offset: 2px; }
/* Both are spans in the markup so the whole card stays one clickable label.
   Without display:block the help text runs straight on from the title —
   "Japan.Japanese and English calls" — and the margin below is ignored. */
.choice-title { display: block; font-weight: 500; font-size: 0.9rem; }
.choice-help { display: block; margin-top: 4px; font-size: 0.8125rem; color: var(--grey); line-height: 1.55; }

fieldset { border: 0; margin: 0; padding: 0; }
legend { padding: 0; font-size: 0.8125rem; font-weight: 500; margin-bottom: 8px; }

/* ---------- tables ---------- */

.table-wrap { overflow-x: auto; }
table.data { width: 100%; border-collapse: collapse; font-size: 0.8125rem; }
table.data th {
  text-align: left;
  padding: 10px 14px;
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--grey-soft);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
  background: var(--white);
}
table.data td {
  padding: 11px 14px;
  border-bottom: 1px solid var(--line-soft);
  vertical-align: top;
}
table.data tbody tr:hover { background: var(--paper); }
/* A whole row opens the record, so it must look like it does. */
table.data tbody tr[data-href] { cursor: pointer; }
table.data tr.is-unread td { background: rgba(0, 169, 254, 0.045); }
table.data tr.is-unread .cell-title { font-weight: 500; }
table.data td.cell-num { font-variant-numeric: tabular-nums; white-space: nowrap; }
table.data a.cell-link { display: block; color: inherit; }
table.data a.cell-link:hover { opacity: 1; text-decoration: underline; text-underline-offset: 2px; }
.cell-sub { display: block; color: var(--grey-soft); font-size: 0.75rem; margin-top: 2px; }

/* A grid rather than a wrapping flex row. Selects and date inputs each carry
   their own intrinsic width — the widest option, the browser's date picker —
   so a flex row breaks onto a second line at an arbitrary point and leaves a
   ragged tail. Equal tracks wrap into a tidy block at any width instead. */
.filters {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 12px;
  align-items: end;
  padding: 14px 18px; border-bottom: 1px solid var(--line); background: var(--white);
}
.filters .field { margin: 0; min-width: 0; }
.filters select, .filters input { width: 100%; min-width: 0; }
/* Buttons take their own width inside their track rather than stretching to
   fill it — a full-track "Apply" reads as the row's primary action, which it
   is not. */
.filters > .btn { justify-self: start; }
/* Named, not guessed. Three unlabelled selects all reading "All" is the same
   control three times as far as anyone scanning the row is concerned. */
.filter-label {
  display: block;
  margin-bottom: 4px;
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--grey-soft);
}
.filters select, .filters input { font-size: 0.8125rem; padding-top: 7px; padding-bottom: 7px; }

.bulkbar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 18px; background: var(--ink); color: var(--white);
}
.bulkbar select { background: transparent; color: var(--white); border-color: rgba(253,253,251,0.3); padding: 5px 26px 5px 8px; }
.bulkbar select option { color: var(--ink); }
.bulkbar .btn--ghost { color: var(--white); border-color: rgba(253,253,251,0.35); }
.bulkbar .btn--ghost:hover { background: rgba(253,253,251,0.12); }

/* ---------- usage meter ---------- */

.meter { height: 4px; background: var(--line-soft); overflow: hidden; }
.meter > span { display: block; height: 100%; background: var(--ink); }
.meter--warn > span { background: var(--warn); }
.meter--over > span { background: var(--bad); }

/* ---------- action list, timeline, transcript ---------- */

.action-list { list-style: none; margin: 0; padding: 0; }
.action-list li { display: flex; align-items: center; gap: 12px; padding: 11px 0; border-bottom: 1px solid var(--line-soft); }
.action-list li:last-child { border-bottom: 0; }
.action-list .count {
  font-size: 1.25rem;
  font-weight: 300;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  min-width: 2ch;
}
.action-list li a { font-size: 0.9rem; }
.action-list li a:hover { opacity: 1; text-decoration: underline; text-underline-offset: 3px; }

.timeline { list-style: none; margin: 0; padding: 0 0 0 18px; border-left: 1px solid var(--line); }
.timeline li { position: relative; padding: 0 0 16px 18px; }
.timeline li::before {
  content: ""; position: absolute; left: -23px; top: 7px;
  width: 7px; height: 7px; border-radius: 50%; background: var(--white);
  border: 1px solid var(--grey-2);
}
.timeline li:last-child { padding-bottom: 0; }
.timeline .t { font-variant-numeric: tabular-nums; color: var(--grey-soft); font-size: 0.75rem; }

.transcript { display: grid; gap: 14px; }
.transcript .turn { display: grid; grid-template-columns: 76px 1fr; gap: 14px; align-items: baseline; }
.transcript .who { font-size: 0.6875rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--grey-soft); }
.transcript .said { line-height: 1.7; }
.transcript .turn--ai .said { color: var(--grey); }

/* ---------- detail description lists ---------- */

dl.detail { display: grid; grid-template-columns: minmax(120px, 200px) 1fr; gap: 10px 20px; margin: 0; font-size: 0.875rem; }
dl.detail dt { color: var(--grey-soft); font-size: 0.8125rem; }
dl.detail dd { margin: 0; }
@media (max-width: 560px) { dl.detail { grid-template-columns: 1fr; gap: 2px 0; } dl.detail dd { margin-bottom: 12px; } }

/* ---------- empty / error states ---------- */

.empty { padding: clamp(40px, 6vw, 72px) 24px; text-align: center; }
.empty h3 { font-weight: 400; margin-bottom: 6px; font-size: 1.05rem; }
.empty p { color: var(--grey); max-width: 44ch; margin-left: auto; margin-right: auto; }
.empty .btn { margin-top: 18px; }
/* An outlined glyph rather than a filled illustration: it fills the space an
   empty table leaves without claiming to be content. */
.empty-mark {
  margin-bottom: 14px;
  color: transparent;
  -webkit-text-stroke: 1px var(--grey-2);
  font-size: clamp(2.6rem, 6vw, 3.6rem);
  font-weight: 200;
  line-height: 1;
  letter-spacing: -0.05em;
  user-select: none;
}

.notice { padding: 12px 16px; border: 1px solid var(--line); background: var(--white); font-size: 0.875rem; }
.notice--info { border-color: transparent; background: var(--info-bg); }
.notice--warn { border-color: transparent; background: var(--warn-bg); color: var(--warn); }
.notice--bad { border-color: transparent; background: var(--bad-bg); color: var(--bad); }
.notice--ok { border-color: transparent; background: var(--ok-bg); color: var(--ok); }

.gate { border: 1px dashed var(--line); background: transparent; padding: 20px; text-align: center; }
.gate p { color: var(--grey); font-size: 0.875rem; }

/* ---------- auth pages ---------- */

.auth-page { min-height: 100vh; display: grid; place-items: center; padding: 40px 20px; }
.auth-card { width: 100%; max-width: 400px; }
.auth-card .brand-mark { height: 22px; margin: 0 auto 32px; }
.auth-card h1 { font-size: 1.3rem; margin-bottom: 6px; }
.auth-card .sub { color: var(--grey); font-size: 0.875rem; margin-bottom: 26px; }
.auth-box { background: var(--white); border: 1px solid var(--line); padding: 28px; }
.auth-foot { margin-top: 20px; text-align: center; font-size: 0.8125rem; color: var(--grey); }
.auth-foot a { text-decoration: underline; text-underline-offset: 2px; }

/* ---------- onboarding ---------- */

/* ---------- setup conversation ----------

   Onboarding is asked one question at a time, as a conversation, because that
   is what the product itself does on the phone. It is still ordinary forms
   posting to ordinary URLs — the chat is a reading order, not a client-side
   app — so every question works without JavaScript and every answer stays
   editable from its own address. */

.convo { max-width: 660px; margin: 0 auto; padding: clamp(28px, 4vw, 56px) 20px 80px; }
.convo-head { display: flex; align-items: center; gap: 12px; margin-bottom: 34px; }
.convo-head .brand-mark { height: 20px; }
.convo-progress { margin-left: auto; font-size: 0.75rem; color: var(--grey-soft); font-variant-numeric: tabular-nums; }

/* The transcript of what has already been answered. Quiet, because it is
   context — the live question is the only thing that should pull the eye. */
.turns { display: grid; gap: 18px; margin-bottom: 30px; }
.turn-q { display: flex; gap: 12px; align-items: flex-start; }
.turn-a { display: flex; gap: 12px; align-items: flex-start; padding-left: 40px; }

.avatar {
  flex: none;
  display: grid; place-items: center;
  width: 28px; height: 28px;
  background: var(--ink); color: var(--white);
  font-size: 0.625rem; font-weight: 600; letter-spacing: 0.02em;
}
.avatar--you { background: transparent; color: var(--grey-soft); border: 1px solid var(--line); }

.bubble {
  min-width: 0;
  padding: 10px 14px;
  background: var(--white);
  border: 1px solid var(--line);
  font-size: 0.9375rem;
  line-height: 1.6;
}
.bubble--said { background: var(--paper); border-color: var(--line-soft); color: var(--grey); }
.bubble p { margin: 0 0 0.6em; }
.bubble p:last-child { margin-bottom: 0; }
.bubble .edit { margin-left: 10px; font-size: 0.75rem; color: var(--grey-soft); text-decoration: underline; text-underline-offset: 2px; white-space: nowrap; }
.bubble .edit:hover { color: var(--ink); opacity: 1; }

/* The question being asked now. Same shape as the transcript above it, one
   step louder, with the answer's controls attached underneath. */
.ask { display: flex; gap: 12px; align-items: flex-start; margin-bottom: 22px; }
.ask .bubble { border-color: var(--ink); font-size: 1.0625rem; line-height: 1.55; }
.ask .bubble .hint { display: block; margin-top: 8px; font-size: 0.8125rem; color: var(--grey); line-height: 1.6; }

.answer { padding-left: 40px; }
.answer .field:last-of-type { margin-bottom: 0; }
.answer-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 22px; }
.answer-actions .spacer { flex: 1 1 auto; }

@media (max-width: 560px) {
  .turn-a, .answer { padding-left: 0; }
}

.convo-foot {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 48px; padding-top: 18px; border-top: 1px solid var(--line-soft);
}

.plan-grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.plan-price { font-size: 1.4rem; font-weight: 300; margin: 8px 0 4px; font-variant-numeric: tabular-nums; }
.plan-features { list-style: none; margin: 12px 0 0; padding: 0; font-size: 0.8125rem; color: var(--grey); }
.plan-features li { padding: 3px 0 3px 14px; position: relative; }
.plan-features li::before { content: "·"; position: absolute; left: 3px; }

/* ---------- toast ---------- */

#toasts { position: fixed; right: 20px; bottom: 20px; z-index: 300; display: grid; gap: 8px; max-width: 340px; }
.toast {
  background: var(--ink); color: var(--white); padding: 11px 16px; font-size: 0.8125rem;
  animation: toast-in 0.22s var(--ease);
}
.toast--bad { background: var(--bad); }
@keyframes toast-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* ---------- dialogs ---------- */

dialog {
  border: 1px solid var(--line); background: var(--white); color: var(--ink);
  padding: 0; max-width: 460px; width: calc(100% - 40px);
}
dialog::backdrop { background: rgba(12, 12, 11, 0.42); }
dialog .panel-body { padding: 24px; }
dialog .panel-foot { display: flex; gap: 10px; justify-content: flex-end; }

/* ---------- skeletons ---------- */

.skeleton { background: linear-gradient(90deg, var(--line-soft) 25%, rgba(17,17,16,0.04) 50%, var(--line-soft) 75%); background-size: 200% 100%; animation: sk 1.3s linear infinite; height: 1em; }
@keyframes sk { to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) {
  .skeleton { animation: none; }
  .toast { animation: none; }
  * { transition-duration: 0.01ms !important; }
}

/* ---------- impersonation banner ---------- */

.impersonating {
  background: var(--warn); color: #fff; padding: 8px var(--pad);
  font-size: 0.8125rem; display: flex; align-items: center; gap: 12px;
  position: sticky; top: 0; z-index: 60;
}
.impersonating a { text-decoration: underline; }

/* ---------- responsive ---------- */

@media (max-width: 900px) {
  .shell { display: block; }
  .topbar { display: flex; }
  .sidebar {
    position: fixed; inset: 0 auto 0 0; z-index: 80;
    transform: translateX(-100%);
    transition: transform 0.24s var(--ease);
    box-shadow: 0 0 0 100vmax rgba(12,12,11,0);
  }
  body.nav-open .sidebar { transform: none; }
  body.nav-open::after {
    content: ""; position: fixed; inset: 0; background: rgba(12,12,11,0.4); z-index: 70;
  }
  .content { padding-bottom: 56px; }
}

@media (max-width: 700px) {
  /* Once the status banner wraps, the flex spacer would leave the second
     column hanging off the first one's edge. Stack both columns flush left. */
  .hero-status { display: block; }
  .hero-status > * { min-width: 0 !important; }
  .hero-status > * + * { margin-top: 24px; }
  .hero-status .spacer { display: none; }
}

@media print {
  .sidebar, .topbar, .filters, .bulkbar, .btn { display: none !important; }
  body { background: #fff; }
  .card, .panel { border-color: #ccc; }
}

/* ============================================================
   Portal landing

   Where somebody arrives from linerelay.ai. It is the sign-in page — the
   marketing already happened, so this confirms where you are and gets you in,
   rather than selling the product a second time.

   Two columns: the marketing site's own hero footage on the left, the form on
   white to the right. On a phone the form comes first and the footage becomes
   a band beneath it, because almost everybody here is an existing customer
   coming back to read their messages.
   ============================================================ */

.landing {
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(392px, 0.98fr);
  grid-template-rows: minmax(100vh, auto);
  min-height: 100vh;
}
.landing a.plain:hover { opacity: 1; text-decoration: underline; text-underline-offset: 3px; }

.landing-brand { display: block; }
.landing-brand img { height: 22px; width: auto; }

.landing-title {
  font-size: clamp(2rem, 4.2vw, 3.15rem);
  font-weight: 300;
  line-height: 1.04;
  letter-spacing: -0.038em;
  max-width: 16ch;
}
.landing-title strong { font-weight: 500; }

.landing-foot { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; font-size: 0.8125rem; color: var(--grey-soft); }
.landing-foot a { color: var(--grey); }

.landing-form { width: 100%; max-width: 372px; }
.landing-form h2 { font-size: 1.0625rem; font-weight: 500; margin-bottom: 4px; }
.landing-form .sub { color: var(--grey); font-size: 0.875rem; margin-bottom: 24px; }

/* ---------- the footage ---------- */

.landing-media {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: clamp(32px, 4vw, 60px);
  overflow: hidden;
  background: var(--black);
  isolation: isolate;
}
.landing-media > * { position: relative; z-index: 2; }

.landing-media .shot {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The footage is a saturated tech blue; the portal is paper and ink. Pulling
     the saturation down and the contrast up lets it sit beside the rest of the
     interface instead of shouting over it. */
  filter: saturate(0.68) contrast(1.04) brightness(0.9);
}

/* Two scrims rather than one: an even wash so the whole frame recedes, and a
   stronger foot so the headline has something solid under it at any moment of
   the loop. */
.landing-media::before,
.landing-media::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}
.landing-media::before { background: rgba(12, 12, 11, 0.24); }
.landing-media::after {
  background: linear-gradient(to top, rgba(12, 12, 11, 0.78) 0%, rgba(12, 12, 11, 0.34) 30%, rgba(12, 12, 11, 0) 58%);
}

.landing-media .landing-title { color: var(--white); margin-bottom: 0; }

/* ---------- the form ---------- */

.landing-panel {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(36px, 5vw, 76px);
  background: var(--white);
}
.landing-panel .landing-foot { margin-top: 34px; padding-top: 20px; border-top: 1px solid var(--line-soft); }

/* The logo lives over the footage on a wide screen. On a phone the form panel
   comes first, so it moves into that instead of appearing twice. */
.landing-brand-mobile { display: none; }

@media (max-width: 900px) {
  .landing { grid-template-columns: 1fr; grid-template-rows: auto; }
  .landing-panel { order: -1; }
  .landing-form { max-width: none; }
  .landing-brand-mobile { display: block; margin-bottom: 30px; }
  .landing-media {
    order: 1;
    min-height: 62vh;
    padding: clamp(28px, 7vw, 40px);
    justify-content: flex-end;
  }
  .landing-media > .landing-brand { display: none; }
}
