/* ═══════════════════════════════════════════════════════════════
   app.mendipsys.co.uk — App-specific styles
   Mobile-first. Supplements _shared/internal/assets/css/style.css
   ═══════════════════════════════════════════════════════════════ */

/* ── iOS standalone (home-screen web app) safe areas ──────────── */
/* With black-translucent, the page extends under the iPhone status bar and
   the clock/battery sit on top of whatever is first on the page. Paint a
   brand-blue strip behind the status bar and push everything below it —
   including the TEST MODE / View-as bars, which render above the header.
   env(safe-area-inset-top) is 0 in normal browsers, so this is a no-op
   outside the installed web app. */
body::before {
  content: '';
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: env(safe-area-inset-top, 0px);
  background: var(--brand);
  z-index: 1000;
}
body {
  padding-top: env(safe-area-inset-top, 0px);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
/* Sticky header parks below the strip instead of sliding under the clock. */
.app-header {
  top: env(safe-area-inset-top, 0px);
}
/* Sticky submit bar clears the home indicator. */
.submit-bar {
  bottom: env(safe-area-inset-bottom, 0px);
}

/* iOS sometimes reports ZERO safe-area insets inside an installed web app
   (long-standing WebKit bug), which leaves the header under the Dynamic
   Island / clock / battery. In standalone mode, guarantee the room instead
   of trusting env(): at least 59px top (Dynamic Island status bar) and 24px
   bottom (home indicator) — more if the device reports more. Normal browser
   tabs are untouched. */
/* PORTRAIT ONLY (2026-09-02): sideways, iOS hides the status bar and the
   notch sits at the side, so a forced 59px top band was pure waste — David
   noticed it in the framed diary, where turning the phone is the whole point.
   Landscape trusts env() (usually 0 at the top) plus the 24px home-indicator
   floor at the bottom. */
/* ONLY when the page spans the whole screen (html.ios-under-bar, set in
   header.php: a black-translucent install). Since the 2026-09-11 switch to
   an opaque status bar, a re-added app starts BELOW the bar — env() is 0
   there legitimately and a forced 59px would be a wasted band at the top. */
@media (display-mode: standalone) and (orientation: portrait) {
  html.ios-under-bar body::before {
    height: max(env(safe-area-inset-top, 0px), 59px);
  }
  html.ios-under-bar body {
    padding-top: max(env(safe-area-inset-top, 0px), 59px);
  }
  html.ios-under-bar .app-header {
    top: max(env(safe-area-inset-top, 0px), 59px);
  }
}
@media (display-mode: standalone) {
  body {
    padding-bottom: max(env(safe-area-inset-bottom, 0px), 24px);
  }
  .submit-bar {
    bottom: max(env(safe-area-inset-bottom, 0px), 24px);
  }
}

/* ── Friendly home ────────────────────────────────────────────── */
/* Scenic band below the header — same brand blue at the seam so header and
   scenery read as one; SVG mountains + sun + pines (dashboard.php). */
.home-scene {
  background: linear-gradient(180deg, var(--brand) 0%, #1073a3 100%);
  height: 106px;
  line-height: 0;
  overflow: hidden;
}
.home-scene svg {
  width: 100%;
  height: 100%;
  display: block;
}
.home-hello { margin: .8rem 0 1.1rem; }
.home-hello__greet {
  font-size: 1.55rem;
  margin: 0;
  font-weight: 800;
}
.home-hello__sub {
  margin: .1rem 0 .8rem;
  color: var(--text-muted);
  font-size: .92rem;
}
.home-today {
  display: flex;
  align-items: center;
  gap: .8rem;
  background: #fff;
  border-radius: 16px;
  box-shadow: var(--shadow);
  padding: .95rem 1rem;
  text-decoration: none;
  color: var(--text);
  -webkit-tap-highlight-color: transparent;
}
.home-today:active { background: var(--brand-light); text-decoration: none; }
.home-today__icon {
  font-size: 1.8rem;
  flex: 0 0 52px;
  height: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--brand-light);
  border-radius: 14px;
}
.home-today__body { flex: 1; min-width: 0; }
.home-today__body strong { display: block; font-size: 1.05rem; }
.home-today__body small { display: block; color: var(--text-muted); font-size: .8rem; margin-top: .1rem; }
.home-today__go {
  color: var(--text-muted);
  font-size: 1.35rem;
  flex: 0 0 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  border-radius: 50%;
}
.home-today__next { color: var(--brand) !important; font-weight: 700; }

/* ── Push opt-in card (dashboard) ─────────────────────────────── */
#push-card {
  display: flex;
  align-items: center;
  gap: .75rem;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-left: 4px solid var(--brand);
  border-radius: var(--radius-sm);
  padding: .75rem;
  margin-top: 1rem;
}
#push-card[hidden] { display: none; }
.push-card__body {
  flex: 1;
  min-width: 0;
}
.push-card__body strong {
  display: block;
  font-size: .9rem;
}
.push-card__hint {
  display: block;
  color: var(--text-muted);
  font-size: .78rem;
  margin-top: .1rem;
}
#push-card button { flex: 0 0 auto; }

/* ── Header ☰ menu ────────────────────────────────────────────── */
.hdr-menu { position: relative; }
.hdr-menu__btn {
  background: none;
  border: none;
  color: #fff;
  font-size: 1.25rem;
  line-height: 1;
  padding: .45rem .55rem;      /* touch target */
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.hdr-menu__btn:active { opacity: .7; }
.hdr-menu__list {
  position: absolute;
  top: calc(100% + .35rem);
  right: 0;
  z-index: 300;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  min-width: 200px;
  overflow: hidden;
}
.hdr-menu__list a {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .8rem .95rem;
  font-size: .9rem;
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px solid var(--border);
  -webkit-tap-highlight-color: transparent;
}
.hdr-menu__list a:last-child { border-bottom: none; }
.hdr-menu__list a:active { background: var(--brand-light); }
.hdr-menu__icon { font-size: 1.05rem; color: var(--text-muted); }
.hdr-menu__danger { color: var(--danger) !important; }
.hdr-menu__danger .hdr-menu__icon { color: var(--danger); }

/* ── Testing bar ──────────────────────────────────────────────── */
.testing-bar {
  background: #f39c12;
  color: #000;
  text-align: center;
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .1em;
  padding: .25rem;
}

/* ── View as bar ──────────────────────────────────────────────── */
.viewas-bar {
  background: #6344a8;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  padding: .4rem .75rem;
  font-size: .8rem;
}
.viewas-bar__text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.viewas-bar__form {
  margin: 0;
  flex: 0 0 auto;
}
.viewas-bar__btn {
  background: rgba(255,255,255,.18);
  color: #fff;
  border: 1px solid rgba(255,255,255,.5);
  border-radius: var(--radius-sm);
  padding: .25rem .6rem;
  font-size: .75rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}
.viewas-bar__btn:active {
  background: rgba(255,255,255,.32);
}

/* ── View as picker (admin) ───────────────────────────────────── */
.viewas-search {
  display: flex;
  gap: .5rem;
  margin-bottom: 1rem;
}
.viewas-search input[type="search"] {
  flex: 1;
  min-width: 0;
  padding: .5rem .65rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 16px;
}
.viewas-list {
  display: flex;
  flex-direction: column;
  gap: .4rem;
}
.viewas-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: .6rem .75rem;
}
.viewas-row--self {
  background: var(--bg);
}
.viewas-row__body {
  min-width: 0;
  flex: 1;
  display: flex;
  flex-direction: column;
}
.viewas-row__name {
  font-weight: 600;
  font-size: .9rem;
}
.viewas-row__meta {
  color: var(--text-muted);
  font-size: .75rem;
  margin-top: .1rem;
}
.viewas-row form {
  margin: 0;
  flex: 0 0 auto;
}
/* Whole panel = the tap target (form wraps a full-row submit button) */
.viewas-rowform {
  margin: 0;
}
.viewas-row--btn {
  width: 100%;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.viewas-row--btn:active {
  background: var(--bg);
  border-color: var(--brand, #005e85);
}
.viewas-row__go {
  flex: 0 0 auto;
  font-size: 1.4rem;
  line-height: 1;
  color: var(--text-muted);
}

/* ── Admin tool link ──────────────────────────────────────────── */
.admin-tool {
  display: flex;
  align-items: center;
  gap: .75rem;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-left: 4px solid #6344a8;
  border-radius: var(--radius-sm);
  padding: .75rem;
  margin-bottom: 1.25rem;
  text-decoration: none;
  color: var(--text);
}
.admin-tool:hover {
  background: var(--bg);
  text-decoration: none;
}
.admin-tool__icon {
  font-size: 1.35rem;
  line-height: 1;
}
.admin-tool__body {
  flex: 1;
  min-width: 0;
  display: block;
}
.admin-tool__body strong {
  display: block;
  font-size: .9rem;
}
.admin-tool__body small {
  display: block;
  color: var(--text-muted);
  font-size: .75rem;
  margin-top: .1rem;
}
.admin-tool__go {
  color: var(--text-muted);
  font-size: 1.4rem;
  line-height: 1;
}

/* ── Main content area ────────────────────────────────────────── */
.app-main {
  padding: 1rem;
  max-width: 600px;
  margin: 0 auto;
  width: 100%;
}

/* ── Main menu grid ───────────────────────────────────────────── */
.menu-grid {
  display: grid;
  /* minmax(0,…): a tile's content must never inflate the columns past the
     screen (rich-tile text did exactly that with plain 1fr). */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: .875rem;
  padding-top: .5rem;
}

.menu-btn {
  position: relative;   /* corner unread badge anchors here */
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 110px;
  border-radius: var(--radius);
  text-decoration: none;
  color: #fff;
  background-color: var(--brand);
  /* The mockup's sheen: a soft light-to-dark fade laid over the tile colour
     (tiles set background-COLOR inline, so this image layer survives). */
  background-image: linear-gradient(180deg,
      rgba(255, 255, 255, .16) 0%,
      rgba(255, 255, 255, .04) 38%,
      rgba(0, 0, 0, .10) 100%);
  box-shadow: var(--shadow-md);
  -webkit-tap-highlight-color: transparent;
  transition: filter .15s, transform .1s;
  padding: 1rem;
  text-align: center;
}
.menu-btn:hover,
.menu-btn:focus {
  filter: brightness(1.08);
  text-decoration: none;
  color: #fff;
}
.menu-btn:active {
  transform: scale(.97);
}

.menu-btn--full {
  grid-column: 1 / -1;
  min-height: 100px;
}

.menu-btn__label {
  font-size: 1.15rem;
  font-weight: 700;
  line-height: 1.2;
}

/* Rich tiles (icon and/or subtitle set in Admin — David's mockup 2026-08-20).
   Tiles without either keep the original centred-label look. */
.menu-btn--rich {
  justify-content: flex-start;
  text-align: left;
  gap: .55rem;
  padding: .85rem .7rem;
  min-height: 96px;
  min-width: 0;
  position: relative;
}
.menu-btn__icon {
  font-size: 1.45rem;
  flex: 0 0 42px;
  height: 42px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, .18);
  border-radius: 12px;
}
.menu-btn__text {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1;
}
.menu-btn--rich .menu-btn__label { font-size: 1rem; }
.menu-btn__sub {
  font-size: .7rem;
  font-weight: 500;
  opacity: .85;
  margin-top: .15rem;
  line-height: 1.25;
}
.menu-btn__go {
  font-size: 1.2rem;
  opacity: .65;
  flex: 0 0 auto;
}
/* Full-width rich tile = the hero app (mockup's big Timesheet card):
   stacked and centred, chevron riding the right edge. */
.menu-btn--full.menu-btn--rich {
  flex-direction: column;
  justify-content: center;
  text-align: center;
  gap: .5rem;
  min-height: 150px;
  padding: 1.1rem;
}
.menu-btn--full.menu-btn--rich .menu-btn__icon {
  flex: 0 0 auto;
  width: 54px;
  height: 54px;
  font-size: 1.8rem;
  border-radius: 50%;
}
.menu-btn--full.menu-btn--rich .menu-btn__label { font-size: 1.35rem; }
.menu-btn--full.menu-btn--rich .menu-btn__sub   { font-size: .85rem; }
.menu-btn--full.menu-btn--rich .menu-btn__text  { align-items: center; }
.menu-btn--full.menu-btn--rich .menu-btn__go {
  position: absolute;
  right: 1rem;
  top: 50%;
  transform: translateY(-50%);
  margin: 0;
}

/* A tile's title never runs off the tile (David 2026-09-17: "if people make
   this button smaller the title doesn't fit and runs off the button"). A
   ONE-word title that is too long is cut with an ellipsis on one line. A
   title of several words (--words, set in dashboard.php) still wraps onto a
   second line as it always did, and is cut with an ellipsis only after that:
   the first cut truncated "Accommodation Planner" to one line although it
   fitted on two. The full name is the label's title attribute. Covers all
   three layouts: plain, rich row (icon · text · chevron) and the stacked
   full-width hero, whose text also keeps clear of its chevron. */
.menu-btn__text,
.menu-btn__label { min-width: 0; max-width: 100%; }
.menu-btn__label {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.menu-btn__label--words,
.menu-btn__sub {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  white-space: normal;
  /* Never break inside a word ("Accommodatio/n", "Equip/ment" — tried, and
     it read worse than the cut). */
  overflow-wrap: normal;
}
.menu-btn--full.menu-btn--rich .menu-btn__text { padding-inline: 1.6rem; }
/* Plain (label-only) tiles: before this fix a title that nearly fitted simply
   spilled into the 1rem side padding. Now that the label is held inside the
   content box, give it that room back so those titles still show whole. */
.menu-btn:not(.menu-btn--rich) { padding-inline: .5rem; }

/* ── Admin — button list ──────────────────────────────────────── */
.admin-button-list {
  display: flex;
  flex-direction: column;
  gap: .625rem;
}

.admin-button-card {
  display: flex;
  align-items: stretch;
  background: var(--card-bg);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.admin-button-card--inactive {
  opacity: .55;
}

.admin-button-card__colour {
  width: 6px;
  flex-shrink: 0;
}

.admin-button-card__body {
  flex: 1;
  padding: .75rem .875rem;
  min-width: 0;
}

.admin-button-card__title {
  font-weight: 600;
  font-size: .95rem;
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
}

.admin-button-card__meta {
  font-size: .8rem;
  color: var(--text-muted);
  margin-top: .15rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.admin-button-card__actions {
  display: flex;
  align-items: center;
  gap: .375rem;
  padding: .5rem .75rem;
  flex-shrink: 0;
}

.admin-button-card__reorder {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.btn-reorder {
  width: 28px;
  height: 28px;
  font-size: .85rem;
  padding: 0;
  line-height: 26px;
  text-align: center;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  cursor: pointer;
  color: var(--text);
}
.btn-reorder:hover {
  background: var(--brand-light);
  border-color: var(--brand);
}

.badge {
  display: inline-block;
  font-size: .7rem;
  font-weight: 600;
  padding: .1rem .4rem;
  border-radius: 3px;
  line-height: 1.3;
}
.badge--muted {
  background: var(--border);
  color: var(--text-muted);
}

/* ── Admin — colour picker ───────────────────────────────────── */
.colour-picker {
  display: flex;
  gap: .5rem;
  flex-wrap: wrap;
}

.colour-swatch {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border-radius: var(--radius-sm);
  border: 3px solid transparent;
  cursor: pointer;
  transition: border-color .15s, transform .1s;
}
.colour-swatch:hover {
  transform: scale(1.1);
}
.colour-swatch.selected {
  border-color: var(--text);
  box-shadow: var(--shadow-md);
}
.colour-swatch input[type="radio"] {
  display: none;
}

/* ── Admin — staff selector ──────────────────────────────────── */
.staff-selector {
  max-height: 250px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: .5rem;
  background: var(--card-bg);
}

.staff-selector__item {
  display: block;
  padding: .3rem .25rem;
  font-size: .9rem;
  cursor: pointer;
}
.staff-selector__item:hover {
  background: var(--bg);
}
.staff-selector__item input[type="checkbox"] {
  margin-right: .4rem;
}

/* ── Timesheet shared ─────────────────────────────────────────── */

/* Impersonation banner */
.ts-impersonating {
  background: #f39c12;
  color: #000;
  text-align: center;
  font-size: .8rem;
  font-weight: 700;
  padding: .4rem 1rem;
  border-radius: var(--radius-sm);
  margin-bottom: .75rem;
}

/* View toggle: Day | Week | Month */
.ts-view-toggle {
  display: flex;
  gap: .5rem;
  margin-bottom: .75rem;
}
.ts-view-toggle__btn {
  flex: 1;
  text-align: center;
  padding: .55rem;
  border-radius: var(--radius-sm);
  font-size: .9rem;
  font-weight: 600;
  background: #fff;
  color: var(--brand);
  border: 1.5px solid var(--brand);
  text-decoration: none;
  transition: background .15s, color .15s;
  -webkit-tap-highlight-color: transparent;
}
.ts-view-toggle__btn--active,
.ts-view-toggle__btn:active {
  background: var(--brand);
  color: #fff;
  text-decoration: none;
}
.ts-view-toggle__btn:hover {
  text-decoration: none;
  background: var(--brand-light);
}

/* Prev/next nav bar */
.ts-nav {
  display: flex;
  align-items: center;
  background: #fff;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  margin-bottom: .875rem;
  overflow: hidden;
}
.ts-nav__arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  min-height: 64px;
  font-size: 2rem;
  color: var(--brand);
  text-decoration: none;
  flex-shrink: 0;
  -webkit-tap-highlight-color: transparent;
  transition: background .15s;
}
.ts-nav__arrow:hover { background: var(--brand-light); text-decoration: none; }
.ts-nav__label {
  flex: 1;
  text-align: center;
  padding: .5rem 0;
}
.ts-nav__day  { font-size: .8rem; color: var(--text-muted); font-weight: 600; text-transform: uppercase; letter-spacing: .05em; }
.ts-nav__date { font-size: 1.05rem; font-weight: 700; color: var(--text); }

/* Today / this-period link */
.ts-today-link {
  text-align: center;
  padding: 1rem 0 .5rem;
  font-size: .9rem;
}

/* ── Day view ─────────────────────────────────────────────────── */
.ts-day {
  display: flex;
  flex-direction: column;
  gap: .625rem;
}

/* Status cards (Day Off, Holiday, etc.) */
.ts-status {
  background: #fff;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.25rem 1rem;
  text-align: center;
  font-size: 1.2rem;
  font-weight: 700;
}
.ts-status--off    { color: var(--text-muted); }
.ts-status--flag   { font-size: 1.1rem; }
.ts-status__hours  { font-size: .9rem; font-weight: 500; margin-left: .35rem; opacity: .85; }

/* Flag colours */
/* Day-state colours follow ver5's semantics so the month grid reads the same as
   the CRM the team already knows: holiday red, lieu blue, off pink, working
   green. Deepened from ver5's pale originals for small phone screens. */
.ts-hol   { background: #f08b8b; color: #5c1616; }
.ts-sick  { background: #f7c9c9; color: #6e2222; border: 1px dotted #c0392b; }
.ts-leave { background: #f7c9c9; color: #6e2222; border: 1px solid #d4690e; }
.ts-lieu  { background: #c2ccf5; color: #23306e; }

/* Block cards */
.ts-block {
  position: relative;
  background: #fff;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: .875rem 1rem;
  display: flex;
  flex-direction: column;
  gap: .3rem;
}
.ts-block--dm {
  border-left: 4px solid var(--accent);
}
.ts-block--worked {
  border-left: 4px solid var(--success);
}
.ts-block--note {
  background: var(--brand-light);
  border-left: 4px solid var(--brand);
}

.ts-block__times {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--text);
  letter-spacing: .02em;
}
.ts-block__role {
  display: flex;
  align-items: center;
  gap: .5rem;
  font-size: .95rem;
  color: var(--text-muted);
  font-weight: 500;
}
.ts-block__role-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  flex-shrink: 0;
  display: inline-block;
}
.ts-block__dm-badge {
  background: var(--accent);
  color: #fff;
  font-size: .7rem;
  font-weight: 700;
  padding: .1rem .35rem;
  border-radius: 3px;
  letter-spacing: .05em;
}
.ts-block__hours {
  font-size: .8rem;
  color: var(--text-muted);
}
.ts-block__note {
  font-style: italic;
  color: var(--brand);
  font-size: .95rem;
}

/* ── Week view ────────────────────────────────────────────────── */
.ts-week {
  display: flex;
  flex-direction: column;
  gap: .5rem;
}

.ts-week-row {
  display: flex;
  align-items: center;
  background: #fff;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: .75rem 1rem;
  text-decoration: none;
  color: var(--text);
  gap: .875rem;
  min-height: 62px;
  -webkit-tap-highlight-color: transparent;
  transition: background .15s;
}
.ts-week-row:hover { background: var(--brand-light); text-decoration: none; color: var(--text); }
.ts-week-row--today { border-left: 4px solid var(--brand); }

.ts-week-row__day {
  min-width: 40px;
  text-align: center;
  flex-shrink: 0;
}
.ts-week-row__dname {
  font-size: .75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--text-muted);
}
.ts-week-row__dnum {
  font-size: 1.35rem;
  font-weight: 700;
  line-height: 1;
}

.ts-week-row__status {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: .3rem;
}
.ts-week-row__pills {
  display: flex;
  flex-wrap: wrap;
  gap: .35rem;
  align-items: center;
}
/* Shift start–finish on working days (housekeeping asked, 2026-09-08). */
.ts-week-row__times {
  font-size: .95rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.ts-week-row__hours {
  margin-left: .5rem;
  font-weight: 500;
  color: var(--text-muted);
}

.ts-week-row__arrow {
  font-size: 1.25rem;
  color: var(--text-muted);
  flex-shrink: 0;
}

/* Pills (used in week view) */
.ts-pill {
  display: inline-block;
  padding: .25rem .6rem;
  border-radius: 20px;
  font-size: .78rem;
  font-weight: 700;
}
.ts-pill--off     { background: #f7c9c9; color: #6e2222; }
.ts-pill--working { background: #b7e4b7; color: #1d4d1d; }
/* Role pills carry ver5's pastel fill + border inline (ts_role_style), so the
   text is dark — white on #fcf3e1 (House Keeping) was unreadable. */
.ts-pill--role    { color: #1f2937; }
.ts-pill--flag    { }
/* Overlays — can appear alongside any state pill. */
.ts-pill--course  { background: #f2c811; color: #5c4a05; }
.ts-pill--booked  { background: #fff; color: #2560c4; box-shadow: inset 0 0 0 2px #2560c4; }

/* Day view: course / booked-off markers above the day content */
.ts-day-marks {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
  margin-bottom: .75rem;
}

/* ── Month / calendar view ────────────────────────────────────── */
.ts-cal {
  background: #fff;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
  margin-bottom: .875rem;
}

.ts-cal__header {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  background: var(--brand);
}
.ts-cal__hcell {
  text-align: center;
  padding: .5rem 0;
  font-size: .75rem;
  font-weight: 700;
  color: rgba(255,255,255,.85);
  text-transform: uppercase;
  letter-spacing: .05em;
}

.ts-cal__grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
}

.ts-cal__cell {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: .4rem .15rem .5rem;
  min-height: 52px;
  border-top: 1px solid var(--border);
  border-right: 1px solid var(--border);
  text-decoration: none;
  color: var(--text);
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
}
.ts-cal__cell:nth-child(7n) { border-right: none; }
.ts-cal__cell:hover { text-decoration: none; }
.ts-cal__cell:active { filter: brightness(.94); }

/* Day-state fills — ver5 semantics, deepened for phone screens. */
.ts-cal__cell--working { background: #b7e4b7; color: #1d4d1d; }
.ts-cal__cell--off     { background: #f7c9c9; color: #6e2222; }
.ts-cal__cell--hol     { background: #f08b8b; color: #5c1616; }
.ts-cal__cell--lieu    { background: #c2ccf5; color: #23306e; }
.ts-cal__cell--sick    { background: #f7c9c9; color: #6e2222; box-shadow: inset 0 0 0 2px #c0392b; }
.ts-cal__cell--leave   { background: #f7c9c9; color: #6e2222; box-shadow: inset 0 0 0 2px #d4690e; }

.ts-cal__cell--out { opacity: .28; pointer-events: none; }

/* Booked off — blue ring, as in ver5. Overlays any state fill. */
.ts-cal__cell--booked { box-shadow: inset 0 0 0 2px #2560c4; }

/* On course — yellow bar across the top of the cell, as in ver5. */
.ts-cal__course-bar {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 6px;
  background: #f2c811;
}
.ts-cal__cell--course .ts-cal__cell-num { margin-top: .2rem; }

.ts-cal__cell--today { box-shadow: inset 0 0 0 2px var(--brand); }
.ts-cal__cell--today .ts-cal__cell-num {
  background: var(--brand);
  color: #fff;
  border-radius: 50%;
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.ts-cal__cell-num {
  font-size: .82rem;
  font-weight: 700;
  line-height: 1;
  margin-bottom: .2rem;
}
.ts-cal__cell-status {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 2px;
  min-height: 8px;
}

.ts-cal__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  display: inline-block;
  box-shadow: 0 0 0 1px rgba(0,0,0,.12);
}

/* State letter (H / S / L / Li) and the booked-off B. Colour is inherited from
   the cell fill so it always sits legibly on its own background. */
.ts-cal__mark {
  font-size: .68rem;
  font-weight: 700;
  line-height: 1;
}
.ts-cal__mark--booked {
  position: absolute;
  bottom: 2px;
  right: 3px;
  color: #2560c4;
}

/* Legend swatches */
.ts-swatch {
  width: 14px;
  height: 14px;
  border-radius: 3px;
  display: inline-block;
  flex: 0 0 auto;
}
.ts-swatch--working { background: #b7e4b7; }
.ts-swatch--off     { background: #f7c9c9; }
.ts-swatch--hol     { background: #f08b8b; }
.ts-swatch--lieu    { background: #c2ccf5; }
.ts-swatch--sick    { background: #f7c9c9; box-shadow: inset 0 0 0 2px #c0392b; }
.ts-swatch--leave   { background: #f7c9c9; box-shadow: inset 0 0 0 2px #d4690e; }
.ts-swatch--course  { background: #f2c811; }
.ts-swatch--booked  { box-shadow: inset 0 0 0 2px #2560c4; }

/* Calendar legend */
.ts-cal__legend {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  padding: .75rem 1rem;
  font-size: .78rem;
  color: var(--text-muted);
  border-top: 1px solid var(--border);
  background: #fff;
  border-radius: 0 0 var(--radius) var(--radius);
}
.ts-cal__legend-item {
  display: flex;
  align-items: center;
  gap: .3rem;
}

/* ── Worked-line adjustments (day view) ───────────────────────── */
/* Grey = worked, matching ver5's timesheet semantics. */
.ts-worked-line {
  background: #f0f1f3;
  border-left: 4px solid #9aa0a8;
  border-radius: var(--radius-sm);
  padding: .5rem .7rem;
  margin-top: .45rem;
}
.ts-worked-line__main {
  display: flex;
  align-items: baseline;
  gap: .6rem;
  flex-wrap: wrap;
}
.ts-worked-line__label {
  font-size: .68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: #6b7280;
}
.ts-worked-line__times {
  font-weight: 700;
  font-size: .95rem;
}
.ts-worked-line__hours {
  color: var(--text-muted);
  font-size: .8rem;
}
.ts-worked-line__note {
  margin-top: .25rem;
  font-size: .8rem;
  font-style: italic;
  color: var(--text-muted);
}

/* Single-action icon button — subtle, top-right of the card.
   (.ts-adjust-cog is a JS binding class only, unstyled.) */
.ts-icon-btn {
  position: absolute;
  top: .5rem;
  right: .6rem;
  background: none;
  border: none;
  font-size: 1.15rem;
  line-height: 1;
  color: #b6bcc4;
  padding: .3rem;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.ts-icon-btn:active { color: var(--brand); }
/* The icon is an SVG from the registry now (it was the ✎ character), so drop
   the inline baseline gap that would otherwise nudge it off-centre. */
.ts-icon-btn svg { display: block; }

/* Two-plus actions: the ⋯ menu (house rule — see CLAUDE.md). */
.ts-actions {
  position: absolute;
  top: .35rem;
  right: .5rem;
}
.ts-actions__btn {
  background: none;
  border: none;
  font-size: 1.3rem;
  line-height: 1;
  color: #b6bcc4;
  padding: .3rem .45rem;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.ts-actions__btn:active { color: var(--brand); }
.ts-actions__menu {
  position: absolute;
  top: 100%;
  right: 0;
  z-index: 50;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  min-width: 220px;
  overflow: hidden;
}
.ts-actions__menu button {
  display: flex;
  align-items: center;
  gap: .6rem;
  width: 100%;
  background: none;
  border: none;
  border-bottom: 1px solid var(--border);
  padding: .75rem .9rem;      /* proper touch target */
  font-size: .9rem;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.ts-actions__menu button:last-child { border-bottom: none; }
.ts-actions__menu button:active { background: var(--brand-light); }
.ts-actions__icon { font-size: 1.1rem; color: var(--text-muted); }

.ts-locked-chip {
  background: #fff;
  border: 1.5px solid #c0392b;
  color: #842029;
  border-radius: var(--radius-sm);
  padding: .45rem .75rem;
  font-size: .8rem;
  font-weight: 600;
  margin-bottom: .75rem;
  text-align: center;
}

/* Bottom sheet */
#adjust-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.45);
  z-index: 200;
}
#adjust-sheet {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 201;
  background: #fff;
  border-radius: var(--radius) var(--radius) 0 0;
  box-shadow: 0 -4px 24px rgba(0,0,0,.25);
  padding: 1rem 1rem calc(1rem + env(safe-area-inset-bottom, 0px));
  max-width: 600px;
  margin: 0 auto;
}
.adjust-sheet__title {
  font-size: 1rem;
  margin: 0 0 .75rem;
}
.adjust-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: .6rem;
}
.adjust-row__label {
  font-size: .85rem;
  font-weight: 600;
  color: var(--text-muted);
}
.adjust-row--total {
  border-top: 1px solid var(--border);
  padding-top: .5rem;
}
#adjust-total { font-weight: 700; }
.adjust-stepper {
  display: flex;
  align-items: center;
  gap: .4rem;
}
.adjust-stepper__btn {
  width: 56px;
  height: 44px;               /* proper touch target */
  border: 1.5px solid var(--brand);
  background: #fff;
  color: var(--brand);
  border-radius: var(--radius-sm);
  font-size: .95rem;
  font-weight: 700;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.adjust-stepper__btn:active {
  background: var(--brand);
  color: #fff;
}
.adjust-stepper__time {
  min-width: 64px;
  text-align: center;
  font-size: 1.15rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
#adjust-role {
  width: 100%;
  padding: .55rem .65rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: .9rem;
  margin: .25rem 0 .9rem;
  background: #fff;
}
#adjust-note {
  width: 100%;
  padding: .55rem .65rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: .9rem;
  margin: .25rem 0 .9rem;
}
.adjust-actions {
  display: flex;
  gap: .5rem;
}
.adjust-actions .btn { flex: 1; }
.adjust-actions #adjust-remove { flex: 0 0 auto; }

.ts-cal-feed-link { font-size: .82rem; }
.ts-cal-feed-link a { color: var(--text-muted); }

/* IIC deep link into the booking file (customer app) */
.ts-session__bookinglink {
  font-size: .72rem;
  font-weight: 700;
  color: var(--brand);
  border: 1.5px solid var(--brand);
  border-radius: 20px;
  padding: .1rem .5rem;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.ts-session__bookinglink:active { background: var(--brand); color: #fff; }

/* ── Holiday request form ─────────────────────────────────────── */
/* iOS renders bare date inputs as grey centred pills — restyle them into
   proper white fields. 16px font also stops iOS zoom-jumping on focus. */
.req-form { padding: 1rem; margin-bottom: 1.25rem; }
.req-form__dates {
  display: flex;
  align-items: flex-end;
  gap: .5rem;
  margin-bottom: .85rem;
}
.req-form__dates .req-form__field { flex: 1; min-width: 0; }
.req-form__arrow { color: var(--text-muted); padding-bottom: .8rem; }
.req-form__field { margin-bottom: .85rem; }
.req-form__dates .req-form__field { margin-bottom: 0; }
.req-form input[type="date"],
.req-form input[type="text"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  min-height: 48px;
  padding: .6rem .7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fff;
  font-size: 16px;
  color: var(--text);
  font-family: inherit;
}
.req-form input:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 2px var(--brand-light);
}
.req-form input[type="date"]::-webkit-date-and-time-value { text-align: left; }
.req-form__send { width: 100%; min-height: 48px; }

/* ── Programme month view (list of days + sessions) ───────────── */
.pm-toggle { margin-bottom: .75rem; }
.pm-list {
  background: #fff;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
  margin-bottom: .875rem;
}
.pm-day {
  display: flex;
  gap: .75rem;
  padding: .55rem .75rem;
  border-bottom: 1px solid var(--border);
  border-left: 4px solid transparent;
}
/* Cheers — peer recognition (ver5's tb_staff_cheers), phone-shaped. */
.ch-give { padding: .9rem; margin-top: .8rem; }
.ch-give__lead {
  display: block;
  font-size: .85rem;
  font-weight: 700;
  color: var(--text);
  margin: 0 0 .4rem;
}
.ch-give__select,
.ch-give__text {
  display: block;
  width: 100%;
  box-sizing: border-box;
  font-size: 16px;              /* stops the iOS zoom-jump */
  font-family: inherit;
  padding: .6rem;
  border: 1px solid #d5dbe1;
  border-radius: 8px;
  background: #fff;
  color: var(--text);
  margin-bottom: .8rem;
  -webkit-appearance: none;
  appearance: none;
}
.ch-give__text { resize: vertical; min-height: 5.5rem; }
.ch-give__btn {
  width: 100%;
  font-size: 16px;
  font-weight: 700;
  padding: .7rem;
  border: none;
  border-radius: 8px;
  background: var(--brand);
  color: #fff;
  -webkit-tap-highlight-color: transparent;
}
.ch-give__btn:active { filter: brightness(.9); }
.ch-tabs { margin-top: .9rem; }
.ch-card { padding: .75rem .85rem; margin-top: .6rem; }
.ch-card--new { box-shadow: inset 0 0 0 2px #4f9e4f; }
.ch-card__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .5rem;
  margin-bottom: .3rem;
}
.ch-card__who { font-weight: 700; font-size: .9rem; }
.ch-card__when { font-size: .74rem; color: var(--text-muted); white-space: nowrap; }
.ch-card__text { margin: 0; font-size: .92rem; line-height: 1.4; }
.ch-empty {
  text-align: center;
  color: var(--text-muted);
  font-size: .88rem;
  padding: 1.6rem 1rem;
}
.hdr-menu__badge {
  font-style: normal;
  font-size: .7rem;
  font-weight: 800;
  color: #fff;
  background: #4f9e4f;
  border-radius: 999px;
  padding: .05rem .4rem;
  margin-left: .25rem;
}

/* My stats — Insight's team-member dossier, phone-shaped. */
.st-kpis {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .6rem;
  margin-top: .8rem;
}
.st-kpi {
  background: #fff;
  border-radius: 10px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .07);
  padding: .75rem .8rem;
  display: flex;
  flex-direction: column;
  gap: .1rem;
}
.st-kpi--good { box-shadow: inset 0 0 0 2px #4f9e4f; }
.st-kpi--low  { box-shadow: inset 0 0 0 2px #cf6060; }
.st-kpi__v { font-size: 1.45rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.st-kpi__l { font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .02em; color: var(--text-muted); }
.st-kpi__s { font-size: .74rem; color: var(--text-muted); }
.st-card {
  background: #fff;
  border-radius: 10px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .07);
  padding: .85rem .9rem;
  margin-top: .8rem;
}
.st-card__title {
  font-size: .78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .03em;
  color: var(--text-muted);
  margin: 0 0 .6rem;
}
.st-role, .st-month {
  display: flex;
  align-items: center;
  gap: .55rem;
  padding: .22rem 0;
  font-size: .85rem;
}
.st-role__name { flex: 0 0 34%; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.st-role__dot { display: inline-block; width: .6rem; height: .6rem; border-radius: 50%; margin-right: .3rem; vertical-align: -1px; }
.st-role__job { font-style: normal; font-size: .68rem; color: var(--text-muted); }
.st-role__bar, .st-month__bar {
  flex: 1;
  height: 9px;
  background: #eef1f4;
  border-radius: 5px;
  overflow: hidden;
}
.st-role__bar i, .st-month__bar i {
  display: block;
  height: 100%;
  background: var(--brand);
  border-radius: 5px;
}
.st-month__bar--low { background: #d98a3d !important; }
.st-role__hrs { flex: 0 0 auto; font-variant-numeric: tabular-nums; color: var(--text-muted); font-size: .78rem; }
.st-month__name { flex: 0 0 2.4rem; font-weight: 700; }
.st-month__pc { flex: 0 0 2.6rem; text-align: right; font-variant-numeric: tabular-nums; font-size: .78rem; color: var(--text-muted); }
.st-fact { display: flex; align-items: baseline; gap: .55rem; padding: .25rem 0; }
.st-fact__v { font-size: 1.2rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.st-fact__l { font-size: .8rem; color: var(--text-muted); }
.st-acts { display: flex; flex-wrap: wrap; gap: .35rem; margin-top: .5rem; }
.st-act {
  font-size: .74rem;
  font-weight: 600;
  background: #eef4f8;
  border-radius: 999px;
  padding: .22rem .6rem;
}
.st-act em { font-style: normal; font-weight: 800; color: var(--brand); }
.st-note { font-size: .72rem; color: var(--text-muted); margin: .6rem 0 0; }

/* Team timesheet picker — ver5's staff picker, phone-shaped. */
.tm-picker {
  background: #fff;
  border-radius: 10px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .07);
  padding: .8rem .9rem;
  margin-top: .8rem;
}
.tm-picker__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: .45rem;
}
.tm-picker__label {
  display: block;
  font-size: .78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .03em;
  color: var(--text-muted);
}
.tm-picker__menu-wrap { position: relative; }
.tm-picker__menu-btn {
  font-size: 1.15rem;
  line-height: 1;
  padding: .25rem .5rem;
  border: none;
  background: none;
  color: var(--text-muted);
  -webkit-tap-highlight-color: transparent;
}
.tm-picker__menu-btn:active { color: var(--brand); }
.tm-picker__menu {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  z-index: 60;
  min-width: 190px;
  list-style: none;
  margin: 0;
  padding: .25rem;
  background: #fff;
  border: 1px solid #d5dbe1;
  border-radius: 10px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .14);
}
.tm-picker__menu li + li { border-top: 1px solid #eef1f4; }
.tm-picker__group {
  display: block;
  width: 100%;
  text-align: left;
  font-size: .95rem;
  font-weight: 600;
  padding: .6rem .7rem;
  border: none;
  background: none;
  color: var(--text);
  -webkit-tap-highlight-color: transparent;
}
.tm-picker__group:active { background: #f2f6f9; }
.tm-picker__group--active { color: var(--brand); }
.tm-picker__group--active::after { content: " ✓"; }
.tm-picker__members {
  list-style: none;
  margin: 0 0 .6rem;
  padding: 0;
  border: 1px solid #e3e8ed;
  border-radius: 8px;
  overflow: hidden;
}
.tm-picker__members li + li { border-top: 1px solid #eef1f4; }
.tm-picker__member {
  display: block;
  padding: .6rem .7rem;
  font-size: .95rem;
  font-weight: 600;
  color: var(--text);
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.tm-picker__member:active { background: #f2f6f9; }
.tm-picker__member--active { color: var(--brand); }
.tm-picker__member--active::after { content: " ✓"; }
.tm-picker__row { display: flex; gap: .5rem; }
.tm-picker__select {
  flex: 1;
  min-width: 0;
  font-size: 16px;           /* stops the iOS zoom-jump */
  padding: .55rem .6rem;
  border: 1px solid #d5dbe1;
  border-radius: 8px;
  background: #fff;
  color: var(--text);
  -webkit-appearance: none;
  appearance: none;
}
.tm-picker__go {
  font-size: 16px;
  font-weight: 700;
  padding: .55rem 1.1rem;
  border: none;
  border-radius: 8px;
  background: var(--brand);
  color: #fff;
  -webkit-tap-highlight-color: transparent;
}
.tm-picker__go:active { filter: brightness(.9); }
.ts-impersonating__back {
  float: right;
  color: inherit;
  font-weight: 700;
  text-decoration: underline;
}

/* Navigation veil — raised by app.js when a tap starts a page load. The
   delayed opacity transition means it only ever appears on slow loads.
   pointer-events stays none: it's an indicator, never a blocker. */
.nav-veil {
  position: fixed;
  inset: 0;
  z-index: 500;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, .55);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .2s ease;
}
.nav-veil--on {
  visibility: visible;
  opacity: 1;
  transition-delay: .35s;
}
.nav-veil__spinner {
  width: 44px;
  height: 44px;
  border: 4px solid rgba(0, 94, 133, .2);
  border-top-color: var(--brand);
  border-radius: 50%;
  animation: nav-veil-spin .8s linear infinite;
}
@keyframes nav-veil-spin {
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .nav-veil__spinner { animation-duration: 2s; }
}

/* Row tints follow ver5 / the month grid: green working, light red off,
   darker red holiday & friends. */
.pm-day--working { background: #eef7ee; border-left-color: #74b874; }
.pm-day--off     { background: #fdeeee; }
.pm-day--flag    { background: #f6cfcf; border-left-color: #c0392b; }
.pm-day--today   { box-shadow: inset 0 0 0 2px var(--brand); }
.pm-day__date {
  flex: 0 0 44px;
  text-align: center;
  text-decoration: none;
  color: var(--text);
}
.pm-day__dow { display: block; font-size: .65rem; font-weight: 700; text-transform: uppercase; color: var(--text-muted); }
.pm-day__num { display: block; font-size: 1.05rem; font-weight: 800; line-height: 1.1; }
.pm-day__body { flex: 1; min-width: 0; }
.pm-day__quiet { color: var(--text-muted); font-size: .8rem; }
.pm-day__blocks { font-size: .8rem; color: var(--text-muted); margin-bottom: .15rem; }
.pm-day__block { margin-right: .6rem; white-space: nowrap; }
.pm-row {
  display: flex;
  align-items: center;
  gap: .45rem;
  padding: .18rem 0;
}
/* Session pills — ver5's colour language. */
.pm-pill {
  position: relative;
  display: block;
  flex: 1;
  min-width: 0;
  border-radius: 7px;
  padding: .4rem 2.1rem .4rem .6rem;
  text-decoration: none;
  color: var(--text);
  border: 1.5px solid transparent;
  -webkit-tap-highlight-color: transparent;
}
a.pm-pill:active { filter: brightness(.95); }
/* OAP states: green = open with bookings, purple = open but nobody booked
   yet, red = closed. Private programme sessions are light blue. */
.pm-pill--oap  { background: #e0f2e0; border-color: #4f9e4f; }
.pm-pill--oap.pm-pill--zero   { background: #efe4f9; border-color: #ab7fd4; }
.pm-pill--oap.pm-pill--closed { background: #fbe0e0; border-color: #cf6060; }
/* Private programmes follow ver5's status colours: provisional = ms-blue,
   confirmed = ms-green, confirmed evening = darker green. */
.pm-pill--prog { background: #c3eafb; border-color: #b5d9ea; }
.pm-pill--prog-confirmed { background: #cee3ac; border-color: #b8da83; }
.pm-pill--prog-evening   { background: #96e56c; border-color: #b8da83; }
/* Personal Outlook appointments — deliberately plain next to work pills */
.pm-pill--cal {
  background: #fff;
  border: 1.5px dashed var(--border);
  padding-right: .6rem;
}
.pm-pill--cal .pm-pill__name { font-weight: 500; }
.pm-pill__tag {
  display: inline-block;
  font-style: normal;
  font-size: .6rem;
  font-weight: 800;
  letter-spacing: .02em;
  color: #fff;
  background: #2560c4;
  border-radius: 3px;
  padding: 0 .28rem;
  margin-right: .3rem;
  vertical-align: 1px;
}
.pm-pill__name { display: block; font-weight: 700; font-size: .85rem; }
.pm-pill__iic {
  font-style: normal;
  font-size: .62rem;
  font-weight: 800;
  color: #fff;
  background: var(--success);
  border-radius: 3px;
  padding: 0 .28rem;
  vertical-align: 1px;
}
.pm-pill__meta {
  display: block;
  font-size: .74rem;
  color: var(--text-muted);
  margin-top: .05rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pm-pill__count {
  position: absolute;
  top: 50%;
  right: .5rem;
  transform: translateY(-50%);
  min-width: 1.5rem;
  text-align: center;
  font-weight: 800;
  font-size: .85rem;
  color: #1d6f1d;
  background: #cfeacf;
  border-radius: 5px;
  padding: .15rem .25rem;
}
.pm-pill--zero .pm-pill__count   { color: #7a4fa0; background: #e4d2f4; }
.pm-pill--closed .pm-pill__count { color: #a83232; background: #f4caca; }

/* ── OAP session register ─────────────────────────────────────── */
.ts-session__reglink {
  color: inherit;
  font-weight: 700;
  text-decoration: none;
}
.ts-session__reglink:active { color: var(--brand); }

.oap-head {
  background: #fff;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: .875rem 1rem;
  margin-bottom: .875rem;
}
.oap-head__name { font-size: 1.1rem; margin: 0 0 .25rem; }
.oap-head__meta { color: var(--text-muted); font-size: .85rem; }
.oap-head__note {
  margin-top: .5rem;
  font-size: .85rem;
  font-style: italic;
  background: var(--brand-light);
  border-radius: var(--radius-sm);
  padding: .4rem .6rem;
}

.oap-booking {
  background: #fff;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: .75rem 1rem;
  margin-bottom: .75rem;
}
.oap-booking__top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: .75rem;
}
.oap-booking__name { font-weight: 700; }
.oap-booking__meta { color: var(--text-muted); font-size: .82rem; margin-top: .15rem; }
.oap-booking__note {
  margin-top: .5rem;
  font-size: .82rem;
  font-style: italic;
  background: var(--warn-bg);
  color: var(--warn);
  border-radius: var(--radius-sm);
  padding: .4rem .6rem;
}

.oap-arrived {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .15rem;
  padding: .25rem .4rem;
  -webkit-tap-highlight-color: transparent;
}
.oap-arrived__box { width: 28px; height: 28px; accent-color: var(--success); }
.oap-arrived__label { font-size: .65rem; font-weight: 700; text-transform: uppercase; color: var(--text-muted); }
.oap-arrived__stamp { font-size: .7rem; color: var(--success); font-weight: 700; min-height: .9em; }
.oap-arrived--readonly { opacity: .7; }

.oap-people { margin-top: .6rem; border-top: 1px solid var(--border); padding-top: .45rem; }
.oap-person { font-size: .88rem; padding: .18rem 0; }
.oap-person__age  { color: var(--text-muted); font-size: .78rem; margin-left: .35rem; }
.oap-person__note { display: block; color: var(--text-muted); font-size: .78rem; font-style: italic; }
.oap-extra { font-size: .82rem; color: var(--text-muted); margin-top: .35rem; }

/* ── Sessions (Phase 2 — inside day view blocks) ──────────────── */
/* Light-only app (matches the color-scheme meta): stops iOS dark mode
   restyling native controls. Buttons inherit the surrounding text colour —
   the UA default ('buttontext') goes WHITE in dark mode and made the
   messenger's person rows invisible. Classes that set their own colour
   (.btn, .menu-btn, …) still win. */
:root { color-scheme: light; }
button { color: inherit; }

/* iOS zooms the whole page when a focused input's font is under 16px —
   and it STAYS zoomed after the keyboard closes, clipping the right edge
   (found via the messenger composer, 2026-08-20). Mobile-only app: every
   text-entry control gets 16px, so no page can ever trigger the zoom. */
input[type="text"],
input[type="search"],
input[type="url"],
input[type="email"],
input[type="password"],
input[type="number"],
textarea,
select {
  font-size: 16px;
}

/* ── "Waiting for you" badge-explainer card (dashboard) ──────────── */
.att-card {
  background: #fff;
  border-radius: 16px;
  box-shadow: var(--shadow);
  padding: .75rem .9rem;
  margin-top: .7rem;
}
.att-card__head {
  font-size: .8rem;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .04em;
  display: flex;
  align-items: center;
  gap: .45rem;
  margin-bottom: .35rem;
}
.att-card__total {
  background: #d33;
  color: #fff;
  border-radius: 999px;
  font-size: .72rem;
  min-width: 1.35rem;
  text-align: center;
  padding: .08rem .3rem;
}
.att-row {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .5rem .1rem;
  text-decoration: none;
  color: var(--text);
  font-size: .92rem;
  border-top: 1px solid var(--border);
  -webkit-tap-highlight-color: transparent;
}
.att-row:first-of-type { border-top: 0; }
.att-row:active { background: var(--brand-light); }
.att-row__icon { font-size: 1.15rem; }
.att-row__label { flex: 1; }
.att-row .home-today__go { flex-basis: 26px; height: 26px; font-size: 1.1rem; }

/* Header messages button — one tap from every page, with unread badge */
.hdr-msg {
  position: relative;
  display: inline-flex;
  align-items: center;
  color: #fff;
  text-decoration: none;
  font-size: 1.3rem;
  line-height: 1;
  padding: .3rem .15rem;
  margin-right: .35rem;
  -webkit-tap-highlight-color: transparent;
}
.hdr-msg__ico { display: block; }          /* the rail's speech bubble (2026-09-02), sized by its width/height attrs */
.hdr-msg--preview { opacity: .45; }
.hdr-msg__badge {
  position: absolute;
  top: -3px;
  right: -8px;
  background: #d33;
  color: #fff;
  font-style: normal;
  font-size: .62rem;
  font-weight: 700;
  border-radius: 999px;
  min-width: 1.05rem;
  text-align: center;
  padding: .08rem .2rem;
  border: 2px solid var(--brand);
}

/* Unread corner badge on a Messages home tile */
.menu-btn__unread {
  position: absolute;
  top: -7px;
  right: -7px;
  background: #d33;
  color: #fff;
  font-size: .75rem;
  font-weight: 700;
  border-radius: 999px;
  min-width: 1.5rem;
  text-align: center;
  padding: .15rem .3rem;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .3);
  z-index: 2;
}

/* Photo avatars: the person's real image fills the circle */
.msg-ava--photo {
  overflow: hidden;
  background: #dfe7ef;
}
.msg-ava--photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: 50%;
}

/* ── Messages (msg-*, includes/messages.php) ─────────────────────── */
.msg-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: .25rem 0 .9rem;
}
.msg-head h1 { font-size: 1.35rem; margin: 0; font-weight: 800; }
.msg-ava {
  flex: 0 0 46px;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-weight: 700;
  font-size: 1rem;
}
.msg-ava--sm { flex-basis: 34px; width: 34px; height: 34px; font-size: .8rem; }

/* Inbox */
.msg-list { display: flex; flex-direction: column; gap: .45rem; }
.msg-item {
  display: flex;
  align-items: center;
  gap: .7rem;
  background: #fff;
  border-radius: 14px;
  box-shadow: var(--shadow);
  padding: .7rem .85rem;
  text-decoration: none;
  color: var(--text);
  -webkit-tap-highlight-color: transparent;
}
.msg-item:active { background: var(--brand-light); }
.msg-item__body { flex: 1; min-width: 0; }
.msg-item__top { display: flex; justify-content: space-between; align-items: baseline; gap: .5rem; }
.msg-item__name { font-weight: 700; font-size: .95rem; }
.msg-item__time { font-size: .72rem; color: var(--text-muted); white-space: nowrap; }
.msg-item__bottom { display: flex; align-items: center; gap: .4rem; margin-top: .1rem; }
.msg-item__preview {
  flex: 1;
  min-width: 0;
  font-size: .82rem;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.msg-item__mute { font-size: .75rem; opacity: .6; }
.msg-item__badge {
  background: var(--brand);
  color: #fff;
  border-radius: 999px;
  font-size: .7rem;
  font-weight: 700;
  min-width: 1.35rem;
  text-align: center;
  padding: .1rem .3rem;
}
.msg-item--unread .msg-item__name,
.msg-item--unread .msg-item__preview { color: var(--text); font-weight: 700; }

/* ── The PAGE must never scroll behind a conversation (David 2026-09-03) ──
   style.css gives body `min-height: 100vh`. On a phone with the browser bar
   showing, 100vh is the LARGE viewport, so the body ran taller than what was
   visible by the height of that bar — and the page could scroll by that
   much. Scroll it while the thread was still loading and the name bar sat
   half off the top of the screen, stuck there ("stays locked like that").
   The conversation view pins the body to the DYNAMIC viewport instead and
   forbids page scroll; only #msg-scroll moves. Phones only: the desktop
   two-pane has its own fixed-height frame and its own rules. The same trick
   already holds the phone-frame page (body.mf-page). */
/* NOT 100dvh (2026-09-04). In the installed iOS app the page extends under
   the status bar, but 100dvh (and 100vh) come back WITHOUT that band — about
   59pt short of the screen. So a body sized by dvh ended 59pt above the
   bottom, the composer with it, and the "deeper than ideal" space beneath
   the message box was exactly that band plus the home-indicator padding.
   Both yesterday's subtraction and the flex version inherited it, which is
   why the gap never moved. A fixed body with all four edges at zero spans
   the whole screen whatever iOS says the viewport is; the safe-area
   paddings then sit INSIDE it (border-box), and flex fills the rest. */
/* MEASURED on David's phone, 2026-09-04 (the Layout check overlay):
     screen 874   innerHeight 812   env(safe-area-inset-top) 62
   The viewport is exactly the status-bar height SHORTER than the screen, and
   it is anchored to the TOP of the screen (the header sits at viewport 62–122
   and at screen 62–122). So the missing 62pt is at the BOTTOM: the web view
   extends under the status bar, but iOS reports a viewport that stops 62pt
   above the bottom edge. Every height figure — vh, dvh, innerHeight, a fixed
   body's bottom:0 — is short by that much, which is why the flex pane and
   the fixed body both left the band untouched. The body therefore takes the
   SCREEN's height: the viewport plus the top inset. In an ordinary browser
   tab the inset is 0 and this is plain 100dvh again. */
/* …and the second screenshot showed the composer CUT OFF at 812 with blank
   screen beneath: the web view really is only 812 tall and anchored to the
   top. The bottom 62pt of the screen is not part of the page at all — no
   stylesheet can reach it — and giving the body the screen's height only
   pushed the message box into unpaintable space. So the body is the true
   viewport again (inset: 0). What CAN be reclaimed is the 34pt the body pads
   for the home indicator: that indicator sits at 840–874, entirely outside
   the view, so on this page the padding guards against nothing.
   html.ios-short-view is set by messages.js when it measures exactly this
   state (installed, portrait, innerHeight short of the screen by at least
   a top inset that is itself present — an opaque-bar install is short at
   the TOP with inset 0, reaches the indicator, and keeps the padding), so
   the padding returns by itself the day iOS paints the whole screen. The
   remaining 62pt band is iOS's, not ours. */
html:not(.desktop) body.msg-conv {
  position: fixed;
  inset: 0;
  width: 100%;
  height: auto;
  box-sizing: border-box;
  min-height: 0;
  overflow: hidden;
  overscroll-behavior: none;
}
html.ios-short-view body.msg-conv { padding-bottom: 0; }
/* With the body pinned, the pane can be sized by FLEX instead of by
   subtraction (David 2026-09-03, "some threads open further up the page than
   ideal … the space at the base is a little deeper than ideal"). The old
   `calc(100dvh − header − inset)` had to guess at every padding between the
   viewport edge and the pane — the body's safe-area padding top and bottom,
   .app-main's 1rem each way — and was out by their sum, so the composer sat
   above dead space and the thread's foot went under it. Flex fills exactly
   what is left; there is nothing to guess. */
html:not(.desktop) body.msg-conv .app-main {
  flex: 1 1 0; min-height: 0; display: flex; flex-direction: column;
  padding-top: .3rem; padding-bottom: 0;
}
html:not(.desktop) body.msg-conv .msg-main { flex: 1 1 0; min-height: 0; height: auto; }
/* The bottom safe-area inset was applied TWICE on this page — once by the
   body (app.css top), again by the composer's own padding — which is the
   "deeper than ideal" band under the message box. The body's is the one
   that stays. */
html:not(.desktop) body.msg-conv .msg-composer { padding-bottom: .55rem; }
/* Reaching the top or bottom of the thread must not hand the scroll on to
   the page (which is what let it creep in the first place). */
.msg-scroll { overscroll-behavior: contain; }
/* Layout check overlay (super admins): the device's own numbers, on screen. */
.msg-diag {
  position: fixed; left: 6px; right: 6px; top: 70px; z-index: 9999; margin: 0;
  background: rgba(10, 14, 18, .93); color: #d7f5ff; font: 11px/1.45 ui-monospace, Menlo, monospace;
  padding: .6rem .7rem; border-radius: 10px; white-space: pre-wrap; max-height: 80vh; overflow: auto;
}
/* The "loading earlier messages" line at the top of what has been loaded. */
.msg-older { text-align: center; font-size: .76rem; color: var(--muted); padding: .35rem 0 .5rem; }
.msg-older[hidden] { display: none !important; }

/* Conversation layout: bar + scrolling history + sticky composer */
.msg-main {
  display: flex;
  flex-direction: column;
  height: calc(100vh - var(--header-h) - env(safe-area-inset-top, 0px));
  height: calc(100dvh - var(--header-h) - env(safe-area-inset-top, 0px));
  /* body is a column FLEXBOX and .app-main is flex:1 1 0% — with the default
     min-height:auto the content's size beat the height above, so a long
     thread grew the page and bar/composer scrolled away (David 2026-08-26).
     flex-basis auto + no grow makes the height rule the law again, and
     min-height:0 stops content re-inflating it. */
  flex: 0 0 auto;
  min-height: 0;
  padding-top: .4rem;
  padding-bottom: 0;
  min-width: 0;
}
/* Installed iOS app: env() can report ZERO inset while 59px is actually
   consumed (same WebKit bug the header works around) — mirror its guarantee
   here or the composer sits below the fold. */
@media (display-mode: standalone) {
  .msg-main {
    height: calc(100dvh - var(--header-h) - max(env(safe-area-inset-top, 0px), 59px));
  }
}
.msg-bar {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .2rem 0 .55rem;
  border-bottom: 1px solid var(--border);
}
.msg-bar .msg-ava { flex-basis: 38px; width: 38px; height: 38px; font-size: .85rem; }
.msg-bar__back {
  font-size: 1.9rem;
  line-height: 1;
  text-decoration: none;
  color: var(--brand);
  padding: 0 .2rem;
}
.msg-bar__who { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.msg-bar__who strong { font-size: 1rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.msg-bar__who small { font-size: .72rem; color: var(--text-muted); }
.msg-bar__menu { position: relative; }

.msg-members { padding: .8rem .9rem; margin: .5rem 0; }
/* Members / Settings sheets (2026-09-15): a Close at the top right; a tap
   outside or Escape closes them too. The sheets are positioned so the
   button can sit in the corner. */
.msg-members, .msg-settings { position: relative; }
.msg-sheet__close {
  position: absolute; top: .45rem; right: .55rem;
  font: inherit; font-size: .8rem; font-weight: 600; color: var(--brand);
  background: transparent; border: 1px solid var(--border); border-radius: 999px;
  padding: .15rem .6rem; cursor: pointer;
}
.msg-sheet__close:hover { background: var(--brand-light); }
.msg-members__row {
  display: flex;
  align-items: center;
  gap: .55rem;
  font-size: .88rem;
  padding: .25rem 0;
}
.msg-members__row small { color: var(--text-muted); }
.msg-members__add, .msg-members__rename {
  display: flex;
  gap: .5rem;
  margin-top: .6rem;
}
.msg-members__add select, .msg-members__rename input {
  flex: 1;
  min-width: 0;
  padding: .45rem .55rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 16px;
}

.msg-scroll {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: .7rem .15rem;
  display: flex;
  flex-direction: column;
  gap: .15rem;
}
.msg-day {
  text-align: center;
  margin: .7rem 0 .4rem;
}
.msg-day span {
  background: #dfe7ef;
  color: var(--text-muted);
  font-size: .7rem;
  font-weight: 600;
  border-radius: 999px;
  padding: .2rem .7rem;
}
.msg-sys { text-align: center; margin: .3rem 0; }
.msg-sys span { font-size: .72rem; color: var(--text-muted); font-style: italic; }

.msg-row { display: flex; }
.msg-row--me   { justify-content: flex-end; }
.msg-row--them { justify-content: flex-start; }
.msg-row--first { margin-top: .45rem; }
.msg-bubble {
  max-width: 80%;
  border-radius: 16px;
  padding: .45rem .7rem .3rem;
  box-shadow: 0 1px 1px rgba(0, 0, 0, .07);
  display: flex;
  flex-direction: column;
  /* iOS delivers a tap on a plain <div> to a DELEGATED listener only when the
     element looks clickable — without this, tap-to-open-the-picker is dead on
     an iPhone while working fine on a desktop. */
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.msg-row--me .msg-bubble {
  background: var(--brand);
  color: #fff;
  border-bottom-right-radius: 5px;
}
/* Received bubbles were #fff — invisible on the desktop pane (#fff) and only
   faint on the mobile page (#f4f6f9). A soft cool grey with a hairline edge
   reads on both (David 2026-09-10: "a bit of contrast between the background
   colour and the senders message block"). */
.msg-row--them .msg-bubble {
  background: #e9eef3;
  border: 1px solid #d9e0e7;
  border-bottom-left-radius: 5px;
}
.msg-bubble__sender { font-size: .72rem; font-weight: 700; margin-bottom: .05rem; }
.msg-bubble__text { font-size: .92rem; line-height: 1.35; word-wrap: break-word; white-space: pre-wrap; }
/* Links in a message: visible in both bubble colours, and long URLs wrap
   rather than widen the bubble. */
/* A file being dragged over the conversation: the composer says "drop it here". */
.msg-composer.msg-drop--over { outline: 2px dashed var(--brand); outline-offset: 3px; border-radius: 14px; }
.msg-link { color: inherit; text-decoration: underline; text-underline-offset: 2px; overflow-wrap: anywhere; }
.msg-row--them .msg-link { color: var(--brand); }
/* Link preview card (2026-09-03): picture on top, title / description / host
   under it, the whole card a link. Sits under the words, above the time. */
.msg-pv {
    display: block; margin: .35rem 0 .2rem; max-width: min(100%, 320px);
    border-radius: 10px; overflow: hidden; text-decoration: none; color: inherit;
    background: rgba(0, 0, 0, .06);
}
.msg-row--me .msg-pv { background: rgba(255, 255, 255, .16); }
.msg-pv__img { display: block; }
.msg-pv__img[hidden] { display: none !important; }
.msg-pv__img img { display: block; width: 100%; max-height: 170px; object-fit: cover; }
.msg-pv__text { display: flex; flex-direction: column; gap: .1rem; padding: .45rem .6rem .5rem; }
.msg-pv__title { font-weight: 700; font-size: .86rem; line-height: 1.25; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.msg-pv__desc { font-size: .78rem; line-height: 1.3; opacity: .85; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.msg-pv__host { font-size: .7rem; opacity: .65; margin-top: .1rem; }
.msg-bubble__time {
  font-size: .62rem;
  opacity: .65;
  align-self: flex-end;
  margin-top: .1rem;
}
.msg-empty {
  text-align: center;
  color: var(--text-muted);
  margin-top: 3rem;
  font-size: .95rem;
}

.msg-composer {
  display: flex;
  align-items: flex-end;
  gap: .5rem;
  padding: .55rem 0 calc(.55rem + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--border);
  background: var(--bg);
}
.msg-composer textarea {
  flex: 1;
  min-width: 0;
  resize: none;
  border: 1px solid var(--border);
  border-radius: 18px;
  padding: .55rem .8rem;
  font: inherit;
  font-size: 16px;
  max-height: 120px;
  background: #fff;
}
.msg-composer__send {
  flex: 0 0 42px;
  height: 42px;
  border: 0;
  border-radius: 50%;
  background: var(--brand);
  color: #fff;
  font-size: 1.15rem;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.msg-composer__send:active { filter: brightness(1.15); }

/* New message page */
.msg-newtabs { display: flex; gap: .5rem; margin-bottom: .7rem; }
.msg-newtab {
  flex: 1;
  padding: .5rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fff;
  font: inherit;
  font-size: .9rem;
  color: var(--text);
  cursor: pointer;
}
.msg-newtab--on { background: var(--brand); color: #fff; border-color: var(--brand); }
.msg-new-search {
  width: 100%;
  padding: .55rem .7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 16px;
  margin-bottom: .7rem;
}
.msg-person { margin: 0 0 .4rem; }
.msg-person__btn {
  display: flex;
  align-items: center;
  gap: .6rem;
  width: 100%;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: .5rem .7rem;
  font: inherit;
  color: var(--text);   /* explicit — iOS dark mode made buttontext white */
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.msg-person__btn:active { background: var(--brand-light); }
.msg-person__name { flex: 1; min-width: 0; font-size: .92rem; font-weight: 600; }
.msg-person__go { color: var(--text-muted); font-size: 1.3rem; }
.msg-group-name {
  width: 100%;
  padding: .55rem .7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 16px;
  margin-bottom: .7rem;
}
.msg-group-list { padding-bottom: 5rem; }
.msg-group-bar { position: sticky; bottom: 0; padding: .6rem 0; background: var(--bg); }

/* Personal Outlook calendar on the day view (xc-*, includes/ext_cal.php) */
.xc-card {
  padding: .875rem 1rem;
  margin-top: .75rem;
}
.xc-title {
  font-size: .95rem;
  margin: 0 0 .55rem;
  display: flex;
  align-items: baseline;
  gap: .5rem;
}
.xc-title__private {
  font-size: .68rem;
  font-weight: 400;
  color: var(--text-muted);
}
.xc-appt {
  display: flex;
  gap: .6rem;
  padding: .45rem .6rem;
  background: var(--bg);
  border-radius: var(--radius-sm);
  margin-bottom: .35rem;
  font-size: .85rem;
}
.xc-appt:last-child { margin-bottom: 0; }
.xc-appt__times {
  flex: 0 0 auto;
  font-weight: 600;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.xc-appt__body {
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.xc-appt__loc {
  color: var(--text-muted);
  font-size: .75rem;
}

/* Prominent worked-hours button at the foot of a set block (the app's
   most-used write — promoted out of the ⋯ menu, David 2026-08-21) */
.ts-adjust-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .45rem;
  width: 100%;
  margin-top: .6rem;
  padding: .6rem;
  background: var(--brand-light);
  color: var(--brand);
  border: 1.5px solid var(--brand);
  border-radius: 10px;
  font: inherit;
  font-size: .9rem;
  font-weight: 700;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.ts-adjust-btn:active { background: var(--brand); color: #fff; }
.ts-adjust-btn[data-preview] { opacity: .55; }

/* Standalone sessions panel — no delivery block to nest under */
.ts-block--sessions {
  display: block;
}
.ts-sessions-standalone-title {
  font-size: .8rem;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.ts-block--sessions .ts-sessions {
  border-top: 0;
  padding-top: 0;
  margin-top: .5rem;
}

.ts-sessions {
  margin-top: .625rem;
  display: flex;
  flex-direction: column;
  gap: .4rem;
  border-top: 1px solid var(--border);
  padding-top: .625rem;
}

.ts-session {
  background: var(--bg);
  border-radius: var(--radius-sm);
  padding: .6rem .75rem;
}

.ts-session--inactive {
  opacity: .4;
}

.ts-session__times {
  font-size: 1rem;
  font-weight: 700;
  color: var(--text);
  margin-bottom: .2rem;
}

.ts-session__name {
  font-size: .92rem;
  font-weight: 600;
  color: var(--text);
  margin-bottom: .25rem;
}

.ts-session__meta {
  font-size: .8rem;
  color: var(--text-muted);
  margin-bottom: .3rem;
  line-height: 1.6;
}
.ts-session__sep {
  margin: 0 .4rem;
  opacity: .4;
}

.ts-session__badges {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem;
  margin-top: .25rem;
}

.ts-session__badge {
  display: inline-block;
  font-size: .68rem;
  font-weight: 700;
  padding: .1rem .4rem;
  border-radius: 3px;
  letter-spacing: .04em;
  text-transform: uppercase;
  background: var(--brand);
  color: #fff;
}
.ts-session__badge--private  { background: var(--accent); }
.ts-session__badge--lead     { background: var(--success); }
.ts-session__badge--inactive { background: var(--text-muted); }

.ts-session__notes {
  margin-top: .35rem;
  font-size: .8rem;
  color: var(--text-muted);
  font-style: italic;
  border-top: 1px solid var(--border);
  padding-top: .35rem;
  /* ver5 stores notes as typed and shows them with nl2br; 769 of 1,409 live
     notes since June have line breaks, and without this they ran together
     on one line here. None contain <br>, so there is no double spacing. */
  white-space: pre-line;
}
.st-empty {
  text-align: center;
  color: var(--text-muted);
  font-size: .85rem;
  line-height: 1.5;
  padding: 1.2rem 1.4rem;
  margin-top: .8rem;
}

/* Instructor notes — prompt + completion (see notes/INSTRUCTOR_NOTES.md). */
.in-intro { font-size: .85rem; color: var(--text-muted); margin: 0 0 .9rem; }
.in-h2 {
  font-size: .78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .03em;
  color: var(--text-muted);
  margin: 1.1rem 0 .5rem;
}
.in-card { padding: .8rem .85rem; margin-top: .6rem; }
.in-card--due { box-shadow: inset 0 0 0 2px #d98a3d; }
.in-card__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .5rem;
}
.in-card__org { font-weight: 700; font-size: .95rem; }
.in-card__when { font-size: .76rem; color: var(--text-muted); white-space: nowrap; }
.in-card__meta { font-size: .78rem; color: var(--text-muted); margin-top: .15rem; }
.in-card__due { font-size: .82rem; font-weight: 600; color: #a4611f; margin-top: .5rem; }
.in-card__done { font-size: .82rem; font-weight: 600; color: #2f7d32; margin-top: .5rem; }
.in-card__write, .in-form__save {
  display: block;
  width: 100%;
  font-size: 16px;
  font-weight: 700;
  padding: .65rem;
  margin-top: .55rem;
  border: none;
  border-radius: 8px;
  background: var(--brand);
  color: #fff;
  -webkit-tap-highlight-color: transparent;
}
.in-card__write:active, .in-form__save:active { filter: brightness(.9); }
.in-card__more {
  display: inline-block;
  font-size: .82rem;
  font-weight: 600;
  padding: .4rem .8rem;
  margin-top: .55rem;
  border: 1px solid #d5dbe1;
  border-radius: 8px;
  background: #fff;
  color: var(--text);
  -webkit-tap-highlight-color: transparent;
}
.in-form__text {
  display: block;
  width: 100%;
  box-sizing: border-box;
  font-size: 16px;              /* stops the iOS zoom-jump */
  font-family: inherit;
  padding: .6rem;
  margin-top: .6rem;
  border: 1px solid #d5dbe1;
  border-radius: 8px;
  resize: vertical;
  min-height: 7rem;
}
.in-prompt {
  display: flex;
  align-items: center;
  gap: .7rem;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .07), inset 0 0 0 2px #d98a3d;
  padding: .75rem .85rem;
  margin: .7rem 0 0;
  text-decoration: none;
  color: var(--text);
}
.in-prompt__icon { font-size: 1.5rem; }
.in-prompt__body { flex: 1; display: flex; flex-direction: column; }
.in-prompt__body strong { font-size: .95rem; }
.in-prompt__body small { font-size: .78rem; color: var(--text-muted); }

/* Button editor: group chips + searchable staff selector. */
.grp-chips { display: flex; flex-wrap: wrap; gap: .35rem; margin-bottom: .55rem; }
.grp-chip {
  font-size: .78rem;
  font-weight: 600;
  padding: .32rem .6rem;
  border: 1.5px solid #d5dbe1;
  border-radius: 999px;
  background: #fff;
  color: var(--text);
  -webkit-tap-highlight-color: transparent;
}
.grp-chip em { font-style: normal; font-weight: 800; color: var(--text-muted); }
.grp-chip--on { background: var(--brand); border-color: var(--brand); color: #fff; }
.grp-chip--on em { color: #cfe6f0; }
.sel-bar { display: flex; gap: .6rem; align-items: center; margin-bottom: .45rem; }
.sel-search {
  flex: 1;
  min-width: 0;
  font-size: 16px;
  padding: .5rem .6rem;
  border: 1px solid #d5dbe1;
  border-radius: 8px;
  -webkit-appearance: none;
}
.sel-count { font-size: .78rem; color: var(--text-muted); white-space: nowrap; }
.sel-count em { font-style: normal; font-weight: 800; color: var(--text); }
.staff-selector__role { color: var(--text-muted); font-size: .72rem; margin-left: .3rem; }

/* Sickness report form. */
.sk-audience {
  font-size: .78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .02em;
  color: var(--text-muted);
  border-top: 1px solid #e6ebef;
  padding-top: .8rem;
  margin: 1rem 0 .6rem;
}
.sk-audience:first-of-type { border-top: none; padding-top: 0; margin-top: 0; }
.sk-audience--hr { color: #7a4fa0; }
.sk-opt {
  display: block;
  font-size: .92rem;
  padding: .35rem 0;
}
.sk-opt small { color: var(--text-muted); }

/* Activity icons (assets/images/activities — the diary app's 96px pack). */
.act-ico {
  width: 20px;
  height: 20px;
  object-fit: contain;
  vertical-align: -5px;
  margin-right: .35rem;
}
.act-ico--pill { width: 22px; height: 22px; vertical-align: -6px; }
.act-ico--chip { width: 15px; height: 15px; vertical-align: -3px; margin-right: .25rem; }
.home-acts { display: flex; gap: .45rem; margin-top: .4rem; }
.home-acts img { width: 26px; height: 26px; object-fit: contain; }

/* Housekeeping changeover panel (day view). */
.hk-card { padding: .85rem .9rem; margin-top: .8rem; }
.hk-title { font-size: 1rem; font-weight: 800; margin: 0 0 .6rem; }
.hk-venue { border-top: 1px solid #e6ebef; padding: .6rem 0 .2rem; }
.hk-venue:first-of-type { border-top: none; padding-top: 0; }
.hk-venue__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  margin-bottom: .35rem;
}
.hk-venue__name { font-weight: 700; font-size: .95rem; }
.hk-chip {
  font-size: .68rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .02em;
  border-radius: 999px;
  padding: .18rem .55rem;
}
.hk-chip--change { background: #fbe8c3; color: #8a5a00; }
.hk-chip--out    { background: #f9dede; color: #9c2f2f; }
.hk-chip--in     { background: #e0f2e0; color: #226622; }
.hk-row {
  display: flex;
  gap: .55rem;
  align-items: baseline;
  padding: .22rem .45rem;
  border-radius: 6px;
  margin-bottom: .2rem;
  font-size: .88rem;
}
.hk-row--out    { background: #fdf1f1; }
.hk-row--in     { background: #eff8ef; }
.hk-row--change { background: #fdf6e8; }
.hk-row__dir {
  flex: 0 0 auto;
  min-width: 4.2rem;
  font-weight: 800;
  font-size: .74rem;
  padding-top: .1rem;
}
.hk-row--out .hk-row__dir { color: #9c2f2f; }
.hk-row--in .hk-row__dir  { color: #226622; }
.hk-row__who { flex: 1; min-width: 0; }
.hk-row__who em { font-style: normal; color: var(--text-muted); }
.hk-prov, .hk-overlap {
  font-style: normal;
  font-size: .7rem;
  font-weight: 700;
  color: #a4611f;
}
.hk-note {
  font-size: .76rem;
  color: var(--text-muted);
  font-style: italic;
  margin: -.1rem 0 .3rem 4.75rem;
}
.hk-quiet { font-size: .78rem; color: var(--text-muted); padding: .2rem 0 .4rem; }

/* View As app-access editor on the dashboard. */
.va-access { padding: .85rem .9rem; margin-top: .8rem; }
.va-row {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .45rem 0;
  border-top: 1px solid #eef1f4;
}
.va-row:first-of-type { border-top: none; }
.va-row--off { opacity: .45; }
.va-row__dot {
  flex: 0 0 auto;
  width: 1rem;
  height: 1rem;
  border-radius: 4px;
}
.va-row__label { flex: 1; min-width: 0; font-weight: 600; font-size: .92rem; }
.va-row__label small {
  font-weight: 600;
  font-size: .68rem;
  color: var(--text-muted);
  margin-left: .3rem;
}
.va-row input[type="checkbox"] { width: 1.25rem; height: 1.25rem; }
.va-row__form { display: flex; }

/* Personalise home screen. */
.pz-row { padding: .55rem .7rem; margin-top: .5rem; }
.pz-row__main { display: flex; align-items: center; gap: .6rem; }
.pz-row__tile {
  flex: 0 0 auto;
  width: 2.2rem;
  height: 2.2rem;
  border-radius: 8px;
  color: #fff;
  font-weight: 800;
  font-size: .8rem;
  display: flex;
  align-items: center;
  justify-content: center;
}
.pz-row__label { flex: 1; min-width: 0; font-weight: 600; }
.pz-row__label small { color: var(--text-muted); font-size: .7rem; margin-left: .3rem; }
.pz-row__ctl { display: flex; gap: .3rem; align-items: center; }
.pz-row__ctl form { display: flex; }
.pz-arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.2rem;
  height: 2.2rem;
  border: 1px solid #d5dbe1;
  border-radius: 8px;
  background: #fff;
  color: var(--text);
  font-size: .85rem;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.pz-arrow:active { background: #f2f6f9; }
.pz-row__opts { border-top: 1px solid #eef1f4; margin-top: .55rem; padding-top: .6rem; }
.pz-swatch-form { display: inline-flex; }
.pz-opts-row { display: flex; gap: .5rem; margin-top: .6rem; flex-wrap: wrap; }

/* Home-screen in-place editor: iPhone-style wobble + tile menu + drag. */
.menu-grid .menu-btn {
  -webkit-touch-callout: none;   /* no iOS link preview on long-press */
  -webkit-user-select: none;
  user-select: none;
}
.menu-grid--editing .menu-btn {
  animation: home-wobble .28s ease-in-out infinite alternate;
  touch-action: none;            /* the finger drags tiles, not the page */
  cursor: grab;
}
.menu-grid--editing .menu-btn:nth-child(2n)  { animation-delay: -.12s; }
.menu-grid--editing .menu-btn:nth-child(3n)  { animation-delay: -.2s; }
@keyframes home-wobble {
  from { transform: rotate(-1.2deg); }
  to   { transform: rotate(1.2deg); }
}
@media (prefers-reduced-motion: reduce) {
  .menu-grid--editing .menu-btn { animation: none; outline: 2px dashed rgba(255,255,255,.7); outline-offset: -6px; }
}
.home-edit-source { opacity: .35; }
.home-edit-ghost {
  position: fixed;
  z-index: 900;
  margin: 0;
  transform: scale(1.06) rotate(-1deg);
  box-shadow: 0 10px 28px rgba(0, 0, 0, .35);
  opacity: .92;
  pointer-events: none;
}
.home-edit-done {
  position: fixed;
  top: calc(env(safe-area-inset-top, 0px) + 10px);
  right: 12px;
  z-index: 950;
  font-size: 15px;
  font-weight: 800;
  padding: .45rem 1rem;
  border: none;
  border-radius: 999px;
  background: #fff;
  color: var(--brand);
  box-shadow: 0 3px 12px rgba(0, 0, 0, .25);
  -webkit-tap-highlight-color: transparent;
}
.home-edit-menu {
  position: absolute;
  z-index: 920;
  width: min(320px, calc(100vw - 16px));
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, .28);
  padding: .7rem;
}
.home-edit-menu__swatches {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: .3rem;
  margin-bottom: .6rem;
}
.home-edit-swatch {
  aspect-ratio: 1;
  border: none;
  border-radius: 6px;
  -webkit-tap-highlight-color: transparent;
}
.home-edit-swatch:active { transform: scale(.9); }
.home-edit-menu__row { display: flex; gap: .5rem; }
.home-edit-menu__btn {
  flex: 1;
  font-size: .85rem;
  font-weight: 700;
  padding: .55rem;
  border: 1px solid #d5dbe1;
  border-radius: 8px;
  background: #fff;
  color: var(--text);
  -webkit-tap-highlight-color: transparent;
}
.home-edit-menu__hint {
  font-size: .72rem;
  color: var(--text-muted);
  text-align: center;
  margin: .55rem 0 0;
}

/* ── Messenger: availability banner + per-thread notification settings ── */
.msg-avail {
  display: flex;
  align-items: center;
  gap: .45rem;
  background: #fff6e0;
  border: 1px solid #f0d9a0;
  color: #6b4f00;
  border-radius: 10px;
  padding: .45rem .7rem;
  font-size: .82rem;
  margin: .5rem 0 0;
}
.msg-avail__icon { font-size: 1rem; }
.msg-settings { padding: .85rem .9rem; margin: .5rem 0; }
.msg-settings__title {
  font-size: .8rem;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .04em;
  margin-bottom: .5rem;
}
.msg-settings__opt {
  display: flex;
  align-items: flex-start;
  gap: .6rem;
  padding: .45rem 0;
  border-top: 1px solid var(--border);
  cursor: pointer;
}
.msg-settings__opt:first-of-type { border-top: 0; }
/* A second block in the sheet (per-person settings, 2026-09-02) */
.msg-settings__sect { margin-top: .9rem; padding-top: .7rem; border-top: 2px solid var(--border); }
.msg-settings__sect .msg-settings__opt { border-top: 0; }
.msg-settings__opt input { margin-top: .25rem; }
.msg-settings__opt span { display: flex; flex-direction: column; }
.msg-settings__opt strong { font-size: .9rem; }
.msg-settings__opt small { font-size: .74rem; color: var(--text-muted); }
.msg-settings__window {
  display: flex;
  align-items: center;
  gap: .5rem;
  font-size: .85rem;
  padding: .5rem 0 .2rem 1.6rem;
}
.msg-settings__window input[type="time"] {
  padding: .35rem .5rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 16px;
}
.msg-settings .btn { margin-top: .7rem; }

/* ── Install-the-app card (dashboard, install.js) ─────────────────── */
.pwa-card {
  background: #fff;
  border: 1.5px solid var(--brand);
  border-radius: 16px;
  box-shadow: var(--shadow);
  padding: .8rem .9rem;
  /* top margin matters: this card follows "Waiting for you" / prompts and
     had none, so they touched (David 2026-08-28) — same .7rem rhythm as
     .att-card and .in-prompt. Desktop is unaffected (.dk-side uses gap). */
  margin: .7rem 0 .9rem;
}
.pwa-card__main { display: flex; align-items: center; gap: .7rem; }
.pwa-card__icon { font-size: 1.6rem; }
.pwa-card__body { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.pwa-card__body strong { font-size: .95rem; }
.pwa-card__body small { font-size: .78rem; color: var(--text-muted); }
.pwa-card__ios { margin-top: .7rem; border-top: 1px solid var(--border); padding-top: .6rem; }
.pwa-card__ios ol { margin: 0; padding-left: 1.2rem; font-size: .88rem; line-height: 1.5; }
.pwa-card__ios li { margin-bottom: .35rem; }
.pwa-share { width: 1.1em; height: 1.1em; vertical-align: -.15em; fill: var(--brand); }
.pwa-card__note { font-size: .75rem; color: var(--text-muted); margin: .5rem 0 0; }

/* ══════════════════════════════════════════════════════════════════════
   DESKTOP SHELL (DESKTOP_VISION.md) — everything keyed on html.desktop,
   set by header.php's inline script from (min-width:1000px) + fine pointer
   and NOT standalone. Phones and the installed app never see any of this.
   ══════════════════════════════════════════════════════════════════════ */

/* Hidden by default (phones) */
.dk-rail, .dk-greet, .dk-search, .dk-bell, .dk-frames, .dk-pulse,
.msg-main .dk-msg-side, .dk-msg-pane--empty { display: none; }

/* ── Frame: rail + top bar ─────────────────────────────────────────── */
html.desktop body { padding-left: 72px; }
html.desktop .header-inner { max-width: none; padding: 0 24px; gap: 18px; }
html.desktop .header-user, html.desktop .hdr-msg, html.desktop .logo-img { display: none; }
html.desktop .header-logo .logo-text { font-size: 1.05rem; }
html.desktop .header-actions { flex: 1; display: flex; align-items: center; gap: 14px; min-width: 0; }

html.desktop .dk-rail {
  display: flex; flex-direction: column; align-items: center;
  position: fixed; left: 0; top: 0; bottom: 0; width: 72px; z-index: 120;
  background: var(--brand-dark); padding: 12px 0; gap: 6px;
}
.dk-rail__logo { display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; margin-bottom: 8px; }
.dk-rail__item {
  position: relative; width: 58px; height: 54px; border-radius: 12px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  color: rgba(255,255,255,.78); text-decoration: none; font-size: 10px; font-weight: 600; letter-spacing: .02em;
}
.dk-rail__item:hover { background: rgba(255,255,255,.10); color: #fff; }
.dk-rail__item--on { background: rgba(255,255,255,.18); color: #fff; }
.dk-rail__item--preview { opacity: .45; }
.dk-rail__badge {
  position: absolute; top: 4px; right: 8px; background: #d33; color: #fff;
  font-style: normal; font-size: .62rem; font-weight: 700; border-radius: 999px;
  min-width: 1.05rem; text-align: center; padding: .08rem .2rem; border: 2px solid var(--brand-dark);
}
.dk-rail__spacer { flex: 1; }

/* Open shell tabs live in the rail below a divider, in the rail's own
   icon + label format (David 2026-08-26 — replaced the top tab strip,
   which bounced around with the window width). Rendered by desktop.js. */
.dk-rail__sep { width: 40px; border-top: 1px solid rgba(255,255,255,.28); margin: 6px 0 2px; flex: 0 0 auto; }
.dk-rail__sep[hidden] { display: none !important; }   /* explicit display beats [hidden] — the dk-frames lesson */
.dk-rail__tabs {
  display: flex; flex-direction: column; align-items: center; gap: 6px; width: 100%;
  min-height: 0; overflow-y: auto; overflow-x: hidden; scrollbar-width: none;
}
.dk-rail__tabs::-webkit-scrollbar { display: none; }
.dk-rail__item--tab { flex: 0 0 auto; }
.dk-rail__tabicon { font-size: 19px; line-height: 1.2; }
.dk-rail__tabicon--dot { width: 14px; height: 14px; border-radius: 4px; }
.dk-rail__tablabel { max-width: 56px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dk-rail__x {
  position: absolute; top: 2px; right: 2px; width: 16px; height: 16px; padding: 0;
  border: 0; border-radius: 50%; background: rgba(0,0,0,.4); color: #fff;
  font-size: 12px; line-height: 1; cursor: pointer;
  display: none; align-items: center; justify-content: center;
}
.dk-rail__item--tab:hover .dk-rail__x, .dk-rail__x:focus-visible { display: flex; }
.dk-rail__avatar {
  width: 36px; height: 36px; border-radius: 50%; background: #2b6ca3; color: #fff; font-weight: 700; font-size: 13px;
  display: flex; align-items: center; justify-content: center; border: 2px solid rgba(255,255,255,.6);
  text-decoration: none; margin-bottom: 6px;
}

html.desktop .dk-greet { display: flex; flex-direction: column; line-height: 1.15; color: #fff; margin-right: auto; }
.dk-greet strong { font-size: 1rem; font-weight: 800; }
.dk-greet span { font-size: .72rem; opacity: .8; }

html.desktop .dk-search {
  display: flex; align-items: center; gap: 8px; position: relative;
  width: 360px; height: 38px; border-radius: 10px; background: rgba(255,255,255,.14); padding: 0 12px; color: #fff;
}
html.desktop .dk-search input {
  flex: 1; min-width: 0; background: transparent; border: 0; outline: none; color: #fff; font-size: 14px; padding: 0;
}
html.desktop .dk-search input::placeholder { color: rgba(255,255,255,.75); }
.dk-search__results {
  position: absolute; top: 44px; left: 0; width: 440px; max-height: 70vh; overflow: auto;
  background: #fff; color: var(--text); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: var(--shadow-md); padding: 6px; z-index: 250;
}
.dk-sr__h { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--text-muted); padding: 8px 10px 4px; }
.dk-sr__row { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 8px; text-decoration: none; color: var(--text); font-size: 14px; }
.dk-sr__row:hover { background: var(--brand-light); }
.dk-sr__ava { flex: 0 0 30px; width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 11px; font-weight: 700; overflow: hidden; }
.dk-sr__ava img { width: 100%; height: 100%; object-fit: cover; display: block; }
.dk-sr__name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dk-sr__acts { display: flex; gap: 6px; }
.dk-sr__acts a, .dk-sr__acts button {
  font: inherit; font-size: 12px; padding: 4px 10px; border-radius: 999px; border: 1px solid var(--border);
  background: #fff; color: var(--brand); cursor: pointer; text-decoration: none;
}
.dk-sr__acts form { margin: 0; }
.dk-sr__dot { width: 10px; height: 10px; border-radius: 3px; flex: 0 0 auto; }
.dk-sr__empty { padding: 12px; color: var(--text-muted); font-size: 13px; }

html.desktop .dk-bell { display: block; position: relative; }
.dk-bell__btn {
  width: 38px; height: 38px; border-radius: 10px; border: 1px solid rgba(255,255,255,.3); background: transparent;
  color: #fff; display: flex; align-items: center; justify-content: center; cursor: pointer; position: relative;
}
.dk-bell__count {
  position: absolute; top: -6px; right: -6px; background: #d33; color: #fff; font-style: normal; font-size: .62rem;
  font-weight: 700; border-radius: 999px; min-width: 1.05rem; text-align: center; padding: .08rem .2rem; border: 2px solid var(--brand);
}
.dk-bell__list {
  position: absolute; right: 0; top: 46px; width: 320px; background: #fff; color: var(--text);
  border: 1px solid var(--border); border-radius: 12px; box-shadow: var(--shadow-md); padding: 8px; z-index: 250;
}
.dk-bell__title { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--text-muted); padding: 6px 10px; }
.dk-bell__row { display: flex; align-items: center; gap: 8px; padding: 9px 10px; border-radius: 8px; text-decoration: none; color: var(--text); font-size: 14px; }
.dk-bell__row:hover { background: var(--brand-light); }
.dk-bell__empty { padding: 10px; font-size: 13px; color: var(--text-muted); }

/* ── Page widths ───────────────────────────────────────────────────── */
html.desktop .app-main { max-width: 860px; padding-left: 32px; padding-right: 32px; }
html.desktop .app-main:has(.dk-home), html.desktop .app-main.dk-msg-page { max-width: 1400px; }

/* ── Home: two columns, no scene band (greeting lives in the top bar) ── */
html.desktop .home-scene, html.desktop .home-hello__greet, html.desktop .home-hello__sub { display: none; }
html.desktop .pwa-card { display: none !important; }
html.desktop .dk-home { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 28px; align-items: start; }
html.desktop .dk-side { order: 2; display: flex; flex-direction: column; gap: 14px; }
html.desktop .dk-side > * { margin: 0 !important; }
html.desktop .dk-main { order: 1; min-width: 0; }
html.desktop .home-hello { margin: 0; }
html.desktop .menu-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; padding-top: 0; }
html.desktop .menu-btn--full { grid-column: span 2; }
html.desktop .menu-btn { min-height: 140px; }

/* ── Frames (Home; the tab list itself lives in the rail) ──────────── */
html.desktop .dk-frames:not([hidden]) { display: block; }
/* Framed app tab active: use the full window (minus rail), not the 1400px
   home column — the diary canvas needs the room (David 2026-08-23). */
html.desktop .app-main.dk-wide { max-width: none; padding-left: 20px; padding-right: 20px; }

/* An explicit display on these beats the UA's [hidden] rule — every frame
   showed at once and tabs appeared not to switch (David 2026-08-23). */
.dk-frame[hidden], html.desktop .dk-home[hidden], html.desktop .dk-frames[hidden] { display: none !important; }
/* was -110px while the tab strip sat above the frame; the rail tabs freed
   that room (David 2026-08-26) */
.dk-frame { display: flex; flex-direction: column; height: calc(100vh - var(--header-h) - 48px); background: #fff; border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }
.dk-frame__bar { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 6px 12px; font-size: 12px; color: var(--text-muted); border-bottom: 1px solid var(--border); background: var(--bg); }
.dk-frame__open { color: var(--brand); font-weight: 600; text-decoration: none; white-space: nowrap; }
.dk-frame__iframe { flex: 1; width: 100%; border: 0; background: #fff; }

/* ── "Today at Mendip" pulse ───────────────────────────────────────── */
html.desktop .dk-pulse { display: block; margin-top: 22px; }
.dk-pulse__title { font-size: 15px; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: .04em; margin-bottom: 12px; }
.dk-pulse__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.dk-pulse__card { background: #fff; border-radius: 14px; box-shadow: var(--shadow); padding: 16px; display: flex; flex-direction: column; gap: 6px; }
.dk-pulse__label { font-size: 12px; color: var(--text-muted); font-weight: 700; text-transform: uppercase; letter-spacing: .04em; }
.dk-pulse__big { font-size: 26px; font-weight: 800; }
.dk-pulse__big span { font-size: 13px; color: var(--text-muted); font-weight: 500; }
.dk-pulse__sub { font-size: 12px; color: var(--text-muted); }

/* ── Messages: two-pane ────────────────────────────────────────────── */
/* The 2026-08-23 two-pane wrapped bar/scroll/composer in .dk-msg-pane —
   a plain block on phones, which broke .msg-main's flex chain: the pane
   grew with content and the PAGE scrolled (David 2026-08-26). Make the
   wrapper a stretching flex column everywhere; desktop's rule below only
   adds the card chrome. (:not keeps the phone-hidden empty pane hidden.) */
.dk-msg-pane:not(.dk-msg-pane--empty) {
  display: flex; flex-direction: column; flex: 1; min-height: 0; min-width: 0;
}
html.desktop .dk-msg-page {
  display: grid; grid-template-columns: 340px minmax(0, 1fr); gap: 20px; align-items: stretch;
  /* minmax(0,1fr) row is LOAD-BEARING: the default auto row sizes to its
     CONTENT, so a long thread grew the row past the container and the whole
     page scrolled — bar and composer drifted off screen (David 2026-08-26).
     Pinning the row to the container height lets .msg-scroll be the one
     scroller, with the person's bar held above and the composer below. */
  grid-template-rows: minmax(0, 1fr);
  height: calc(100vh - var(--header-h) - 8px); padding-top: 16px; padding-bottom: 16px;
  /* same flexbox trap as .msg-main above: without these, body's column flex
     let content override the height and the whole page scrolled */
  flex: 0 0 auto; min-height: 0;
}
html.desktop .msg-main.dk-msg-page { display: grid; }
html.desktop .dk-msg-side { display: flex; flex-direction: column; min-height: 0; overflow: auto; padding-right: 4px; }
html.desktop .dk-msg-pane {
  display: flex; flex-direction: column; min-height: 0; background: #fff; border: 1px solid var(--border);
  border-radius: 14px; padding: 0 16px;
}
html.desktop .dk-msg-pane--empty { display: flex; align-items: center; justify-content: center; color: var(--text-muted); }
.dk-msg-empty { text-align: center; font-size: 14px; }
.dk-msg-empty svg { margin: 0 auto 8px; opacity: .4; }
html.desktop .msg-item--active { outline: 2px solid var(--brand); }
html.desktop .msg-bubble { max-width: 62%; }
/* inside the shell's Messages tab there is no header — fill the frame */
body.embedded .dk-msg-page { height: calc(100vh - 32px); }

/* ── Embedded mode (body.embedded): running inside the MendipSys desktop
   shell — the parent shows the rail/tabs, so drop our own header + rail.
   Reference implementation for the Phase 2 briefs (DESKTOP_VISION.md). */
body.embedded .app-header, body.embedded .dk-rail, body.embedded .home-scene { display: none !important; }
html.desktop body.embedded { padding-left: 0; }
body.embedded .app-main { padding-top: 12px; }
.dk-sr__ref { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; font-weight: 700; color: var(--brand); background: var(--brand-light); border-radius: 6px; padding: 2px 6px; flex: 0 0 auto; }

/* ── Desktop timesheet: calendar + live day pane (Phase 3) ──────────── */
.dk-cal__pane { display: none; }
html.desktop .app-main.dk-cal-page { max-width: 1400px; }
html.desktop .dk-cal { display: grid; grid-template-columns: 480px minmax(0, 1fr); gap: 24px; align-items: start; }
html.desktop .dk-cal__left { min-width: 0; }
html.desktop .dk-cal__pane {
  display: block; position: sticky; top: calc(var(--header-h) + 16px);
  height: calc(100vh - var(--header-h) - 32px);
  background: #fff; border: 1px solid var(--border); border-radius: 14px; overflow: hidden; box-shadow: var(--shadow);
}
.dk-cal__frame { width: 100%; height: 100%; border: 0; display: block; }
html.desktop .dk-cal__selected { outline: 2px solid var(--brand); outline-offset: -2px; border-radius: 8px; }
html.desktop .ts-cal__cell.dk-cal__selected { outline-offset: -2px; }
html.desktop .pm-day.dk-cal__selected { outline-offset: 0; }
/* the framed day page sits in a narrower pane: tighten its main padding */
body.embedded .app-main { padding-left: 16px; padding-right: 16px; max-width: none; }
/* inside the calendar pane the parent already carries Day/Week/Month —
   scoped to the DAY page: the month/week pages run embedded in the shell's
   Timesheet tab and need their toggles (David 2026-08-26) */
body.embedded .ts-view-toggle--day { display: none; }

/* Personalise: phone / desktop layout switch */
.pz-surface { margin: 0 0 .4rem; }
.pz-surface__note { font-size: .82rem; color: var(--muted); margin: 0 0 .9rem; }

/* ── Sign-in security (Phase 1) ───────────────────────────────────────── */
.pw-form .form-group { margin-bottom: .8rem; }
.pw-show { display: flex; align-items: center; gap: .4rem; font-size: .85rem; color: var(--muted); margin: 0 0 .8rem; }
.pw-rules { font-size: .82rem; color: var(--muted); padding-left: 1.1rem; margin: 0 0 1rem; }
.pw-rules li { margin-bottom: .25rem; }
.pw-card { text-align: center; padding: 1.6rem 1rem; }
.pw-card__icon { width: 56px; height: 56px; border-radius: 50%; background: #27a560; color: #fff; font-size: 1.6rem; line-height: 56px; margin: 0 auto .6rem; }
.pw-card__title { font-size: 1.2rem; margin: 0 0 .3rem; }
.dv-row { display: flex; gap: .8rem; align-items: center; padding: .8rem .9rem; }
.dv-row--current { border-color: var(--brand); }
.dv-row__icon { font-size: 1.5rem; }
.dv-row__label { font-weight: 600; }
.dv-row__me { font-size: .72rem; font-weight: 600; color: var(--brand); background: var(--brand-light); border-radius: 999px; padding: .1rem .5rem; margin-left: .4rem; }
.dv-row__meta { font-size: .78rem; color: var(--muted); }
.dv-signout { background: #a02020; color: #fff; }
.sec-h { font-size: .95rem; margin: 0 0 .5rem; display: flex; align-items: center; gap: .5rem; }
.sec-n { font-size: .75rem; background: var(--bg); border-radius: 999px; padding: .1rem .5rem; color: var(--muted); }
.sec-empty { color: var(--muted); font-size: .85rem; margin: 0; }
.sec-line { display: flex; justify-content: space-between; align-items: center; gap: .6rem; padding: .35rem 0; border-top: 1px solid var(--border); font-size: .9rem; }
.sec-line:first-of-type { border-top: 0; }
.sec-line small { color: var(--muted); }
.sec-act { display: grid; gap: .6rem; }
.sec-act__btns { display: flex; gap: .5rem; flex-wrap: wrap; }

/* ── Two-factor sign-in ────────────────────────────────────────────────── */
.mfa-card { max-width: 440px; }
.mfa-opt { display: flex; align-items: center; gap: .8rem; text-align: left; padding: .8rem .9rem; line-height: 1.25; }
.mfa-opt small { display: block; font-weight: 400; font-size: .78rem; opacity: .85; }
.mfa-opt__icon { font-size: 1.4rem; }
.mfa-opt--alt { background: var(--bg); color: var(--text); border: 1px solid var(--border); }
.mfa-or { text-align: center; color: var(--muted); font-size: .8rem; margin: .8rem 0 .5rem; }
.mfa-code { margin-top: .7rem; }
.mfa-code label { display: block; margin-bottom: .35rem; }
.mfa-code label small { display: block; font-weight: 400; color: var(--muted); font-size: .78rem; }
.mfa-code__row { display: flex; gap: .5rem; }
.mfa-code__row .form-control { font-size: 1.25rem; letter-spacing: .15em; text-align: center; font-variant-numeric: tabular-nums; }
.mfa-msg { font-size: .85rem; margin: .4rem 0 0; padding: .45rem .6rem; border-radius: 8px; background: var(--bg); color: var(--muted); }
.mfa-msg--ok { background: #e3f6ea; color: #1b6b3a; }
.mfa-msg--warn { background: #fdecea; color: #8a1c1c; }
.mfa-remember { display: flex; align-items: center; gap: .45rem; font-size: .85rem; margin: 1rem 0 .4rem; }
.mfa-foot { font-size: .78rem; color: var(--muted); text-align: center; margin: .6rem 0 0; }
.mfa-sec + .mfa-sec { margin-top: .8rem; }
.mfa-sec--alert { border-color: #d4690e; }
.mfa-line__btns { display: flex; gap: .35rem; align-items: center; }
.mfa-add { margin-top: .6rem; display: grid; gap: .5rem; }
.mfa-hint { font-size: .78rem; color: var(--muted); margin: 0; }
.mfa-hint--nopasskey { display: none; color: #8a1c1c; }
#mfa.mfa--nopasskey .mfa-hint--nopasskey { display: block; }
#mfa.mfa--nopasskey #mfa-register { opacity: .5; }
.mfa-live { display: grid; gap: .4rem; margin-top: .5rem; }
.mfa-live__code { font-size: 2.2rem; font-weight: 700; letter-spacing: .12em; font-variant-numeric: tabular-nums; text-align: center; }
.mfa-live__track { height: 4px; background: var(--bg); border-radius: 2px; overflow: hidden; }
.mfa-live__bar { height: 100%; background: var(--brand); width: 0; transition: width 1s linear; }
.mfa-ask { padding: 1rem; }
.mfa-ask__what { margin-bottom: .7rem; }
.mfa-ask__btns { display: grid; gap: .5rem; }
a.mfa-card-home { display: block; text-decoration: none; color: inherit; }
/* Programme view at desktop: grid left (navigator), programme list right */
.ts-cal-wrap--side { display: none; }
html.desktop .ts-cal-wrap--side { display: block; }
html.desktop .dk-cal__pane--list { overflow: auto; padding: 12px 14px; background: var(--bg); }
html.desktop .dk-cal__pane--list .pm-list { margin: 0; }
html.desktop .pm-day--selected { outline: 2px solid var(--brand); outline-offset: 0; border-radius: 10px; }
/* Group members sheet: admin controls */
.msg-members__name { flex: 1; min-width: 0; }
.msg-members__name small { color: var(--brand); font-weight: 600; margin-left: .3rem; }
.msg-members__ctl { display: flex; gap: .3rem; }
.msg-members__btn { border: 1px solid var(--border); background: #fff; border-radius: 8px; padding: .25rem .5rem; font-size: .9rem; line-height: 1; color: var(--brand); }
.msg-members__btn--danger { color: #a02020; }

/* ── Webmail launcher ─────────────────────────────────────────────────── */
.wm-list { display: grid; gap: .6rem; }
.wm-btn { display: flex; align-items: center; gap: .8rem; padding: .9rem 1rem; text-decoration: none; color: inherit; }
.wm-btn__icon { font-size: 1.5rem; color: var(--brand); }
.wm-btn__body { flex: 1; min-width: 0; }
.wm-btn__body small { display: block; color: var(--muted); overflow: hidden; text-overflow: ellipsis; }
.wm-btn__go { color: var(--muted); font-size: 1.3rem; }

/* ── Messenger: read receipts + typing ─────────────────────────────────── */
.msg-row--me .msg-bubble__time::after { content: " \2713"; color: #9ab3c0; letter-spacing: -.12em; }
.msg-row--me.msg-row--read .msg-bubble__time::after { content: " \2713\2713"; color: #2b8cff; }
/* Typing indicator: a grey "them" bubble with three pulsing dots and the
   little trailing circles (David 2026-09-02, "like in other apps").
   .msg-row is display:flex, so [hidden] needs the !important — the usual trap. */
.msg-typing[hidden] { display: none !important; }
.msg-typing { animation: msgtype-in .18s ease-out; }
.msg-row--them .msg-bubble--typing {   /* outranks .msg-row--them .msg-bubble */
  position: relative; background: #e5e5ea; color: #8e8e93;
  padding: .55rem .8rem; margin-left: .35rem; margin-bottom: .35rem;
  border-bottom-left-radius: 16px; min-width: 0;
}
.msg-bubble--typing::before, .msg-bubble--typing::after {
  content: ""; position: absolute; background: #e5e5ea; border-radius: 50%;
}
.msg-bubble--typing::before { width: 10px; height: 10px; left: -3px; bottom: -2px; }
.msg-bubble--typing::after  { width: 5px;  height: 5px;  left: -9px; bottom: -7px; }
.msg-bubble--typing .msg-bubble__sender { color: #6b7a86; margin-bottom: .2rem; }
.msg-typing__dots { display: inline-flex; gap: 5px; align-items: center; height: 12px; }
.msg-typing__dots i { width: 8px; height: 8px; border-radius: 50%; background: #9a9aa0; animation: msgtype 1.4s ease-in-out infinite; }
.msg-typing__dots i:nth-child(2) { animation-delay: .18s; }
.msg-typing__dots i:nth-child(3) { animation-delay: .36s; }
.msg-typing__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
@keyframes msgtype    { 0%, 55%, 100% { opacity: .35; transform: scale(.85); } 25% { opacity: 1; transform: scale(1.1); } }
@keyframes msgtype-in { from { opacity: 0; transform: translateY(6px) scale(.9); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .msg-typing__dots i { animation: none; opacity: .7; } .msg-typing { animation: none; } }
/* ── Messenger reactions ───────────────────────────────────────────────── */
.msg-scroll { position: relative; }
.msg-reacts { display: flex; gap: .25rem; margin: -2px 0 2px; align-self: flex-end; align-items: flex-end; padding-bottom: 2px; }
.msg-row--me .msg-reacts { justify-content: flex-end; }
.msg-react { background: #fff; border: 1px solid var(--border); border-radius: 999px; padding: 0 .45rem; font-size: .8rem; line-height: 1.4; box-shadow: 0 1px 2px rgba(0,0,0,.06); }
.msg-react--mine { border-color: var(--brand); background: var(--brand-light); }
.msg-picker[hidden] { display: none !important; }   /* explicit display beats [hidden] — the dk-frames lesson */
/* Bulk delete / tick-box mode (David 2026-09-12). The composer and the note
   set their own display, so [hidden] needs the same lesson applied. */
.msg-composer[hidden], .msg-announce-note[hidden], .msg-bulk-bar[hidden] { display: none !important; }
.msg-sel { display: flex; align-items: center; padding: 0 .55rem 0 .15rem; align-self: center; }
.msg-sel__box { width: 22px; height: 22px; margin: 0; accent-color: var(--brand); cursor: pointer; }
.msg-scroll--select .msg-row, .msg-scroll--select .msg-bubble { cursor: pointer; }
.msg-scroll--select .msg-row:has(.msg-sel__box:checked) .msg-bubble { outline: 2px solid var(--brand); outline-offset: 1px; }
.msg-bulk-bar {
  display: flex; align-items: center; gap: .6rem;
  padding: .55rem 0 calc(.55rem + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--border); background: var(--bg);
}
html:not(.desktop) body.msg-conv .msg-bulk-bar { padding-bottom: .55rem; }   /* the body's inset is the one that stays — see .msg-composer */
.msg-bulk-bar__count { flex: 1; font-size: .9rem; color: var(--text-muted); }
.msg-bulk-bar__btn { padding: .5rem 1.1rem; border-radius: 10px; border: 1px solid var(--border); background: #fff; font: inherit; font-weight: 600; cursor: pointer; }
.msg-bulk-bar__btn--danger { background: #c62828; color: #fff; border-color: #c62828; }
.msg-bulk-bar__btn:disabled { opacity: .45; cursor: default; }
/* While the delete is in flight (2026-09-12): a spinner in the Delete button,
   the bar's buttons locked, the ticked rows dimmed. */
.msg-bulk-bar--busy .msg-bulk-bar__btn--danger { opacity: 1; padding-left: 2.1rem; position: relative; }
.msg-bulk-bar--busy .msg-bulk-bar__btn--danger::before {
  content: ""; position: absolute; left: .8rem; top: 50%; width: 14px; height: 14px; margin-top: -8px;
  border: 2px solid rgba(255, 255, 255, .45); border-top-color: #fff; border-radius: 50%;
  animation: msg-bulk-spin .7s linear infinite;
}
@keyframes msg-bulk-spin { to { transform: rotate(360deg); } }
.msg-row--busy { opacity: .5; transition: opacity .2s; }
@media (prefers-reduced-motion: reduce) { .msg-bulk-bar--busy .msg-bulk-bar__btn--danger::before { animation: none; } }
.msg-picker {
  position: absolute; z-index: 30; display: block; background: #fff;
  border: 1px solid var(--border); border-radius: 14px; padding: 0; overflow: hidden;
  min-width: 200px; max-width: min(280px, 80vw);
  box-shadow: 0 8px 26px rgba(0,0,0,.22);
}
.msg-picker__emoji { display: flex; gap: .15rem; padding: .3rem .4rem; border-bottom: 1px solid var(--border); }
.msg-picker__btn { border: 0; background: none; font-size: 1.35rem; line-height: 1; padding: .25rem; border-radius: 50%; cursor: pointer; color: inherit; }
.msg-picker__btn:active { background: var(--bg); transform: scale(1.15); }
.msg-picker__more {
  border: 1px dashed var(--border); background: none; color: var(--text-muted, #6b7a86);
  font-size: 1.05rem; line-height: 1; width: 1.9rem; height: 1.9rem; margin-left: .1rem;
  border-radius: 50%; cursor: pointer; flex: 0 0 auto;
}
.msg-picker__more:active { background: var(--bg); }
.msg-picker__palette {
  display: grid; grid-template-columns: repeat(6, 1fr); gap: .1rem;
  padding: .35rem .4rem; border-bottom: 1px solid var(--border); background: var(--bg, #f4f7f9);
}
.msg-picker__palette[hidden] { display: none !important; }   /* grid — the usual trap */
.msg-picker__pal { border: 0; background: none; font-size: 1.25rem; line-height: 1; padding: .3rem 0; border-radius: 8px; cursor: pointer; color: inherit; }
.msg-picker__pal:active { background: #fff; }
.msg-picker__menu { display: block; padding: .15rem 0; }
.msg-picker__row {
  display: flex; align-items: center; gap: .6rem; width: 100%;
  border: 0; background: none; font: inherit; font-size: .92rem; color: var(--text);
  padding: .55rem .85rem; text-align: left; cursor: pointer;
}
.msg-picker__row:active { background: var(--bg); }
.msg-picker__row[hidden] { display: none !important; }   /* flex row — the usual trap */
.msg-picker__ic { font-size: 1.05rem; line-height: 1; width: 1.4rem; text-align: center; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; }
.msg-picker__ic img { width: 18px; height: 18px; display: block; }
.msg-picker__row--danger { color: #c0392b; }
/* ── Messenger: edit / delete / group photo ────────────────────────────── */
.msg-bubble__text--deleted { font-style: italic; opacity: .65; }
.msg-edited { font-size: .65rem; opacity: .8; font-style: italic; margin-right: .2rem; }
.msg-picker__own { display: block; border-top: 1px solid var(--border); margin-top: .15rem; padding-top: .15rem; }
.msg-picker__own[hidden] { display: none !important; }
.msg-picker__btn[hidden] { display: none !important; }
#msg-pick-edit, #msg-pick-del { font-size: 1.05rem; color: var(--text); }
#msg-pick-del { color: #a02020; }
.msg-editing { display: flex; align-items: center; gap: .5rem; font-size: .8rem; color: var(--brand); padding: .25rem .9rem; }
.msg-editing[hidden] { display: none !important; }
.msg-editing button { margin-left: auto; border: 0; background: none; color: var(--muted); font-size: .9rem; }

/* ── Reply-to (WhatsApp-style quotes, David 2026-08-26) ─────────────── */
.msg-quote {
  display: block; max-width: 100%; margin: 0 0 .3rem; padding: .25rem .5rem;
  border-left: 3px solid var(--brand); border-radius: 7px;
  background: rgba(0, 94, 133, .08); cursor: pointer;
}
.msg-row--me .msg-quote { border-left-color: rgba(255,255,255,.85); background: rgba(255,255,255,.18); }
.msg-quote--gone { cursor: default; font-style: italic; }
.msg-quote__name { display: block; font-size: .7rem; font-weight: 700; color: var(--brand); }
.msg-row--me .msg-quote__name { color: #fff; }
.msg-quote__body {
  display: block; font-size: .78rem; opacity: .8;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* jump-to-original flash */
.msg-row--flash .msg-bubble { animation: msgflash 1.6s ease; }
@keyframes msgflash { 0%, 40% { box-shadow: 0 0 0 3px rgba(0, 94, 133, .45); } 100% { box-shadow: 0 1px 1px rgba(0,0,0,.07); } }
@media (prefers-reduced-motion: reduce) { .msg-row--flash .msg-bubble { animation: none; outline: 2px solid var(--brand); } }
/* the "Replying to …" bar above the composer (shares .msg-editing layout) */
.msg-replying__who { font-weight: 700; }
.msg-replying__snip { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1; }
.msg-members__photo { display: flex; align-items: center; gap: .5rem; margin: .6rem 0; }
.msg-members__photo input[type=file] { flex: 1; min-width: 0; font-size: .8rem; }
/* ── Home side column: My programme feed (desktop) ─────────────────────── */
.dk-prog { background: #fff; border: 1px solid var(--border); border-radius: 14px; padding: .8rem .9rem; margin-top: 14px; box-shadow: var(--shadow); }
.dk-prog__head { font-weight: 700; font-size: .92rem; display: flex; align-items: center; justify-content: space-between; margin-bottom: .4rem; }
.dk-prog__all { font-size: .78rem; font-weight: 600; color: var(--brand); text-decoration: none; }
.dk-prog__day { display: flex; gap: .6rem; padding: .45rem 0; border-top: 1px solid var(--border); text-decoration: none; color: inherit; align-items: flex-start; }
.dk-prog__day:first-of-type { border-top: 0; }
.dk-prog__day:hover .dk-prog__name { color: var(--brand); }
.dk-prog__date { flex: 0 0 34px; text-align: center; line-height: 1.1; }
.dk-prog__date span { display: block; font-size: .62rem; text-transform: uppercase; color: var(--muted); font-weight: 600; }
.dk-prog__date strong { font-size: 1.05rem; }
.dk-prog__sess { flex: 1; min-width: 0; display: grid; gap: .25rem; }
.dk-prog__pill { display: flex; align-items: center; gap: .35rem; min-width: 0; }
.dk-prog__pill img { width: 15px; height: auto; flex: 0 0 auto; }
.dk-prog__pill--off { opacity: .55; }
.dk-prog__name { font-size: .82rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.dk-prog__time { font-size: .74rem; color: var(--muted); font-variant-numeric: tabular-nums; margin-left: auto; padding-left: .4rem; }
.dk-prog__more { font-size: .74rem; color: var(--muted); }

/* ── Home panels (David 2026-09-18; includes/home_panels.php) ─────────────
   My days / My tasks / Notifications in the desktop side column. Rendered
   server-side for a desktop surface only, so nothing here needs html.desktop.
   One card look (.hp), one row look (.hp-row); each panel adds only its own. */
.hp { background: #fff; border: 1px solid var(--border); border-radius: 14px; padding: .8rem .9rem; box-shadow: var(--shadow); }
.hp__head { display: flex; align-items: center; justify-content: space-between; gap: .5rem; margin-bottom: .55rem; }
.hp__title { font-weight: 700; font-size: .92rem; display: inline-flex; align-items: center; gap: .4rem; }
.hp__title svg { color: var(--brand); flex: 0 0 auto; }
.hp__all { font-size: .78rem; font-weight: 600; color: var(--brand); text-decoration: none; white-space: nowrap; }
.hp__n { font-style: normal; font-size: .68rem; font-weight: 700; background: #d6336c; color: #fff; border-radius: 999px; padding: .08rem .45rem; }
.hp__sub { font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); margin: .7rem 0 .15rem; }
.hp__none { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
.hp__more { display: block; font-size: .78rem; font-weight: 600; color: var(--brand); text-decoration: none; padding-top: .5rem; border-top: 1px solid var(--border); margin-top: .1rem; }

.hp-row { display: flex; gap: .6rem; align-items: flex-start; padding: .45rem 0; border-top: 1px solid var(--border); text-decoration: none; color: inherit; min-width: 0; }
.hp__head + .hp-row, .hp__sub + .hp-row { border-top: 0; }
.hp-row:hover .hp-row__t { color: var(--brand); }
.hp-row__body { flex: 1; min-width: 0; display: grid; gap: .1rem; }
.hp-row__t { font-size: .84rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hp-row small { font-size: .74rem; color: var(--muted); display: flex; flex-wrap: wrap; gap: .1rem .55rem; align-items: center; min-width: 0; }
.hp-row__clip { display: -webkit-box !important; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.hp-row__when { flex: 0 0 52px; font-size: .72rem; color: var(--muted); line-height: 1.25; font-variant-numeric: tabular-nums; }
.hp-row__when strong { display: block; color: var(--text, #1f2933); font-size: .74rem; }
.hp-row__time { flex: 0 0 auto; font-size: .7rem; color: var(--muted); white-space: nowrap; padding-top: .1rem; }
.hp-row--new { position: relative; }
.hp-row--new .hp-row__t::before { content: ""; display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: #d6336c; margin-right: .4rem; vertical-align: middle; }

/* My days: five weeks, Monday first. The fill says "in"; the dot says "appointment". */
.hp-cal__grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 3px; }
.hp-cal__dow { text-align: center; font-size: .62rem; font-weight: 700; color: var(--muted); padding-bottom: .15rem; }
.hp-cal__day { position: relative; aspect-ratio: 1 / .82; display: flex; align-items: center; justify-content: center; border-radius: 8px; font-size: .8rem; font-variant-numeric: tabular-nums; text-decoration: none; color: var(--muted); background: #f4f6f8; }
.hp-cal__day:hover { outline: 2px solid var(--brand); outline-offset: -2px; }
.hp-cal__day--working { background: var(--brand-light); color: var(--brand-dark); font-weight: 700; }
.hp-cal__day--hol, .hp-cal__day--leave, .hp-cal__day--lieu { background: #fdf0d5; color: #8a5a00; font-weight: 600; }
.hp-cal__day--sick { background: #fde2e4; color: #a02020; font-weight: 600; }
.hp-cal__day--past { opacity: .45; }
.hp-cal__day--today { outline: 2px solid var(--brand); outline-offset: -2px; opacity: 1; }
.hp-cal__mon { position: absolute; top: 1px; left: 4px; font-style: normal; font-size: .52rem; font-weight: 700; text-transform: uppercase; color: var(--muted); }
.hp-cal__dot { position: absolute; bottom: 3px; left: 50%; width: 5px; height: 5px; margin-left: -2.5px; border-radius: 50%; background: #d6336c; }
.hp-cal__key { display: flex; flex-wrap: wrap; gap: .2rem .8rem; margin-top: .5rem; font-size: .68rem; color: var(--muted); }
.hp-cal__key span { display: inline-flex; align-items: center; gap: .3rem; }
.hp-cal__sw { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
.hp-cal__sw--working { background: var(--brand-light); border: 1px solid #b9d9ee; }
.hp-cal__sw--hol { background: #fdf0d5; border: 1px solid #f0d9a8; }
.hp-cal__dot--key { position: static; margin: 0; display: inline-block; }

/* My tasks: Projects' tiles, then the next few rows. */
.hp-tk__tiles { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 4px; margin-bottom: .35rem; }
.hp-tk__tile { display: grid; justify-items: center; gap: .05rem; padding: .4rem .1rem; border-radius: 9px; background: #f4f6f8; text-decoration: none; color: inherit; min-width: 0; }
.hp-tk__tile:hover { background: var(--brand-light); }
.hp-tk__tile b { font-size: 1.05rem; line-height: 1.1; font-variant-numeric: tabular-nums; }
.hp-tk__tile span { font-size: .58rem; font-weight: 600; color: var(--muted); text-align: center; line-height: 1.15; }
.hp-tk__tile--over { background: #fde2e4; } .hp-tk__tile--over b { color: #a02020; }
.hp-tk__tile--today { background: #fdf0d5; } .hp-tk__tile--today b { color: #8a5a00; }
.hp-tk__tile--new { background: var(--brand-light); } .hp-tk__tile--new b { color: var(--brand); }
.hp-row__tick { flex: 0 0 15px; width: 15px; height: 15px; margin-top: .12rem; border: 1.5px solid #b6c0ca; border-radius: 50%; }
.hp-due--over { color: #a02020; font-weight: 700; }
.hp-due--today { color: #8a5a00; font-weight: 700; }
.hp-pj { display: inline-flex; align-items: center; gap: .3rem; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hp-pj i { flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%; display: inline-block; }
/* ── My profile (profile.php) ─────────────────────────────────────────── */
.page-title { font-size: 1.25rem; margin: 0 0 .8rem; }
.pf-card { padding: 1rem 1.1rem; margin-bottom: 1rem; }
.pf-card__title { font-size: 1rem; margin: 0 0 .6rem; }
.pf-hint { font-size: .85rem; color: var(--muted); margin: .2rem 0 .6rem; }
.pf-photo { display: flex; gap: 1rem; align-items: flex-start; }
.pf-photo__img { width: 96px; height: 96px; border-radius: 14px; object-fit: cover; flex: 0 0 auto; background: var(--bg); }
.pf-photo__img--none { display: flex; align-items: center; justify-content: center; font-size: 2.2rem; color: var(--muted); border: 1px dashed var(--border); }
.pf-photo__side { min-width: 0; }
.pf-photo__pick { cursor: pointer; display: inline-block; }
.pf-name { font-weight: 700; margin: 0 0 .6rem; }
.pf-name__note { display: block; font-weight: 400; font-size: .78rem; color: var(--muted); }
.pf-row { display: flex; gap: .7rem; align-items: flex-start; padding: .55rem 0; border-top: 1px solid var(--border); text-decoration: none; color: inherit; }
.pf-row--ro { pointer-events: none; }
.pf-row__icon { flex: 0 0 1.6rem; text-align: center; font-size: 1.1rem; }
.pf-row__body { flex: 1; min-width: 0; }
.pf-row__value { display: block; font-weight: 600; overflow-wrap: anywhere; }
.pf-row__def { font-style: normal; font-size: .7rem; font-weight: 700; color: var(--brand); background: var(--brand-light); border-radius: 999px; padding: .05rem .45rem; margin-left: .3rem; }
.pf-row__sub { display: block; font-size: .8rem; color: var(--muted); }
.pf-row__go { color: var(--muted); font-size: 1.2rem; align-self: center; }
.pf-edit { border-top: 1px solid var(--border); padding: .6rem 0; }
.pf-edit__grid { display: grid; gap: .5rem; margin-bottom: .6rem; }
.pf-edit__grid select, .pf-edit__grid input[type=text], .pf-edit__grid textarea { font: inherit; padding: .45rem .6rem; border: 1px solid var(--border); border-radius: 8px; width: 100%; }
.pf-edit__tick { font-size: .85rem; display: flex; align-items: center; gap: .4rem; }
.pf-edit__acts { display: flex; gap: .5rem; }
.pf-edit__del { margin-left: auto; }
.pf-log { display: flex; gap: .7rem; font-size: .82rem; padding: .35rem 0; border-top: 1px solid var(--border); }
.pf-log__when { flex: 0 0 5.4rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.pf-log__what { min-width: 0; overflow-wrap: anywhere; }
/* crop modal */
.pf-crop { position: fixed; inset: 0; background: rgba(0,0,0,.55); z-index: 400; display: flex; align-items: center; justify-content: center; padding: 16px; }
.pf-crop[hidden] { display: none !important; }
.pf-crop__panel { background: #fff; border-radius: 16px; padding: 1rem; width: min(360px, 100%); text-align: center; }
.pf-crop__panel h3 { font-size: .95rem; margin: 0 0 .6rem; }
#pf-crop-canvas { width: min(320px, 100%); border-radius: 12px; touch-action: none; cursor: grab; background: var(--bg); }
#pf-crop-zoom { width: 100%; margin: .6rem 0; }
.pf-crop__acts { display: flex; justify-content: space-between; }

/* admin: profile change log */
.pfl-filter { margin-bottom: .8rem; }
.pfl-filter select { font: inherit; padding: .45rem .6rem; border: 1px solid var(--border); border-radius: 8px; }
.pfl-row { padding: .7rem .9rem; margin-bottom: .6rem; }
.pfl-row__head { display: flex; justify-content: space-between; gap: .6rem; font-size: .85rem; }
.pfl-row__head span { color: var(--muted); }
.pfl-row__what { font-size: .85rem; color: var(--muted); margin: .15rem 0; }
.pfl-row__vals { font-size: .9rem; overflow-wrap: anywhere; }
.pfl-row__note { font-size: .78rem; color: var(--muted); margin-top: .25rem; }
.pfl-row__photos { display: flex; align-items: center; gap: .8rem; margin-top: .3rem; }
.pfl-ph { text-align: center; }
.pfl-ph img { width: 56px; height: 56px; border-radius: 10px; object-fit: cover; display: block; }
.pfl-ph small { color: var(--muted); font-size: .68rem; }
.pfl-ph__arrow { color: var(--muted); }
.pfl-row__photos form { margin-left: auto; }

/* ── Rail avatar menu (desktop) + profile shortcuts (phones) ──────────── */
button.dk-rail__avatar { padding: 0; cursor: pointer; font-family: inherit; }
.dk-ava__menu {
  position: fixed; left: 80px; bottom: 14px; z-index: 300; min-width: 215px;
  background: #fff; border: 1px solid var(--border); border-radius: 12px;
  box-shadow: var(--shadow-md); padding: 6px;
}
.dk-ava__menu[hidden] { display: none !important; }
.dk-ava__menu a {
  display: flex; align-items: center; gap: .6rem; padding: 9px 12px;
  border-radius: 8px; text-decoration: none; color: var(--text); font-size: 14px;
}
.dk-ava__menu a:hover { background: var(--brand-light); }
/* the shortcuts card lives on the profile page for PHONES — the desktop
   rail's avatar menu carries the same links */
html.desktop .pf-links { display: none; }

/* ── Housekeeping day itinerary (planner areas, day view) ─────────────── */
.hkd { margin-top: .55rem; border-top: 1px solid var(--border); padding-top: .5rem; }
.hkd__title { font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); margin-bottom: .35rem; }
.hkd__row {
  display: flex; align-items: baseline; gap: .6rem; font-size: .88rem;
  padding: .3rem .55rem; margin-bottom: .25rem; border-radius: 8px;
  border-left: 3px solid var(--border); background: var(--bg);
}
.hkd__row--gen { font-style: italic; color: var(--text-muted); }
.hkd__time { font-variant-numeric: tabular-nums; font-size: .8rem; color: var(--text-muted); flex: 0 0 auto; }
.hkd__name { font-weight: 600; min-width: 0; overflow-wrap: anywhere; }
.hkd__row--gen .hkd__name { font-weight: 400; }
/* the team panel */
.hkd-team { padding: .9rem 1rem; margin-top: .9rem; }
.hkd-team__person { border-top: 1px solid var(--border); padding: .5rem 0; }
.hkd-team__person:first-of-type { border-top: 0; }
.hkd-team__head { display: flex; justify-content: space-between; gap: .6rem; font-size: .9rem; margin-bottom: .3rem; }
.hkd-team__head span { color: var(--text-muted); font-variant-numeric: tabular-nums; }
.hkd-team__chips { display: flex; flex-wrap: wrap; gap: .3rem; }
.hkd-chip {
  font-size: .76rem; padding: .12rem .5rem; border-radius: 999px;
  border: 1px solid var(--border); background: var(--bg); white-space: nowrap;
}
.hkd-chip em { font-style: normal; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.hkd-chip--gen { font-style: italic; color: var(--text-muted); }

/* ── Today card quick view (phones: tap to expand) ────────────────────── */
.home-today[data-drop] .home-today__go { transition: transform .18s ease; }
.home-today--open .home-today__go { transform: rotate(90deg); }
.home-today--open { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.home-today__drop {
  background: #fff; border-radius: 0 0 14px 14px; box-shadow: var(--shadow);
  margin-top: -8px; padding: .7rem .9rem .6rem; position: relative;
}
.home-today__drop[hidden] { display: none !important; }
.htd-head { font-size: .7rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--text-muted); margin: .5rem 0 .2rem; }
.htd-row { display: flex; align-items: baseline; gap: .6rem; font-size: .88rem; padding: .22rem 0; }
.htd-row--block .htd-row__name { font-weight: 700; }
.htd-row--off { opacity: .55; }
.htd-row__time { flex: 0 0 auto; font-variant-numeric: tabular-nums; font-size: .8rem; color: var(--text-muted); min-width: 5.4em; }
.htd-row__name { min-width: 0; overflow-wrap: anywhere; }
.htd-row__name em { font-style: normal; color: var(--text-muted); }
.htd-row__name img { width: 14px; height: auto; vertical-align: -2px; margin-right: .15rem; }
.htd-full { display: block; text-align: right; font-size: .82rem; font-weight: 600; color: var(--brand); text-decoration: none; padding-top: .4rem; }
/* quick view: personal Outlook rows — dashed, like the Programme pills */
.htd-row--cal { border-left: 3px dashed var(--border); padding-left: .5rem; }
.htd-row--cal .htd-row__name em { font-style: normal; color: var(--text-muted); }

/* ── Team picker: search-as-you-type ──────────────────────────────────── */
.tm-picker__q {
  width: 100%; font: inherit; font-size: 16px;   /* 16px stops iOS zoom-on-focus */
  padding: .55rem .7rem; border: 1px solid var(--border); border-radius: 10px;
}
.tm-picker__results { list-style: none; margin: .3rem 0 0; padding: 0; }
/* explicit display beats [hidden] — the dk-frames lesson */
.tm-picker__q[hidden], .tm-picker__row[hidden], .tm-picker__results[hidden],
.tm-picker__results li[hidden] { display: none !important; }
.tm-picker__none { font-size: .85rem; color: var(--text-muted); padding: .4rem .2rem; }

/* ── MM group kinds (private / open / announce) ───────────────────────── */
.msg-announce-note {
  text-align: center; font-size: .85rem; color: var(--text-muted);
  background: #fff; border: 1px dashed var(--border); border-radius: 12px;
  padding: .6rem .8rem; margin: .3rem 0 .6rem;
}
/* Notifications thread (2026-09-11): a bell where a face would be, and each
   push as a card with its title, its words and where it went. */
.msg-ava--notify { display: inline-flex; align-items: center; justify-content: center; background: var(--brand); color: #fff; }
.msg-ava--notify svg { width: 24px; height: 24px; stroke: currentColor; fill: none; stroke-width: 2; }
.msg-row--notify .msg-bubble { max-width: 92%; border-left: 3px solid var(--brand); }
.msg-notify__title { font-weight: 700; font-size: .9rem; margin-bottom: .1rem; }
.msg-notify__open { display: inline-block; margin-top: .3rem; font-weight: 600; color: var(--brand); text-decoration: none; }
.msg-notify__open:hover { text-decoration: underline; }
.msg-kind-pick { margin: .6rem 0; }
.msg-kind__opt { display: flex; gap: .5rem; align-items: flex-start; padding: .3rem 0; cursor: pointer; }
.msg-kind__opt span { display: flex; flex-direction: column; }
.msg-kind__opt strong { font-size: .9rem; }
.msg-kind__opt small { font-size: .76rem; color: var(--text-muted); }
.msg-kind__opt--sub { padding-left: 1.4rem; }
.msg-kind__modes[hidden] { display: none !important; }
.msg-members__kind { border-top: 1px solid var(--border); margin-top: .7rem; padding-top: .5rem; }
.msg-members__reqs { border-top: 1px solid var(--border); margin-top: .7rem; padding-top: .5rem; }
.msg-members__reqs-title { font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); margin-bottom: .25rem; }
.msg-person--group .msg-person__btn { display: flex; align-items: center; gap: .55rem; width: 100%; padding: .55rem .6rem; }
.msg-person__sub { display: block; font-weight: 400; font-size: .76rem; color: var(--text-muted); }
.msg-join-form { margin-left: auto; }
.msg-join-empty { color: var(--text-muted); font-size: .88rem; text-align: center; padding: 1rem 0; }
.msg-announce-seed { padding: .8rem .9rem; margin-bottom: .8rem; }
.msg-announce-seed__blurb { font-size: .85rem; margin: 0 0 .5rem; }
.msg-announce-seed__row { display: flex; gap: .5rem; }
.msg-announce-seed__row input { flex: 1; min-width: 0; font: inherit; font-size: 16px; padding: .45rem .6rem; border: 1px solid var(--border); border-radius: 8px; }
#msg-new-join[hidden], #msg-new-q[hidden] { display: none !important; }

/* ── New-message screen at desktop / in the shell frame ───────────────── */
/* The shell's embedded rule widens .app-main to the full frame, which
   stretched this phone-shaped page across the whole window (David
   2026-08-28: "this view could do with a tidy") — pin it to a centred
   column on any wide surface instead. */
html.desktop .app-main.msg-new-page,
body.embedded .app-main.msg-new-page { max-width: 680px; margin: 0 auto; }

/* frame bar: refresh-this-frame button */
.dk-frame__refresh {
  border: 0; background: none; color: var(--brand); font: inherit; font-size: 15px;
  font-weight: 700; cursor: pointer; padding: 0 6px; line-height: 1; border-radius: 6px;
}
.dk-frame__refresh:hover { background: var(--brand-light); }

/* ── Desk home (desktop main column for flagged people) ───────────────── */
.desk { display: flex; flex-direction: column; gap: 16px; margin-bottom: 26px; }
.desk__card { padding: 1rem 1.1rem; }
.desk__title { font-size: 1rem; margin: 0 0 .55rem; display: flex; align-items: center; gap: .5rem; }
.desk__count { font-style: normal; font-size: .72rem; font-weight: 700; color: var(--brand); background: var(--brand-light); border-radius: 999px; padding: .1rem .5rem; }
.desk__empty { font-size: .85rem; color: var(--text-muted); margin: .2rem 0; }
.desk__appsnote { text-align: center; font-size: .8rem; color: var(--text-muted); }
.desk-ref { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .8rem; font-weight: 700; color: var(--brand); background: var(--brand-light); border-radius: 6px; padding: 1px 6px; text-decoration: none; white-space: nowrap; }
/* chasers */
.desk-chaser { border-top: 1px solid var(--border); padding: .5rem 0; }
.desk-chaser:first-of-type { border-top: 0; }
.desk-chaser--urgent { border-left: 3px solid #a02020; padding-left: .6rem; }
.desk-chaser--future { opacity: .6; }
.desk-chaser__head { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; font-size: .78rem; color: var(--text-muted); }
.desk-chaser__when { font-variant-numeric: tabular-nums; }
.desk-chaser__when i { font-style: normal; color: var(--brand); }
.desk-chaser__urgent { color: #fff; background: #a02020; font-weight: 700; font-size: .66rem; border-radius: 999px; padding: .08rem .45rem; }
.desk-chaser__from { margin-left: auto; }
.desk-chaser__msg { font-size: .9rem; margin-top: .15rem; overflow-wrap: anywhere; }
/* booking tables */
.desk-tablewrap { overflow-x: auto; }
.desk-table { width: 100%; border-collapse: collapse; font-size: .84rem; }
.desk-table th { text-align: left; font-size: .68rem; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); padding: .25rem .5rem .25rem 0; border-bottom: 1px solid var(--border); }
.desk-table td { padding: .4rem .5rem .4rem 0; border-bottom: 1px solid var(--border); vertical-align: top; }
.desk-table tr:last-child td { border-bottom: 0; }
.desk-table__title { max-width: 260px; }
.desk-table__num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* admin: desk-home list (View As layout + state at a glance) */
.desk-badge { background: #d9f2e3; color: #1e7d43; font-size: .68rem; font-weight: 700; border-radius: 999px; padding: .1rem .5rem; margin-left: .35rem; }
.desk-row--on { border-left: 3px solid #1e7d43; }
.desk-row__act { flex: 0 0 auto; font-size: .8rem; font-weight: 600; color: var(--brand); white-space: nowrap; }
.desk-row--on .desk-row__act { color: #a02020; }

/* desk-home split: Home = desk only, Apps = tiles only (desktop.js toggles) */
html.desktop .dk-main--hasdesk #menu-grid { display: none; }
html.desktop .dk-main--hasdesk.dk-main--apps #menu-grid { display: grid; }
html.desktop .dk-main--hasdesk.dk-main--apps .desk { display: none; }

/* desk panels v2: capped height + scroll, header search */
.desk__body { max-height: 380px; overflow-y: auto; }
.desk__filter {
  margin-left: auto; font: inherit; font-size: .82rem; padding: .3rem .6rem;
  border: 1px solid var(--border); border-radius: 8px; width: 200px;
}
.desk__title { flex-wrap: wrap; }
.desk__none { font-size: .85rem; color: var(--text-muted); padding: .4rem 0; }
.desk [data-search][hidden] { display: none !important; }
.desk-table thead th { position: sticky; top: 0; background: #fff; }

/* waiting-for-you: the profile-photo nudge is a camera control */
.att-row--photo { padding: 0; }
.att-row__hit { display: flex; align-items: center; gap: .6rem; width: 100%; padding: .55rem .8rem; cursor: pointer; }
.att-row--photo .att-row__label small { display: block; font-size: .74rem; color: var(--text-muted); }

.desk__title-link { color: inherit; text-decoration: none; border-bottom: 1px dashed var(--border); }
.desk__title-link:hover { color: var(--brand); border-bottom-color: var(--brand); }

/* ── Built-in tiles + desk doors (David 2026-08-31) ───────────────────
   A "built-in" tile is driven by a PERMISSION, not by the button admin or
   anyone's personalisation, so it carries no data-bid and the wobble editor
   skips it (home-edit.js filters on [data-bid]). It otherwise wears the
   same rich-tile clothes as everything else in the grid.                */

/* The desk's slim Chasers row: shown only when the person can see chasers
   but has none of their own, so the "no data = no panel" rule still holds
   while the board stays reachable from Home. */
.desk__door {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .8rem .95rem;
    text-decoration: none;
    color: inherit;
}
.desk__door:hover { background: #f4f8fa; }
.desk__door-icon { font-size: 1.35rem; line-height: 1; }
.desk__door-text { display: flex; flex-direction: column; gap: .1rem; min-width: 0; }
.desk__door-text strong { font-size: .98rem; color: #005e85; }
.desk__door-text em { font-style: normal; font-size: .82rem; color: #6b7a82; }
.desk__door-go { margin-left: auto; color: #9bb0ba; font-size: 1.3rem; }

/* ── Desk booking actions (David 2026-08-31) ──────────────────────────
   The table survives: at Garry scale the value of this panel IS the dense
   scannable row, so the actions ride in one narrow ⋯ column at the end
   rather than turning 100 rows into 100 panels.                        */
.desk-table__acth { width: 34px; }
.desk-table__act  { width: 34px; text-align: right; padding-right: .2rem; }
.desk-act {
    border: 0;
    background: transparent;
    color: #8fa3ad;
    font-size: 1.05rem;
    line-height: 1;
    padding: .15rem .3rem;
    border-radius: 5px;
    cursor: pointer;
}
.desk-act:hover, .desk-act[aria-expanded="true"] { background: #e8eff3; color: #005e85; }

/* status reads as state, using ver5's own colour semantics so the chip here
   means what the radio in the booking window means */
.desk-st { white-space: nowrap; }
.desk-st[data-st="0"] { color: #1c5fa8; }
.desk-st[data-st="1"] { color: #2f7a44; }
.desk-st[data-st="2"] { color: #a02020; }
.desk-st[data-st="3"] { color: #8a6a09; }

/* one menu, moved to whichever ⋯ was pressed */
.desk-menu {
    position: absolute;
    z-index: 60;
    min-width: 190px;
    padding: .3rem;
    background: #fff;
    border: 1px solid #dbe4e9;
    border-radius: 10px;
    box-shadow: 0 8px 26px rgba(0, 40, 60, .18);
}
.desk-menu[hidden] { display: none !important; }
.desk-menu__ref {
    margin: 0;
    padding: .3rem .55rem .35rem;
    font-size: .78rem;
    font-weight: 700;
    color: #005e85;
    letter-spacing: .03em;
}
.desk-menu__lbl {
    margin: 0;
    padding: .25rem .55rem .15rem;
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: #93a5ae;
}
.desk-menu__item {
    display: block;
    width: 100%;
    text-align: left;
    border: 0;
    background: transparent;
    color: inherit;                 /* iOS dark mode paints buttontext white */
    font: inherit;
    font-size: .88rem;
    padding: .42rem .55rem;
    border-radius: 6px;
    cursor: pointer;
}
.desk-menu__item:hover { background: #eef4f7; }
.desk-menu__item.is-now::after { content: ' ¹3'; color: #2f7a44; font-weight: 700; }
.desk-menu__item--bin { margin-top: .25rem; border-top: 1px solid #eceff1; color: #a02020; }

/* row feedback */
.desk-table tr.is-working { opacity: .5; }
.desk-table tr.is-done    { background: #e7f5ec; }
.desk-table tr.is-failed  { background: #fbe6e6; }
.desk-table tr.is-gone    { opacity: 0; transition: opacity .25s ease; }
@media (prefers-reduced-motion: reduce) {
    .desk-table tr.is-gone { transition: none; }
}

/* ── Desk accounts: status filter chips (David 2026-08-31) ────────────
   The panel shows Current only by default; the chips are how you reach the
   rest, and they carry counts so the panel says what it is holding back
   rather than silently hiding it.                                      */
.desk-fils {
    display: flex;
    flex-wrap: wrap;
    gap: .3rem;
    padding: 0 .95rem .6rem;
    margin-top: -.25rem;
}
.desk-fil {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    padding: .2rem .55rem;
    border: 1px solid #dde5ea;
    border-radius: 999px;
    background: #fff;
    font-size: .76rem;
    color: #55707d;
    text-decoration: none;
    white-space: nowrap;
}
.desk-fil em {
    font-style: normal;
    font-size: .7rem;
    color: #93a5ae;
    font-variant-numeric: tabular-nums;
}
.desk-fil:hover { border-color: #b9ccd6; color: #005e85; }
.desk-fil.is-on {
    background: #005e85;
    border-color: #005e85;
    color: #fff;
    font-weight: 600;
}
.desk-fil.is-on em { color: rgba(255, 255, 255, .75); }

.desk__card--accounts.is-loading { opacity: .55; }
.desk__empty {
    margin: 0;
    padding: .9rem .95rem 1.1rem;
    font-size: .85rem;
    color: #7b8d96;
}

/* ── Who's in (David 2026-08-31) ──────────────────────────────────────
   ver5's timeline as grouped lists: one <details> per team wearing ver5's
   own role colour (--wi-bg/--wi-bd from tb_staff_roles.role_color via
   WI_COLOURS), so orange still means Alpine Lounge. Native disclosure —
   no JS, works on every phone.                                          */
.ts-whosin {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin: -.25rem 0 .75rem;
    padding: .55rem .85rem;
    background: #fff;
    border: 1px solid #dde5ea;
    border-radius: 10px;
    text-decoration: none;
    color: #005e85;
    font-weight: 600;
    font-size: .92rem;
}
.ts-whosin__sub {
    font-weight: 400;
    font-size: .78rem;
    color: #7b8d96;
}
.ts-whosin__go { margin-left: auto; color: #9bb0ba; font-size: 1.15rem; }
.ts-whosin:active { background: #f2f7fa; }
body.embedded .ts-whosin { display: none; }   /* the framed day pane stays lean */

.wi-summary {
    margin: 0 0 .75rem;
    font-size: .9rem;
    color: #55707d;
}
.wi-summary strong { font-size: 1.05rem; color: #1c2b33; }
.wi-today-link { margin: -.35rem 0 .75rem; font-size: .85rem; }

.wi-team {
    margin-bottom: .55rem;
    padding: 0;                       /* summary carries its own padding */
    overflow: hidden;
}
.wi-team__head {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .7rem .85rem;
    cursor: pointer;
    list-style: none;                 /* no default marker */
    -webkit-tap-highlight-color: transparent;
}
.wi-team__head::-webkit-details-marker { display: none; }
.wi-team__chip {
    width: 1.05rem;
    height: 1.05rem;
    border-radius: 5px;
    background: var(--wi-bg, #e5e5e5);
    border: 1px solid var(--wi-bd, #b2b2b2);
    flex: 0 0 auto;
}
.wi-team__icon { font-size: 1rem; line-height: 1; }
.wi-team__name { font-weight: 600; font-size: .95rem; color: #1c2b33; }
.wi-team__n {
    margin-left: auto;
    font-size: .82rem;
    font-weight: 700;
    color: #55707d;
    background: #eef3f6;
    border-radius: 999px;
    padding: .1rem .55rem;
    font-variant-numeric: tabular-nums;
}
.wi-team__arrow { color: #9bb0ba; font-size: 1.2rem; transition: transform .15s ease; }
.wi-team[open] .wi-team__arrow { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) {
    .wi-team__arrow { transition: none; }
}

.wi-people {
    list-style: none;
    margin: 0;
    padding: .1rem .85rem .6rem;
    border-top: 1px solid #eef2f4;
}
.wi-person {
    display: flex;
    align-items: baseline;
    gap: .6rem;
    padding: .42rem .1rem;
    border-bottom: 1px solid #f4f7f8;
    font-size: .9rem;
}
.wi-person:last-child { border-bottom: 0; }
.wi-person__name { color: #1c2b33; }
.wi-person__times {
    margin-left: auto;
    color: #55707d;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.wi-dm {
    font-style: normal;
    font-size: .68rem;
    font-weight: 700;
    color: #fff;
    background: #2560c4;
    border-radius: 4px;
    padding: .05rem .3rem;
    margin-left: .3rem;
    vertical-align: middle;
}
.wi-away-title {
    margin: 1.2rem 0 .55rem;
    font-size: .82rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: #7b8d96;
}
.wi-away-title em { font-style: normal; color: #55707d; }
.wi-team--away .wi-team__name { font-weight: 500; }
.wi-none { margin: 0; padding: .3rem 0; color: #7b8d96; font-size: .9rem; }
.wi-back { margin: 1rem 0 0; font-size: .88rem; }

/* desktop: cap the width so 200-name lists don't stretch across the shell */
html.desktop .app-main:has(.wi-summary) { max-width: 720px; }

/* the pulse card that is now a door */
.dk-pulse__card--link { text-decoration: none; color: inherit; display: block; }
.dk-pulse__card--link:hover { box-shadow: 0 2px 10px rgba(0, 40, 60, .10); }

/* ── Who's in: view toggle + person search (David 2026-08-31) ─────────
   The toggle reuses .ts-view-toggle so it reads like Day/Week/Month.
   Searching forces the flat People list, so a name query always answers
   with the person, whichever view was showing.                          */
.wi-toggle { margin-bottom: .6rem; }
.wi-search {
    display: block;
    width: 100%;
    box-sizing: border-box;
    padding: .55rem .8rem;
    margin-bottom: .6rem;
    border: 1px solid #dde5ea;
    border-radius: 10px;
    background: #fff;
    font: inherit;
    font-size: 16px;              /* 16px stops iOS zooming the page on focus */
    color: #1c2b33;
}
.wi-search:focus { outline: 2px solid #005e85; outline-offset: 1px; }

.wi-flatcard { padding: .15rem .85rem; }
.wi-people--flat { border-top: 0; padding: 0; }
.wi-people--flat .wi-person__times { text-align: right; white-space: normal; }

/* away states inline in the People list — the app's own state colours
   (ver5 semantics, see the day-state table in CLAUDE.md) */
.wi-state {
    font-style: normal;
    font-size: .78rem;
    font-weight: 600;
    border-radius: 999px;
    padding: .12rem .55rem;
    white-space: nowrap;
}
.wi-state--hol   { background: #f08b8b; color: #5a1414; }
.wi-state--sick  { background: #f7c9c9; color: #8c1d1d; box-shadow: inset 0 0 0 1.5px #c0392b; }
.wi-state--leave { background: #f7c9c9; color: #7a3b06; box-shadow: inset 0 0 0 1.5px #d4690e; }
.wi-state--lieu  { background: #c2ccf5; color: #22307a; }
.wi-state--off   { background: #f7c9c9; color: #7a2e2e; }
/* the [hidden] trap (see CLAUDE.md): .wi-person's display:flex beats the
   UA's [hidden] rule, so filtered rows stayed visible — force it */
.wi-person[hidden] { display: none !important; }

/* Who's in rows carry the person's photo (mmsg_avatar_html, the messenger's
   own helper — photo, else coloured initials, incl. 404 fallback) */
.wi-ava {
    flex: 0 0 30px;
    width: 30px;
    height: 30px;
    font-size: .68rem;
}
.wi-person { align-items: center; }
.wi-person__name { min-width: 0; }

/* Who's in: clickable rows (viewer holds timesheet_edit, target in the
   use_timesheet roster — same guard as the team picker) + "next in" */
.wi-row {
    display: flex;
    align-items: center;
    gap: .6rem;
    flex: 1;
    min-width: 0;
    text-decoration: none;
    color: inherit;
}
.wi-person--link { cursor: pointer; }
.wi-person--link:hover { background: #f4f8fa; }
.wi-person__go { color: #b6c6ce; font-size: 1.1rem; flex: 0 0 auto; }
.wi-next {
    display: block;
    font-size: .74rem;
    color: #7b8d96;
    margin-top: .15rem;
    white-space: nowrap;
}
.wi-person__times.wi-next { display: inline; margin: 0; margin-left: auto; }

/* ── Admin → Storage (self-test + usage) ─────────────────────────────── */
.st-card { margin-bottom: .9rem; }
.st-title { font-size: 1rem; margin: 0 0 .25rem; display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.st-bucket { font-size: .78rem; background: #eef3f6; padding: .1rem .45rem; border-radius: 5px; color: #55707d; font-weight: 400; }
.st-sub { margin: 0 0 .7rem; font-size: .85rem; color: #7b8d96; }
.st-actions { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: .75rem; }
.st-list { list-style: none; margin: .5rem 0 0; padding: 0; border-top: 1px solid #eef2f4; }
.st-row { display: grid; grid-template-columns: 1.4rem 1fr; gap: .1rem .5rem; padding: .5rem .2rem; border-bottom: 1px solid #f2f5f7; font-size: .88rem; }
.st-mark { font-weight: 700; text-align: center; }
.st-row--ok .st-mark { color: #2f7a44; }
.st-row--fail .st-mark { color: #a02020; }
.st-row--info .st-mark { color: #9bb0ba; }
.st-row--fail .st-label { color: #a02020; font-weight: 600; }
.st-detail { grid-column: 2; font-size: .78rem; color: #7b8d96; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; word-break: break-word; }
.st-stats { display: flex; gap: 1.5rem; margin: .4rem 0 .8rem; }
.st-stats strong { display: block; font-size: 1.4rem; }
.st-stats small { color: #7b8d96; font-size: .78rem; }
.st-h3 { font-size: .74rem; text-transform: uppercase; letter-spacing: .06em; color: #93a5ae; margin: .8rem 0 .3rem; }
.st-table { width: 100%; border-collapse: collapse; font-size: .84rem; }
.st-table td { padding: .3rem .2rem; border-bottom: 1px solid #f2f5f7; }
.st-key { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .78rem; word-break: break-all; }
.st-num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }

/* ── Messenger attachments (2026-09-02) ───────────────────────────────── */
.msg-composer__attach {
    flex: 0 0 auto;
    border: 0;
    background: transparent;
    color: #55707d;
    font-size: 1.25rem;
    line-height: 1;
    padding: .35rem .4rem;
    cursor: pointer;
    border-radius: 8px;
}
.msg-composer__attach:hover, .msg-composer__attach:focus-visible { background: #eef3f6; color: #005e85; }
.msg-composer__attach[disabled] { opacity: .4; cursor: default; }

.msg-attach-strip {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
    padding: .45rem .75rem 0;
}
.msg-attach-strip[hidden] { display: none !important; }   /* the [hidden] trap — flex beats the UA rule */
.msg-attach-chip {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    max-width: 100%;
    padding: .25rem .35rem .25rem .5rem;
    background: #eef3f6;
    border: 1px solid #dde5ea;
    border-radius: 999px;
    font-size: .8rem;
    color: #1c2b33;
}
.msg-attach-chip img { width: 28px; height: 28px; object-fit: cover; border-radius: 6px; }
.msg-attach-chip__name { max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg-attach-chip__x { border: 0; background: transparent; color: #7b8d96; font-size: 1rem; line-height: 1; padding: 0 .2rem; cursor: pointer; }
.msg-attach-chip--busy { opacity: .6; }
.msg-attach-chip--busy .msg-attach-chip__name::after { content: ' …'; }
.msg-attach-chip--err { background: #fbe6e6; border-color: #e8b4b4; color: #a02020; }
.msg-send-hint { font-size: .78rem; color: var(--text-muted); padding: .3rem .15rem 0; }
.msg-send-hint[hidden] { display: none !important; }

/* in the bubble */
.msg-att { display: block; text-decoration: none; color: inherit; margin: .15rem 0 .3rem; }
.msg-att--img img {
    display: block;
    max-width: min(100%, 320px);
    max-height: 320px;
    border-radius: 10px;
    background: #e8eff3;
}
.msg-att--file {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .45rem .6rem;
    background: rgba(0, 0, 0, .06);
    border-radius: 9px;
    font-size: .85rem;
}
.msg-row--me .msg-att--file { background: rgba(255, 255, 255, .18); }
.msg-att__icon { font-size: 1.25rem; line-height: 1; }
.msg-att__name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.msg-att__size { font-size: .72rem; opacity: .75; white-space: nowrap; }

/* Forward: the chooser page — tick list, search, note (2026-09-03) */
.msg-fwd__src { padding: .7rem .9rem; margin-bottom: .7rem; }
.msg-fwd__lbl { font-size: .72rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); margin-bottom: .25rem; }
.msg-fwd__body { font-size: .9rem; color: var(--text); }
.msg-fwd__list { background: #fff; border: 1px solid var(--border); border-radius: 12px; overflow: hidden; }
.msg-fwd__row {
  display: flex; align-items: center; gap: .6rem; margin: 0;
  padding: .5rem .8rem; border-top: 1px solid var(--border); cursor: pointer;
}
.msg-fwd__row:first-child { border-top: 0; }
.msg-fwd__row[hidden] { display: none !important; }        /* flex row — the usual trap */
.msg-fwd__row:has(.msg-fwd__tick:checked) { background: #eaf4f9; }
.msg-fwd__tick { width: 1.15rem; height: 1.15rem; flex: 0 0 auto; accent-color: var(--brand); }
.msg-fwd__name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; font-size: .92rem; }
.msg-fwd__note { padding: .7rem .9rem; margin-bottom: .7rem; }
.msg-fwd__note textarea {
  width: 100%; box-sizing: border-box; font: inherit; font-size: 16px;   /* 16px: no iOS zoom */
  padding: .5rem .7rem; border: 1px solid var(--border); border-radius: 12px; resize: none;
}
/* Sticky so it is reachable however long the list is (David 2026-09-03). */
.msg-fwd__bar {
  position: sticky; bottom: 0; z-index: 5;
  padding: .6rem 0 .5rem; margin-top: .6rem;
  background: var(--bg, #f1f5f7); border-top: 1px solid var(--border);
}
.msg-fwd__bar .btn { width: 100%; }
.msg-fwd__bar .btn:disabled { opacity: .5; }

/* Messages: the "you" row at the top of the Direct list (self-DM, 2026-09-02) */
.msg-person__hint { font-weight: 400; color: #6b7a86; font-size: .8rem; }

/* ── Inbox search (David 2026-09-02) ─────────────────────────────────────── */
.msg-search { margin: -.4rem 0 .7rem; }
.msg-search__q {
  width: 100%; box-sizing: border-box; font: inherit; font-size: 16px;   /* 16px: no iOS zoom */
  padding: .55rem .9rem .55rem 2.2rem; border: 1px solid var(--border); border-radius: 999px;
  background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%238a98a6' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.5-3.5'/%3E%3C/svg%3E") .8rem center no-repeat;
  color: var(--text);
}
.msg-search__q:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px rgba(0,94,133,.12); }
.msg-search__q::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.msg-item[hidden] { display: none !important; }              /* .msg-item is flex — the usual trap */
.msg-search__none-conv { margin: .1rem 0 .5rem; font-size: .82rem; color: var(--muted); }
.msg-search__hits { margin-top: .6rem; display: flex; flex-direction: column; gap: .35rem; }
.msg-search__head { font-size: .72rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); margin: .2rem 0 .1rem; }
.msg-hit {
  display: flex; flex-direction: column; gap: .15rem; text-decoration: none; color: var(--text);
  background: #fff; border: 1px solid var(--border); border-radius: 12px; padding: .5rem .75rem;
}
.msg-hit:hover, .msg-hit:focus-visible { border-color: var(--brand); outline: none; }
.msg-hit__top { display: flex; justify-content: space-between; gap: .5rem; font-size: .8rem; }
.msg-hit__thread { font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.msg-hit__when { color: var(--muted); white-space: nowrap; }
.msg-hit__snip { font-size: .86rem; color: #4a5560; line-height: 1.3; }
.msg-hit__snip b { color: var(--text); font-weight: 600; }
.msg-hit mark { background: #ffe58a; color: inherit; border-radius: 3px; padding: 0 1px; }

/* ── Attachments: thumbnails keep their shape; the image viewer (2026-09-02) ── */
.msg-att--img img { width: auto; height: auto; }   /* width/height attrs = aspect ratio placeholder */
/* A tap opens the picker (with its own 🔍 button), so attachments are not
   directly selectable or draggable — a stray long press should do nothing
   rather than highlight the tile. */
.msg-att { -webkit-user-select: none; user-select: none; }
/* Long-press a photo to reach the picker, so iOS must not put its own
   "Open in New Tab / Save Image" sheet over the top of it. */
.msg-att--img { -webkit-touch-callout: none; }

/* ── Album grid for a message carrying several photos (David 2026-09-02) ──
   One photo keeps its natural shape. Two to four tile up as squares. Past
   four, the fourth wears a "+N" badge and the rest are hidden — hidden, not
   dropped, because the image viewer pages through the whole set. */
.msg-atts { display: grid; gap: 3px; max-width: min(100%, 320px); margin: .15rem 0 .3rem; }
/* Video in a bubble (2026-09-16). The box holds the clip's shape before a
   byte loads (aspect-ratio + width set inline from the upload's size; a 16:9
   frame otherwise), so a thread of clips never jumps. Portrait clips are
   narrowed so they are at most ~420px tall. */
.msg-video { position: relative; width: 320px; max-width: 100%; aspect-ratio: 16 / 9; background: #111; border-radius: 10px; overflow: hidden; margin: .15rem 0 .2rem; }
.msg-video__player { display: block; width: 100%; height: 100%; object-fit: contain; background: #111; }
.msg-video--bad .msg-video__player { opacity: .35; }
.msg-video__note { position: absolute; left: .5rem; right: .5rem; bottom: .5rem; color: #fff; font-size: .78rem; line-height: 1.3; text-align: center; background: rgba(0, 0, 0, .65); border-radius: 6px; padding: .35rem .5rem; pointer-events: none; }
.msg-att--video { max-width: 320px; }
/* Report groups (2026-09-17). "Mark done" sits in the bubble under the words;
   super admins see the AI's decision below it, small. */
.msg-report { display: flex; flex-direction: column; align-items: flex-start; gap: .25rem; margin: .35rem 0 .1rem; }
.msg-report__tick {
  display: inline-flex; align-items: center; gap: .4rem; font: inherit; font-size: .8rem; font-weight: 600;
  color: inherit; background: rgba(0, 0, 0, .05); border: 1px solid rgba(0, 0, 0, .15); border-radius: 999px;
  padding: .2rem .7rem .2rem .35rem; cursor: pointer;
}
.msg-row--me .msg-report__tick { background: rgba(255, 255, 255, .16); border-color: rgba(255, 255, 255, .5); }
.msg-report__box { width: 16px; height: 16px; border: 2px solid currentColor; border-radius: 4px; opacity: .8; }
.msg-report__tick:hover .msg-report__box { background: currentColor; opacity: .35; }
.msg-triage { font-size: .72rem; line-height: 1.3; opacity: .8; white-space: normal; }
.msg-report-hint { font-size: .78rem; color: var(--text-muted); padding: .35rem .15rem 0; }
.msg-report-admin { font-size: .8rem; color: var(--text-muted); margin: .2rem 0 .4rem; }
.msg-report-admin__select { margin-right: .4rem; }
/* The three questions: a sheet over the thread. */
.msg-done[hidden] { display: none !important; }
.msg-done { position: fixed; inset: 0; z-index: 60; background: rgba(0, 0, 0, .45); display: flex; align-items: flex-end; justify-content: center; padding: 1rem; }
.msg-done__card { width: min(440px, 100%); background: #fff; border-radius: 16px; padding: 1rem 1rem .8rem; box-shadow: 0 10px 30px rgba(0, 0, 0, .25); max-height: 90vh; overflow: auto; }
@media (min-width: 700px) { .msg-done { align-items: center; } }
.msg-done__title { font-weight: 700; font-size: 1.05rem; margin-bottom: .4rem; }
.msg-done__q { font-weight: 600; font-size: .9rem; margin: .7rem 0 .35rem; }
.msg-done__chips { display: flex; flex-wrap: wrap; gap: .35rem; }
.msg-done__chip { font: inherit; font-size: .85rem; padding: .35rem .7rem; border-radius: 999px; border: 1px solid var(--border); background: #fff; cursor: pointer; }
.msg-done__chip.is-on { background: var(--brand); color: #fff; border-color: var(--brand); }
.msg-done__custom { display: block; margin-top: .4rem; font-size: .9rem; }
.msg-done__custom[hidden], .msg-done__cost[hidden], .msg-done__err[hidden] { display: none !important; }
.msg-done__custom input, .msg-done__cost input { width: 6.5rem; }
.msg-done__yn { display: flex; flex-wrap: wrap; gap: .4rem 1rem; align-items: center; font-size: .9rem; }
.msg-done__note { width: 100%; box-sizing: border-box; margin-top: .7rem; font: inherit; font-size: 16px; padding: .45rem .55rem; border: 1px solid var(--border); border-radius: 10px; }
.msg-done__err { color: #c62828; font-size: .85rem; margin-top: .45rem; }
.msg-done__actions { display: flex; justify-content: flex-end; gap: .5rem; margin-top: .8rem; }
.msg-done__save { background: var(--brand); color: #fff; border-color: var(--brand); }
.msg-atts--1 { display: block; }
/* A lone photo sits in a FIXED square frame (David 2026-09-03: "all photos
   only ever have a set window frame on load"). The old rule let the picture
   take its own shape, so a thread pinned to the bottom before its pictures
   arrived was pushed up as each one landed — you opened it and were reading
   the middle. Six of the fifteen photos on live carry no stored dimensions
   at all, so reserving the natural shape could never be relied on. The
   frame is the same square the album tiles use; tap → View full size. */
.msg-atts--1 .msg-att--img img {
    width: min(100%, 240px); height: auto; max-height: none;
    aspect-ratio: 1 / 1; object-fit: cover;
}
.msg-atts--2, .msg-atts--3, .msg-atts--4 { grid-template-columns: 1fr 1fr; }
.msg-atts--3 .msg-att:first-child { grid-column: 1 / -1; }
.msg-atts .msg-att { margin: 0; position: relative; }
.msg-atts .msg-att[hidden] { display: none !important; }   /* .msg-att is display:block — the usual trap */
.msg-atts:not(.msg-atts--1) .msg-att--img img {
    width: 100%; height: 100%; max-width: none; max-height: none;
    aspect-ratio: 1 / 1; object-fit: cover; border-radius: 8px;
}
.msg-atts--3 .msg-att:first-child img { aspect-ratio: 2 / 1; }
.msg-att[data-more]::after {
    content: attr(data-more);
    position: absolute; inset: 0; border-radius: 8px;
    background: rgba(12, 18, 24, .55);
    display: flex; align-items: center; justify-content: center;
    color: #fff; font-size: 1.7rem; font-weight: 700; letter-spacing: -.02em;
}
.msg-lb { position: fixed; inset: 0; z-index: 500; background: rgba(10, 14, 18, .94); display: flex; flex-direction: column; color: #fff; }
.msg-lb[hidden] { display: none !important; }
body.msg-lb-open { overflow: hidden; }
.msg-lb__bar { display: flex; align-items: center; justify-content: space-between; gap: .75rem; padding: .6rem .9rem; padding-top: max(.6rem, env(safe-area-inset-top)); background: rgba(0, 0, 0, .35); }
.msg-lb__title { min-width: 0; display: flex; flex-direction: column; }
.msg-lb__name { font-weight: 700; font-size: .95rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.msg-lb__meta { font-size: .75rem; opacity: .7; }
.msg-lb__acts { display: flex; gap: .4rem; flex-shrink: 0; }
.msg-lb__btn {
  display: inline-flex; align-items: center; gap: .35rem; padding: .45rem .8rem; border-radius: 999px;
  background: rgba(255, 255, 255, .14); color: #fff; text-decoration: none; font: inherit; font-size: .85rem; font-weight: 600;
  border: 0; cursor: pointer; min-height: 40px;
}
.msg-lb__btn:hover, .msg-lb__btn:focus-visible { background: rgba(255, 255, 255, .26); outline: none; }
.msg-lb__btn--dl { background: var(--brand); }
.msg-lb__btn--dl:hover { background: #0b7bb0; }
.msg-lb__btn--x { padding: .45rem .7rem; font-size: 1rem; }
.msg-lb__stage { flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; position: relative; padding: .5rem; }
.msg-lb__img { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 4px; box-shadow: 0 10px 40px rgba(0, 0, 0, .5); }
.msg-lb__spin { position: absolute; right: 14px; bottom: 14px; width: 18px; height: 18px; border: 2px solid rgba(255,255,255,.35); border-top-color: #fff; border-radius: 50%; animation: msglb-spin .8s linear infinite; }
.msg-lb__spin[hidden] { display: none; }
@keyframes msglb-spin { to { transform: rotate(360deg); } }
.msg-lb__nav {
  position: absolute; top: 50%; transform: translateY(-50%); width: 46px; height: 64px; border: 0; border-radius: 10px;
  background: rgba(255, 255, 255, .12); color: #fff; font-size: 2rem; line-height: 1; cursor: pointer;
}
.msg-lb__nav[hidden] { display: none; }
.msg-lb__nav:hover { background: rgba(255, 255, 255, .24); }
.msg-lb__nav--prev { left: 10px; }
.msg-lb__nav--next { right: 10px; }
@media (max-width: 600px) {
  .msg-lb__btn span + * { }                       /* labels stay — the buttons are the point */
  .msg-lb__nav { display: none; }                 /* swipe instead; arrows crowd a phone */
}
@media (prefers-reduced-motion: reduce) { .msg-lb__spin { animation: none; } }

/* Who's in: the person's initials after the name (2026-09-02) */
.wi-abbr { font-style: normal; font-size: .7rem; font-weight: 700; letter-spacing: .03em; color: #5f6f7b;
           background: #edf2f5; border-radius: 5px; padding: .05rem .3rem; margin-left: .35rem; vertical-align: 1px; }
.wi-person--link:hover .wi-abbr { background: #dfe8ee; }

/* ── Phone frame shell (pilot, 2026-09-02) — frame.php ─────────────────────
   The app's own header stays (messages icon + ☰ in view — David); under it a
   THIN strip in the tile's colour, then the frame fills what is left. The
   page, not the frame, owns the viewport: body is pinned to 100dvh and the
   frame gets a fixed box (iOS iframes grow to their content otherwise). */
body.mf-page { height: 100vh; height: 100dvh; min-height: 0; overflow: hidden; display: flex; flex-direction: column; }
.mf-main { flex: 1 1 0%; min-height: 0; max-width: none; padding: 0; display: flex; flex-direction: column; }
.mf-bar {
  flex: 0 0 auto; display: flex; align-items: center; gap: .2rem; color: #fff;
  padding: .15rem .4rem; min-height: 38px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .2); position: relative; z-index: 2;
}
.mf-btn {
  display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 30px;
  border: 0; border-radius: 8px; background: rgba(255, 255, 255, .14); color: #fff; font: inherit;
  font-size: 1.2rem; line-height: 1; cursor: pointer; list-style: none; -webkit-tap-highlight-color: transparent;
}
.mf-btn::-webkit-details-marker { display: none; }
.mf-btn:active { background: rgba(255, 255, 255, .3); }
.mf-back { font-size: 1.6rem; padding-bottom: 3px; }
.mf-title { flex: 1; min-width: 0; font-weight: 700; font-size: .95rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mf-more { position: relative; }
.mf-menu {
  position: absolute; right: 0; top: 34px; min-width: 190px; background: #fff; color: var(--text, #1c2b33);
  border-radius: 12px; box-shadow: 0 8px 28px rgba(0, 0, 0, .25); padding: .3rem; z-index: 5;
}
.mf-menu a { display: block; padding: .6rem .8rem; border-radius: 8px; text-decoration: none; color: inherit; font-size: .95rem; }
.mf-menu a:active { background: #eef2f5; }
/* The stage is pinned to the REAL bottom of the screen rather than sized from
   the page: in the installed iPhone app the body carries safe-area padding top
   and bottom, and a flex-derived height left a blank band under the frame
   (David 2026-09-02). Its top is measured from the strip by frame.php's script. */
.mf-stage { position: fixed; left: 0; right: 0; bottom: 0; top: 98px; z-index: 1; }
.mf-frame { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; background: #fff; }
.mf-loading { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: #fff; }
.mf-loading[hidden] { display: none; }
.mf-loading span { width: 30px; height: 30px; border: 3px solid #dfe6ea; border-top-color: #005e85; border-radius: 50%; animation: mf-spin .8s linear infinite; }
@keyframes mf-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .mf-loading span { animation: none; } }

/* ── Admin → Calendar feeds (2026-09-02) ─────────────────────────────────── */
.cal-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: .5rem; margin-bottom: .9rem; }
.cal-kpi { background: #fff; border: 1px solid var(--border); border-radius: 10px; padding: .55rem .7rem; display: flex; flex-direction: column; }
.cal-kpi strong { font-size: 1.35rem; font-variant-numeric: tabular-nums; }
.cal-kpi small { font-size: .7rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: .02em; }
.cal-kpi--warn { box-shadow: inset 0 0 0 2px #d98a3d; }
.cal-card { padding: .3rem .6rem; overflow-x: auto; }
.cal-table { width: 100%; border-collapse: collapse; font-size: .85rem; }
.cal-table th { text-align: left; font-size: .7rem; text-transform: uppercase; letter-spacing: .03em; color: var(--text-muted); padding: .45rem .3rem; border-bottom: 1px solid var(--border); }
.cal-table td { padding: .45rem .3rem; border-bottom: 1px solid #f2f5f7; vertical-align: top; }
.cal-who { display: flex; align-items: center; gap: .5rem; min-width: 180px; }
.cal-who .msg-ava { flex: 0 0 30px; width: 30px; height: 30px; font-size: .7rem; }
.cal-yes { color: #2f7a44; font-weight: 600; white-space: nowrap; }
.cal-no { color: #b8c4cc; }
.cal-sub { display: block; font-size: .72rem; color: var(--text-muted); line-height: 1.35; }
.cal-bad { color: #a02020; font-weight: 600; }
.cal-gone { font-style: normal; font-size: .7rem; color: #a02020; margin-left: .3rem; }
.cal-row--gone { opacity: .6; }
.cal-act { text-align: right; white-space: nowrap; }
.cal-act form { display: inline; }

/* Framed app, phone turned sideways (2026-09-02): height is the scarce thing,
   so the app header goes and only the thin strip stays (back · name · ⋯ with
   Close). Portrait keeps the header — David wanted the messages icon and ☰
   in view there. */
@media (orientation: landscape) and (max-height: 520px) {
  body.mf-page .app-header { display: none; }
  body.mf-page { padding-top: 0; }
  body.mf-page::before { display: none; }
  body.mf-page .mf-bar { min-height: 32px; padding-top: .05rem; padding-bottom: .05rem; }
  body.mf-page .mf-btn { height: 26px; width: 30px; font-size: 1.05rem; }
  body.mf-page .mf-back { font-size: 1.4rem; padding-bottom: 2px; }
  body.mf-page .mf-title { font-size: .88rem; }
}

/* ── App deep-link "opening…" page (go.php, 2026-09-03) ─────────────────── */
.deeplink-page { display: flex; align-items: center; justify-content: center; min-height: 100vh; min-height: 100dvh; margin: 0; background: var(--bg, #f2f5f7); }
.dl-wrap { text-align: center; padding: 1.5rem; max-width: 22rem; }
.dl-open { font-size: 1.05rem; margin: 0 0 1rem; color: var(--text, #1c2b33); }
.dl-hint { font-size: .85rem; color: var(--text-muted, #5f6f7b); line-height: 1.45; margin: 1rem 0 0; }
.dl-hint[hidden] { display: none; }
.dl-back { font-size: .85rem; color: var(--brand, #005e85); text-decoration: none; display: inline-block; margin-top: 1.25rem; }

/* ── Customer feedback cheers (2026-09-03) ──────────────────────────────── */
.cf-give { padding: 0; margin-bottom: .8rem; }
.cf-give__head { display: flex; gap: .6rem; align-items: center; padding: .85rem 1rem; cursor: pointer; list-style: none; }
.cf-give__head::-webkit-details-marker { display: none; }
.cf-give__star { font-size: 1.35rem; line-height: 1; }
.cf-give__head small { display: block; font-size: .78rem; color: var(--text-muted, #5f6f7b); margin-top: .1rem; }
.cf-form { padding: 0 1rem 1rem; }
.cf-ref-row { display: flex; gap: .5rem; align-items: center; }
.cf-ref { flex: 1; min-width: 0; font-size: 16px; padding: .55rem .7rem; border: 1px solid var(--border); border-radius: var(--radius-sm, 8px); text-transform: uppercase; }
.cf-msg { font-size: .84rem; color: var(--text-muted, #5f6f7b); margin: .5rem 0 0; }
.cf-msg--bad { color: #a02020; }
.cf-msg[hidden] { display: none; }
.cf-booking { background: #eef5f9; border-radius: 10px; padding: .6rem .75rem; margin: .75rem 0; display: flex; flex-direction: column; gap: .1rem; }
.cf-booking small { color: var(--text-muted, #5f6f7b); font-size: .78rem; }
.cf-dates { margin: .75rem 0 .35rem; font-size: .85rem; }
.cf-dates small { color: var(--text-muted, #5f6f7b); font-weight: 400; }
.cf-dates__row { display: flex; gap: .75rem; margin-top: .35rem; flex-wrap: wrap; }
.cf-dates__row label { font-size: .8rem; color: var(--text-muted, #5f6f7b); display: flex; align-items: center; gap: .35rem; }
.cf-dates__row input { font-size: 16px; padding: .35rem .5rem; border: 1px solid var(--border); border-radius: 8px; }
.cf-team__head { display: flex; align-items: center; gap: .5rem; margin: .9rem 0 .35rem; flex-wrap: wrap; }
.cf-count { font-size: .8rem; color: var(--text-muted, #5f6f7b); flex: 1; }
.cf-all { border: 0; background: transparent; color: var(--brand, #005e85); font: inherit; font-size: .8rem; font-weight: 600; cursor: pointer; padding: .2rem .3rem; }
.cf-team { max-height: 17rem; overflow-y: auto; border: 1px solid var(--border); border-radius: 10px; }
.cf-team:empty { display: none; }
.cf-person { display: flex; gap: .6rem; align-items: flex-start; padding: .5rem .7rem; border-bottom: 1px solid #f2f5f7; cursor: pointer; }
.cf-person:last-child { border-bottom: 0; }
.cf-person input { margin-top: .15rem; width: 1.05rem; height: 1.05rem; flex: 0 0 auto; }
.cf-person__name { display: block; font-size: .9rem; font-weight: 600; }
.cf-person__sub { display: block; font-size: .74rem; color: var(--text-muted, #5f6f7b); }
.cf-person--added { background: #f6fbf6; }
.cf-hint { font-size: .78rem; color: var(--text-muted, #5f6f7b); margin: .25rem 0 .5rem; line-height: 1.4; }
.cf-note { display: flex; gap: .6rem; align-items: flex-start; margin: .9rem 0 .2rem; font-size: .88rem; cursor: pointer; }
.cf-note input { margin-top: .15rem; width: 1.05rem; height: 1.05rem; flex: 0 0 auto; }
.cf-note small { display: block; font-size: .76rem; color: var(--text-muted, #5f6f7b); margin-top: .1rem; }

/* ── Admin hub: grouped tools (2026-09-08) ────────────────────── */
.admin-section { margin-bottom: 1.4rem; }
.admin-section__head { display: flex; align-items: baseline; gap: .6rem; margin: 0 0 .55rem; flex-wrap: wrap; }
.admin-section__head h2 {
  margin: 0; font-size: .74rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-muted);
}
.admin-section__head small { color: var(--text-muted); font-size: .78rem; }
.admin-grid { display: grid; grid-template-columns: 1fr; gap: .6rem; }
.admin-grid .admin-tool { margin-bottom: 0; }
@media (min-width: 640px) { .admin-grid { grid-template-columns: 1fr 1fr; } }

/* ── Admin → On the app: the roll-out roster ──────────────────── */
/* On contract / Everyone (2026-09-18): a two-way switch above the counts. */
.oa-who-toggle { display: inline-flex; margin: 0 0 .7rem; border: 1px solid var(--border); border-radius: 999px; background: var(--card-bg); padding: 2px; }
.oa-who-toggle a { padding: .35rem .85rem; border-radius: 999px; font-size: .82rem; color: var(--text-muted); text-decoration: none; }
.oa-who-toggle a:hover { color: var(--text); text-decoration: none; }
.oa-who-toggle a.is-on { background: #6344a8; color: #fff; }
.oa-who-toggle small { opacity: .8; margin-left: .2rem; font-variant-numeric: tabular-nums; }
.oa-ct { display: inline-block; margin-left: .3rem; padding: .02rem .4rem; border-radius: 999px; font-size: .68rem; font-weight: 600; background: #eef0f6; color: #55607a; vertical-align: middle; }
.oa-ct--none { background: #fdecec; color: #9b2c2c; }
/* Grouped by default role, each group folds (2026-09-18). The heading is the
   toggle and carries what is left to do, so a folded group still says so. */
.oa-fold-all { display: flex; justify-content: flex-end; gap: .75rem; margin: -.35rem 0 .6rem; }
.oa-fold-all button { border: 0; background: none; padding: .2rem 0; font: inherit; font-size: .8rem; color: #6344a8; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }
.oa-group { margin-bottom: .9rem; }
.oa-group[hidden] { display: none; }
.oa-group__h { margin: 0 0 .45rem; font-size: inherit; font-weight: inherit; }
.oa-group__head { display: flex; flex-wrap: wrap; align-items: center; gap: .45rem .55rem; width: 100%; padding: .55rem .7rem; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg); font: inherit; color: var(--text); text-align: left; cursor: pointer; }
.oa-group__head:hover { border-color: #b9a8dc; }
.oa-group__head:focus-visible { outline: 2px solid #6344a8; outline-offset: 2px; }
.oa-group__chev { display: inline-block; width: .8rem; font-size: 1.1rem; line-height: 1; color: var(--text-muted); transform: rotate(90deg); transition: transform .15s; }
.oa-group.is-folded .oa-group__chev { transform: none; }
.oa-group__dot { width: .8rem; height: .8rem; border-radius: 50%; flex: none; }
.oa-group__name { font-weight: 700; font-size: .95rem; }
.oa-group__n { font-size: .78rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.oa-group__todo { display: flex; flex-wrap: wrap; gap: .3rem; margin-left: auto; }
.oa-group--done .oa-group__head { background: var(--card-bg); }
.oa-group__body[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) { .oa-group__chev { transition: none; } }
.oa-stats { display: flex; flex-wrap: wrap; gap: .45rem; margin: 0 0 1rem; }
.oa-stat {
  display: flex; flex-direction: column; min-width: 5.6rem; padding: .45rem .65rem;
  background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--radius-sm);
  text-decoration: none; color: var(--text);
}
.oa-stat:hover { text-decoration: none; background: var(--bg); }
.oa-stat--active { border-color: #6344a8; box-shadow: inset 0 0 0 1px #6344a8; }
.oa-stat strong { font-size: 1.2rem; line-height: 1.1; font-variant-numeric: tabular-nums; }
.oa-stat small { font-size: .72rem; color: var(--text-muted); }
.oa-tools { display: flex; gap: .5rem; align-items: center; margin-bottom: .75rem; }
.oa-tools input { flex: 1; min-width: 0; padding: .5rem .65rem; border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: .9rem; }
.oa-list { display: flex; flex-direction: column; gap: .45rem; }
.oa-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .35rem .75rem; align-items: center;
  background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: .55rem .7rem;
}
.oa-row--never { border-left: 4px solid #d9822b; }
.oa-row--ready { border-left: 4px solid #2f9e44; }
.oa-who { min-width: 0; }
.oa-who strong { font-size: .92rem; margin-right: .3rem; }
.oa-who small { display: block; color: var(--text-muted); font-size: .74rem; margin-top: .1rem; }
.oa-pills { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: .3rem; }
.oa-pill {
  display: inline-flex; align-items: center; gap: .25rem; font-size: .72rem; line-height: 1;
  padding: .28rem .5rem; border-radius: 999px; border: 1px solid var(--border);
  color: var(--text-muted); background: var(--bg); white-space: nowrap;
}
.oa-pill--on { color: #1f6f36; background: #e6f4ea; border-color: #b7dfc3; }
.oa-pill--warn { color: #8a4b08; background: #fdf1e3; border-color: #f2cfa1; }
.oa-tick { margin: 0; }
.oa-tick button {
  font-size: .74rem; padding: .32rem .6rem; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--border); background: var(--card-bg); color: var(--text-muted); white-space: nowrap;
}
.oa-tick button.is-on { color: #1f6f36; background: #e6f4ea; border-color: #b7dfc3; }
.oa-tick small { display: block; text-align: right; color: var(--text-muted); font-size: .68rem; margin-top: .2rem; }
@media (min-width: 720px) {
  .oa-row { grid-template-columns: minmax(12rem, 1fr) 2fr auto; }
  .oa-pills { grid-column: auto; }
}

/* ── Icons (includes/icons.php): the admin hub tool icons (2026-09-09) ── */
.admin-tool__icon { display: flex; align-items: center; color: #6344a8; }
.admin-tool__icon svg { width: 22px; height: 22px; display: block; }

/* Arriving at Home with #dk-tab-… (rail tab clicked from another page, or a
   reload): the head script stamps html.dk-tab-in before first paint so the
   Home columns never flash before desktop.js shows the frame (David
   2026-09-09 "briefly loads the home page first"). Same width as .dk-wide
   so nothing jumps when the frame appears. desktop.js removes the class. */
html.desktop.dk-tab-in .dk-home { display: none !important; }
html.desktop.dk-tab-in .app-main:has(.dk-home) { max-width: none; padding-left: 20px; padding-right: 20px; }

/* ── Today's weather on Home (includes/weather.php, 2026-09-12) ──────
   Sits under the greeting on a phone and at the top of the desktop side
   column, where the scenic band is hidden. */
.wx { display: flex; align-items: center; gap: .6rem; margin: 0 0 .85rem; }
.wx__icon { display: flex; color: var(--brand); flex: 0 0 auto; }
.wx__body { min-width: 0; }
.wx__body strong { display: block; font-size: 1rem; font-weight: 700; }
.wx__words { font-weight: 400; color: var(--text-muted); }
.wx__body small { display: block; font-size: .76rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }

/* ── In charge (timesheet/in-charge.php) ────────────────────────────────────
   An instructor's IIC jobs for the next 30 days, grouped by booking. Same
   white-card language as the day view's session cards. */
.ts-whosin--ic { color: #7a4a00; border-color: #e8d9c2; }
.ts-whosin--ic:active { background: #fdf6ec; }

.ic-head { margin: 0 0 .5rem; }
.ic-head__title { margin: 0; font-size: 1.35rem; font-weight: 700; }
.ic-head__sub {
  margin: .15rem 0 0;
  font-size: .85rem;
  color: var(--text-muted);
}
.ic-head__dates { display: block; font-variant-numeric: tabular-nums; }

.ic-summary { margin: 0 0 .85rem; font-size: .9rem; color: #55707d; }

.ic-job {
  background: #fff;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: .9rem 1rem 1rem;
  margin: 0 0 .85rem;
}
.ic-job__head { border-bottom: 1px solid #eef2f5; padding-bottom: .6rem; }
.ic-job__org { margin: 0; font-size: 1.05rem; font-weight: 700; line-height: 1.25; }
.ic-job__when {
  margin-top: .15rem;
  font-size: .9rem;
  font-weight: 600;
  color: #005e85;
  font-variant-numeric: tabular-nums;
}
.ic-job__days { font-weight: 400; color: var(--text-muted); margin-left: .4rem; }
/* Said only when the visit is wider than the part they are in charge of. */
.ic-job__span { margin-top: .3rem; font-size: .8rem; color: #7b8d96; }
.ic-job__ref { margin-top: .5rem; }
.ic-job__booking {
  display: inline-block;
  font-size: .82rem;
  font-weight: 700;
  color: #005e85;
  text-decoration: none;
  background: #eef6fa;
  border-radius: 6px;
  padding: .3rem .55rem;
  font-variant-numeric: tabular-nums;
}

.ic-day { padding-top: .7rem; }
.ic-day + .ic-day { border-top: 1px dashed #eef2f5; margin-top: .3rem; }
.ic-day__head { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.ic-day__date {
  font-size: .88rem;
  font-weight: 700;
  color: var(--text);
  text-decoration: none;
  font-variant-numeric: tabular-nums;
}
.ic-chip { font-size: .7rem; font-weight: 700; border-radius: 20px; padding: .12rem .45rem; }
.ic-chip--prov { background: #fff3cd; color: #7a5a00; }

.ic-day__notes {
  white-space: pre-line;   /* same line-break fix as .ts-session__notes */
  margin: .4rem 0 0;
  font-size: .82rem;
  font-style: italic;
  color: #55707d;
  background: var(--brand-light);
  border-radius: 6px;
  padding: .4rem .55rem;
}

.ic-sess {
  padding: .45rem 0 .1rem .6rem;
  border-left: 3px solid #e7edf1;
  margin-top: .4rem;
}
/* Their own sessions stand out from the ones they only answer for. */
.ic-sess--mine { border-left-color: #2560c4; }
.ic-sess--none { border-left-color: transparent; color: var(--text-muted); font-size: .84rem; }
.ic-sess__times {
  font-size: .82rem;
  font-weight: 600;
  color: #55707d;
  font-variant-numeric: tabular-nums;
}
.ic-sess__name {
  display: flex;
  align-items: center;
  gap: .35rem;
  flex-wrap: wrap;
  font-size: .95rem;
  font-weight: 600;
  line-height: 1.3;
}
.ic-sess__meta { font-size: .78rem; color: var(--text-muted); margin-top: .1rem; }
.ic-sess__sep { margin: 0 .3rem; opacity: .6; }
.ic-badge {
  font-size: .66rem;
  font-weight: 700;
  border-radius: 4px;
  padding: .1rem .3rem;
  letter-spacing: .02em;
}
.ic-badge--iic  { background: #1d7a3d; color: #fff; }
.ic-badge--mine { background: #e7edf1; color: #40525c; }

.ic-empty {
  background: #fff;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.1rem 1rem;
}
.ic-empty__lead { margin: 0; font-weight: 600; }
.ic-empty__note { margin: .5rem 0 0; font-size: .85rem; color: var(--text-muted); }

.ic-foot { margin: .25rem 0 0; font-size: .78rem; color: var(--text-muted); }
.ic-back { margin: 1rem 0 0; text-align: center; }
.ic-back a { font-size: .88rem; color: #005e85; }

/* ── Worked-hours reminders ─────────────────────────────────────────────────
   The Home card (.wr-nag) and Admin → Worked-hours reminders (.wr-*).
   Engine + reasoning: includes/worked_reminders.php. */
.wr-nag {
  display: flex;
  align-items: center;
  gap: .7rem;
  background: #fff8e6;
  border: 1px solid #f0dcae;
  border-left: 4px solid #e8a90c;
  border-radius: var(--radius);
  padding: .7rem .85rem;
  margin: 0 0 .85rem;
  text-decoration: none;
  color: var(--text);
}
.wr-nag:active { background: #fdf0d2; }
.wr-nag__ico { color: #9a6c00; display: flex; flex-shrink: 0; }
.wr-nag__text { display: flex; flex-direction: column; min-width: 0; }
.wr-nag__title { font-weight: 700; font-size: .95rem; }
.wr-nag__sub { font-size: .8rem; color: #7a5c1c; }
.wr-nag__go { margin-left: auto; color: #c2a15e; font-size: 1.2rem; }

.wr-lede { margin: 0 0 1rem; font-size: .9rem; color: var(--text-muted); }
.wr-h2 { margin: 1.5rem 0 .25rem; font-size: 1rem; }
.wr-note { margin: 0 0 .75rem; font-size: .82rem; color: var(--text-muted); }
.wr-empty { margin: 0 0 .75rem; font-size: .88rem; color: var(--text-muted); font-style: italic; }

.wr-teams { display: flex; flex-direction: column; gap: .4rem; }
.wr-actions { margin: .9rem 0 0; }

.wr-preview { list-style: none; margin: 0 0 .75rem; padding: 0; display: flex; flex-direction: column; gap: .2rem; }
.wr-preview li { display: flex; gap: .6rem; flex-wrap: wrap; font-size: .85rem; }
.wr-preview__name { font-weight: 600; }
.wr-preview__when { color: var(--text-muted); font-variant-numeric: tabular-nums; }

.wr-foot { margin: 1rem 0 0; font-size: .78rem; color: var(--text-muted); }

/* Reminder groups list (admin/worked-reminders.php). The group EDITOR reuses
   the dashboard-button picker's classes (.grp-chip / .staff-selector), so
   there is deliberately nothing here for it. */
.wr-groups { display: flex; flex-direction: column; gap: .4rem; }
.wr-group {
  display: flex;
  align-items: center;
  gap: .75rem;
  background: #fff;
  border: 1px solid #e7edf1;
  border-radius: 10px;
  padding: .6rem .75rem;
}
.wr-group--off { opacity: .6; }
.wr-group__main { flex: 1; min-width: 0; }
.wr-group__name { font-weight: 700; color: var(--text); text-decoration: none; }
.wr-group__meta { font-size: .8rem; color: var(--text-muted); margin-top: .1rem; }
.wr-group__edit { font-size: .85rem; color: #005e85; text-decoration: none; flex-shrink: 0; }
.wr-delayrow { display: flex; align-items: center; gap: .4rem; }
.wr-delayrow input { width: 5.5rem; font-size: 16px; padding: .35rem .45rem; }
.wr-delete { margin-top: 1.5rem; }
.wr-delete__btn {
  background: none;
  border: none;
  color: #a33;
  font-size: .85rem;
  cursor: pointer;
  padding: .3rem 0;
}

/* ── Feedback form (feedback.php) ─────────────────────────────────────────
   Redesigned 2026-09-17, David: "can you make this widget much more friendly
   and cool please". Brand blue hero that greets them, four colour-coded kind
   tiles, a segmented "how much is it in the way", a writing box that grows,
   a screenshot drop zone with real previews, and a thank-you with a tick that
   draws itself. Kind colours are semantic and used ONLY here: coral = wrong,
   amber = missing, violet = idea, green = good. Motion respects
   prefers-reduced-motion. */
.fbx { max-width: 44rem; margin-inline: auto; }
.fbx-form { display: grid; gap: 1rem; margin-bottom: 2rem; }

/* Hero */
.fbx-hero {
  position: relative; overflow: hidden;
  padding: 1.4rem 1.3rem 1.2rem;
  border-radius: 20px;
  color: #fff;
  background:
    radial-gradient(120% 90% at 100% 0%, rgba(0, 168, 224, .55) 0%, rgba(0, 168, 224, 0) 60%),
    linear-gradient(140deg, #004669 0%, var(--brand) 55%, #0b78a6 100%);
  box-shadow: 0 10px 30px rgba(0, 70, 105, .18);
}
.fbx-hero--quiet { margin-bottom: 1rem; }
.fbx-hero__art {
  position: absolute; right: -6px; top: 10px; width: 132px; height: auto;
  fill: rgba(255, 255, 255, .10); stroke: rgba(255, 255, 255, .22); stroke-width: 2;
  stroke-linejoin: round; pointer-events: none;
}
.fbx-hero__art circle { fill: rgba(255, 255, 255, .45); stroke: none; }
.fbx-hero__hi { margin: 0 0 .15rem; font-size: .95rem; font-weight: 600; opacity: .9; }
.fbx-hero__title { margin: 0 0 .4rem; font-size: 1.6rem; line-height: 1.15; font-weight: 800; letter-spacing: -.01em; max-width: 22ch; text-wrap: balance; }
.fbx-hero__lede { margin: 0; max-width: 34rem; font-size: .95rem; line-height: 1.45; color: rgba(255, 255, 255, .88); text-wrap: pretty; }

/* "About Diary · diary.mendipsys.co.uk" */
.fbx-about { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin-top: 1rem; }
.fbx-about__chip {
  display: inline-flex; align-items: center; gap: .45rem; min-width: 0; max-width: 100%;
  padding: .4rem .75rem .4rem .55rem; border-radius: 999px;
  background: rgba(255, 255, 255, .16); border: 1px solid rgba(255, 255, 255, .28);
  font-size: .88rem; backdrop-filter: blur(4px);
}
.fbx-about__chip svg { flex: none; }
.fbx-about__chip > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fbx-about__where { margin-left: .4rem; opacity: .72; font-size: .8rem; }
.fbx-about__change {
  border: 0; background: none; color: #fff; font: inherit; font-size: .85rem; font-weight: 600;
  text-decoration: underline; text-underline-offset: 3px; cursor: pointer; padding: .3rem .2rem; opacity: .9;
}
.fbx-about__change:hover { opacity: 1; }
.fbx-about__pick { display: grid; gap: .3rem; width: 100%; }
.fbx-about__pick label { font-size: .85rem; font-weight: 600; }
.fbx-about__pick select {
  width: 100%; max-width: 22rem; min-height: 44px; padding: .5rem .75rem;
  border: 0; border-radius: 12px; font-size: 1rem; color: var(--text); background: #fff;
}
.fbx-about__pick[hidden], .fbx-about__chip[hidden], .fbx-about__change[hidden] { display: none; }

/* Steps */
.fbx-step {
  background: var(--card-bg); border-radius: 18px; padding: 1.1rem 1.1rem 1.15rem;
  box-shadow: 0 1px 2px rgba(16, 40, 60, .06), 0 4px 16px rgba(16, 40, 60, .05);
}
.fbx-step[hidden] { display: none; }
.fbx-step__h { display: flex; align-items: center; gap: .55rem; margin: 0 0 .85rem; font-size: 1.02rem; font-weight: 700; color: var(--text); }
.fbx-step__h label { display: flex; align-items: center; gap: .55rem; cursor: text; }
.fbx-step__h em { font-style: normal; font-weight: 500; color: var(--text-muted); font-size: .88rem; }
.fbx-step__n {
  display: inline-grid; place-items: center; flex: none; width: 1.6rem; height: 1.6rem; border-radius: 50%;
  background: var(--brand-light); color: var(--brand); font-size: .82rem; font-weight: 800;
}
.fbx-step__n--sub { background: transparent; color: var(--text-muted); font-size: 1.1rem; }

/* Kind tiles */
.fbx-tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .65rem; }
.fbx-tile {
  --c: var(--brand); --tint: var(--brand-light);
  position: relative; display: flex; align-items: flex-start; gap: .7rem; min-height: 5.2rem;
  padding: .85rem .8rem; border-radius: 14px; border: 2px solid var(--border); background: #fff;
  cursor: pointer; user-select: none;
  transition: border-color .15s ease, background-color .15s ease, transform .15s ease, box-shadow .15s ease;
}
.fbx-tile--wrong   { --c: #d9383e; --tint: #fdeced; }
.fbx-tile--missing { --c: #c46a00; --tint: #fff3e0; }
.fbx-tile--idea    { --c: #6d4fe8; --tint: #f0ecff; }
.fbx-tile--good    { --c: #178a4c; --tint: #e4f5ea; }
.fbx-tile input { position: absolute; opacity: 0; pointer-events: none; }
.fbx-tile__icon {
  display: grid; place-items: center; flex: none; width: 2.6rem; height: 2.6rem; border-radius: 12px;
  background: var(--tint); color: var(--c); transition: background-color .15s ease, color .15s ease, transform .2s ease;
}
.fbx-tile__text { display: grid; gap: .15rem; min-width: 0; padding-right: .9rem; }
.fbx-tile__text strong { font-size: .95rem; line-height: 1.2; color: var(--text); }
.fbx-tile__text small { font-size: .78rem; line-height: 1.3; color: var(--text-muted); }
.fbx-tile__tick {
  position: absolute; top: .5rem; right: .5rem; display: grid; place-items: center;
  width: 1.3rem; height: 1.3rem; border-radius: 50%; background: var(--c); color: #fff;
  transform: scale(0); transition: transform .2s cubic-bezier(.2, 1.4, .4, 1);
}
.fbx-tile:hover { border-color: color-mix(in srgb, var(--c) 45%, var(--border)); transform: translateY(-1px); box-shadow: 0 4px 14px rgba(16, 40, 60, .07); }
.fbx-tile:has(input:checked) { border-color: var(--c); background: var(--tint); box-shadow: 0 6px 18px color-mix(in srgb, var(--c) 18%, transparent); }
.fbx-tile:has(input:checked) .fbx-tile__icon { background: var(--c); color: #fff; transform: rotate(-6deg) scale(1.05); }
.fbx-tile:has(input:checked) .fbx-tile__tick { transform: scale(1); }
.fbx-tile:has(input:focus-visible) { outline: 3px solid color-mix(in srgb, var(--c) 45%, transparent); outline-offset: 2px; }

/* Impact: a segmented choice */
.fbx-in { animation: fbx-rise .28s ease both; }
.fbx-seg { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .45rem; }
.fbx-seg__opt { position: relative; cursor: pointer; }
.fbx-seg__opt input { position: absolute; opacity: 0; pointer-events: none; }
.fbx-seg__opt span {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .35rem; min-height: 4.3rem;
  padding: .6rem .4rem; border-radius: 12px; border: 2px solid var(--border); background: #fff;
  font-size: .82rem; font-weight: 600; text-align: center; line-height: 1.2; color: var(--text);
  transition: border-color .15s ease, background-color .15s ease, color .15s ease;
}
.fbx-seg__opt--stops { --c: #d9383e; --tint: #fdeced; }
.fbx-seg__opt--slows { --c: #c46a00; --tint: #fff3e0; }
.fbx-seg__opt--minor { --c: #178a4c; --tint: #e4f5ea; }
.fbx-seg__opt span svg { color: var(--c); }
.fbx-seg__opt:hover span { border-color: color-mix(in srgb, var(--c) 45%, var(--border)); }
.fbx-seg__opt input:checked + span { border-color: var(--c); background: var(--tint); color: var(--c); }
.fbx-seg__opt input:focus-visible + span { outline: 3px solid color-mix(in srgb, var(--c) 45%, transparent); outline-offset: 2px; }

/* Writing */
.fbx-write { position: relative; }
.fbx-write textarea {
  display: block; width: 100%; min-height: 8.5rem; max-height: 32.5rem; resize: vertical;
  padding: .85rem .95rem 1.6rem; border: 2px solid var(--border); border-radius: 14px;
  font: inherit; font-size: 1rem; line-height: 1.5; color: var(--text); background: #fbfcfd;
  transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease;
}
.fbx-write textarea::placeholder { color: #8a93a0; }
.fbx-write textarea:focus { outline: none; border-color: var(--brand); background: #fff; box-shadow: 0 0 0 4px rgba(0, 94, 133, .12); }
.fbx-write__count { position: absolute; right: .8rem; bottom: .5rem; font-size: .75rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }

/* Friendly nudges (what's missing, said next to it) */
.fbx-nudge { margin: .65rem 0 0; padding: .5rem .7rem; border-radius: 10px; background: #fff4e0; color: #7a4a00; font-size: .85rem; }
.fbx-nudge--soft { background: var(--brand-light); color: var(--brand-dark); }
.fbx-nudge[hidden] { display: none; }
.fbx-shake { animation: fbx-shake .4s ease; }

/* Screenshot drop zone */
.fbx-drop {
  display: flex; align-items: center; gap: .85rem; padding: 1rem;
  border: 2px dashed #c3ccd6; border-radius: 14px; background: #fbfcfd; cursor: pointer;
  transition: border-color .15s ease, background-color .15s ease;
}
.fbx-drop input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.fbx-drop__icon { display: grid; place-items: center; flex: none; width: 3rem; height: 3rem; border-radius: 12px; background: var(--brand-light); color: var(--brand); }
.fbx-drop__text { display: grid; gap: .15rem; }
.fbx-drop__text strong { font-size: .95rem; color: var(--text); }
.fbx-drop__text small { font-size: .8rem; color: var(--text-muted); }
.fbx-drop:hover, .fbx-drop--over { border-color: var(--brand); background: var(--brand-light); }
.fbx-drop:focus-within { border-color: var(--brand); box-shadow: 0 0 0 4px rgba(0, 94, 133, .12); }
.fbx-drop--full { cursor: default; opacity: .65; }
.fbx-drop--full:hover { border-color: #c3ccd6; background: #fbfcfd; }
.fbx-shots { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: .7rem; }
.fbx-shots:empty { display: none; }
.fbx-shot {
  position: relative; margin: 0; width: 6.2rem; height: 6.2rem; border-radius: 12px; overflow: hidden;
  background: #eef2f6; box-shadow: 0 2px 8px rgba(16, 40, 60, .12); animation: fbx-pop .25s ease both;
}
.fbx-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.fbx-shot__ph { display: grid; place-items: center; height: 100%; padding: .4rem; font-size: .7rem; text-align: center; color: var(--text-muted); overflow-wrap: anywhere; }
.fbx-shot--loading img { filter: saturate(.4) brightness(.9); }
.fbx-shot--loading::after {
  content: ""; position: absolute; inset: 0; margin: auto; width: 1.6rem; height: 1.6rem; border-radius: 50%;
  border: 3px solid rgba(255, 255, 255, .6); border-top-color: var(--brand); animation: fbx-spin .8s linear infinite;
}
.fbx-shot__x {
  position: absolute; top: .3rem; right: .3rem; display: grid; place-items: center; width: 1.6rem; height: 1.6rem;
  border: 0; border-radius: 50%; background: rgba(20, 30, 45, .72); color: #fff; cursor: pointer;
}
.fbx-shot__x:hover { background: #d9383e; }

/* Send */
.fbx-send { display: grid; gap: .5rem; justify-items: center; padding: .25rem 0 0; }
.fbx-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .55rem;
  min-height: 46px; padding: .6rem 1.2rem; border-radius: 999px; border: 2px solid transparent;
  font: inherit; font-size: .98rem; font-weight: 700; text-decoration: none; cursor: pointer;
  transition: transform .12s ease, box-shadow .15s ease, background-color .15s ease, filter .15s ease;
}
.fbx-btn--primary { background: linear-gradient(140deg, var(--brand) 0%, #0b78a6 100%); color: #fff; box-shadow: 0 6px 18px rgba(0, 94, 133, .28); }
.fbx-btn--primary:hover { filter: brightness(1.06); transform: translateY(-1px); box-shadow: 0 10px 22px rgba(0, 94, 133, .32); color: #fff; }
.fbx-btn--primary:active { transform: translateY(0) scale(.99); }
.fbx-btn--ghost { background: #fff; color: var(--brand); border-color: var(--border); }
.fbx-btn--ghost:hover { border-color: var(--brand); color: var(--brand); }
.fbx-btn--big { width: 100%; max-width: 26rem; min-height: 54px; font-size: 1.05rem; }
.fbx-btn:disabled { opacity: .6; cursor: progress; transform: none; }
.fbx-btn--sending svg { animation: fbx-fly .9s ease-in-out infinite; }
.fbx-send__small { margin: 0; font-size: .78rem; color: var(--text-muted); text-align: center; }

/* Thank you */
.fbx-thanks { margin: 1.5rem auto 2rem; padding: 2rem 1.3rem 1.7rem; max-width: 30rem; text-align: center; background: var(--card-bg); border-radius: 22px; box-shadow: 0 10px 30px rgba(16, 40, 60, .08); }
.fbx-thanks__tick svg { width: 5rem; height: 5rem; }
.fbx-thanks__tick circle { fill: #e4f5ea; stroke: #178a4c; stroke-width: 3; stroke-dasharray: 151; stroke-dashoffset: 151; animation: fbx-draw .6s ease forwards; }
.fbx-thanks__tick path { fill: none; stroke: #178a4c; stroke-width: 4; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 40; stroke-dashoffset: 40; animation: fbx-draw .35s .5s ease forwards; }
.fbx-thanks__title { margin: .9rem 0 .35rem; font-size: 1.55rem; font-weight: 800; color: var(--text); text-wrap: balance; }
.fbx-thanks__text { margin: 0 auto 1.3rem; max-width: 24rem; color: var(--text-muted); line-height: 1.45; }
.fbx-thanks__acts { display: flex; flex-wrap: wrap; justify-content: center; gap: .6rem; }

@keyframes fbx-rise  { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes fbx-pop   { from { opacity: 0; transform: scale(.85); } to { opacity: 1; transform: none; } }
@keyframes fbx-spin  { to { transform: rotate(360deg); } }
@keyframes fbx-draw  { to { stroke-dashoffset: 0; } }
@keyframes fbx-fly   { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(3px, -3px); } }
@keyframes fbx-shake { 0%, 100% { transform: none; } 20% { transform: translateX(-6px); } 40% { transform: translateX(6px); } 60% { transform: translateX(-4px); } 80% { transform: translateX(3px); } }

@media (max-width: 420px) {
  .fbx-hero { padding: 1.2rem 1rem 1.05rem; border-radius: 18px; }
  .fbx-hero__title { font-size: 1.4rem; }
  .fbx-hero__art { width: 104px; opacity: .8; }
  .fbx-tiles { gap: .5rem; }
  .fbx-tile { flex-direction: column; gap: .5rem; min-height: 0; padding: .75rem .7rem; }
  .fbx-tile__text { padding-right: 0; }
  .fbx-step { padding: 1rem .9rem 1.05rem; }
}
@media (prefers-reduced-motion: reduce) {
  .fbx-tile, .fbx-tile__icon, .fbx-tile__tick, .fbx-btn { transition: none; }
  .fbx-in, .fbx-shot, .fbx-shake, .fbx-btn--sending svg { animation: none; }
  .fbx-thanks__tick circle, .fbx-thanks__tick path { animation: none; stroke-dashoffset: 0; }
}

/* Admin -> Feedback: the on/off word in the status card (2026-09-15). */
.fb-on  { color: #1f6f36; font-weight: 700; }
.fb-off { color: #8a4b08; font-weight: 700; }

/* ── Programme note editor (day view; includes/programme_note.php) ──────────
   Only drawn for holders of ver5's "Edit Diary Note". Subtle until opened. */
.pn { margin-top: .35rem; }
.pn__toggle {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  font-size: .78rem;
  color: #005e85;
  cursor: pointer;
  list-style: none;
  padding: .15rem 0;
  -webkit-tap-highlight-color: transparent;
}
.pn__toggle::-webkit-details-marker { display: none; }
.pn[open] .pn__toggle { color: var(--text-muted); }
.pn__form { margin-top: .4rem; display: flex; flex-direction: column; gap: .35rem; }
.pn__label { font-size: .78rem; font-weight: 600; color: var(--text); }
.pn__hint { font-weight: 400; color: var(--text-muted); }
/* 16px stops iOS zooming the page when the note takes focus. */
.pn__text {
  width: 100%;
  font-size: 16px;
  font-family: inherit;
  line-height: 1.35;
  padding: .45rem .55rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  resize: vertical;
  box-sizing: border-box;
}
.pn__actions { display: flex; align-items: center; gap: .6rem; }
.pn__save { padding: .4rem .9rem; font-size: .85rem; }
.pn__cancel {
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: .85rem;
  cursor: pointer;
  padding: .4rem .2rem;
}

/* ═══ Birthday celebration (David 2026-09-16) ═══════════════════════════════
   assets/js/birthday.js builds this on the person's birthday (and on
   Admin → Birthdays as a test). The overlay never blocks the page: only the
   card takes clicks, so the app stays usable while things are still falling.
   Above everything (the TEST MODE bar is 9999). */
.bd-overlay {
  position: fixed; inset: 0;
  z-index: 10050;
  pointer-events: none;
}
.bd-canvas {
  position: absolute; inset: 0;
  transition: opacity .4s ease;
}
.bd-canvas--out { opacity: 0; }
.bd-card {
  pointer-events: auto;
  position: absolute; left: 50%; top: 42%;
  width: min(22rem, calc(100vw - 2.5rem));
  padding: 1.6rem 1.4rem 1.3rem;
  background: var(--card-bg, #fff);
  border-radius: 18px;
  box-shadow: 0 18px 50px rgba(0, 40, 70, .28), 0 2px 8px rgba(0, 40, 70, .12);
  text-align: center;
  transform: translate(-50%, -50%);
  animation: bd-pop .55s cubic-bezier(.2, 1.4, .4, 1) both;
}
.bd-card--out { animation: bd-out .25s ease-in both; }
.bd-card__cake { font-size: 3.2rem; line-height: 1; margin-bottom: .55rem; }
.bd-card__title {
  margin: 0 0 .45rem;
  font-size: 1.45rem;
  line-height: 1.2;
  color: var(--brand, #005e85);
  text-wrap: balance;
}
.bd-card__text {
  margin: 0 0 1.15rem;
  color: var(--text, #1a1a2e);
  font-size: 1rem;
  line-height: 1.45;
  text-wrap: balance;
}
.bd-card__btn { min-width: 9rem; min-height: 44px; font-size: 1rem; }
@keyframes bd-pop {
  from { opacity: 0; transform: translate(-50%, -50%) scale(.6); }
  to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
@keyframes bd-out {
  to { opacity: 0; transform: translate(-50%, -50%) scale(.92); }
}
@media (prefers-reduced-motion: reduce) {
  .bd-card, .bd-card--out { animation: none; }
}
