/* masa booking simulator — CLIENT VIEW.
   `?view=client` — what you hand a barber. Everything here is scoped under
   `html.client`, so this file is inert in the dev view and the two modes cannot
   drift into each other.

   ── WHY IT LOOKS LIKE THIS ──

   🔴 GREEN BUBBLES, NOT BLUE. This product is SMS. On an iPhone, SMS is green.
   Blue would be iMessage, which masa deliberately does NOT do — chasing blue
   bubbles means an unofficial bridge, an Apple ToS risk, and enforcement moving
   from carriers to account termination (ruling, Jul 28 2026). Demoing blue
   would be selling something we do not deliver, and the barber would find out
   the first week. The wedge was never bubble colour; it is that his customers
   already text him.

   ⛔ NO TYPING INDICATOR, and its absence is deliberate — see booking.js. SMS has
   no typing indicator, no read receipts and no "Delivered" under a green bubble.
   Every one of those would demo a capability the channel cannot provide.

   Zero blur layers, per the masa blur budget: iOS Safari silently drops blur
   past ~3–5 layers and paints nothing for the excess. A solid header costs
   nothing and cannot fail that way.

   Light by default because that is how most phones are set, with a dark-mode
   block below — a barber's own phone could be either, and the demo should look
   native on whichever he is holding.

   ⚠️ CONTRAST, MEASURED RATHER THAN EYEBALLED (validated the calculator against
   black-on-white = 21.00 and #767676-on-white = 4.54 before trusting it):

     black on the received bubble  #e9e9eb   17.32:1   ✓
     white on the sent bubble      #34c759    2.22:1   ✗ WCAG AA wants 4.5:1

   🔴 The failing one is KEPT, deliberately, and this is the reasoning. #34c759
   is the colour Apple actually ships for SMS bubbles — the customer's real
   phone is 2.22:1 whatever we do here, and this mockup's entire job is to show
   the barber what his customer sees. Darkening it would make the demo prettier
   and less true, and would not improve one real conversation.
   ⇒ The rule applied: match iOS exactly where we are MIMICKING iOS, and meet AA
   everywhere the text is ours (see `--muted`). If this ever becomes a surface a
   customer reads rather than a picture of one, that trade flips. */

html.client,
html.client body {
  height: 100%;
  background: #f2f2f7;
}

@media (prefers-color-scheme: dark) {
  html.client, html.client body { background: #000; }
}

/* ── the phone chrome belongs to the CLIENT view only ───────────────────── */
/* It lives in index.html unconditionally, so the DEV view has to hide it —
   otherwise the status bar and contact header render unstyled above the thread.
   `:not(.client)` rather than a positive rule, so the no-JS case (className
   stays `no-js`) also hides it: the dev view is the fail-open default and it
   should not show half a handset. */

html:not(.client) .status,
html:not(.client) .contact { display: none; }

/* ── strip the dev surface ──────────────────────────────────────────────── */

html.client .bar,
html.client .trace,
html.client .note { display: none; }

/* A pitch demo's note stays visible: it says whose demo this is, which facts
   are placeholders, and that no payment is real (lib/demos.js). */
html.client .note.note--demo {
  display: block;
  color: var(--muted);
  padding: 0.5rem 0.75rem 0.75rem;
  line-height: 1.4;
}

html.client .wrap {
  display: block;
  max-width: none;
  margin: 0;
  padding: 0;
  height: 100dvh;
}

/* ── the handset ────────────────────────────────────────────────────────── */

html.client .phone {
  --recv: #e9e9eb;
  --recv-ink: #000;
  --sent: #34c759;         /* iOS systemGreen: SMS, not iMessage */
  --sent-ink: #fff;
  --chrome: #f6f6f6;
  --chrome-ink: #000;
  --hair: rgba(0, 0, 0, 0.18);
  /* ⚑ Apple's own secondary grey is #8e8e93, which measures 3.02:1 on this
     background — below WCAG AA's 4.5:1. Apple's colour is right for the parts
     that MIMIC iOS chrome; it is not right for text WE author. #6e6e73 measures
     4.69:1 and is visually indistinguishable at this size. */
  --muted: #6e6e73;

  display: flex;
  flex-direction: column;
  width: min(390px, 100vw);
  height: min(844px, 100dvh);
  /* ⚑ booking.css sets `max-height: 78vh` on .phone, and a `height` DOES NOT
     override a `max-height` — the panel silently clipped to 78% of the viewport
     and the composer floated in the middle of the screen. Grep the property you
     are fighting, not the one you are setting. */
  max-height: 100dvh;
  min-height: 0;
  margin: max(0px, calc((100dvh - 844px) / 2)) auto;
  background: #fff;
  border-radius: 0;
  overflow: hidden;
  border: 0;
}

/* Only draw a bezel when there is room for one. On a real phone the page IS the
   phone, and a fake bezel inside a real one looks like a mistake. */
@media (min-width: 440px) and (min-height: 900px) {
  html.client .phone {
    border: 10px solid #1c1c1e;
    border-radius: 44px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25);
  }
}

@media (prefers-color-scheme: dark) {
  html.client .phone {
    --recv: #262628;
    --recv-ink: #fff;
    --chrome: #1c1c1e;
    --chrome-ink: #fff;
    --hair: rgba(255, 255, 255, 0.16);
    background: #000;
  }
}

/* ── status bar ─────────────────────────────────────────────────────────── */

html.client .status {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.7rem 1.5rem 0.2rem;
  background: var(--chrome);
  color: var(--chrome-ink);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.01em;
}

html.client .status-r { display: flex; align-items: center; gap: 5px; }

/* Signal and battery, drawn rather than imaged — two elements, no asset. */
html.client .sig,
html.client .batt {
  display: inline-block;
  background: currentColor;
  opacity: 0.85;
}
html.client .sig  { width: 16px; height: 10px; clip-path: polygon(0 70%,20% 70%,20% 100%,0 100%,25% 45%,45% 45%,45% 100%,25% 100%,50% 22%,70% 22%,70% 100%,50% 100%,75% 0,95% 0,95% 100%,75% 100%); }
html.client .batt { width: 22px; height: 11px; border-radius: 3px; }

/* ── contact header ─────────────────────────────────────────────────────── */

html.client .contact {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.35rem 1rem 0.7rem;
  background: var(--chrome);
  color: var(--chrome-ink);
  border-bottom: 1px solid var(--hair);
}

html.client .avatar {
  width: 30px; height: 30px;
  border-radius: 50%;
  background: #8e8e93;
  color: #fff;
  display: grid; place-items: center;
  font-size: 0.72rem; font-weight: 600;
  text-transform: uppercase;
  flex: none;
}

html.client .who {
  font-size: 0.95rem;
  font-weight: 600;
  /* min-width:0 so a long shop name shrinks instead of widening the header —
     a flex child defaults to min-width:auto and would overflow. */
  min-width: 0;
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

html.client .restart {
  flex: none;
  background: none; border: 0;
  color: var(--muted);
  font-size: 1.05rem;
  line-height: 1;
  padding: 0.35rem;
  cursor: pointer;
  border-radius: 8px;
  /* 24x24 minimum target, WCAG 2.5.8 */
  min-width: 24px; min-height: 24px;
}
html.client .restart:hover { color: var(--chrome-ink); }

/* ── the thread ─────────────────────────────────────────────────────────── */

html.client .thread {
  flex: 1;
  gap: 2px;
  padding: 0.9rem 0.85rem;
  background: transparent;
  overflow-y: auto;
}

html.client .msg {
  max-width: 76%;
  padding: 0.5rem 0.78rem;
  border-radius: 19px;
  font-size: 1.0rem;
  line-height: 1.35;
  border: 0;
}

html.client .msg.them {
  background: var(--recv);
  color: var(--recv-ink);
  border-bottom-left-radius: 19px;
  margin-bottom: 0.35rem;
}

html.client .msg.us {
  background: var(--sent);
  color: var(--sent-ink);
  border-bottom-right-radius: 19px;
  margin-bottom: 0.35rem;
}

/* Consecutive bubbles from the same side tuck together, the way Messages does. */
html.client .msg.them + .msg.them,
html.client .msg.us + .msg.us { margin-top: -0.25rem; }

html.client .msg a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
}

html.client .sys {
  align-self: center;
  color: var(--muted);
  font-size: 0.74rem;
  padding: 0.5rem 0;
  text-align: center;
}

/* A demo's handoff: the text the owner would get (booking.js ownerPreview). */
html.client .sys.sys--owner,
.sys.sys--owner {
  align-self: stretch;
  text-align: left;
  margin: 0.25rem 0.75rem;
  padding: 0.6rem 0.75rem;
  border: 1px dashed var(--hair);
  border-radius: 12px;
  line-height: 1.4;
}

/* The piece a visitor picked, attached to the demo owner card. */
.sys--owner .sys__pic { display: block; width: 96px; height: 96px; object-fit: cover; border-radius: 8px; margin-top: 8px; }

/* ── composer ───────────────────────────────────────────────────────────── */

html.client .composer {
  display: flex;
  /* The field grows upward as it wraps; the camera and send stay on the bottom line, like Messages. */
  align-items: flex-end;
  gap: 0.5rem;
  padding: 0.6rem 0.75rem calc(0.6rem + env(safe-area-inset-bottom));
  background: var(--chrome);
  border-top: 1px solid var(--hair);
}

html.client .composer .composer__field {
  /* Wraps and grows like the Messages field (booking.js sizes it; capped ~5 lines). */
  resize: none;
  overflow-y: auto;
  max-height: 8.5em;
  line-height: 1.35;
  font-family: inherit;
  flex: 1;
  min-width: 0;
  background: transparent;
  color: var(--chrome-ink);
  border: 1px solid var(--hair);
  border-radius: 18px;
  padding: 0.5rem 0.9rem;
  /* 16px minimum or iOS Safari zooms the whole page on focus. */
  font-size: 16px;
}

html.client .composer .composer__field:focus {
  outline: none;
  border-color: var(--muted);
}

/* The iOS send affordance: a filled circle with an arrow, not a word. */
html.client .composer .composer__send {
  flex: none;
  width: 30px; height: 30px;
  padding: 0;
  border: 0; border-radius: 50%;
  background: var(--sent);
  color: #fff;
  font-size: 0;
  cursor: pointer;
  position: relative;
}
html.client .composer .composer__send::after {
  content: "↑";
  font-size: 1rem;
  font-weight: 700;
  position: absolute; inset: 0;
  display: grid; place-items: center;
}
html.client .composer .composer__send:disabled { opacity: 0.35; cursor: default; }

/* The camera button left of the field (Messages puts it there). Named, never a bare
   element selector: `.composer button` once styled every control in here as Send. */
html.client .composer .composer__photo[hidden] { display: none !important; }
html.client .composer .composer__photo {
  flex: none;
  width: 30px; height: 30px;
  border-radius: 50%;
  display: grid; place-items: center;
  color: var(--muted);
  cursor: pointer;
}
html.client .composer .composer__photo::before {
  content: "";
  width: 22px; height: 22px;
  background: currentColor;
  -webkit-mask: url("/assets/img/icons/camera.svg") center / contain no-repeat;
          mask: url("/assets/img/icons/camera.svg") center / contain no-repeat;
}
html.client .composer .composer__photo:focus-within { outline: 2px solid var(--muted); outline-offset: 2px; }
/* A picture in the thread: the customer's own, shown only on their device. */
html.client .msg.us.msg--photo { padding: 3px; background: var(--sent); }
.msg--photo img { display: block; max-width: 180px; max-height: 220px; border-radius: 14px; object-fit: cover; }

/* ── the way back ───────────────────────────────────────────────────────── */
/* The "demo" marker IS the link home. Styled as plain status-bar text so it
   reads as chrome rather than as a control a customer would tap. */

html.client .status-l {
  color: inherit;
  text-decoration: none;
}
html.client .status-l:hover { text-decoration: underline; }

@media (prefers-reduced-motion: no-preference) {
  html.client .msg { animation: pop 140ms ease-out; }
  @keyframes pop {
    from { transform: translateY(3px); opacity: 0; }
    to   { transform: none; opacity: 1; }
  }
}
