/* ============================================================
   Tattoo Studio — Internal Scheduling
   Self-contained stylesheet. No external fonts or frameworks.
   Designed iPad-first (landscape + portrait), scales to iPhone.
   ============================================================ */

:root {
  --canvas: #F4F4F2;
  --surface: #FFFFFF;
  --ink: #17181A;
  --ink-soft: #2A2C2F;
  --muted: #6B7075;
  --muted-2: #9AA0A6;
  --line: #E6E6E3;
  --line-strong: #D8D8D4;

  --accent: #C23B3B;
  --accent-dark: #A82F2F;

  --ok: #1E8A5B;
  --ok-bg: #E3F3EB;
  --warn: #B97614;
  --warn-bg: #FBF0DC;
  --info: #3B6FD4;
  --info-bg: #E8EEF9;
  --neutral-bg: #EEEEEC;
  --danger-bg: #F9E7E7;

  --sidebar-bg: #1B1C1E;
  --sidebar-ink: #E8E8E6;
  --sidebar-muted: #9C9FA3;

  --radius: 12px;
  --radius-sm: 9px;
  --shadow: 0 1px 2px rgba(23,24,26,.05), 0 4px 16px rgba(23,24,26,.06);
  --shadow-lift: 0 6px 28px rgba(23,24,26,.16);

  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  --sidebar-w: 240px;
  --drawer-w: 400px;
  --touch: 44px;

  /* Safe-area insets. The viewport is declared viewport-fit=cover and the iOS
     status bar style is black-translucent (see includes/layout_header.php), so
     once this is added to the Home Screen the page really does extend under
     the notch / Dynamic Island and the home indicator. Everything that touches
     a screen edge has to pay these back, or content sits under the hardware.
     The 0px fallbacks make every rule below a no-op on a normal desktop
     browser. */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
}

* { box-sizing: border-box; }
/* Several classes below set their own unconditional `display` (e.g. .btn,
   .field-hint, .confirm-row) which — per how the cascade actually works —
   silently wins over the browser's built-in `[hidden] { display: none }`
   rule, since author styles beat user-agent styles regardless of
   specificity. Without this, toggling `el.hidden = true` on any such
   element from JS does nothing visible. This one rule is the standard fix. */
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.45;
  color: var(--ink);
  background: var(--canvas);
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4 { margin: 0; line-height: 1.2; letter-spacing: -0.01em; }
p { margin: 0 0 .6em; }
/* Every <ul> in this app is a custom-styled list (appointment rows, client
   rows, updates, etc.) — none want the default bullet/indent, and
   display:flex on the <ul> alone doesn't reliably suppress markers across
   browsers. */
ul { list-style: none; margin: 0; padding: 0; }
a { color: var(--info); text-decoration: none; }
a:hover { text-decoration: underline; }
img { max-width: 100%; }
button { font: inherit; color: inherit; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  clip: rect(0 0 0 0); overflow: hidden; white-space: nowrap;
}
.pre-line { white-space: pre-line; }
.wrap-anywhere { overflow-wrap: anywhere; }
.muted { color: var(--muted); }
.small { font-size: 13px; }

/* ---------- Auth pages (login / setup) ---------- */
.auth-body {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: calc(24px + var(--safe-top)) calc(24px + var(--safe-right)) calc(24px + var(--safe-bottom)) calc(24px + var(--safe-left));
  background:
    radial-gradient(1200px 500px at 80% -10%, #ECECE9 0%, transparent 60%),
    var(--canvas);
}
.auth-card {
  width: 100%;
  max-width: 420px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: var(--shadow);
  padding: 32px 28px;
}
.auth-card h1 { font-size: 21px; margin-bottom: 4px; }
.auth-intro { color: var(--muted); font-size: 14px; margin-bottom: 18px; }
.auth-foot { margin-top: 18px; font-size: 13px; color: var(--muted); }
.auth-quote {
  margin: 0 0 18px; font-size: 13.5px; font-style: italic; color: var(--muted);
  border-left: 3px solid var(--line-strong); padding-left: 12px;
}
.auth-attribution {
  margin: 0; font-size: 12px; color: var(--muted-2); text-align: center;
  max-width: 420px;
}

/* ---------- App shell ---------- */
.shell { min-height: 100vh; min-height: 100dvh; }

.sidebar {
  position: fixed;
  inset: 0 auto 0 0;
  width: var(--sidebar-w);
  background: var(--sidebar-bg);
  color: var(--sidebar-ink);
  display: flex;
  flex-direction: column;
  z-index: 60;
  transform: translateX(-100%);
  transition: transform .22s ease;
}
.sidebar.is-open { transform: translateX(0); box-shadow: var(--shadow-lift); }

.sidebar-brand { padding: calc(22px + var(--safe-top)) 20px 16px calc(20px + var(--safe-left)); }
.sidebar-brand > div { min-width: 0; flex: 1; }
/* Studio name and subtitle must never be cut off with "…" — wrap onto a
   second line instead if the sidebar is ever too narrow for them. */
.sidebar-brand .brand-name {
  font-size: 17px; font-weight: 700; color: #fff; letter-spacing: .01em;
  overflow-wrap: break-word;
}
.sidebar-brand .brand-sub {
  font-size: 12px; color: var(--sidebar-muted); margin-top: 2px;
  overflow-wrap: break-word;
}

.sidebar-nav { flex: 1; padding: 8px 12px 8px calc(12px + var(--safe-left)); overflow-y: auto; -webkit-overflow-scrolling: touch; }
.nav-item {
  display: flex; align-items: center; gap: 10px;
  min-height: var(--touch);
  padding: 0 12px;
  margin-bottom: 2px;
  border-radius: 9px;
  color: var(--sidebar-ink);
  font-size: 14.5px;
  font-weight: 500;
  text-decoration: none;
}
.nav-item:hover { background: rgba(255,255,255,.06); text-decoration: none; }
.nav-item.is-active { background: rgba(255,255,255,.12); color: #fff; font-weight: 600; }
.nav-item-label { flex: 1; }
.nav-badge {
  flex: none;
  min-width: 20px; height: 20px; padding: 0 6px;
  border-radius: 999px;
  background: var(--accent); color: #fff;
  font-size: 11px; font-weight: 700; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
}

.sidebar-user {
  border-top: 1px solid rgba(255,255,255,.08);
  padding: 14px 16px calc(14px + var(--safe-bottom)) calc(16px + var(--safe-left));
  display: flex; align-items: center; gap: 10px;
}
.sidebar-user .avatar { flex: none; }
.sidebar-user-meta { min-width: 0; flex: 1; }
.sidebar-user-name { font-size: 13.5px; font-weight: 600; color: #fff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sidebar-user-role { font-size: 12px; color: var(--sidebar-muted); text-transform: capitalize; }
.sidebar-signout {
  color: var(--sidebar-muted); font-size: 12.5px; text-decoration: none;
  padding: 8px 6px; border-radius: 7px;
}
.sidebar-signout:hover { color: #fff; text-decoration: none; background: rgba(255,255,255,.06); }

/* Explicit in-panel close button: once the sidebar is open it visually covers
   the hamburger toggle underneath it (same on-screen position at narrow
   widths), so that button alone can never close it again — this one lives
   inside the open panel itself and is always reachable. */
.sidebar-close {
  margin-left: auto; flex: none;
  width: 34px; height: 34px;
  border: 1px solid rgba(255,255,255,.16); background: transparent;
  color: var(--sidebar-ink); border-radius: 9px;
  font-size: 18px; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.sidebar-close:hover { background: rgba(255,255,255,.08); color: #fff; }

#navScrim {
  position: fixed; inset: 0; background: rgba(23,24,26,.44);
  z-index: 55; opacity: 0; pointer-events: none; transition: opacity .2s ease;
}
#navScrim.is-on { opacity: 1; pointer-events: auto; }

.main { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; }

.topbar {
  display: flex; align-items: center; gap: 12px;
  padding: calc(14px + var(--safe-top)) calc(18px + var(--safe-right)) 10px calc(18px + var(--safe-left));
}
.topbar-titles { flex: 1; min-width: 0; }
.page-title { font-size: 24px; font-weight: 700; }
.page-subtitle { font-size: 13.5px; color: var(--muted); margin-top: 2px; }
.topbar-actions { display: flex; align-items: center; gap: 10px; flex: none; }

.nav-toggle {
  flex: none;
  width: var(--touch); height: var(--touch);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
}
.nav-toggle span { display: block; width: 18px; height: 2px; background: var(--ink); border-radius: 2px; position: relative; }
.nav-toggle span::before, .nav-toggle span::after {
  content: ""; position: absolute; left: 0; width: 18px; height: 2px; background: var(--ink); border-radius: 2px;
}
.nav-toggle span::before { top: -6px; }
.nav-toggle span::after { top: 6px; }

.content {
  flex: 1; max-width: 1240px; width: 100%;
  padding: 6px calc(18px + var(--safe-right)) calc(90px + var(--safe-bottom)) calc(18px + var(--safe-left));
}

/* Wide screens: sidebar starts open beside the content, and the hamburger
   collapses/expands it (app.js toggles .nav-collapsed on .shell). The in-panel
   × close button is mobile-only — hidden here via an ID selector with
   !important on purpose: the button also carries the shared .btn class, whose
   own `display` rule sits later in this file and would otherwise win the
   display tie against a plain class rule here. */
@media (min-width: 1100px) {
  /* The sidebar is pinned to the left edge, so in landscape on a notched
     phone/iPad it has to widen by the left inset and the content start where
     it really ends — otherwise the nav sits under the hardware cutout. */
  .sidebar { transform: none; box-shadow: none; width: calc(var(--sidebar-w) + var(--safe-left)); }
  #navScrim { display: none !important; }
  #sidebarClose { display: none !important; }
  .main { margin-left: calc(var(--sidebar-w) + var(--safe-left)); transition: margin-left .22s ease; }
  /* Content is no longer against the left edge here, so only the right inset
     is still owed on that side. */
  .topbar { padding: calc(22px + var(--safe-top)) calc(28px + var(--safe-right)) 12px 28px; }
  .content { padding: 8px calc(28px + var(--safe-right)) calc(60px + var(--safe-bottom)) 28px; }

  .shell.nav-collapsed .sidebar { transform: translateX(-100%); }
  .shell.nav-collapsed .main { margin-left: 0; }
  .shell.nav-collapsed .topbar { padding-left: calc(28px + var(--safe-left)); }
  .shell.nav-collapsed .content { padding-left: calc(28px + var(--safe-left)); }
}

/* ---------- Cards / sections ---------- */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 18px;
  margin-bottom: 16px;
}
.card-title { font-size: 16.5px; font-weight: 700; margin-bottom: 12px; }
.card-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 12px;
}
.card-head .card-title { margin-bottom: 0; }

.empty {
  color: var(--muted);
  font-size: 14px;
  padding: 22px 8px;
  text-align: center;
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: var(--touch);
  padding: 0 18px;
  border-radius: 10px;
  border: 1px solid transparent;
  font-size: 14.5px;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}
.btn { transition: background-color .15s ease, border-color .15s ease, box-shadow .15s ease, transform .1s ease; }
.btn:hover { text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .55; cursor: default; transform: none; }

.btn-primary { background: var(--ink); color: #fff; }
.btn-primary:hover { background: #000; }
.btn-accent { background: var(--accent); color: #fff; }
.btn-accent:hover { background: var(--accent-dark); }
.btn-secondary { background: var(--surface); color: var(--ink); border-color: var(--line-strong); }
.btn-secondary:hover { background: #FAFAF8; }
.btn-ghost { background: transparent; color: var(--ink); border-color: transparent; }
.btn-ghost:hover { background: var(--neutral-bg); }
.btn-danger-ghost { background: transparent; color: var(--accent); border-color: var(--line-strong); }
.btn-danger-ghost:hover { background: var(--danger-bg); border-color: #E4B8B8; }
.btn-sm { min-height: 38px; padding: 0 13px; font-size: 13.5px; border-radius: 9px; }
.btn-block { width: 100%; }
.btn-icon { width: var(--touch); padding: 0; }

/* ---------- Badges ---------- */
.badge {
  display: inline-flex; align-items: center;
  padding: 4px 11px;
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
}
.badge-confirmed { background: var(--ok-bg); color: var(--ok); }
.badge-deposit_required { background: var(--warn-bg); color: var(--warn); }
.badge-rescheduled { background: var(--info-bg); color: var(--info); }
.badge-cancelled { background: var(--neutral-bg); color: var(--muted); }
.badge-no_show { background: var(--danger-bg); color: var(--accent); }
.badge-role { background: var(--neutral-bg); color: var(--ink-soft); text-transform: capitalize; }

/* ---------- Dots / avatars ---------- */
.dot {
  display: inline-block; width: 10px; height: 10px; border-radius: 50%;
  background: var(--artist, var(--muted-2)); flex: none;
}
.avatar {
  width: 38px; height: 38px; border-radius: 50%;
  background: var(--artist, #3B6FD4);
  color: #fff; font-size: 13.5px; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center;
  letter-spacing: .02em;
  /* An avatar is always a fixed circle. !important because it sits inside a
     lot of flex rows, and one careless "> span { flex: 1 }" elsewhere is
     enough to stretch it into an unrecognisable bar. */
  flex: none !important;
  aspect-ratio: 1;
}
.avatar-img {
  object-fit: cover; background: var(--neutral-bg);
  border: 1px solid rgba(0,0,0,.06);
}
.avatar-xl { width: 96px; height: 96px; font-size: 30px; }
.avatar-lg { width: 56px; height: 56px; font-size: 18px; }

/* ---------- Forms ---------- */
.field { display: block; margin-bottom: 14px; min-width: 0; }
.field-label {
  display: block; font-size: 12.5px; font-weight: 600; color: var(--ink-soft);
  margin-bottom: 6px; letter-spacing: .01em;
}
.field input[type="text"],
.field input[type="email"],
.field input[type="password"],
.field input[type="number"],
.field input[type="date"],
.field input[type="time"],
.field input[type="search"],
.field select,
.field textarea {
  width: 100%;
  min-height: var(--touch);
  padding: 10px 13px;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  background: #FCFCFB;
  font: inherit;
  color: var(--ink);
}
.field textarea { min-height: 84px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: var(--ink);
  background: #fff;
  box-shadow: 0 0 0 3px rgba(23,24,26,.08);
}
.field-hint { display: block; font-size: 12.5px; color: var(--muted); margin-top: 5px; }
.field-hint-inline { font-size: 12.5px; font-weight: 400; color: var(--muted); }

.field-check {
  display: flex; align-items: center; gap: 10px;
  min-height: var(--touch); margin-bottom: 10px;
  font-size: 14.5px; cursor: pointer;
}
.field-check input[type="checkbox"] {
  width: 22px; height: 22px; accent-color: var(--ink); flex: none;
}

.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; }
.form-grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0 16px; }
.span-2 { grid-column: 1 / -1; }
.form-foot { display: flex; gap: 10px; justify-content: flex-end; margin-top: 6px; flex-wrap: wrap; }
.inline-fields { display: flex; gap: 12px; }
.inline-fields .field { flex: 1; }

@media (max-width: 560px) {
  .form-grid, .form-grid-3 { grid-template-columns: 1fr; }
}

/* ---------- Alerts / toast ---------- */
.alert {
  border-radius: 10px; padding: 12px 14px; margin-bottom: 14px; font-size: 14px;
}
.alert-error { background: var(--danger-bg); color: #8C2626; border: 1px solid #EFC9C9; }
.alert-ok { background: var(--ok-bg); color: #14603F; border: 1px solid #C4E4D4; }
.alert ul { margin: 0; padding-left: 18px; }

#toast {
  /* Clears the home indicator, which otherwise sits right on top of it. */
  position: fixed; left: 50%; bottom: calc(24px + var(--safe-bottom)); transform: translateX(-50%) translateY(20px);
  background: var(--ink); color: #fff;
  padding: 12px 20px; border-radius: 999px;
  font-size: 14px; font-weight: 500;
  box-shadow: var(--shadow-lift);
  opacity: 0; pointer-events: none;
  transition: opacity .2s ease, transform .2s ease;
  z-index: 200; max-width: calc(100vw - 40px); text-align: center;
}
#toast.is-on { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ---------- Upload / saving feedback: spinners on buttons, thumbnails, avatars ---------- */
.spinner {
  display: inline-block; width: 15px; height: 15px;
  border: 2px solid rgba(255,255,255,.35); border-top-color: currentColor;
  border-radius: 50%; animation: ts-spin .7s linear infinite;
  vertical-align: -3px; flex: none;
}
.btn-secondary .spinner, .btn-ghost .spinner { border-color: rgba(23,24,26,.2); border-top-color: var(--ink); }
@keyframes ts-spin { to { transform: rotate(360deg); } }

.thumb-uploading {
  display: flex; align-items: center; justify-content: center;
  background: var(--neutral-bg); cursor: default;
}
.thumb-uploading .spinner { border-color: rgba(23,24,26,.15); border-top-color: var(--muted); width: 20px; height: 20px; }

.avatar-uploading { position: relative; overflow: hidden; }
.avatar-uploading::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background: rgba(23,24,26,.6); z-index: 1;
}
.avatar-uploading::before {
  content: ""; position: absolute; top: 50%; left: 50%; width: 28px; height: 28px;
  margin: -14px 0 0 -14px; border-radius: 50%; z-index: 2;
  border: 3px solid rgba(255,255,255,.35); border-top-color: #fff;
  animation: ts-spin .7s linear infinite;
}

/* ---------- Dashboard ---------- */
.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 12px;
  margin-bottom: 16px;
}
.stat-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 4px solid var(--stat, var(--info));
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 14px 16px;
  display: block; text-decoration: none; color: inherit;
}
.stat-card:hover { text-decoration: none; box-shadow: var(--shadow-lift); }
.stat-label { font-size: 13px; color: var(--muted); }
.stat-value { font-size: 22px; font-weight: 700; margin-top: 3px; }
.stat-link { font-size: 13px; color: var(--info); font-weight: 600; margin-top: 4px; display: inline-block; }

.dash-grid { display: grid; grid-template-columns: 1fr; gap: 0 16px; }
@media (min-width: 980px) {
  .dash-grid { grid-template-columns: minmax(0, 1.9fr) minmax(260px, 1fr); align-items: start; }
}

/* ---------- Appointment list rows ---------- */
.apt-list { display: flex; flex-direction: column; gap: 10px; }
.apt-row {
  display: flex; align-items: center; gap: 14px;
  width: 100%;
  text-align: left;
  background: #FAFAF8;
  border: 1px solid var(--line);
  border-left: 4px solid var(--artist, var(--muted-2));
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.apt-row:hover { background: #F5F5F2; }
.apt-time { flex: none; width: 76px; font-weight: 700; font-size: 14px; }
.apt-main { flex: 1; min-width: 0; }
.apt-client { font-weight: 700; font-size: 15px; }
.apt-sub { font-size: 13px; color: var(--muted); margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.apt-side { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 5px; }
.apt-deposit { font-size: 12.5px; color: var(--muted); }
.apt-row.is-past { opacity: .78; }

@media (max-width: 560px) {
  .apt-time { width: 62px; font-size: 13px; }
  .apt-side { align-items: flex-end; }
  .apt-deposit { display: none; }
}

/* ---------- Team snapshot / recent changes ---------- */
.team-snap { display: flex; flex-direction: column; gap: 12px; }
.team-snap-row { display: flex; align-items: center; gap: 10px; }
.team-snap-name { font-weight: 600; font-size: 14px; }
.team-snap-next { font-size: 12.5px; color: var(--muted); }

.change-list { display: flex; flex-direction: column; gap: 12px; }
.change-item { border-left: 3px solid var(--line-strong); padding-left: 11px; }
.change-action { font-weight: 600; font-size: 13.5px; }
.change-meta { font-size: 12.5px; color: var(--muted); margin-top: 1px; }

/* ---------- Filter bar / day groups (Appointments page) ---------- */
.filter-bar { display: flex; flex-wrap: wrap; gap: 0 12px; align-items: flex-end; }
.filter-bar .field { margin-bottom: 10px; flex: 1 1 150px; }
.filter-bar .btn { margin-bottom: 10px; }

.day-group { margin-bottom: 16px; }
.day-heading {
  font-size: 13px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .05em;
  margin: 0 4px 8px;
}

/* ---------- Clients ---------- */
.client-tools { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.client-tools form { flex: 1; display: flex; gap: 10px; min-width: 220px; }
.client-tools .field { flex: 1; margin-bottom: 0; }

.client-list { display: flex; flex-direction: column; gap: 10px; }
.client-row {
  display: flex; align-items: center; gap: 14px;
  background: #FAFAF8;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 13px 15px;
  color: inherit; text-decoration: none;
}
.client-row:hover { background: #F5F5F2; text-decoration: none; }
.client-name { font-weight: 700; font-size: 15px; }
.client-legal { font-weight: 400; color: var(--muted); font-size: 13.5px; }
.client-addedby {
  display: inline-block; margin-left: 8px; font-weight: 600; font-size: 11.5px;
  color: var(--muted); background: var(--neutral-bg); border-radius: 999px; padding: 2px 9px;
  vertical-align: middle;
}
.client-contact { font-size: 13px; color: var(--muted); margin-top: 1px; }
.client-row-side { margin-left: auto; text-align: right; flex: none; }
.client-next { font-size: 13px; font-weight: 600; }
.client-count { font-size: 12.5px; color: var(--muted); margin-top: 2px; }

.client-grid { display: grid; grid-template-columns: 1fr; gap: 0 16px; align-items: start; }
@media (min-width: 980px) {
  .client-grid { grid-template-columns: minmax(0, 1.4fr) minmax(280px, 1fr); }
}

.thumb-grid { display: flex; flex-wrap: wrap; gap: 10px; }
.thumb {
  position: relative;
  width: 86px; height: 86px;
  border-radius: 10px; overflow: hidden;
  border: 1px solid var(--line);
  padding: 0; background: var(--neutral-bg); cursor: pointer;
}
.thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.thumb-grid-lg { gap: 12px; margin-top: 10px; }
.thumb-lg { width: 160px; height: 160px; border-radius: 12px; }
@media (max-width: 480px) {
  .thumb-lg { width: calc(50% - 6px); height: auto; aspect-ratio: 1; }
}
.thumb-del {
  position: absolute; top: 4px; right: 4px;
  width: 26px; height: 26px; border-radius: 50%;
  background: rgba(23,24,26,.72); color: #fff;
  border: none; font-size: 15px; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}

/* ---------- Messages: see the "Messages tab" block lower down ---------- */

.seen-details summary {
  cursor: pointer; font-size: 12.5px; font-weight: 600; color: var(--muted);
  list-style: none;
}
.seen-details summary::-webkit-details-marker { display: none; }
.seen-details[open] summary { color: var(--ink); }
.seen-list { margin: 6px 0 0; padding: 0; list-style: none; font-size: 12.5px; color: var(--muted); }
.seen-list li { padding: 2px 0; }

.reaction-btn {
  display: inline-flex; align-items: center; gap: 3px;
  min-height: 30px; padding: 0 8px;
  border: 1px solid var(--line-strong); border-radius: 999px; background: var(--surface);
  font-size: 13px; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.reaction-btn:hover { background: var(--neutral-bg); }
.reaction-btn.is-mine { border-color: var(--ink); background: var(--neutral-bg); }
.reaction-btn .reaction-count { font-size: 11.5px; font-weight: 700; color: var(--muted); min-width: 8px; }

.reaction-details { margin-top: 0; }
.reaction-details summary {
  cursor: pointer; font-size: 13px; font-weight: 600; color: var(--muted);
  list-style: none;
}
.reaction-details summary::-webkit-details-marker { display: none; }
.reaction-details[open] summary { color: var(--ink); }
.reaction-names-list { margin: 6px 0 0; padding: 0; list-style: none; font-size: 12.5px; color: var(--muted); }
.reaction-names-list li { padding: 2px 0; }
.reaction-names-emoji { margin-right: 4px; }

/* ---------- Team page ---------- */
.member-list { display: flex; flex-direction: column; gap: 12px; }
.member-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
  background: #FAFAF8; border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 13px 15px;
}
.member-row.is-disabled { opacity: .6; }
.member-main { min-width: 160px; }
.member-name { font-weight: 700; }
.member-sub { font-size: 12.5px; color: var(--muted); }
.member-controls { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-left: auto; }
.member-controls select {
  min-height: 38px; border: 1px solid var(--line-strong); border-radius: 9px;
  padding: 6px 9px; font: inherit; font-size: 13.5px; background: #fff;
}
.reset-details summary {
  cursor: pointer; font-size: 13.5px; font-weight: 600; color: var(--info);
  min-height: 38px; display: flex; align-items: center; padding: 0 6px;
}
.reset-details form { display: flex; gap: 8px; margin-top: 6px; flex-wrap: wrap; }
.reset-details input {
  min-height: 38px; border: 1px solid var(--line-strong); border-radius: 9px;
  padding: 6px 10px; font: inherit; font-size: 13.5px;
}

/* ---------- Login quotes (quotes.php) ---------- */
.quote-list { display: flex; flex-direction: column; gap: 12px; }
.quote-row {
  display: flex; flex-wrap: wrap; align-items: flex-start; gap: 10px 16px;
  background: #FAFAF8; border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 13px 15px;
}
.quote-row-inactive { opacity: .55; }
.quote-edit-form { display: flex; gap: 10px; flex: 1 1 260px; min-width: 0; }
.quote-edit-form textarea {
  flex: 1; min-height: 0; padding: 8px 11px; border: 1px solid var(--line-strong);
  border-radius: 10px; background: #FCFCFB; font: inherit; font-size: 13.5px; resize: vertical;
}
.quote-row-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.quote-meta { font-size: 12px; color: var(--muted); margin-right: 4px; }

/* ---------- Segmented toggles / chips ---------- */
.seg {
  display: inline-flex; background: var(--neutral-bg);
  border-radius: 10px; padding: 3px; gap: 2px;
}
/* Segments are <button> on the client-side toggles (calendar views) and <a> on
   the server-side ones (Confirmations scope/filter, Messages categories), so
   both element types have to look identical here. */
.seg button, .seg .seg-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 38px; padding: 0 14px;
  border: none; background: transparent; border-radius: 8px;
  font-size: 13.5px; font-weight: 600; color: var(--muted); cursor: pointer;
  text-decoration: none; white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}
.seg .seg-btn:hover { text-decoration: none; color: var(--ink); }
.seg button.is-on, .seg .seg-btn.is-on { background: var(--ink); color: #fff; }
/* The seg is a horizontal rail; on a phone it must scroll rather than force
   the page sideways. */
.seg { max-width: 100%; overflow-x: auto; scrollbar-width: none; }
.seg::-webkit-scrollbar { display: none; }

.artist-filters { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 38px; padding: 0 13px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  font-size: 13.5px; font-weight: 600; color: var(--muted);
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.chip.is-on { border-color: var(--artist, var(--ink)); color: var(--ink); background: #fff; }
.chip .dot { opacity: .35; }
.chip.is-on .dot { opacity: 1; }

/* ---------- Dashboard: by-artist breakdown ---------- */
#byArtistToggles { margin-bottom: 14px; }
.by-artist-table { display: flex; flex-direction: column; gap: 8px; }
.by-artist-row {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  background: #FAFAF8; border: 1px solid var(--line); border-left: 4px solid var(--artist, var(--muted-2));
  border-radius: var(--radius-sm); padding: 11px 14px;
  transition: opacity .15s ease;
}
.by-artist-row.is-hidden { display: none; }
.by-artist-name { font-weight: 700; font-size: 14px; min-width: 120px; }
.by-artist-stats { display: flex; align-items: center; gap: 18px; margin-left: auto; flex-wrap: wrap; }
.by-artist-stat { font-size: 13px; color: var(--muted); font-weight: 600; }
.by-artist-stat.is-warn { color: var(--warn); }
@media (max-width: 640px) {
  .by-artist-stats { margin-left: 0; gap: 12px; }
}

/* ---------- Calendar toolbar ---------- */
.cal-toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  padding: 12px 14px;
}
.cal-nav { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.cal-title { font-size: 17px; font-weight: 700; margin: 0 8px; min-width: 130px; }
/* Today + ‹ + › + a 130px-min date title is wider than a 320px phone; below
   that the title drops its reserved width and shrinks instead of pushing the
   whole toolbar sideways. */
@media (max-width: 380px) {
  .cal-title { min-width: 0; margin: 0 4px; font-size: 15.5px; }
}
.cal-toolbar-spacer { flex: 1; }
.cal-toolbar .artist-filters { width: 100%; }
@media (min-width: 900px) {
  .cal-toolbar .artist-filters { width: auto; }
}

/* ---------- Custom calendar: month ---------- */
.cal-card { padding: 10px; overflow: hidden; }
#calendar { min-height: 480px; }

.cal-month { width: 100%; }
.cal-month-head {
  display: grid; grid-template-columns: repeat(7, 1fr);
  border-bottom: 1px solid var(--line);
}
.cal-month-head div {
  padding: 8px 6px; font-size: 12px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .04em; text-align: center;
}
.cal-month-grid { display: grid; grid-template-columns: repeat(7, 1fr); }
.cal-mday {
  min-height: 108px;
  border-bottom: 1px solid var(--line);
  border-right: 1px solid var(--line);
  padding: 5px;
  cursor: pointer;
  min-width: 0;
}
.cal-mday:nth-child(7n) { border-right: none; }
.cal-mday.is-out { background: #FAFAF8; }
.cal-mday.is-out .cal-mday-num { color: var(--muted-2); }
.cal-mday-num {
  font-size: 13px; font-weight: 600; color: var(--ink-soft);
  width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
}
.cal-mday.is-today .cal-mday-num { background: var(--accent); color: #fff; font-weight: 700; }
.cal-mchips { display: flex; flex-direction: column; gap: 3px; margin-top: 3px; }
.cal-mchip {
  display: block; width: 100%; text-align: left;
  border: none; cursor: pointer;
  background: color-mix(in srgb, var(--artist, #888) 13%, #fff);
  border-left: 3px solid var(--artist, #888);
  border-radius: 6px;
  padding: 3px 6px;
  font-size: 11.5px; line-height: 1.3;
  color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  -webkit-tap-highlight-color: transparent;
}
.cal-mchip .t { font-weight: 700; margin-right: 4px; }
.cal-mchip.is-cancelled, .cal-mchip.is-no_show { opacity: .55; text-decoration: line-through; }
.cal-mchip.is-block {
  background: repeating-linear-gradient(45deg, #ECECEA, #ECECEA 4px, #F6F6F4 4px, #F6F6F4 8px);
  border-left-color: var(--muted-2); color: var(--muted);
}
/* Another artist's booking: visible as busy, but not styled like a real
   appointment card — signals "you can't see into this one". */
.cal-mchip.is-restricted { opacity: .82; font-style: italic; }
.cal-mmore {
  border: none; background: none; cursor: pointer;
  font-size: 11.5px; font-weight: 700; color: var(--info);
  padding: 2px 6px; text-align: left;
}

/* ---------- Custom calendar: week / day time grid ---------- */
.cal-tg { display: flex; flex-direction: column; }
.cal-tg-head { display: flex; border-bottom: 1px solid var(--line); }
.cal-tg-gutter { flex: none; width: 52px; }
.cal-tg-headcols { flex: 1; display: grid; }
.cal-tg-headcol { padding: 8px 4px; text-align: center; cursor: pointer; border-left: 1px solid var(--line); }
.cal-tg-headcol:first-child { border-left: none; }
.cal-tg-dow { font-size: 11.5px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.cal-tg-dnum {
  font-size: 16px; font-weight: 700; margin-top: 1px;
  width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center; border-radius: 50%;
}
.cal-tg-headcol.is-today .cal-tg-dnum { background: var(--accent); color: #fff; }

.cal-tg-body { display: flex; position: relative; }
.cal-tg-times { flex: none; width: 52px; position: relative; }
.cal-tg-time {
  position: absolute; right: 8px; transform: translateY(-50%);
  font-size: 11px; color: var(--muted-2); font-weight: 600;
}
.cal-tg-cols { flex: 1; display: grid; position: relative; }
.cal-tg-col { position: relative; border-left: 1px solid var(--line); min-width: 0; }
.cal-tg-col:first-child { border-left: none; }
.cal-tg-hline { position: absolute; left: 0; right: 0; border-top: 1px solid var(--line); }
.cal-tg-hline.is-half { border-top-style: dotted; border-top-color: #EFEFEC; }

.cal-ev {
  position: absolute;
  border: none; text-align: left; cursor: pointer;
  background: color-mix(in srgb, var(--artist, #888) 14%, #fff);
  border-left: 3px solid var(--artist, #888);
  border-radius: 7px;
  padding: 4px 7px;
  font-size: 12px; line-height: 1.3;
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(23,24,26,.07);
  -webkit-tap-highlight-color: transparent;
}
.cal-ev .t { font-weight: 700; font-size: 11.5px; }
.cal-ev .n { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; }
.cal-ev .s { display: inline-block; margin-top: 2px; font-size: 10.5px; font-weight: 700; padding: 1px 7px; border-radius: 999px; background: #fff; }
.cal-ev .s.s-confirmed { color: var(--ok); }
.cal-ev .s.s-deposit_required { color: var(--warn); }
.cal-ev .s.s-rescheduled { color: var(--info); }
.cal-ev .s.s-cancelled, .cal-ev .s.s-no_show { color: var(--muted); }
.cal-ev.is-cancelled, .cal-ev.is-no_show { opacity: .5; }
.cal-ev.is-cancelled .n, .cal-ev.is-no_show .n { text-decoration: line-through; }
.cal-ev.is-block {
  background: repeating-linear-gradient(45deg, #EDEDEB, #EDEDEB 5px, #F7F7F5 5px, #F7F7F5 10px);
  border-left-color: var(--muted-2); color: var(--muted); box-shadow: none;
}
.cal-ev.is-restricted .n { font-style: italic; }

/* ---------- Drawer (appointment details) ---------- */
#drawerScrim {
  position: fixed; inset: 0; background: rgba(23,24,26,.44);
  z-index: 90; opacity: 0; pointer-events: none; transition: opacity .2s ease;
}
#drawerScrim.is-on { opacity: 1; pointer-events: auto; }

.drawer {
  position: fixed; top: 0; right: 0; bottom: 0;
  width: min(var(--drawer-w), 100vw);
  background: var(--surface);
  z-index: 95;
  box-shadow: var(--shadow-lift);
  transform: translateX(102%);
  transition: transform .24s ease;
  display: flex; flex-direction: column;
}
.drawer.is-open { transform: translateX(0); }
.drawer-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: calc(14px + var(--safe-top)) calc(18px + var(--safe-right)) 10px 18px; gap: 10px;
}
.drawer-body {
  flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: 0 calc(18px + var(--safe-right)) calc(18px + var(--safe-bottom)) 18px;
}
.drawer-close {
  width: var(--touch); height: var(--touch); flex: none;
  border: 1px solid var(--line-strong); border-radius: 10px; background: #fff;
  font-size: 19px; cursor: pointer; display: flex; align-items: center; justify-content: center;
}
.drawer-client { font-size: 21px; font-weight: 700; margin-top: 6px; }
.drawer-artist { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 14px; margin-top: 3px; }
.d-section { margin-top: 16px; }
.d-label {
  font-size: 11.5px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .06em; margin-bottom: 4px;
}
.d-value { font-size: 14.5px; }
.d-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 20px; }
.d-actions .span-2 { grid-column: 1 / -1; }

@media (max-width: 640px) {
  .drawer { width: 100vw; }
}

/* ---------- Modals ---------- */
.modal {
  position: fixed; inset: 0; z-index: 110;
  display: none; align-items: center; justify-content: center;
  padding: calc(18px + var(--safe-top)) calc(18px + var(--safe-right)) calc(18px + var(--safe-bottom)) calc(18px + var(--safe-left));
  background: rgba(23,24,26,.5);
}
.modal.is-open { display: flex; }
.modal-card {
  background: var(--surface);
  border-radius: 16px;
  box-shadow: var(--shadow-lift);
  width: 100%; max-width: 640px;
  max-height: calc(100vh - 36px);
  max-height: calc(100dvh - 36px);
  display: flex; flex-direction: column;
  min-height: 0;
  overflow: hidden;
}
/* The form (or any single wrapper) between modal-head and modal-actions must
   itself become a flex column, or modal-body's overflow-y:auto never has a
   constrained height to scroll within — the whole card just grows instead. */
.modal-card > form,
.modal-card > .modal-form {
  display: flex; flex-direction: column;
  min-height: 0; flex: 1 1 auto;
}
.client-success:not([hidden]) { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; }
.client-success .modal-actions { flex-wrap: wrap; }
.client-success-msg { font-size: 15px; }
.modal-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 20px 8px; gap: 12px;
  flex: none;
}
.modal-title { font-size: 18px; font-weight: 700; }
.modal-body {
  padding: 8px 20px 20px; overflow-y: auto; -webkit-overflow-scrolling: touch;
  flex: 1 1 auto; min-height: 0;
}

@media (max-width: 640px) {
  .modal { padding: 0; align-items: stretch; }
  .modal-card { max-width: none; max-height: none; border-radius: 0; height: 100vh; height: 100dvh; }
}

/* ---------- Client picker ---------- */
.client-pick { position: relative; }
.client-results {
  position: absolute; left: 0; right: 0; top: calc(100% + 4px);
  background: #fff; border: 1px solid var(--line-strong);
  border-radius: 10px; box-shadow: var(--shadow-lift);
  z-index: 20; overflow: hidden; display: none;
  max-height: 240px; overflow-y: auto;
}
.client-results.is-open { display: block; }
.client-results button {
  display: block; width: 100%; text-align: left;
  border: none; background: none; cursor: pointer;
  padding: 11px 14px; font-size: 14px; min-height: var(--touch);
}
.client-results button:hover { background: var(--neutral-bg); }
.client-results .cr-phone { color: var(--muted); font-size: 12.5px; }
.client-results .cr-addedby {
  color: var(--muted); font-size: 11.5px; font-weight: 600;
  background: var(--neutral-bg); border-radius: 999px; padding: 1px 8px; margin-left: 6px;
}
.client-results .cr-empty { padding: 14px; font-size: 13.5px; color: var(--muted); }
.client-chosen {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  background: var(--info-bg); border-radius: 10px; padding: 10px 14px;
  font-weight: 600; font-size: 14.5px;
}

/* ---------- Lightbox ---------- */
#lightbox {
  position: fixed; inset: 0; z-index: 150;
  background: rgba(10,10,11,.88);
  display: none; align-items: center; justify-content: center;
  padding: 22px; cursor: zoom-out;
}
#lightbox.is-open { display: flex; }
#lightbox img {
  max-width: 100%; max-height: 100%;
  border-radius: 10px; box-shadow: var(--shadow-lift);
}

/* ---------- Misc ---------- */
.form-error { color: #8C2626; font-size: 13.5px; margin: 6px 0 0; min-height: 1em; }
.hr { border: none; border-top: 1px solid var(--line); margin: 14px 0; }

/* ============================================================
   Additions — classes used by the final page markup that the
   sections above (written earlier) didn't yet cover.
   ============================================================ */

/* Brand mark (sidebar + auth pages) */
.sidebar-brand { display: flex; align-items: center; gap: 12px; }
.brand-mark {
  width: 34px; height: 34px; border-radius: 9px; flex: none; display: inline-block;
  background: linear-gradient(155deg, var(--accent) 0%, var(--accent-dark) 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.16);
}
.brand-mark-lg { width: 52px; height: 52px; border-radius: 14px; margin-bottom: 14px; display: inline-block; }
.auth-lede { color: var(--muted); font-size: 14px; margin-bottom: 18px; }

/* Dashboard stat cards: markup uses class="stat card stat-today" etc. */
.stat {
  display: block; text-decoration: none; color: inherit;
  border-left: 4px solid var(--stat, var(--info));
}
.stat:hover { text-decoration: none; box-shadow: var(--shadow-lift); }
.stat-today { --stat: var(--info); }
.stat-week { --stat: var(--ok); }
.stat-deposit { --stat: var(--warn); }
.stat-blocked { --stat: #7C4DC4; }

/* Appointment rows: meta line + compact variant used on the client page */
.apt-meta { font-size: 13px; color: var(--muted); margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.apt-list-compact .apt-time { width: 68px; font-size: 12.5px; line-height: 1.3; }

/* Dashboard team snapshot / recent changes: bare <li> markup */
.team-snap li { display: flex; align-items: center; gap: 10px; }
.change-list li { border-left: 3px solid var(--line-strong); padding-left: 11px; }
.change-detail { font-size: 13px; display: block; }
.change-when { font-size: 12px; color: var(--muted); display: block; margin-top: 1px; }

/* Filter bar actions (Appointments page). Wraps: three buttons side by side
   overflow a 375px phone otherwise. */
.filter-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 10px; }

/* Two-column layout helpers */
.dash-main, .dash-side, .client-side { min-width: 0; }

/* Client list row spacing */
.client-contact { flex: 1; min-width: 0; }
.client-next { text-align: right; }


/* Team page: actual member-row markup */
.member {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
  background: #FAFAF8; border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 13px 15px;
}
.member.member-disabled { opacity: .6; }
.member-id { display: flex; align-items: center; gap: 12px; min-width: 170px; }
.member-role { font-size: 12.5px; color: var(--muted); }
.member-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-left: auto; }
.member-locked { font-size: 13px; color: var(--muted); font-style: italic; }
/* ---------- Colour swatch picker ---------- */
.swatch-list { display: flex; flex-wrap: wrap; align-items: center; gap: 9px; }
.swatch {
  width: 32px; height: 32px; border-radius: 50%; flex: none;
  border: 2px solid transparent; padding: 0; cursor: pointer;
  background: var(--sw, var(--muted-2));
  display: inline-flex; align-items: center; justify-content: center;
  -webkit-tap-highlight-color: transparent;
}
.swatch:hover { transform: scale(1.08); }
.swatch.is-selected {
  border-color: var(--ink);
  box-shadow: 0 0 0 2px #fff inset;
}
.swatch.is-selected::after {
  content: "✓"; color: #fff; font-size: 13px; font-weight: 700;
  text-shadow: 0 1px 2px rgba(0,0,0,.45);
}
.swatch-custom {
  position: relative; overflow: hidden;
  background: conic-gradient(red, #ff0, lime, cyan, blue, magenta, red);
}
.swatch-custom.is-selected { background: var(--sw); }
.swatch-custom-input {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; cursor: pointer; border: none; padding: 0;
}
.inline-form select, .inline-form input {
  min-height: 38px; border: 1px solid var(--line-strong); border-radius: 9px;
  padding: 6px 10px; font: inherit; font-size: 13.5px;
}
.reset-form { display: flex; gap: 8px; margin-top: 6px; flex-wrap: wrap; }

/* Settings page card width */
.settings-card { max-width: 720px; }

/* Calendar toolbar rows (actual markup: cal-toolbar-row / cal-toolbar-row-2 / cal-tools / cal-actions) */
.cal-toolbar { flex-direction: column; align-items: stretch; }
.cal-toolbar-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; justify-content: space-between; }
.cal-toolbar-row-2 { align-items: center; }
.cal-tools { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-left: auto; }
.cal-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-left: auto; }
@media (max-width: 760px) {
  .cal-toolbar-row-2 { flex-direction: column; align-items: stretch; }
  .cal-tools, .cal-actions { margin-left: 0; }
}

/* Appointment drawer: actual section/heading markup */
.drawer-title { font-size: 21px; font-weight: 700; margin-top: 6px; }
.drawer-section { margin-top: 16px; }
.drawer-section h3 {
  font-size: 11.5px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .06em; margin-bottom: 4px;
}
.drawer-section p { font-size: 14.5px; margin: 0; }
.mini-facts { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 12px; margin-top: 8px; font-size: 13.5px; }
.mini-facts dt { color: var(--muted); font-size: 12px; }
.mini-facts dd { margin: 0; font-weight: 600; }
.drawer-clientlink { margin-top: 18px; font-size: 13.5px; }
.drawer-actions { display: flex; flex-direction: column; gap: 8px; padding: 14px 18px; border-top: 1px solid var(--line); }
.upload-row { display: flex; align-items: center; gap: 10px; margin-top: 10px; flex-wrap: wrap; }
.upload-btn { cursor: pointer; }
.upload-hint { font-size: 12px; color: var(--muted); }

/* Appointment / block modal extras */
.modal-card-sm { max-width: 420px; }
.modal-actions {
  display: flex; gap: 10px; justify-content: flex-end; padding: 10px 20px 18px; flex-wrap: wrap;
  flex: none; border-top: 1px solid var(--line);
}
.client-picker { position: relative; }
.new-client-fields { margin-top: 8px; margin-bottom: 14px; }
.new-client-fields .inline-fields { flex-wrap: wrap; }
.new-client-fields .inline-fields input { flex: 1 1 160px; min-height: var(--touch); padding: 10px 13px; border: 1px solid var(--line-strong); border-radius: 10px; background: #FCFCFB; font: inherit; }

/* Sidebar sign-out button sits on the dark sidebar, not the light surface */
.btn-signout { color: var(--sidebar-ink); border-color: rgba(255,255,255,.14); flex: none; }
.btn-signout:hover { background: rgba(255,255,255,.08); color: #fff; }

.text-link { font-size: 13.5px; font-weight: 600; color: var(--info); text-decoration: none; }
.text-link:hover { text-decoration: underline; }

/* ---------- Scheduling conflict warnings (appointment form) ---------- */
.conflict-minor-note {
  background: var(--info-bg); color: #1D4E8C; border-radius: 10px;
  padding: 9px 12px; margin: -4px 0 14px;
}
.conflict-banner {
  border: 2px solid var(--accent); background: var(--danger-bg);
  border-radius: 12px; padding: 14px 16px; margin: 4px 0 14px;
}
.conflict-banner-title { font-size: 15px; font-weight: 700; color: var(--accent-dark); margin-bottom: 6px; }
.conflict-list { margin: 0 0 12px; padding: 0; list-style: none; font-size: 13.5px; color: var(--ink-soft); }
.conflict-list li { padding: 3px 0; }
.conflict-banner-actions { display: flex; gap: 10px; flex-wrap: wrap; }

/* ---------- Confirmations tab ---------- */
.confirm-toolbar { display: flex; flex-direction: column; gap: 12px; }
.confirm-toolbar-row { display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: flex-end; }
.confirm-toolbar-row .field { margin-bottom: 0; flex: 1 1 180px; }
.confirm-search-field { flex: 2 1 220px; }
.confirm-toolbar-controls { align-items: center; }
.confirm-toolbar-controls .seg { flex: 0 1 auto; }
.seg-scope { font-size: 14.5px; }
/* Counts sit inside the filter chips so the size of each pile is visible
   without switching to it. */
.seg-count {
  display: inline-block; margin-left: 5px; padding: 0 6px;
  border-radius: 999px; background: rgba(23,24,26,.09);
  font-size: 11.5px; font-weight: 700; line-height: 18px; vertical-align: 1px;
}
.seg-btn.is-on .seg-count { background: rgba(255,255,255,.22); }
.confirm-owed {
  margin-left: auto; font-size: 13px; font-weight: 700;
  color: var(--warn); background: var(--warn-bg);
  border-radius: 999px; padding: 4px 12px;
}
.confirm-sort-toggle { white-space: nowrap; }

.confirm-list { display: flex; flex-direction: column; gap: 10px; }
.confirm-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px;
  background: #FAFAF8; border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 13px 15px;
  border-left: 3px solid transparent;
}
/* Already handled: recedes without disappearing, so the list still reads as
   a checklist rather than rows vanishing as you work through it. */
.confirm-row.is-sent { background: #FCFCFB; border-left-color: var(--ok); }
.confirm-row.is-sent .confirm-client { color: var(--ink-soft); }
/* Unconfirmed and happening within 48 hours — the rows worth chasing first. */
.confirm-row.is-soon { border-left-color: var(--warn); background: #FFFDF8; }
.confirm-main { display: flex; flex-direction: column; gap: 2px; min-width: 160px; }
.confirm-client { font-weight: 700; font-size: 15px; }
.confirm-when { font-size: 13px; color: var(--muted); }
.confirm-rel {
  display: inline-block; margin-left: 6px; padding: 1px 7px;
  border-radius: 999px; background: var(--neutral-bg); color: var(--muted);
  font-size: 11.5px; font-weight: 700;
}
.confirm-rel.is-soon { background: var(--warn-bg); color: var(--warn); }
.confirm-artist { font-size: 12.5px; color: var(--muted); display: inline-flex; align-items: center; gap: 6px; margin-top: 1px; }
.confirm-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-left: auto; }
.confirm-check { margin-bottom: 0; white-space: nowrap; }
.confirm-sent-hint { font-size: 12px; color: var(--muted); white-space: nowrap; }
.confirm-deposit-status {
  font-size: 12.5px; font-weight: 700; color: var(--warn);
  background: var(--warn-bg); border-radius: 999px; padding: 3px 10px; white-space: nowrap;
}
.confirm-deposit-status.is-received { color: var(--ok); background: var(--ok-bg); }

/* Group-by-client view */
.confirm-groups { display: flex; flex-direction: column; gap: 18px; }
.confirm-group-head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
  font-size: 14px; font-weight: 700; margin-bottom: 8px;
  padding-bottom: 6px; border-bottom: 1px solid var(--line);
}
.confirm-group-head a { color: var(--ink); }
.confirm-group-count { font-size: 12.5px; font-weight: 500; color: var(--muted); }

/* Briefly highlights the row deep-linked from the appointment drawer's "send now" link. */
.confirm-row.is-focused { animation: ts-confirm-focus 2.4s ease; }
@keyframes ts-confirm-focus {
  0%, 100% { box-shadow: none; border-color: var(--line); }
  15%, 70% { box-shadow: 0 0 0 2px var(--warn); border-color: var(--warn); }
}

/* ---------- "Not yet confirmed" badge (calendar chips, appointment rows, drawer) ---------- */
.badge-unconfirmed { background: var(--warn-bg); color: var(--warn); }
.cal-mchip.is-unconfirmed, .cal-ev.is-unconfirmed { box-shadow: inset 0 0 0 1px var(--warn); }
.apt-unconfirmed-flag {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; font-weight: 700; color: var(--warn);
  background: var(--warn-bg); border-radius: 999px; padding: 2px 8px; margin-top: 3px;
}
.apt-unconfirmed-flag-drawer {
  display: block; font-size: 13px; font-weight: 500; color: var(--warn);
  background: var(--warn-bg); border-radius: 10px; padding: 8px 12px; margin-top: 8px;
}
.apt-unconfirmed-flag-drawer a { color: var(--warn); font-weight: 700; text-decoration: underline; }

/* ---------- Birthdays ---------- */
/* A small cake marker on the day, tinted with that artist's colour. Sits in the
   corner of the month cell / day column header — a marker, not an event, so it
   never takes a slot in the time grid. */
.cal-bday {
  position: absolute; top: 4px; right: 4px; z-index: 4;
  width: 22px; height: 22px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(23,24,26,.12); border-radius: 50%;
  background: var(--bday, var(--info)); cursor: pointer;
  font-size: 11px; line-height: 1;
  box-shadow: 0 1px 2px rgba(23,24,26,.18);
  -webkit-tap-highlight-color: transparent;
}
/* Two people sharing a day: split the circle between their colours. */
.cal-bday.is-multi {
  background: linear-gradient(135deg, var(--bday) 0 50%, var(--bday2, var(--accent)) 50% 100%);
}
.cal-bday:hover { transform: scale(1.12); }
/* The cake reads better small, but a 22px target is a poor one for a finger.
   This invisible pad grows the hit area to ~40px without changing the look. */
.cal-bday::after {
  content: ''; position: absolute; top: -9px; right: -9px; bottom: -9px; left: -9px;
}
.cal-mday { position: relative; }
.cal-tg-headcol { position: relative; }
.cal-tg-headcol .cal-bday { top: 2px; right: 2px; width: 20px; height: 20px; font-size: 10px; }

/* Birthday prompt after sign-in + the account page's own field */
.modal-card-sm { max-width: 420px; }
.dob-form .form-foot { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.dob-current { font-size: 13px; color: var(--muted); }

/* ---------- Notifications tab ---------- */
.notif-section-title {
  display: flex; align-items: center; gap: 9px;
  font-size: 15px; font-weight: 700; color: var(--muted);
  margin: 0 0 12px; text-transform: uppercase; letter-spacing: .04em;
}
.notif-history { padding: 0; }
.notif-history > details > summary { list-style: none; cursor: pointer; }
.notif-history > details > summary::-webkit-details-marker { display: none; }
.notif-history-summary {
  display: flex; align-items: center; gap: 10px;
  padding: 15px 18px; min-height: var(--touch);
}
.notif-history-summary:hover { background: #FAFAF8; }
.notif-history-title { flex: 1; font-size: 15px; font-weight: 700; }
/* Chevron rotates to show the section is expandable — no icon font needed. */
.notif-history-summary::after {
  content: '›'; font-size: 20px; line-height: 1; color: var(--muted);
  transform: rotate(90deg); transition: transform .18s ease;
}
.notif-history > details[open] .notif-history-summary::after { transform: rotate(-90deg); }
.notif-history-count {
  min-width: 22px; padding: 1px 8px; border-radius: 999px;
  background: var(--neutral-bg); color: var(--muted);
  font-size: 12px; font-weight: 700; text-align: center;
}
.notif-history-group { padding: 0 18px 16px; }
.notif-history-group:first-of-type { padding-top: 4px; }
.notif-history-group-title { font-size: 13.5px; font-weight: 700; margin-bottom: 9px; }
.notif-history .empty { padding: 0 18px 16px; }
.notif-item.is-past { border-left-color: var(--line); }
.notif-item.is-past .notif-label { color: var(--ink-soft); }

.notif-list { display: flex; flex-direction: column; gap: 10px; }
.notif-item {
  display: flex; flex-direction: column; gap: 2px;
  border-left: 3px solid var(--line-strong); padding: 2px 0 2px 11px;
}
.notif-label { font-size: 14px; font-weight: 600; }
.notif-meta { font-size: 12.5px; color: var(--muted); }

/* ---------- Notification preference toggles (account.php + team.php) ---------- */
.notif-group-title {
  font-size: 12.5px; font-weight: 700; color: var(--muted); text-transform: uppercase;
  letter-spacing: .05em; margin: 18px 0 8px;
}
.notif-group-title:first-child { margin-top: 0; }
.notif-pref-list { display: flex; flex-direction: column; gap: 4px; }
.notif-pref-row {
  align-items: flex-start !important; gap: 12px !important;
  min-height: 0 !important; padding: 8px 0; margin-bottom: 0 !important;
  border-bottom: 1px solid var(--line);
}
.notif-pref-row:last-child { border-bottom: none; }
.notif-pref-row input[type="checkbox"] { margin-top: 2px; }
.notif-pref-row span { display: flex; flex-direction: column; gap: 1px; }
.notif-pref-row strong { font-size: 14px; font-weight: 600; }
.notif-pref-row small { font-size: 12.5px; color: var(--muted); }
.notif-reminder-settings { margin-top: 14px; }

/* ---------- Interaction polish: hover/focus consistency ---------- */
.card, .stat, .client-row, .apt-row, .member, .thumb, .chip, .nav-item {
  transition: box-shadow .15s ease, background-color .15s ease, border-color .15s ease, transform .1s ease;
}
.client-row:hover, .apt-row:hover, .member:hover { box-shadow: var(--shadow); }
.thumb:hover img { transform: scale(1.04); }
.thumb img { transition: transform .18s ease; }

/* Keyboard focus must stay visible everywhere, even where hover styles already exist */
a:focus-visible, button:focus-visible, .apt-row:focus-visible, .client-row:focus-visible,
.nav-item:focus-visible, .chip:focus-visible, .seg button:focus-visible, .cal-mchip:focus-visible,
.cal-ev:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--info);
  outline-offset: 2px;
}

/* ---------- Avatar / studio picture editors (account.php, settings.php) ---------- */
.avatar-editor { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.avatar-editor-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.avatar-editor-meta { flex: 1 1 200px; min-width: 200px; }
.brand-mark-img { object-fit: cover; }

/* Sidebar user block becomes a link once wrapped for account.php access */
.sidebar-user-link {
  display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0;
  color: inherit; text-decoration: none;
}
.sidebar-user-link:hover { text-decoration: none; }
.sidebar-user-link:hover .sidebar-user-name { text-decoration: underline; }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ============================================================
   Messages tab
   Five categories, three shapes (board / open request / chat).
   One visual language: the category colour drives the rail dot,
   the card's left edge and its tag.
   ============================================================ */

.cat-important { --cat: var(--accent);  --cat-bg: var(--danger-bg);  --cat-ink: var(--accent-dark); }
.cat-events    { --cat: #7C4DC4;        --cat-bg: #EFE8FA;           --cat-ink: #6A3DB0; }
.cat-leads     { --cat: var(--ok);      --cat-bg: var(--ok-bg);      --cat-ink: var(--ok); }
.cat-team_chat { --cat: var(--info);    --cat-bg: var(--info-bg);    --cat-ink: var(--info); }
.cat-other     { --cat: var(--muted-2); --cat-bg: var(--neutral-bg); --cat-ink: var(--muted); }

/* ---------- category rail ---------- */
.rail {
  display: flex; gap: 7px; margin-bottom: 14px; padding-bottom: 4px;
  overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.rail::-webkit-scrollbar { display: none; }
.rail-tab {
  display: inline-flex; align-items: center; gap: 7px; flex: none;
  min-height: var(--touch); padding: 0 14px;
  border-radius: 999px; border: 1px solid var(--line-strong);
  background: var(--surface); color: var(--ink-soft);
  font-size: 14px; font-weight: 600; text-decoration: none; white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
  transition: border-color .14s ease, background-color .14s ease;
}
.rail-tab:hover { text-decoration: none; border-color: var(--muted-2); }
.rail-tab.is-on { background: var(--ink); border-color: var(--ink); color: #fff; }
.rail-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--cat, var(--muted-2)); flex: none; }
.rail-important { --cat: var(--accent); }
.rail-events    { --cat: #7C4DC4; }
.rail-leads     { --cat: var(--ok); }
.rail-team_chat { --cat: var(--info); }
.rail-other     { --cat: var(--muted-2); }
.rail-count {
  min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px;
  background: var(--accent); color: #fff;
  font-size: 11px; font-weight: 700; line-height: 20px; text-align: center;
}
.rail-tab.is-on .rail-count { background: rgba(255,255,255,.28); }
.rail-hint { font-size: 13px; color: var(--muted); margin: -4px 0 14px; }

/* ---------- shared: attachment control ---------- */
/* One implementation for the chat composer, board composer and replies, so a
   photo behaves the same everywhere. */
.attach { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.attach-btn {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 38px; padding: 0 14px;
  border: 1px dashed var(--line-strong); border-radius: 10px;
  background: var(--surface); color: var(--muted);
  font-size: 13.5px; font-weight: 600; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.attach-btn:hover, .attach-btn:focus-visible { border-color: var(--info); color: var(--info); background: #FBFCFE; }
.attach-btn svg { width: 17px; height: 17px; flex: none; }
.attach-inline .attach-btn { min-height: 34px; padding: 0 11px; font-size: 12.5px; }

.attach-previews { display: flex; flex-wrap: wrap; gap: 8px; }
.attach-previews:empty { display: none; }
.attach-thumb {
  position: relative; width: 62px; height: 62px; border-radius: 10px;
  overflow: hidden; border: 1px solid var(--line); background: var(--neutral-bg); flex: none;
}
.attach-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.attach-x {
  position: absolute; top: 2px; right: 2px;
  width: 20px; height: 20px; border-radius: 50%; border: none;
  background: rgba(23,24,26,.72); color: #fff;
  font-size: 13px; line-height: 20px; text-align: center; cursor: pointer; padding: 0;
}
.attach-x:hover { background: var(--accent); }
.attach-name { font-size: 11px; color: var(--muted); }

/* ---------- shared: image grid on a posted message ---------- */
.shots { display: grid; gap: 5px; margin-top: 10px; border-radius: 12px; overflow: hidden; }
.shots-1 { grid-template-columns: 1fr; max-width: 380px; }
.shots-2 { grid-template-columns: 1fr 1fr; max-width: 420px; }
.shots-3, .shots-4 { grid-template-columns: 1fr 1fr; max-width: 420px; }
.shot {
  padding: 0; border: none; background: var(--neutral-bg); cursor: pointer;
  aspect-ratio: 4 / 3; overflow: hidden; display: block;
}
.shots-1 .shot { aspect-ratio: auto; max-height: 340px; }
.shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.shot:hover img { opacity: .92; }
.shots-sm { max-width: 260px; }
.shots-sm .shot { aspect-ratio: 1; }
.shots-chat { max-width: 260px; margin-top: 7px; }

/* ---------- board ---------- */
.board { display: flex; flex-direction: column; gap: 14px; }
.msg {
  background: var(--surface); border: 1px solid var(--line);
  border-left: 3px solid var(--cat, var(--line-strong));
  border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 15px 17px;
}
.msg.is-pinned { box-shadow: var(--shadow), inset 0 0 0 1px var(--warn); }
.msg-pin {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; font-weight: 700; color: var(--warn);
  background: var(--warn-bg); border-radius: 999px; padding: 3px 10px; margin-bottom: 10px;
}
.msg-head { display: flex; align-items: center; gap: 8px 9px; flex-wrap: wrap; }
.msg-who { min-width: 90px; flex: 1 1 90px; display: flex; flex-direction: column; }
/* Explicit order so the ⋯ menu always finishes the first line. Left to itself
   it was the item that wrapped, dropping to a row of its own and leaving a
   gap under the byline on a phone. The tag wraps instead, which reads fine. */
.msg-head .msg-menu { order: 3; margin-left: auto; }
.msg-head .tag { order: 2; }
@media (max-width: 560px) {
  /* Below this the name, tag and menu genuinely do not fit on one line, so
     the tag takes its own — with the menu still pinned top-right.
     flex-basis forces the line break; max-width stops the pill then stretching
     across the whole card, which looks like a banner rather than a label. */
  .msg-head .tag { order: 4; flex-basis: 100%; max-width: max-content; }
}
.msg-name { font-size: 13.5px; font-weight: 700; }
.msg-time { font-size: 12px; color: var(--muted); }

.tag {
  display: inline-block; padding: 2px 9px; border-radius: 999px;
  background: var(--cat-bg, var(--neutral-bg)); color: var(--cat-ink, var(--muted));
  font-size: 11px; font-weight: 700; text-decoration: none; white-space: nowrap;
}
.tag:hover { text-decoration: none; }
.tag-status { flex: none; }
.tag-open   { background: var(--ok-bg); color: var(--ok); }
.tag-filled { background: var(--info-bg); color: var(--info); }
.tag-closed { background: var(--neutral-bg); color: var(--muted); }

.msg-title { font-size: 16px; font-weight: 700; margin-top: 11px; }
.msg-body-wrap { margin-top: 7px; }
.msg-body { font-size: 14.5px; margin: 0; line-height: 1.5; }
.msg-body[data-clamp].is-clamped {
  display: -webkit-box; -webkit-line-clamp: 5; -webkit-box-orient: vertical; overflow: hidden;
}
.msg-more {
  border: none; background: none; cursor: pointer;
  color: var(--info); font-size: 13px; font-weight: 600;
  padding: 7px 8px 7px 0; margin-left: -1px; min-height: 32px;
}
.msg-more:hover { text-decoration: underline; }

.msg-foot {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  margin-top: 13px; padding-top: 11px; border-top: 1px solid var(--line);
}
.chip-btn {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 32px; padding: 0 11px;
  border: 1px solid var(--line-strong); border-radius: 999px; background: var(--surface);
  font-size: 13px; font-weight: 600; color: var(--muted); cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.chip-btn:hover { background: var(--neutral-bg); color: var(--ink); }
.chip-btn-label { font-weight: 500; }
.msg-seen { margin-left: auto; }

/* overflow menu (pin / delete) */
.msg-menu { position: relative; flex: none; margin-left: auto; }
.msg-menu-btn {
  width: 32px; height: 32px; border-radius: 8px; border: 1px solid transparent;
  background: none; color: var(--muted); cursor: pointer;
  font-size: 17px; line-height: 1; -webkit-tap-highlight-color: transparent;
}
.msg-menu-btn:hover { background: var(--neutral-bg); color: var(--ink); }
.msg-menu-pop {
  position: absolute; top: calc(100% + 4px); right: 0; z-index: 30; min-width: 150px;
  background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: 10px; box-shadow: var(--shadow-lift); padding: 5px; overflow: hidden;
}
.msg-menu-pop form { margin: 0; }
.msg-menu-pop button {
  display: block; width: 100%; text-align: left;
  border: none; background: none; cursor: pointer;
  padding: 9px 11px; border-radius: 7px; font-size: 13.5px; font-weight: 600; color: var(--ink);
}
.msg-menu-pop button:hover { background: var(--neutral-bg); }
.msg-menu-pop button.is-danger { color: var(--accent); }
.msg-menu-pop button.is-danger:hover { background: var(--danger-bg); }

/* reaction pill + picker */
.msg-react { position: relative; flex: none; }
.msg-react-open {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 34px; height: 32px; padding: 0 8px;
  border: 1px solid var(--line-strong); border-radius: 999px; background: var(--surface);
  font-size: 15px; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.msg-react-open:hover { background: var(--neutral-bg); }
/* Exactly one of the two faces shows. The SVG is the "no reaction yet" state;
   once you react, your emoji replaces it. Doing it with CSS rather than an
   emoji character means the button looks the same on iOS and macOS. */
.react-ico { width: 17px; height: 17px; color: var(--muted); display: block; }
.react-emoji { font-size: 15px; line-height: 1; }
.msg-react-open[data-has-reaction="1"] .react-ico { display: none; }
.msg-react-open[data-has-reaction="0"] .react-emoji { display: none; }
.msg-react-open:hover .react-ico { color: var(--ink); }
.msg-react-picker {
  position: absolute; bottom: calc(100% + 6px); left: 0; z-index: 30;
  display: flex; gap: 4px; padding: 6px;
  background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: 999px; box-shadow: var(--shadow-lift);
}
/* A popover on a right-hand element must open leftwards, or it pushes past the
   edge of its container and gives the whole thread a horizontal scrollbar. */
.msg-react-picker.opens-left { left: auto; right: 0; }

/* ---------- open requests ---------- */
.msg-lead.is-filled, .msg-lead.is-closed, .msg-lead.is-past { opacity: .74; }
.lead-facts { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 11px; }
.fact {
  display: inline-flex; flex-direction: column; gap: 1px;
  background: #FAFAF8; border: 1px solid var(--line); border-radius: 9px; padding: 6px 11px;
}
.fact-k { font-size: 10px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
.fact-v { font-size: 13.5px; font-weight: 700; }

.lead-take {
  display: flex; flex-wrap: wrap; align-items: center; gap: 9px 12px;
  margin-top: 13px; padding: 11px 13px;
  background: #F7FBF8; border: 1px solid #DCEDE3; border-radius: var(--radius-sm);
}
.msg-lead.is-filled .lead-take, .msg-lead.is-closed .lead-take, .msg-lead.is-past .lead-take {
  background: #FAFAF8; border-color: var(--line);
}
.lead-btn { text-align: left; height: auto; padding-top: 8px; padding-bottom: 8px; }
.lead-note { font-size: 13px; color: var(--muted); font-style: italic; }
.lead-people { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.lead-people li {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; font-weight: 600;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 999px; padding: 3px 10px 3px 3px;
}
.lead-people li.lead-nobody {
  background: none; border: none; padding: 0; font-weight: 500; font-style: italic; color: var(--muted);
}
.avatar-xs { width: 22px; height: 22px; font-size: 9.5px; flex: none; }
.avatar-sm { width: 32px; height: 32px; font-size: 11.5px; flex: none; }
.lead-admin {
  display: flex; flex-wrap: wrap; align-items: center; gap: 9px;
  margin-top: 11px; padding-top: 11px; border-top: 1px dashed var(--line);
}
.lead-admin form { margin: 0; }
.lead-admin select { min-height: 38px; padding: 0 32px 0 11px; font-size: 13.5px; }

/* ---------- replies ---------- */
.thread { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line); }
.thread-list { display: flex; flex-direction: column; gap: 11px; margin-bottom: 12px; }
.thread-list:empty { margin-bottom: 0; }
.reply { font-size: 13.5px; }
.reply-head { display: flex; align-items: baseline; gap: 8px; }
.reply-head strong { font-size: 13px; }
.reply-when { font-size: 11.5px; color: var(--muted); flex: 1; }
.reply-del { border: none; background: none; color: var(--muted-2); cursor: pointer; font-size: 16px; line-height: 1; padding: 0 3px; }
.reply-del:hover { color: var(--accent); }
.reply-body { margin: 2px 0 0; }
.reply.is-fresh { animation: ts-rise .45s ease; }

.reply-form { display: flex; flex-direction: column; gap: 9px; }
.reply-form textarea {
  width: 100%; min-height: 40px; padding: 9px 12px;
  border: 1px solid var(--line-strong); border-radius: 11px;
  background: #FCFCFB; font: inherit; font-size: 13.5px; resize: vertical;
}
.reply-form-foot { display: flex; align-items: flex-end; justify-content: space-between; gap: 10px; flex-wrap: wrap; }

/* ---------- board composer ---------- */
.poster {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
  margin-bottom: 16px; overflow: hidden;
}
.poster-d > summary { list-style: none; cursor: pointer; }
.poster-d > summary::-webkit-details-marker { display: none; }
.poster-summary {
  display: flex; align-items: center; gap: 11px;
  padding: 13px 16px; min-height: var(--touch); color: var(--muted); font-size: 14.5px;
}
/* Target the prompt text by class, never "any span": avatar_html() renders the
   initials avatar as a <span>, so a blanket rule here stretched it into a
   full-width blue bar. */
.poster-prompt { flex: 1; min-width: 0; }
.poster-summary:hover { background: #FAFAF8; }
.poster-plus {
  width: 28px; height: 28px; border-radius: 999px; flex: none;
  background: var(--neutral-bg); color: var(--ink);
  font-size: 18px; font-weight: 600; line-height: 27px; text-align: center;
  transition: transform .18s ease;
}
.poster-d[open] .poster-plus { transform: rotate(45deg); }
.poster-form { padding: 4px 16px 16px; border-top: 1px solid var(--line); }
.poster-lead { display: flex; gap: 12px; flex-wrap: wrap; }
.poster-lead .field { flex: 1 1 160px; }
.poster-foot { display: flex; justify-content: flex-end; margin-top: 14px; }

/* ---------- empty states ---------- */
.board-empty, .chat-empty {
  text-align: center; padding: 40px 24px; color: var(--ink-soft);
}
.board-empty {
  background: var(--surface); border: 1px dashed var(--line-strong); border-radius: var(--radius);
}
.board-empty p, .chat-empty p { margin: 0 0 4px; }
.chat-empty-emoji { font-size: 28px; opacity: .45; margin-bottom: 8px; }
.board-empty-ico { width: 34px; height: 34px; color: var(--muted-2); margin: 0 auto 10px; display: block; }

/* ---------- team chat ---------- */
.chat {
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden;
  height: calc(100dvh - 260px); min-height: 320px;
}
/* The chat page itself never scrolls — only the thread does, with the composer
   pinned beneath. Sizing by flex means it ends exactly at the bottom of the
   viewport whatever the header and rail above it add up to. */
body.is-chat-view .main { height: 100dvh; min-height: 0; }
body.is-chat-view .content { display: flex; flex-direction: column; min-height: 0; overflow: hidden; padding-bottom: 14px; }
body.is-chat-view .content > *:not(.chat) { flex: 0 0 auto; }
body.is-chat-view .chat { height: auto; flex: 1 1 auto; min-height: 170px; }

/* overflow-x is pinned hidden: a chat thread scrolls vertically and never
   sideways, whatever a popover or a long unbroken word does inside it. */
.chat-thread {
  flex: 1; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch;
  display: flex; flex-direction: column; gap: 2px; padding: 16px 14px;
  background: radial-gradient(760px 320px at 10% -6%, #FBFAF7 0%, transparent 60%), var(--surface);
}
.chat-day { align-self: center; margin: 13px 0 9px; }
.chat-day span {
  display: inline-block; padding: 3px 12px; border-radius: 999px;
  background: var(--neutral-bg); color: var(--muted); font-size: 11.5px; font-weight: 700;
}

.bubble-row { display: flex; align-items: flex-end; gap: 8px; max-width: 100%; }
.bubble-row.is-mine { flex-direction: row-reverse; }
.bubble-row:not(.is-run) { margin-top: 9px; }
.bubble-avatar { width: 32px; flex: none; }
.bubble-row.is-mine .bubble-avatar { display: none; }

.bubble {
  position: relative; max-width: min(76%, 540px);
  padding: 8px 12px 6px; border-radius: 15px;
  background: #F2F2EF; border: 1px solid var(--line);
  overflow-wrap: anywhere;
}
.bubble-row.is-mine .bubble { background: #E7EEFA; border-color: #D2DEF2; }
.bubble-row:not(.is-run) .bubble { border-top-left-radius: 5px; }
.bubble-row.is-mine:not(.is-run) .bubble { border-top-left-radius: 15px; border-top-right-radius: 5px; }
.bubble.is-photo-only { padding: 5px 5px 4px; }
.bubble.is-photo-only .shots-chat { margin-top: 0; }

.bubble-name { display: block; font-size: 12.5px; font-weight: 700; color: var(--artist, var(--ink)); margin-bottom: 2px; }
.bubble-pin { display: inline-block; font-size: 10.5px; font-weight: 700; color: var(--warn); margin-bottom: 2px; }
.bubble-title { display: block; font-size: 14px; margin-bottom: 2px; }
.bubble-text { margin: 0; font-size: 14.5px; line-height: 1.42; }
.bubble-meta {
  display: flex; align-items: center; justify-content: flex-end; gap: 7px;
  margin-top: 2px; font-size: 10.5px; color: var(--muted-2);
}
.bubble.is-photo-only .bubble-meta { padding: 2px 6px 0; }
.bubble-seen { font-weight: 600; }
.bubble-row.is-fresh .bubble { animation: ts-rise .45s ease; }
@keyframes ts-rise { from { transform: translateY(6px); opacity: 0; } to { transform: none; opacity: 1; } }

/* Bubble tools appear on hover (mouse) or tap (touch — app.js adds .is-active). */
.bubble-tools {
  position: absolute; top: -13px; display: flex; align-items: center; gap: 2px;
  opacity: 0; pointer-events: none; transition: opacity .14s ease;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 999px; padding: 1px 3px; box-shadow: var(--shadow);
}
.bubble-row .bubble-tools { right: 6px; }
.bubble-row.is-mine .bubble-tools { right: auto; left: 6px; }
.bubble-row:hover .bubble-tools,
.bubble-row:focus-within .bubble-tools,
.bubble-row.is-active .bubble-tools { opacity: 1; pointer-events: auto; }
.bubble-tools .msg-react-open { min-width: 26px; height: 24px; border: none; background: none; font-size: 13px; padding: 0 4px; }
.bubble-tools .msg-menu-btn { width: 24px; height: 24px; font-size: 14px; }
/* Reaction chips sit in the bubble body and are always visible — they used to
   be nested in the hover strip, which meant no reaction was ever visible in
   Team Chat, and on touch there is no hover to reveal them with anyway. */
.bubble .reaction-details { margin-top: 5px; }
.bubble .reaction-details summary {
  display: inline-flex; align-items: center; gap: 4px;
  background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: 999px; padding: 2px 9px;
  font-size: 12px; font-weight: 600; color: var(--ink-soft);
}
.bubble .reaction-details[open] summary { background: var(--neutral-bg); }
.bubble .reaction-names-list {
  margin-top: 5px; padding: 6px 9px;
  background: rgba(255,255,255,.72); border-radius: 9px; font-size: 12px;
}

/* Seen-by on a bubble: a count that opens into the actual names. */
.bubble-seen summary {
  font-size: 10.5px; font-weight: 600; color: var(--muted-2);
  cursor: pointer; list-style: none;
}
.bubble-seen summary::-webkit-details-marker { display: none; }
.bubble-seen[open] summary { color: var(--ink-soft); }
.bubble-seen .seen-list {
  margin-top: 5px; padding: 6px 9px;
  background: rgba(255,255,255,.72); border-radius: 9px;
  font-size: 11.5px; color: var(--muted); text-align: left;
}
.bubble-meta { flex-wrap: wrap; }
/* Once a seen list is open the meta row becomes a block, so the names get the
   full bubble width instead of being squeezed beside the timestamp. */
.bubble-meta:has(.bubble-seen[open]) { display: block; }
.bubble-meta:has(.bubble-seen[open]) time { display: block; text-align: right; }

.chat-pinned {
  display: flex; gap: 10px; align-items: flex-start;
  background: var(--warn-bg); border: 1px solid #F0DFBC;
  border-radius: var(--radius-sm); padding: 9px 13px; margin-bottom: 12px; font-size: 13px;
}
.chat-pinned-k { font-weight: 700; color: var(--warn); flex: none; }
.chat-pinned ul { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.chat-pinned li { color: var(--ink-soft); overflow-wrap: anywhere; }

/* ---------- chat composer ---------- */
.composer {
  border-top: 1px solid var(--line); background: var(--surface);
  padding: 9px 11px calc(9px + var(--safe-bottom));
}
.composer-previews { display: flex; flex-wrap: wrap; gap: 8px; }
.composer-previews:not(:empty) { margin-bottom: 9px; }
.composer-row { display: flex; align-items: flex-end; gap: 8px; }
.composer-attach, .composer-send {
  width: 42px; height: 42px; flex: none; padding: 0; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.composer-attach {
  border: 1px solid var(--line-strong); background: var(--surface); color: var(--muted);
}
.composer-attach:hover, .composer-attach:focus-visible { color: var(--info); border-color: var(--info); background: #FBFCFE; }
.composer-attach svg { width: 21px; height: 21px; }
.composer textarea {
  flex: 1; min-width: 0; display: block; resize: none;
  min-height: 42px; max-height: 140px; padding: 10px 15px;
  border: 1px solid var(--line-strong); border-radius: 21px;
  background: #FCFCFB; font: inherit; font-size: 15px;
}
.composer-send { border: none; background: var(--ink); color: #fff; }
.composer-send:hover { background: var(--ink-soft); }
.composer-send svg { width: 19px; height: 19px; margin-left: -2px; }
.composer-hint { margin: 7px 2px 0; font-size: 12.5px; color: var(--muted); }

/* ---------- "new messages" pill on a board ---------- */
.board-newbar {
  position: sticky; top: 6px; z-index: 30;
  display: block; width: 100%; margin-bottom: 12px;
  border: none; border-radius: 999px; cursor: pointer;
  background: var(--ink); color: #fff;
  font-size: 13.5px; font-weight: 600; padding: 11px 16px; box-shadow: var(--shadow-lift);
}
.board-newbar:hover { background: var(--ink-soft); }

/* ---------- narrow screens ---------- */
@media (max-width: 430px) {
  .msg { padding: 13px 14px; }
  .bubble { max-width: 86%; }
  .shots-1, .shots-2, .shots-3, .shots-4 { max-width: 100%; }
  .msg-seen { margin-left: 0; }
}

/* Drop-target feedback + HEIC tiles (no browser preview, so show the name). */
.composer.is-dropping, .poster-form.is-dropping, .reply-form.is-dropping {
  outline: 2px dashed var(--info); outline-offset: 3px; border-radius: 12px;
}
.attach-thumb.is-noprev {
  display: flex; align-items: center; justify-content: center;
  background: var(--info-bg); color: var(--info);
  font-size: 10px; font-weight: 700; text-align: center; padding: 4px;
}
.composer-send.is-sending { opacity: .6; }

/* ---------- Team Chat: "only pinned" filter ---------- */
.chat-pinned { flex-wrap: wrap; align-items: center; }
.chat-pinned ul { flex: 1 1 200px; }
.chat-pinned-only {
  flex: none; align-self: center;
  min-height: 34px; padding: 0 13px;
  border: 1px solid #E2CE9E; border-radius: 999px;
  background: var(--surface); color: var(--warn);
  font-size: 12.5px; font-weight: 700; cursor: pointer; white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}
.chat-pinned-only:hover { background: #FFF9EC; }
.chat-pinned-only[aria-pressed="true"] { background: var(--warn); border-color: var(--warn); color: #fff; }

/* While filtered the thread reads as a short list from the top, not a
   conversation, so it starts at the top rather than pinned to the newest end. */
.chat-thread.is-pinned-only { justify-content: flex-start; }
.chat-thread.is-pinned-only .bubble-row { margin-top: 10px; }
/* Consecutive-message grouping is meaningless once the messages between them
   are hidden — every remaining bubble shows its own name and corner. */
.chat-thread.is-pinned-only .bubble-row.is-run .bubble { border-top-left-radius: 5px; }
.chat-thread.is-pinned-only .bubble-row.is-mine.is-run .bubble { border-top-left-radius: 15px; border-top-right-radius: 5px; }
.chat-pinned-none { padding: 26px 16px; text-align: center; color: var(--muted); }
