/* ==========================================================================
   Velenza Support portal.

   A customer reaches this page on a bad day. The visual job is to read as
   calm and staffed — not busy, not clever, and above all not like a debug
   console. Restrained palette, one accent, generous space, system fonts so
   nothing waits on a webfont download during an outage.

   No build step. This file is hand-written and hand-read.
   ========================================================================== */

:root {
  --ink:        #16191d;
  --ink-soft:   #4d545e;
  --ink-faint:  #767d88;
  --paper:      #f7f7f5;
  --card:       #ffffff;
  --line:       #e2e2dd;
  --line-soft:  #eeeeea;
  --accent:     #1f5d50;
  --accent-ink: #ffffff;
  --accent-bg:  #e6efec;
  --warn:       #8a4b1f;
  --warn-bg:    #f8efe6;
  --alert:      #8f2f2a;
  --alert-bg:   #f9ecea;
  --live:       #2e7d63;

  --radius: 10px;
  --shell:  68rem;

  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
          "Liberation Mono", monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --ink:        #e9eaec;
    --ink-soft:   #a8aeb7;
    --ink-faint:  #7d838d;
    --paper:      #131518;
    --card:       #1b1e22;
    --line:       #2c3036;
    --line-soft:  #23272c;
    --accent:     #6fbfa8;
    --accent-ink: #10231e;
    --accent-bg:  #1b2a27;
    --warn:       #d8a271;
    --warn-bg:    #2a2119;
    --alert:      #e08c86;
    --alert-bg:   #2b1b1a;
    --live:       #6fbfa8;
  }
}

*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }

/* Present for a screen reader, absent for everyone else. Used for the
   composer's label, which a sighted reader takes from the placeholder and from
   sitting directly beneath the thread it replies to. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: 1.25rem;
}

/* --- masthead ----------------------------------------------------------- */

.masthead {
  border-bottom: 1px solid var(--line);
  background: var(--card);
}

.masthead__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding-block: 1.15rem;
}

.wordmark {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 1.05rem;
  letter-spacing: 0.005em;
}

.wordmark__mark {
  width: 0.85rem;
  height: 0.85rem;
  border-radius: 3px;
  background: var(--accent);
  flex: none;
}

.wordmark__text { font-weight: 620; }
.wordmark__thin { font-weight: 400; color: var(--ink-soft); }

.session {
  margin: 0;
  font-size: 0.85rem;
  color: var(--ink-faint);
}

.session[data-state="identified"] { color: var(--ink-soft); }

/* --- panels ------------------------------------------------------------- */

main.shell { padding-block: 2rem 1rem; }

.panel {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.6rem;
  margin-bottom: 1.25rem;
}

.panel__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.panel__title {
  margin: 0 0 0.5rem;
  font-size: 1.18rem;
  font-weight: 620;
  letter-spacing: -0.01em;
}

.panel__head .panel__title { margin-bottom: 0.9rem; }

.lede {
  margin: 0 0 1.15rem;
  color: var(--ink-soft);
  max-width: 46rem;
}

.fineprint {
  margin: 1rem 0 0;
  font-size: 0.875rem;
  color: var(--ink-faint);
  max-width: 46rem;
}

/* --- the floor: the mailbox -------------------------------------------- */

.panel--contact {
  border-left: 3px solid var(--accent);
}

/* Plain, selectable, and large enough to read off a screen someone is
   photographing with a phone because their laptop is the thing that broke. */
.address {
  margin: 0;
  font-family: var(--mono);
  font-size: clamp(1.15rem, 3.4vw, 1.6rem);
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--ink);
  user-select: all;
  overflow-wrap: anywhere;
}

.address__actions { margin: 1rem 0 0; }

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

.button {
  display: inline-block;
  border: 1px solid transparent;
  border-radius: 7px;
  padding: 0.55rem 1.05rem;
  font: inherit;
  font-size: 0.95rem;
  font-weight: 550;
  line-height: 1.3;
  text-decoration: none;
  cursor: pointer;
}

.button--primary {
  background: var(--accent);
  color: var(--accent-ink);
}

.button--primary:hover { filter: brightness(1.08); }

.button--quiet {
  background: transparent;
  border-color: var(--line);
  color: var(--ink-soft);
}

.button--quiet:hover { border-color: var(--ink-faint); color: var(--ink); }

.button:focus-visible,
.field__input:focus-visible,
.composer__input:focus-visible,
.convlist__item:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* A disabled fieldset dims its own controls; say why with the cursor too. */
.form__fields[disabled] { opacity: 0.55; }
.form__fields[disabled] .button { cursor: not-allowed; }

/* --- first time here: verify by email (FR-31) ---------------------------- */

/* A SECONDARY route inside the sign-in panel, not a second panel. Part F ranks
   the three ways in by friction — existing login, verify by email, just email us
   — and giving this its own card would present it as a peer of the mailbox
   panel, which is the floor and outranks it. The rule above it is the whole
   visual separation, and it is enough because app.js only ever reveals this
   block when the deployment can actually honour it. */
.self-enrol {
  margin-top: 1.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--line);
}

.self-enrol__title {
  margin: 0 0 0.4rem;
  font-size: 1rem;
  font-weight: 600;
}

/* The fineprint directly under the heading is introducing the form rather than
   trailing a section, so it loses the top margin `.fineprint` carries for its
   usual position. */
.self-enrol .fineprint { margin-top: 0; margin-bottom: 1rem; }

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

.form__fields {
  border: 0;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.9rem;
  max-width: 22rem;
}

.field { display: grid; gap: 0.3rem; }

.field__label {
  font-size: 0.85rem;
  font-weight: 550;
  color: var(--ink-soft);
}

.field__input {
  font: inherit;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--paper);
  color: var(--ink);
}

/* --- notices ------------------------------------------------------------ */

.notice {
  margin: 1rem 0 0;
  padding: 0.75rem 0.95rem;
  border-radius: 8px;
  background: var(--line-soft);
  color: var(--ink-soft);
  font-size: 0.9rem;
  max-width: 46rem;
}

.notice--error {
  background: var(--alert-bg);
  color: var(--alert);
}

.notice--warn {
  background: var(--warn-bg);
  color: var(--warn);
}

.notice__code {
  display: block;
  margin-top: 0.4rem;
  font-family: var(--mono);
  font-size: 0.8rem;
  opacity: 0.85;
}

/* --- the live indicator -------------------------------------------------
   This is the one piece of chrome that exists to make an ARCHITECTURAL claim
   visible: the browser holds an open subscription straight to the datastore,
   so messages land without a refresh and without any compute of ours in the
   path. The timestamp ticking on its own is the proof.
   ------------------------------------------------------------------------ */

.stream {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0 0 0.9rem;
  font-size: 0.8rem;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

.stream__dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--ink-faint);
  flex: none;
}

.stream[data-state="live"] { color: var(--live); }
.stream[data-state="live"] .stream__dot { background: var(--live); }

/* Serving the SDK's local cache rather than the server. Not an error — the
   page still shows real data — but it is emphatically not "live", and saying
   so is the whole reason this pill is trustworthy at all. */
.stream[data-state="cached"] { color: var(--warn); }
.stream[data-state="cached"] .stream__dot { background: var(--warn); }

.stream[data-state="error"] { color: var(--alert); }
.stream[data-state="error"] .stream__dot { background: var(--alert); }

/* --- workspace layout --------------------------------------------------- */

.workspace {
  display: grid;
  gap: 1.25rem;
  align-items: start;
}

@media (min-width: 62rem) {
  .workspace {
    grid-template-columns: minmax(0, 21rem) minmax(0, 1fr);
  }
  .workspace .panel { margin-bottom: 0; }
  .panel--thread { position: sticky; top: 1.25rem; }
}

/* --- conversation list -------------------------------------------------- */

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

.convlist__item {
  display: grid;
  gap: 0.35rem;
  width: 100%;
  text-align: left;
  font: inherit;
  color: inherit;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 0.75rem 0.85rem;
  cursor: pointer;
}

.convlist__item:hover { border-color: var(--ink-faint); }

.convlist__item[aria-current="true"] {
  background: var(--accent-bg);
  border-color: var(--accent);
}

.convlist__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
}

.convlist__when {
  font-size: 0.78rem;
  color: var(--ink-faint);
  white-space: nowrap;
}

.convlist__last {
  font-size: 0.86rem;
  color: var(--ink-soft);
}

.convlist__subject {
  margin: 0;
  color: var(--ink);
  font-weight: 650;
  overflow-wrap: anywhere;
}

.open-conversation {
  margin: 0 0 1.25rem;
  padding: 1rem;
  border: 1px solid var(--line-soft);
  background: var(--accent-bg);
}

.open-conversation__title { margin: 0 0 0.35rem; font-size: 1rem; }

.convlist__ref {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--ink-faint);
  overflow-wrap: anywhere;
}

.convlist__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
}

.tag {
  font-size: 0.72rem;
  padding: 0.05rem 0.4rem;
  border-radius: 4px;
  background: var(--line-soft);
  color: var(--ink-soft);
}

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

.pill {
  display: inline-block;
  font-size: 0.76rem;
  font-weight: 560;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  background: var(--line-soft);
  color: var(--ink-soft);
  white-space: nowrap;
}

.pill[data-tone="attention"] { background: var(--warn-bg);   color: var(--warn); }
.pill[data-tone="active"]    { background: var(--accent-bg); color: var(--accent); }
.pill[data-tone="done"]      { background: var(--line-soft); color: var(--ink-faint); }

/* --- thread ------------------------------------------------------------- */

.thread__meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
  padding-bottom: 0.9rem;
  border-bottom: 1px solid var(--line-soft);
  margin-bottom: 0.4rem;
}

.thread__reference { margin: 0; font-size: 0.82rem; color: var(--ink-faint); }
.thread__subject { margin: 0; width: 100%; font-weight: 650; overflow-wrap: anywhere; }
.thread__reference code {
  font-family: var(--mono);
  color: var(--ink-soft);
  user-select: all;
  overflow-wrap: anywhere;
}
.thread__status { margin: 0; }

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

/* THE THREAD BECOMES ITS OWN SCROLL REGION, BUT ONLY ON A WIDE SCREEN.
   ------------------------------------------------------------------------
   At this width the thread panel is already `position: sticky`, so an
   unbounded message list would push the composer off the bottom of the
   viewport on any long conversation — the one control that must always be
   reachable. Bounding the list keeps the composer pinned in view and makes
   "scrolled to the newest message" mean scrolling the thread rather than the
   whole document.

   Below this width it stays ordinary page flow ON PURPOSE. A nested scroll
   region on a phone is hostile — it steals the gesture and traps the page —
   and app.js's scrollToNewest() checks whether the list actually scrolls
   before touching it, so the narrow layout behaves exactly as it did before
   the composer existed. */
@media (min-width: 62rem) {
  .messages {
    max-height: min(52vh, 30rem);
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-right: 0.35rem;
  }
}

.message { display: grid; gap: 0.3rem; }

.message__head {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  flex-wrap: wrap;
}

.message__author { font-size: 0.86rem; font-weight: 600; }
.message__when   { font-size: 0.78rem; color: var(--ink-faint); }

.message__body {
  margin: 0;
  padding: 0.7rem 0.9rem;
  border-radius: 8px;
  background: var(--paper);
  border: 1px solid var(--line-soft);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.message--outbound .message__body {
  background: var(--accent-bg);
  border-color: transparent;
}

.message--outbound .message__author { color: var(--accent); }

.message__attachments {
  display: grid;
  gap: 0.4rem;
  font-size: 0.8rem;
  color: var(--ink-faint);
  border: 1px dashed var(--line);
  border-radius: 8px;
  padding: 0.55rem;
}

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

.message__attachment {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.message__attachment-name { color: var(--ink); font-weight: 600; overflow-wrap: anywhere; }
.message__attachment-meta { font-family: var(--mono); }
.message__attachment-gate { margin: 0; color: var(--ink-soft); }
.message__attachment-problem { width: 100%; color: var(--alert); }

.message__attachment-preview {
  width: 100%;
  display: grid;
  justify-items: start;
  gap: 0.45rem;
}

.message__attachment-preview img,
.message__attachment-preview iframe {
  display: block;
  width: min(100%, 42rem);
  max-height: 28rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--card);
}

.message__attachment-preview img { object-fit: contain; }
.message__attachment-preview iframe { height: 28rem; }

/* --- a message the server has not confirmed -----------------------------
   Written locally, held by the SDK, not acknowledged. It must be legible —
   it is what the customer just said — and it must not read as delivered.
   Hence a dashed edge and a softened body rather than a spinner: the state is
   "we are still holding this", not "something is happening". */

.message--pending .message__body {
  opacity: 0.72;
  border-style: dashed;
  border-color: var(--line);
}

.message__pending {
  font-size: 0.78rem;
  font-weight: 550;
  color: var(--warn);
}

/* --- the composer -------------------------------------------------------
   The only control on this page that writes anything. Deliberately plain: a
   box, a hint and a button. Nothing animates and the button never changes —
   it is not where a customer learns whether their message has left, because
   the button knows nothing about that. The MESSAGE says it, in the thread,
   from the SDK's own metadata (.message--pending above), and the notice under
   the box says the part the thread cannot. A control that mimed progress it
   could not observe would be the one animated lie on the page. */

.composer {
  margin-top: 1.15rem;
  padding-top: 1.15rem;
  border-top: 1px solid var(--line-soft);
}

.composer__fields {
  border: 0;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.6rem;
}

.attachment-picker {
  display: grid;
  gap: 0.35rem;
  padding: 0.55rem;
  border: 1px dashed var(--line);
  border-radius: 8px;
}

.attachment-picker .fineprint { margin: 0; }

.attachment-files {
  margin: 0;
  padding-left: 1.2rem;
  color: var(--ink-soft);
  font-size: 0.82rem;
}

.attachment-progress {
  display: grid;
  grid-template-columns: minmax(8rem, 1fr) auto;
  align-items: center;
  gap: 0.5rem;
  color: var(--ink-soft);
  font-size: 0.8rem;
}

.attachment-progress progress { width: 100%; }

.composer__input {
  font: inherit;
  width: 100%;
  /* Height is managed by app.js to fit the message; max-height is the clamp it
     grows into, after which the box scrolls rather than swallowing the page. */
  resize: none;
  min-height: 3.2rem;
  max-height: 12rem;
  overflow-y: auto;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--paper);
  color: var(--ink);
  line-height: 1.5;
}

.composer__actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.composer__hint {
  margin: 0;
  font-size: 0.78rem;
  color: var(--ink-faint);
}

/* On a narrow screen the hint and the button will not sit side by side, and a
   half-width Send stranded under a line of small print reads as an afterthought.
   Stack them instead, with the button directly beneath the box it submits and
   the hint underneath, out of the way. */
@media (max-width: 30rem) {
  .composer__actions {
    flex-direction: column-reverse;
    align-items: stretch;
    gap: 0.5rem;
  }
  .composer__actions .button { width: 100%; }
  .composer__hint { text-align: center; }
}

.composer__fields[disabled] { opacity: 0.55; }
.composer__fields[disabled] .button { cursor: not-allowed; }

.composer .notice { margin-top: 0.75rem; }

/* The survey is a narrow, additive authenticated route; it does not replace
   the mailbox or conversations workspace that remains useful without it. */
.csat { max-width: 42rem; }
.csat .field__input { max-width: 100%; }

/* --- footer ------------------------------------------------------------- */

.footer {
  padding-block: 1.5rem 2.5rem;
  color: var(--ink-faint);
  font-size: 0.84rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.footer p { margin: 0; max-width: 42rem; }
.footer__signout { flex: none; }
