/* The Pulse Planner -- design system.
   THE BRAND LIVES IN THIS ONE BLOCK. Every colour, font, space and corner below it is a variable named for the
   ROLE it plays (accent, surface, ink), never for the brand that fills it -- so another business's brand is a change
   to this block and nothing else. tests/unit/designTokens.test.js fails if a hex colour appears anywhere below it.
   The comment beside each value is its name on the brand sheet. */

:root {
  /* ---- Surfaces ---- */
  --surface: #FAF7F0;            /* surface: the page background, everywhere */
  --surface-raised: #FFFFFF;     /* surface-raised: cards, forms, modals */
  --surface-sunken: #F2EDE3;     /* NOT on the brand sheet: the quiet fill behind board columns, chips and code. Between surface and hairline. */

  /* ---- Ink ---- */
  --ink: #1F1D1A;                /* ink: body text, headings, icons */
  --ink-muted: #5E5A54;          /* ink-muted: secondary text, captions, helper text */
  --ink-hover: #3A362F;          /* NOT on the brand sheet: an ink-filled control under the pointer */
  --on-dark: #FFFFFF;            /* text on ink (the sidebar, the music planning form) */

  /* ---- Lines ---- */
  --hairline: #D9D3C7;           /* hairline: dividers and card outlines ONLY -- too light for a control */
  --border: #8C857A;             /* border: input and control borders (3:1 on both surfaces) */

  /* ---- The accent ---- */
  --accent: #00A062;             /* pulse-green: icons, graphics, rules, and text 24px or larger. Never small text. */
  --accent-strong: #007A4B;      /* pulse-green-deep: small text, links, the primary button's fill, the focus ring */
  --accent-strong-hover: #00603B;/* NOT on the brand sheet: the primary button under the pointer (pulse-green-deep, darker) */
  --accent-tint: #E3F2EA;        /* green-tint: quiet success / selected background. Text on it stays ink or accent-strong. */
  --accent-glow: rgba(0,160,98,0.18);   /* pulse-green at 18%: the active item on the dark sidebar */
  --on-accent: #FFFFFF;          /* text on an accent-strong fill */

  /* ---- States that are not the brand's to choose (kept from before the refresh) ---- */
  --warning: #8C6D28;            /* "look at this": owed, nearly full, not sure. Was the deep brass. */
  --warning-tint: #F1E6C9;
  --warning-line: #B4923F;
  --danger: #A5443A;
  --danger-tint: #F6E5E2;
  --info: #3E5C76;
  --info-tint: #E6ECF1;

  /* ---- The dark sidebar ---- */
  --sidebar-bg: var(--ink);
  --sidebar-text: #EFEAE0;
  --sidebar-link: #D9D3C6;
  --sidebar-muted: #B7AF9F;
  --sidebar-section: #A39B8A;
  --sidebar-hover: var(--sidebar-hover);
  --sidebar-rule: var(--sidebar-rule);

  /* ---- Corners ---- */
  --radius-sm: 4px;              /* inputs, chips, small buttons */
  --radius: 8px;                 /* cards, modals, primary buttons */
  --radius-round: 999px;         /* avatars, status dots, pills */

  /* ---- Space: four steps, and nothing in between ---- */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 16px;
  --space-4: 24px;

  /* ---- Depth: cards have none. Only what floats OVER the page (a modal, a menu) casts a shadow. ---- */
  --shadow: none;
  --shadow-float: 0 8px 24px -12px rgba(31,29,26,0.28);
  --scrim: rgba(31,29,26,0.45);
  --sidebar-w: 232px;

  /* ---- Type: two families ---- */
  --font-display: 'Cormorant Garamond', Georgia, 'Times New Roman', serif;      /* Display: weights 500, 600 */
  --font-sans: 'Josefin Sans', 'Gill Sans', 'Helvetica Neue', sans-serif;       /* Sans: weights 400, 600 */
  /* weight size/line-height family -- used as `font: var(--text-...)` */
  --text-display: 500 44px/48px var(--font-display);   /* display: page titles; couples' names on client pages */
  --text-display-phone: 500 32px/36px var(--font-display);   /* NOT on the brand sheet: 44px does not fit a 375px screen */
  --text-heading: 600 28px/34px var(--font-display);   /* heading: section headings */
  --text-title: 600 18px/26px var(--font-sans);        /* title: card titles */
  --text-body: 400 15px/24px var(--font-sans);         /* body: all running text */
  --text-caption: 400 13px/18px var(--font-sans);      /* caption: metadata, helper text, timestamps -- in ink-muted */
  --text-tagline: 600 13px/16px var(--font-sans);      /* tagline: the logo tagline ONLY (0.4em, capitals). Not for UI labels. */
  --text-th: 600 13px/18px var(--font-sans);           /* table headers. The sheet says "title" (18px); in a six-column ledger that wraps every header -- FLAGGED, and one line to change. */
  --tracking-display: 0.01em;
  --tracking-tagline: 0.4em;

  /* ---- The DJ's music planning form: dark at the venue, plain when printed ---- */
  --rs-bg: #131211;
  --rs-panel: #1E1C1A;
  --rs-line: #35312C;
  --rs-text: #F4F0E8;
  --rs-dim: #A49C8F;
  --rs-accent: var(--accent);    /* pulse-green is 5.5:1 on the music planning form's black */
  --rs-red: #E88478;
  --rs-print-line: #CCCCCC;
  --rs-print-text: #000000;
  --rs-print-dim: #444444;
  --rs-print-accent: var(--accent-strong);
  --rs-print-red: #8C2016;
}

/* The two families, served from this app (public/fonts, SIL Open Font License -- the licence texts are beside them).
   Both are variable fonts: one file covers every weight. latin-ext is for the names with accents in them. */
@font-face { font-family: 'Cormorant Garamond'; font-style: normal; font-weight: 500 600; font-display: swap; src: url('/public/fonts/cormorant-garamond-latin-ext.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Cormorant Garamond'; font-style: normal; font-weight: 500 600; font-display: swap; src: url('/public/fonts/cormorant-garamond-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Josefin Sans'; font-style: normal; font-weight: 400 600; font-display: swap; src: url('/public/fonts/josefin-sans-latin-ext.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Josefin Sans'; font-style: normal; font-weight: 400 600; font-display: swap; src: url('/public/fonts/josefin-sans-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }


* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--surface);
  color: var(--ink);
  font: var(--text-body);
  font-synthesis: none;   /* the two families ship 400/600 and 500/600: nothing is faux-bolded past that */
  -webkit-font-smoothing: antialiased;
}
/* The scale: display for a page title, heading for a section, title (sans) for a card. Sentence case throughout. */
h1, .display { font: var(--text-display); letter-spacing: var(--tracking-display); color: var(--ink); margin: 0 0 var(--space-1); }
h2 { font: var(--text-heading); letter-spacing: var(--tracking-display); color: var(--ink); margin: 0 0 var(--space-1); }
h3 { font: var(--text-title); color: var(--ink); margin: 0 0 var(--space-1); }
a { color: inherit; text-decoration: none; }
/* A link in running text is the strong accent, underlined; a link that IS a row, a card, a chip or a button keeps its own look (so not every <li> a). */
p a:not(.btn), .hint a, .small a, .muted a, a.link { color: var(--accent-strong); text-decoration: underline; text-underline-offset: 2px; }
.alert a:not(.btn) { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
/* The focus ring, on everything that can take focus. Never removed. */
:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
input[type=checkbox], input[type=radio], progress { accent-color: var(--accent-strong); }
p { margin: 0 0 10px; }

/* ---------- App shell ---------- */
.shell { display: flex; min-height: 100vh; }
.sidebar {
  width: var(--sidebar-w);
  flex: 0 0 var(--sidebar-w);
  position: sticky; top: 0; height: 100vh; overflow-y: auto; align-self: flex-start;   /* it no longer scrolls off with a long page (UI cleanup, item 1) */
  background: var(--sidebar-bg);
  color: var(--sidebar-text);
  padding: 22px 16px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.brand { display: flex; align-items: center; gap: 10px; padding: 0 8px 22px; }
.brand-mark {
  width: 34px; height: 34px; border-radius: 50%;
  background: var(--accent-strong);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-weight: 600; color: var(--on-accent); font-size: 15px;
}
.brand-name { font-family: var(--font-display); font-size: 15px; line-height: 1.2; color: var(--on-dark); }
.brand-sub { font: var(--text-tagline); text-transform: uppercase; letter-spacing: var(--tracking-tagline); color: var(--sidebar-muted); }   /* the logo tagline: the one place the 0.4em tagline style belongs */

.nav-section { font-family: var(--font-sans); font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: var(--sidebar-section); margin: 16px 10px 6px; }
.nav-link {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: var(--radius); color: var(--sidebar-link); font-size: 13.5px;
}
.nav-link:hover { background: var(--sidebar-hover); color: var(--on-dark); }
.nav-link.active { background: var(--accent-glow); color: var(--on-dark); font-weight: 600; box-shadow: inset 3px 0 0 var(--accent); }   /* the bar is pulse-green; the text is not (too small for it) */
.nav-link svg { flex: 0 0 auto; opacity: 0.9; }
.nav-spacer { flex: 1; }
.nav-user {
  display: flex; align-items: center; gap: 10px; padding: 10px; margin-top: 8px;
  border-top: 1px solid var(--sidebar-rule); padding-top: 14px;
}
.avatar {
  width: 30px; height: 30px; border-radius: 50%; background: var(--accent-strong);
  color: var(--on-accent); display: flex; align-items: center; justify-content: center;
  font-weight: 600; font-size: 12px; flex: 0 0 auto;
}
.nav-user-name { font-size: 13px; color: var(--on-dark); }
.nav-user-role { font-family: var(--font-sans); font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: var(--sidebar-muted); }

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--hairline); background: var(--surface-raised);
}
.content { padding: var(--space-4) var(--space-4) 64px; flex: 1; }
.page-head { display: flex; align-items: flex-end; justify-content: space-between; margin-bottom: var(--space-3); flex-wrap: wrap; gap: 12px;}
.eyebrow { font-family: var(--font-sans); font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.16em; color: var(--accent-strong); margin-bottom: 4px;}

/* ---------- Buttons & form controls ---------- */
.btn {
  display: inline-flex; align-items: center; gap: 6px; justify-content: center;
  border: 1px solid var(--border); background: var(--surface-raised); color: var(--ink);
  padding: 8px 14px; border-radius: var(--radius-sm); font-size: 13px; font-weight: 600;
  cursor: pointer; transition: all .12s ease; white-space: nowrap;   /* a label never wraps onto three lines (D-30) */
}
.btn:hover { border-color: var(--accent-strong); color: var(--accent-strong); }
/* .btn-primary and .btn-gold are the same button: the class names predate the brand sheet and are left alone. */
.btn-primary, .btn-gold { background: var(--accent-strong); color: var(--on-accent); border-color: var(--accent-strong); border-radius: var(--radius); }
.btn-primary:hover, .btn-gold:hover { background: var(--accent-strong-hover); color: var(--on-accent); border-color: var(--accent-strong-hover); }
.btn-danger { color: var(--danger); border-color: var(--danger); }
/* One primary button per screen. Inside a table row an action is never it -- a column of green buttons says nothing. (UI cleanup, item 4) */
td .btn-gold, td .btn-primary, .board-card .btn-gold { background: var(--surface-raised); color: var(--ink); border-color: var(--border); border-radius: var(--radius-sm); }
td .btn-gold:hover, td .btn-primary:hover, .board-card .btn-gold:hover { background: var(--surface-raised); color: var(--accent-strong); border-color: var(--accent-strong); }
.btn-danger:hover { background: var(--danger-tint); }
.btn-sm { padding: 5px 10px; font-size: 12px; }
.btn-block { width: 100%; }
.btn[disabled] { opacity: 0.5; cursor: not-allowed; }

label { display: block; font-size: 12px; font-weight: 600; color: var(--ink-muted); margin-bottom: 5px; }
input[type=text], input[type=email], input[type=password], input[type=number],
input[type=date], input[type=time], input[type=datetime-local], input[type=tel],
input[type=url], input[type=search], input:not([type]),
select, textarea {
  width: 100%; padding: 9px 11px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  font-size: 15px; font-family: inherit; background: var(--surface-raised); color: var(--ink);
}
textarea { resize: vertical; min-height: 70px; }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent-strong); outline-offset: 1px; border-color: var(--accent-strong); }
.field { margin-bottom: var(--space-3); }
.field-row { display: flex; gap: 12px; }
.field-row > .field { flex: 1; }
.hint { font: var(--text-caption); color: var(--ink-muted); margin-top: var(--space-1); }
.checkbox-row { display: flex; align-items: center; gap: 8px; }
.checkbox-row input { width: auto; }

/* ---------- Cards / panels ---------- */
.card { background: var(--surface-raised); border: 1px solid var(--hairline); border-radius: var(--radius); padding: var(--space-3); box-shadow: var(--shadow); }
/* Stacked cards breathe; cards side by side in a grid do not. Without the
   second rule the first one fires inside .grid too and every card after the
   first in a row sits 16px lower than its neighbour. (D-01) */
.card + .card { margin-top: 16px; }
.grid > .card + .card { margin-top: 0; }
.grid { display: grid; gap: 16px; }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) { .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; } }

.stat { position: relative; padding: 16px; border-radius: var(--radius); border: 1px solid var(--hairline); background: var(--surface-raised); }
.stat-label { font-size: 12px; font-weight: 600; color: var(--ink-muted); margin-bottom: 6px; }   /* sentence case: a tile is read, not scanned */
.stat-value { font: var(--text-heading); font-variant-numeric: tabular-nums; }
.stat-sub { font-size: 12px; color: var(--ink-muted); margin-top: 2px; }
.stat.positive .stat-value { color: var(--accent-strong); }
.stat.negative .stat-value { color: var(--danger); }

/* ---------- Badges / pills ---------- */
/* Pills set their own case, so "PAID", "scheduled" and "Live" in the data all
   read the same way. Tracked a little less than a label: a pill can be a
   whole status name and needs to stay a pill, not a banner. (D-24) */
.pill { display: inline-flex; align-items: center; gap: 5px; padding: 3px 10px; border-radius: var(--radius-round); font-family: var(--font-sans); font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; white-space: nowrap; }
.pill-gold { background: var(--warning-tint); color: var(--warning); }
/* Booked, Paid, Signed, Live: the good-news states look like the brand. (D-21) */
.pill-green { background: var(--accent-tint); color: var(--accent-strong); }
.pill-red { background: var(--danger-tint); color: var(--danger); }
.pill-blue { background: var(--info-tint); color: var(--info); }
.pill-gray { background: var(--surface-sunken); color: var(--ink-muted); }

/* ---------- Tables ---------- */
table { width: 100%; border-collapse: collapse; }
th { text-align: left; font: var(--text-th); text-transform: uppercase; letter-spacing: 0.12em; color: var(--ink-muted); padding: 9px 12px; border-bottom: 1px solid var(--hairline); }
/* tabular-nums: dollar amounts and counts line up in a column. (D-39) */
td { padding: 11px 12px; border-bottom: 1px solid var(--hairline); font-size: 13.5px; vertical-align: middle; font-variant-numeric: tabular-nums; }
tr:last-child td { border-bottom: none; }
/* overflow-x: auto, not hidden. Hidden CLIPPED a wide table on a phone; this
   lets it scroll inside its own frame instead of widening the page. (D-11) */
.table-wrap { border: 1px solid var(--hairline); border-radius: var(--radius); overflow-x: auto; overflow-y: hidden; background: var(--surface-raised); }
.table-wrap-plain { border: none; border-radius: 0; background: transparent; }
tbody tr:hover { background: var(--surface); }
.row-link { display: block; }

/* ---------- Tabs ---------- */
.tabs { display: flex; gap: var(--space-1); border-bottom: 1px solid var(--hairline); margin-bottom: var(--space-3); flex-wrap: wrap; }
.tab { padding: 9px 14px; font-size: 13px; font-weight: 600; color: var(--ink-muted); border-bottom: 2px solid transparent; }
.tab.active { color: var(--ink); border-color: var(--accent); }
.tab:hover { color: var(--ink); }

/* ---------- Kanban ---------- */
.board { display: flex; gap: 14px; overflow-x: auto; padding-bottom: 14px; align-items: flex-start; }
.board-col { flex: 0 0 270px; background: var(--surface-sunken); border-radius: var(--radius); padding: 10px; min-height: 120px; }
.board-col-head { display: flex; align-items: center; justify-content: space-between; padding: 6px 6px 10px; }
.board-col-title { font-size: 12.5px; font-weight: 600; }
.board-col-count { font-size: 12px; color: var(--ink-muted); background: var(--surface-raised); padding: 1px 7px; border-radius: var(--radius-round); }
.board-card {
  background: var(--surface-raised); border: 1px solid var(--hairline); border-radius: var(--radius); padding: 10px 12px;
  margin-bottom: var(--space-2); cursor: grab; box-shadow: var(--shadow);
}
.board-card:hover { border-color: var(--accent); }
.board-card.dragging { opacity: 0.4; }
.board-card-title { font-weight: 600; font-size: 13px; margin-bottom: 4px; }
.board-card-meta { font-size: 12px; color: var(--ink-muted); display: flex; flex-direction: column; gap: 2px; }
.board-col.drag-over { outline: 2px dashed var(--accent); outline-offset: -4px; }

/* ---------- Misc ---------- */
.muted { color: var(--ink-muted); }
.small { font-size: 12px; }
.divider { border: none; border-top: 1px solid var(--hairline); margin: 16px 0; }
.flex { display: flex; }
.flex-between { display: flex; align-items: center; justify-content: space-between; }
.flex-gap { display: flex; gap: 8px; align-items: center; }
.mt-0{margin-top:0} .mt-1{margin-top:8px} .mt-2{margin-top:16px} .mt-3{margin-top:24px}
.mb-0{margin-bottom:0} .mb-1{margin-bottom:8px} .mb-2{margin-bottom:16px}
.empty-state { text-align: center; padding: 50px 20px; color: var(--ink-muted); }
.empty-state svg { opacity: 0.4; margin-bottom: 10px; }

.login-wrap { min-height: 100vh; display: flex; align-items: center; justify-content: center; background: var(--ink); padding: 20px; }
.login-card { width: 380px; background: var(--surface); border-radius: var(--radius); padding: 34px 30px; box-shadow: var(--shadow-float); }
.login-brand { text-align: center; margin-bottom: 22px; }
.login-brand .brand-mark { width: 52px; height: 52px; font-size: 22px; margin: 0 auto 12px; }
.alert { padding: 10px 13px; border-radius: var(--radius); font-size: 13px; margin-bottom: 14px; }
.alert-error { background: var(--danger-tint); color: var(--danger); }
.alert-success { background: var(--accent-tint); color: var(--accent-strong); }
/* Used in a few places (deposit warnings, publish problems) but never defined,
   so those notices were rendering as unstyled text. */
.alert-warn { background: var(--warning-tint); color: var(--warning); }
/* Red is for things that have gone wrong. These two are for things that are
   simply true: a fact, or a next step. (D-31) */
.alert-info { background: var(--info-tint); color: var(--info); }
.alert-neutral { background: var(--surface-sunken); color: var(--ink-muted); }
.alert-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.alert-row form { margin: 0; }

.chip-list { display: flex; flex-wrap: wrap; gap: 6px; }
/* minmax(0, 1fr): a long event title can no longer widen its column. (D-12) */
.calendar-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; }
.calendar-day-name { font-family: var(--font-sans); font-size: 12px; font-weight: 600;  color: var(--ink-muted); text-align: center; padding: 4px; }
.calendar-cell { background: var(--surface-raised); border: 1px solid var(--hairline); border-radius: var(--radius); min-height: 96px; padding: 6px; }
.calendar-cell.out { background: var(--surface-sunken); opacity: 0.5; }
.calendar-date { font-size: 12px; font-weight: 600; margin-bottom: 4px; }
.calendar-evt { display: block; font-size: 12px; padding: 2px 5px; border-radius: var(--radius-sm); margin-bottom: 2px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- Fillable contract/form fields ---------- */
.rendered-doc { line-height: 1.8; }
.fill-inline {
  display: inline-block; width: auto; padding: 2px 8px; margin: 0 2px; border: none;
  border-bottom: 2px solid var(--accent); border-radius: 0; background: var(--accent-tint);
  font-family: inherit; font-size: inherit; font-weight: 600; color: var(--ink);
}
.fill-inline:focus { outline: 2px solid var(--accent-strong); outline-offset: 1px; background: var(--surface-raised); border-bottom-color: var(--accent-strong); }
.fill-chip {
  display: inline-flex; align-items: center; padding: 1px 9px; margin: 0 2px; border-radius: var(--radius-round);
  background: var(--accent-tint); color: var(--accent-strong); font-size: 0.85em; font-weight: 600;
  border: 1px dashed var(--accent);
}
.fill-value { color: var(--accent-strong); border-bottom: 1px solid var(--accent); padding: 0 2px; }
.fill-value.fill-empty { color: var(--danger); border-bottom-color: var(--danger-tint); font-weight: 600; font-size: 0.85em; }
.fill-legend { background: var(--accent-tint); border: 1px dashed var(--accent); border-radius: var(--radius); padding: 10px 12px; font-size: 12.5px; color: var(--accent-strong); }

.timeline-item { display: flex; gap: 14px; padding: 10px 0; border-bottom: 1px dashed var(--hairline); }
.timeline-time { flex: 0 0 90px; font-weight: 600; font-size: 12.5px; color: var(--accent-strong); }
.song-row { display:flex; align-items:center; justify-content:space-between; padding:8px 0; border-bottom:1px solid var(--hairline); }

/* ---------- Music planning: segment checklist ---------- */
.segment-checklist { display: flex; flex-direction: column; gap: 8px; }
.segment-card {
  display: flex; align-items: center; gap: 14px; padding: 14px 16px; border: 1px solid var(--hairline);
  border-radius: var(--radius); background: var(--surface-raised); transition: border-color .15s, box-shadow .15s;
}
.segment-card:hover { border-color: var(--accent); box-shadow: var(--shadow); }
.segment-checkbox {
  flex: 0 0 26px; width: 26px; height: 26px; border-radius: var(--radius); border: 2px solid var(--hairline);
  display: flex; align-items: center; justify-content: center; color: var(--on-dark);
}
.segment-checkbox.checked { background: var(--accent); border-color: var(--accent); }   /* done is green, not gold (D-41) */
.segment-checkbox.checked svg { width: 15px; height: 15px; stroke-width: 3; }
.segment-card-body { flex: 1; display: flex; flex-direction: column; gap: 1px; }
.segment-card-title { font-weight: 600; font-size: 14.5px; }
.segment-card-count { flex: 0 0 auto; font-size: 12px; font-weight: 600; color: var(--accent-strong); white-space: nowrap; }

/* ---------- Music planning: song library browser ---------- */
.library-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--hairline); }
.library-row-info { flex: 1; min-width: 0; }
.library-row-actions { display: flex; gap: 6px; flex-wrap: wrap; flex: 0 0 auto; }
.library-row-actions form { margin: 0; }

/* ---------- Modal ---------- */
.modal { display: none; position: fixed; inset: 0; background: var(--scrim); align-items: center; justify-content: center; z-index: 50; padding: 20px; }
.modal-card { background: var(--surface-raised); border-radius: var(--radius); padding: 22px; width: 100%; max-width: 480px; max-height: 88vh; overflow-y: auto; box-shadow: var(--shadow-float); }
.modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.repeat-row { display: flex; gap: 8px; align-items: flex-end; margin-bottom: 8px; }
.repeat-row > * { flex: 1; }
.icon-btn { background: none; border: none; cursor: pointer; color: var(--ink-muted); padding: 6px; border-radius: var(--radius-sm); }
.icon-btn:hover { background: var(--surface-sunken); color: var(--danger); }

/* ---------- Song requests: search, browse, and the three lists ---------- */
.req-search { display: flex; gap: 8px; margin-bottom: 12px; }
.req-search input[type=search] { flex: 1; }

.browse-bar { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-start; margin-bottom: 18px; }
.browse-group { position: relative; }
.browse-group > summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; }
.browse-group > summary::-webkit-details-marker { display: none; }
.browse-group > summary::after { content: '▾'; font-size: 12px; color: var(--ink-muted); }
.browse-group[open] > summary { border-color: var(--accent); }
.browse-panel {
  position: absolute; z-index: 30; top: calc(100% + 6px); left: 0; width: 330px; max-width: 78vw;
  background: var(--surface-raised); border: 1px solid var(--hairline); border-radius: var(--radius);
  padding: 12px; box-shadow: var(--shadow-float);
}
.browse-chip {
  display: inline-block; padding: 5px 11px; border-radius: var(--radius-round); font-size: 12.5px; font-weight: 600;
  background: var(--surface-sunken); color: var(--ink); border: 1px solid transparent;
}
.browse-chip:hover { border-color: var(--accent); background: var(--accent-tint); color: var(--accent-strong); }

/* Results take over the top of the page and close back to the lists. */
.req-results {
  background: var(--surface-raised); border: 1px solid var(--accent); border-radius: var(--radius);
  padding: 16px 18px; margin-bottom: 18px; box-shadow: var(--shadow);
}
.req-results-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
.req-results-head .icon-btn { font-size: 22px; line-height: 1; padding: 0 6px; }
.result-list { max-height: 460px; overflow-y: auto; }
.result-row { display: flex; align-items: center; gap: 12px; padding: 9px 2px; border-bottom: 1px solid var(--hairline); }
.result-row:last-child { border-bottom: none; }
.result-info { flex: 1; min-width: 0; }
.result-title { font-weight: 600; font-size: 13.5px; }
.result-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }

.play-btn {
  flex: 0 0 30px; width: 30px; height: 30px; border-radius: 50%; border: 1px solid var(--hairline);
  background: var(--surface-raised); color: var(--ink); font-size: 12px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; padding: 0;
}
.play-btn:hover { border-color: var(--accent); color: var(--accent-strong); }
.play-btn.playing { background: var(--accent-strong); border-color: var(--accent); color: var(--on-accent); }
.play-btn-off { opacity: 0.22; cursor: default; }
.play-btn-off:hover { border-color: var(--hairline); color: var(--ink); }

/* The one-click add control. */
.add-menu, .req-menu { position: relative; flex: 0 0 auto; }
.add-menu > summary, .req-menu > summary { list-style: none; cursor: pointer; }
.add-menu > summary::-webkit-details-marker, .req-menu > summary::-webkit-details-marker { display: none; }
.add-btn {
  display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px;
  border-radius: 50%; background: var(--accent-tint); color: var(--accent-strong); border: 1px solid transparent;
}
.add-btn:hover { background: var(--accent-strong); color: var(--on-accent); }
.add-btn svg { width: 15px; height: 15px; }
.add-menu-panel, .req-menu-panel {
  position: absolute; z-index: 30; top: calc(100% + 6px); right: 0; width: 240px;
  background: var(--surface-raised); border: 1px solid var(--hairline); border-radius: var(--radius);
  padding: 10px; box-shadow: var(--shadow-float);
}
.add-menu-panel form { margin-bottom: 6px; }
.add-menu-panel form:last-child { margin-bottom: 0; }
.btn-on { background: var(--accent-tint); color: var(--accent-strong); border-color: var(--accent-tint); }
.btn-on svg { width: 13px; height: 13px; }

/* The three lists. */
.req-buckets { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; align-items: start; }
.bucket-panel { background: var(--surface-raised); border: 1px solid var(--hairline); border-radius: var(--radius); padding: 14px; box-shadow: var(--shadow); }
.bucket-panel.bucket-do-not-play { border-color: var(--danger-tint); }
.bucket-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; padding-bottom: 10px; border-bottom: 1px solid var(--hairline); }
.bucket-title { font-size: 16px; margin: 0; }
.bucket-count {
  flex: 0 0 auto; font-size: 12px; font-weight: 600; padding: 3px 9px; border-radius: var(--radius-round);
  background: var(--surface-sunken); color: var(--ink-muted);
}
.bucket-count.full { background: var(--warning-tint); color: var(--warning); }
.bucket-body { min-height: 40px; }
.bucket-empty { padding: 14px 0; }
.bucket-full-note { color: var(--warning); background: var(--warning-tint); border-radius: var(--radius-sm); padding: 6px 9px; margin-bottom: 8px; }
.bucket-add > summary { list-style: none; cursor: pointer; margin-top: 8px; display: block; text-align: center; }
.bucket-add > summary::-webkit-details-marker { display: none; }
.bucket-add > summary svg { width: 13px; height: 13px; vertical-align: -2px; }

.req-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; padding: 9px 0; border-bottom: 1px solid var(--hairline); }
.req-row:last-child { border-bottom: none; }
.req-row-main { flex: 1; min-width: 0; }
.req-title { font-weight: 600; font-size: 13.5px; }
.req-artist { font-size: 12px; color: var(--ink-muted); }
.req-note-shown { font-size: 12px; color: var(--ink-muted); margin-top: 3px; }
.req-note-kind { font-family: var(--font-sans); font-size: 12px; font-weight: 600;  color: var(--accent-strong); }
.req-menu > summary svg { width: 14px; height: 14px; }
.req-note-form textarea { min-height: 48px; }
.req-menu-sep { border-top: 1px solid var(--hairline); margin: 10px 0 8px; }

@media (max-width: 1000px) { .req-buckets { grid-template-columns: 1fr; } }

/* ---------- Toasts ---------- */
.toast-wrap { position: fixed; right: 20px; bottom: 20px; z-index: 80; display: flex; flex-direction: column; gap: 8px; }
.toast {
  background: var(--ink); color: var(--on-dark); padding: 10px 16px; border-radius: var(--radius-round); font-size: 13px;
  font-weight: 600; box-shadow: var(--shadow-float); opacity: 0; transform: translateY(8px);
  transition: opacity .2s, transform .2s;
}
.toast.show { opacity: 1; transform: translateY(0); }
.toast.toast-error { background: var(--danger); }

.azbar { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 12px; padding-bottom: 10px; border-bottom: 1px solid var(--hairline); }
.az {
  display: inline-flex; align-items: center; justify-content: center; min-width: 28px; height: 28px;
  border-radius: var(--radius-sm); font-size: 12.5px; font-weight: 600; color: var(--ink-muted); background: var(--surface-sunken);
}
.az:hover { background: var(--accent-tint); color: var(--accent-strong); }
.az.active { background: var(--accent-strong); color: var(--on-accent); }
.artist-list { display: flex; flex-wrap: wrap; gap: 6px; max-height: 340px; overflow-y: auto; }
.artist-chip {
  display: inline-block; padding: 5px 12px; border-radius: var(--radius-round); font-size: 12.5px; font-weight: 600;
  background: var(--surface-raised); border: 1px solid var(--hairline);
}
.artist-chip:hover { border-color: var(--accent); background: var(--accent-tint); color: var(--accent-strong); }
.req-summary-bar { display: flex; flex-wrap: wrap; gap: 8px; }
.req-summary-chip { font-size: 12px; color: var(--ink-muted); background: var(--surface-sunken); padding: 5px 12px; border-radius: var(--radius-round); }
.req-summary-chip strong { color: var(--accent-strong); }
.browse-chip-count { font-size: 12px; color: var(--ink-muted); font-weight: 600; }
.browse-chip:hover .browse-chip-count { color: var(--accent-strong); }
.lib-filters { display: flex; flex-direction: column; gap: 8px; }
.lib-filter-group { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.lib-filter-label { font-family: var(--font-sans); font-size: 12px; font-weight: 600;  color: var(--ink-muted); min-width: 120px; }
.browse-chip.on { background: var(--accent-strong); color: var(--on-accent); }
.browse-chip.on .browse-chip-count { color: var(--on-accent); }
/* When nothing in a result set has a preview, hide the placeholder buttons
   rather than showing a column of dead controls. */
.result-list:not(.has-previews) .play-btn-off { display: none; }
.browse-chip.zero { opacity: 0.45; }
.store-link { color: var(--accent-strong); font-weight: 600; text-decoration: underline; }
.store-link:hover { color: var(--accent-strong); }
.lookup-panel { border-top: 1px dashed var(--hairline); margin-top: 14px; padding-top: 14px; }
.lookup-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.lookup-badge { font-family: var(--font-sans); font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.16em; color: var(--ink-muted); }
.chain-view { background: var(--surface-sunken); border-radius: var(--radius); padding: 10px 12px; }
.chain-view a { color: var(--accent-strong); text-decoration: underline; }
.chain-loop { color: var(--danger); font-weight: 600; }

/* The brand block was written for the dark sidebar, so its white text is
   invisible on the ivory login and portal-setup cards. */
.login-card .brand-name { color: var(--ink); }
.login-card .brand-sub { color: var(--ink-muted); }

/* ---------------------------------------------------------------- Social */
/* The grid is the point of this screen: nine squares in a row of three is
   what an Instagram profile looks like, and seeing the queue that way is the
   difference between scheduling posts and composing a feed. */
.grid-wrap { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; align-items: start; }
@media (max-width: 1100px) { .grid-wrap { grid-template-columns: 1fr; } }

.ig-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
.grid-tile {
  position: relative; aspect-ratio: 1 / 1; overflow: hidden; border-radius: var(--radius-sm);
  background: var(--surface); border: 1px solid var(--hairline);
  display: flex; align-items: center; justify-content: center; text-decoration: none;
  color: var(--ink); cursor: pointer;
}
.grid-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.grid-tile.is-queued { border-style: dashed; }
.grid-tile.dragging { opacity: .45; }
.grid-tile-text { font-size: 12px; line-height: 1.45; padding: 10px; color: var(--ink-muted); text-align: center; }
.grid-tile-meta {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 5px 6px;
  display: flex; align-items: center; gap: 5px; justify-content: space-between;
  background: linear-gradient(to top, rgba(255,255,255,.94), rgba(255,255,255,0));
}
.grid-tile-when { font-size: 12px; color: var(--ink-muted); }
.grid-tile-count {
  position: absolute; top: 6px; right: 6px; background: rgba(33,31,29,.72); color: var(--on-dark);
  border-radius: var(--radius); font-size: 12px; padding: 1px 7px;
}
.grid-tile-source { position: absolute; top: 6px; left: 6px; opacity: .6; }
.grid-tile-source svg { width: 13px; height: 13px; }

.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.cal-head { font-family: var(--font-sans); font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.16em; color: var(--ink-muted); padding: 4px; }
.cal-cell { min-height: 92px; border: 1px solid var(--hairline); border-radius: var(--radius-sm); padding: 5px; background: var(--surface-raised); }
.cal-empty { background: transparent; border-color: transparent; }
.cal-today { border-color: var(--accent); }
.cal-day { font-size: 12px; color: var(--ink-muted); margin-bottom: 3px; }
.cal-post {
  display: block; font-size: 12px; padding: 2px 5px; border-radius: var(--radius-sm);
  margin-bottom: 2px; text-decoration: none; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}

.editor-wrap { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: 22px; align-items: start; }
@media (max-width: 1100px) { .editor-wrap { grid-template-columns: 1fr; } }

/* A preview that looks roughly like the real thing, so a caption that runs
   long or a photo that crops badly is obvious here rather than afterwards. */
.ig-preview { border: 1px solid var(--hairline); border-radius: var(--radius); overflow: hidden; background: var(--surface-raised); max-width: 340px; }
.ig-preview-head { display: flex; align-items: center; gap: 8px; padding: 9px 11px; border-bottom: 1px solid var(--hairline); font-size: 13px; }
.ig-avatar { width: 26px; height: 26px; border-radius: 50%; background: var(--accent-strong); display: inline-block; }
.ig-preview-media { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; display: block; }
.ig-preview-empty { display: flex; align-items: center; justify-content: center; background: var(--surface); color: var(--ink-muted); font-size: 12px; padding: 12px; text-align: center; }
.ig-preview-caption, .ig-preview-comment { padding: 10px 11px; font-size: 12.5px; line-height: 1.5; white-space: pre-wrap; }
.ig-preview-comment { border-top: 1px solid var(--hairline); color: var(--ink-muted); }

.import-row { border: 1px solid var(--hairline); border-radius: var(--radius); padding: 12px; margin-bottom: 10px; }
.import-caption { white-space: pre-wrap; font-family: inherit; font-size: 12.5px; margin: 8px 0 4px; line-height: 1.5; }
.radio-row { display: flex; align-items: center; gap: 9px; padding: 8px 0; border-bottom: 1px solid var(--hairline); }
.dbx-row { display: block; padding: 4px 2px; font-size: 12.5px; cursor: pointer; text-decoration: none; color: var(--ink); }
.dbx-row:hover { background: var(--surface); }
textarea.mono, .mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }

/* ------------------------------------------------- Social: media picker */
/* Media used to be a textarea of URLs. It worked, but you could not tell at a
   glance whether a post had the grand entrance on it or the cake table. */
.media-strip { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 6px; }
.media-item { width: 132px; border: 1px solid var(--hairline); border-radius: var(--radius); overflow: hidden; background: var(--surface-raised); }
.media-thumb { width: 100%; height: 100px; object-fit: cover; display: block; background: var(--surface); }
.media-thumb-video, .media-thumb-broken {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; font-size: 12px; color: var(--ink-muted); text-align: center; padding: 6px;
}
.media-item-bar { display: flex; align-items: center; justify-content: space-between; padding: 3px 5px; border-top: 1px solid var(--hairline); }
.media-item-bar form { display: inline; }
.media-index { font-size: 12px; color: var(--ink-muted); }
.media-alt { width: 100%; border: 0; border-top: 1px solid var(--hairline); border-radius: 0; font-size: 12px; padding: 5px 6px; }
.media-source { font-size: 12px; color: var(--ink-muted); padding: 0 6px 5px; }
.media-add {
  width: 132px; min-height: 100px; display: flex; flex-direction: column; gap: 6px;
  align-items: stretch; justify-content: center; padding: 8px; border-style: dashed;
}
.media-link-form { display: flex; flex-direction: column; gap: 4px; }
.media-link-form input { font-size: 12px; padding: 5px 6px; }

.modal-wide { max-width: 860px; width: 92vw; }
.dbx-bar { display: flex; align-items: center; gap: 10px; padding: 6px 0 10px; border-bottom: 1px solid var(--hairline); }
.dbx-folders { display: flex; flex-wrap: wrap; gap: 6px; padding: 10px 0; }
.dbx-folder {
  border: 1px solid var(--hairline); background: var(--surface-raised); border-radius: var(--radius-round);
  padding: 5px 12px; font-size: 12.5px; cursor: pointer; color: var(--ink);
}
.dbx-folder:hover { background: var(--surface); }
.dbx-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 8px; max-height: 46vh; overflow-y: auto; padding: 4px 2px;
}
.dbx-tile {
  position: relative; aspect-ratio: 1 / 1; border: 2px solid transparent; border-radius: var(--radius);
  overflow: hidden; padding: 0; cursor: pointer; background: var(--surface);
}
.dbx-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.dbx-tile-fallback { display: block; padding: 10px; font-size: 12px; color: var(--ink-muted); word-break: break-all; }
.dbx-tile.picked { border-color: var(--accent); }
.dbx-tick {
  position: absolute; top: 6px; right: 6px; width: 20px; height: 20px; border-radius: 50%;
  background: var(--accent-strong); color: var(--on-dark); font-size: 12px; line-height: 20px; display: none;
}
.dbx-tile.picked .dbx-tick { display: block; }
.modal-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding-top: 12px; border-top: 1px solid var(--hairline); margin-top: 12px; }

/* ---- Stream G: why a lead died ---- */
/* A lost card says so on the board, and an unanswered one says so louder.
   Gold rather than red: a lost lead is information, not an error. */
.board-card-lost {
  margin-top: 6px; font-size: 12px; letter-spacing: 0.02em; color: var(--ink-muted);
  border-top: 1px solid var(--hairline); padding-top: 5px;
}
.board-card-lost-missing { color: var(--warning); font-weight: 600; }
/* A card that is asking for something, rather than reporting something. */
.card-flag { border-left: 3px solid var(--warning-line); background: linear-gradient(90deg, var(--warning-tint) 0%, var(--surface-raised) 40%); }
/* The share-of-losses bar on the report. Decorative: every row prints its
   own count beside it, so nothing here is the only way to read the number. */
.meter { height: 4px; border-radius: var(--radius-sm); background: var(--hairline); margin-top: 5px; overflow: hidden; }
.meter-fill { height: 100%; background: var(--accent); border-radius: var(--radius-sm); }

/* ---- Stream H: the DJ music planning form ---- */
/* Read in a dark room, on a phone, with one hand — and sometimes printed and
   taped to the back of a speaker. Hence: dark by default so it doesn't blind
   anyone on a dance floor, type large enough to read at arm's length, and a
   print block that flips the whole thing back to ink on white. All of it is
   scoped under .runsheet so nothing here can reach the rest of the app. */
.runsheet {
  background: var(--rs-bg);
  color: var(--rs-text);
  font-size: 17px;
  line-height: 1.55;
  padding-bottom: 60px;
}
.rs-wrap { max-width: 780px; margin: 0 auto; padding: 20px 18px; }
.rs-muted { color: var(--rs-dim); }

.rs-head { border-bottom: 2px solid var(--rs-accent); padding-bottom: 16px; margin-bottom: 8px; }
.rs-eyebrow {
  font-size: 12px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--rs-accent);
}
.rs-title {
  font-family: var(--font-display); color: var(--rs-text);
  font-size: 34px; line-height: 1.15; margin: 4px 0 14px;
}
.rs-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px 20px; }
.rs-fact { display: flex; flex-direction: column; gap: 2px; }
.rs-fact-label {
  font-size: 12px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--rs-dim);
}
.rs-fact-value { font-size: 19px; font-weight: 600; }
.rs-fact-sub { display: block; font-size: 14px; font-weight: 400; color: var(--rs-dim); }
/* A phone number on this page exists to be dialled mid-panic, so it is a tap
   target rather than text that happens to be a link. */
.rs-tel {
  display: inline-block; color: var(--rs-bg); background: var(--rs-accent); text-decoration: none;
  border-radius: var(--radius-sm); padding: 2px 10px; font-size: 16px; font-weight: 600; margin-left: 2px;
}

.rs-jump { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.rs-jump a {
  color: var(--rs-text); text-decoration: none; border: 1px solid var(--rs-line);
  background: var(--rs-panel); border-radius: var(--radius-round); padding: 7px 14px; font-size: 14px;
}
.rs-jump a:active { background: var(--rs-line); }
.rs-jump-print { color: var(--rs-accent) !important; }

.rs-section { margin-top: 26px; scroll-margin-top: 12px; }
.rs-h2 {
  font-family: var(--font-display); color: var(--rs-accent);
  font-size: 22px; letter-spacing: 0.02em; margin: 0 0 10px;
  border-bottom: 1px solid var(--rs-line); padding-bottom: 6px;
}

.rs-vibe { margin-bottom: 12px; }
.rs-vibe-label {
  font-size: 12px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--rs-dim);
}
.rs-vibe-text { margin: 2px 0 0; font-size: 18px; }
/* The couple's own prose rule — "no country, no line dances" — is the one a
   song list cannot express, so it gets the loudest box on the page. */
.rs-danger {
  border: 1px solid var(--rs-red); border-left-width: 4px; border-radius: var(--radius);
  padding: 10px 14px; margin-top: 14px; background: rgba(232,132,120,0.08);
}
.rs-danger-label {
  color: var(--rs-red); font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase; font-weight: 600;
}
.rs-callout {
  border-left: 3px solid var(--rs-accent); background: var(--rs-panel);
  padding: 10px 14px; border-radius: 0 var(--radius) var(--radius) 0; margin-bottom: 14px;
}
.rs-callout-text { font-size: 20px; font-weight: 600; }

.rs-person {
  display: flex; justify-content: space-between; align-items: center; gap: 14px; flex-wrap: wrap;
  border-bottom: 1px solid var(--rs-line); padding: 11px 0;
}
.rs-person-name { font-size: 20px; font-weight: 600; }
/* The phonetic spelling is the reason this section exists. It reads as loud
   as the name itself, not as a footnote under it. */
.rs-say {
  color: var(--rs-accent); font-size: 18px; font-weight: 600; letter-spacing: 0.01em; margin-top: 1px;
}
.rs-person-meta { color: var(--rs-dim); font-size: 14px; margin-top: 2px; }
.rs-audio { height: 34px; max-width: 240px; }
.rs-note { color: var(--rs-dim); font-size: 14px; margin-top: 12px; font-style: italic; }

.rs-kv { margin-bottom: 10px; }
.rs-kv > div { padding: 4px 0; }
.rs-cue {
  display: grid; grid-template-columns: 200px 1fr; gap: 14px;
  border-bottom: 1px solid var(--rs-line); padding: 10px 0;
}
.rs-cue-label { color: var(--rs-dim); font-size: 14px; letter-spacing: 0.04em; text-transform: uppercase; }
.rs-cue-song { font-size: 19px; font-weight: 600; }
.rs-cue-person { font-size: 17px; font-weight: 500; }
.rs-cue-note { color: var(--rs-dim); font-size: 14.5px; font-weight: 400; margin-top: 2px; }

.rs-list { margin-bottom: 16px; }
.rs-list-label {
  font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--rs-accent); font-weight: 600;
}
.rs-list-dnp .rs-song-title { text-decoration: line-through; text-decoration-color: var(--rs-red); }
.rs-song { padding: 6px 0; border-bottom: 1px solid var(--rs-line); font-size: 17px; }
.rs-song-title { font-weight: 600; }
.rs-tag {
  display: inline-block; margin-left: 8px; font-size: 12px; letter-spacing: 0.06em;
  border: 1px solid var(--rs-line); border-radius: var(--radius-round); padding: 1px 8px; color: var(--rs-dim);
}
.rs-foot {
  margin-top: 34px; padding-top: 14px; border-top: 1px solid var(--rs-line);
  font-size: 13px; color: var(--rs-dim);
}

@media (max-width: 560px) {
  .rs-cue { grid-template-columns: 1fr; gap: 2px; }
  .rs-title { font-size: 28px; }
  .rs-audio { max-width: 100%; width: 100%; }
}

/* Paper. Same sheet, opposite palette — a dark page prints as a wall of
   toner, and half the DJs still bring a folder. */
@media print {
  .runsheet {
    --rs-bg: var(--surface-raised); --rs-panel: var(--surface-raised); --rs-line: var(--rs-print-line);
    --rs-text: var(--rs-print-text); --rs-dim: var(--rs-print-dim); --rs-accent: var(--rs-print-accent); --rs-red: var(--rs-print-red);
    background: var(--surface-raised); font-size: 12pt;
  }
  .rs-jump, .rs-audio { display: none; }
  .rs-tel { background: none; color: var(--rs-print-text); padding: 0; font-weight: 600; }
  .rs-section { break-inside: avoid; }
  .rs-person, .rs-cue, .rs-song { break-inside: avoid; }
}

/* ---- Stream F: the rich signature box ---- */
.rich-box {
  min-height: 92px;
  padding: 10px 12px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--surface-raised);
  font-size: 14px;
  line-height: 1.6;
  overflow-wrap: anywhere;
}
.rich-box:focus { outline: 2px solid var(--accent-strong); outline-offset: -1px; }
.rich-box a { color: var(--accent-strong); }   /* gold text on white was 2.9:1 (D-52) */
.rich-box img { max-width: 100%; height: auto; }

/* ---- Stream E: the song library's filter bar ---- */
/* Five dropdown buttons in place of the thirty-odd chips that used to sit on
   the page at once. Reuses .browse-group / .browse-panel from the couples'
   browse bar so both pages behave the same way. */
.browse-bar .browse-chip { display: inline-flex; align-items: center; gap: 5px; }
.browse-bar .browse-panel { width: 300px; max-height: 60vh; overflow-y: auto; }
.lib-count { align-self: center; margin-left: auto; white-space: nowrap; }

/* ---- Stream C: the proposal a couple actually opens ---- */
/* Laid out to read like a document rather than a screen: brand at the top
   left, the reference at the top right, then who it's for, what the event is
   and who it's from, side by side. Collapses to one column on a phone. */
.proposal-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.proposal-page { padding: 26px 0 8px; }
.proposal-brand { flex: 1 1 240px; min-width: 0; }
.proposal-logo { max-height: 64px; max-width: 240px; display: block; }
.proposal-wordmark { font-family: var(--font-display); font-size: 22px; line-height: 1.2; }
.proposal-meta { text-align: right; }
.proposal-title {
  font-family: var(--font-display); font-size: 27px; line-height: 1.2;
  margin: 18px 0 4px; padding-bottom: 14px; border-bottom: 1px solid var(--hairline);
}
.proposal-parties { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin-top: 14px; }
.proposal-label { font-family: var(--font-sans); font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.16em; color: var(--ink-muted); margin-bottom: 4px; }
.proposal-lines td, .proposal-lines th { vertical-align: top; }
.proposal-subtotal td { border-top: 1px solid var(--hairline); }
.proposal-discount td { color: var(--ink-muted); }
.proposal-total td { border-top: 2px solid var(--accent); font-size: 16px; }

@media (max-width: 620px) {
  .proposal-parties { grid-template-columns: 1fr; gap: 12px; }
  .proposal-meta { text-align: left; }
}

/* On paper, the buttons and the status pill are noise. */
@media print {
  .proposal-meta .pill, .proposal + .card { display: none; }
  .proposal { border: none; box-shadow: none; }
}

/* ---- Stream G: the contact profile ---- */
/* The "needs your attention" strip. Gold, not red: these are things to do,
   not things that have gone wrong. It renders only when there is something
   in it, so it never becomes wallpaper people stop reading. */
.card-todo { border-left: 3px solid var(--warning-line); }
.chip {
  display: inline-block; padding: 4px 10px; border-radius: var(--radius-round); font-size: 12px;
  font-weight: 600; background: var(--surface-raised); border: 1px solid var(--hairline); color: var(--ink);
  text-decoration: none; white-space: nowrap;
}
.chip:hover { border-color: var(--accent); }
.chip-warn { background: var(--warning-tint); border-color: var(--warning-line); color: var(--warning); }
/* Section headings inside an event block — quieter than the card's own h3. */
.card h4 { font-family: var(--font-sans); font-size: 12px; font-weight: 600; color: var(--ink-muted); margin: 0 0 6px; }

/* ---- Stream E: moving between the music planning pages ---- */
/* The same strip of tabs on every planning page, so a couple can go from
   The Vibe to Ceremony without going back out to the overview first. Reuses
   .tabs / .tab; the first tab is the way back. .plan-buttons is the same set
   of pages as buttons on the staff card that summarises the plan. */
.plan-nav .tab { display: inline-flex; align-items: center; gap: 6px; }
.plan-nav .tab svg { width: 13px; height: 13px; flex: none; }
.plan-nav-home { color: var(--ink-muted); }
.plan-nav-home:hover { color: var(--ink); }
.plan-buttons { display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end; }

/* ---- D-02: utilities standing in for the most repeated inline styles ---- */
/* Colour and type only. Spacing-only inline styles are left for a later pass. */
.text-right { text-align: right; }
.text-center { text-align: center; }
.nowrap { white-space: nowrap; }
.pre-wrap { white-space: pre-wrap; }
.pointer { cursor: pointer; }
.fw-600 { font-weight: 600; }
.fw-700 { font-weight: 600; }
.w-full { width: 100%; }
.gap-2 { gap: 16px; }
.text-red { color: var(--danger); }
.text-success { color: var(--accent-strong); }
.text-warn { color: var(--warning); }
.text-gold { color: var(--accent-strong); }
.stat-value-sm { font-size: 20px; }
.display-sm { font-family: var(--font-display); font-size: 20px; }
.card-tint { background: var(--surface); }
/* One tracked-uppercase label style. D-23 tunes the tracking and the face. */
/* THE label style. Every tracked-uppercase label in the app shares these
   five values; the rules below restate them rather than composing, because
   CSS cannot compose. Change them here and there together. (D-23) */
.label-caps { font-family: var(--font-sans); font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.16em; }

/* ---- D-10: navigation on a phone ---- */
/* Below 900px the sidebar goes and three things replace it: a bar across the
   top (brand, page title, menu), a drawer that the menu button opens -- a
   <details>, so it works with no JavaScript -- and, for couples and DJs, a
   tab bar pinned to the bottom with their three or four destinations. */
.mobile-bar { display: none; }
.tabbar { display: none; }
.mobile-nav > summary { list-style: none; cursor: pointer; }
.mobile-nav > summary::-webkit-details-marker { display: none; }
body.drawer-open { overflow: hidden; }

@media (max-width: 900px) {
  .sidebar { display: none; }
  .mobile-bar {
    display: flex; align-items: center; gap: 12px;
    position: sticky; top: 0; z-index: 40;
    padding: 10px 14px; background: var(--sidebar-bg); color: var(--sidebar-text);
    border-bottom: 1px solid var(--sidebar-hover);
  }
  .mobile-brand { display: flex; flex: none; }
  .mobile-brand .brand-mark { width: 30px; height: 30px; font-size: 13px; }
  .mobile-title {
    flex: 1; min-width: 0; text-align: center;
    font-family: var(--font-display); font-size: 16px; color: var(--on-dark);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .mobile-menu-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; margin: -7px -8px -7px 0; border-radius: var(--radius);
    color: var(--on-dark);
  }
  .mobile-menu-btn:hover { background: var(--sidebar-hover); }

  .drawer-backdrop { display: none; }
  .mobile-nav[open] .drawer-backdrop { display: block; position: fixed; inset: 0; z-index: 60; background: var(--scrim); }
  .drawer { display: none; }
  .mobile-nav[open] .drawer {
    display: flex; flex-direction: column; gap: 4px;
    position: fixed; top: 0; right: 0; bottom: 0; z-index: 70;
    width: min(300px, 86vw); padding: 18px 16px 22px; overflow-y: auto;
    background: var(--sidebar-bg); color: var(--sidebar-text);
    box-shadow: var(--shadow-float);
    text-align: left; font-size: 14px;
  }
  .drawer-head { display: flex; align-items: flex-start; justify-content: space-between; }
  .drawer-head .brand { padding-bottom: 10px; }
  .drawer-close {
    background: none; border: none; color: var(--sidebar-muted); cursor: pointer;
    width: 44px; height: 44px; margin: -8px -10px 0 0; border-radius: var(--radius);
    display: inline-flex; align-items: center; justify-content: center;
  }
  .drawer-close:hover { color: var(--on-dark); background: var(--sidebar-hover); }
  .drawer .nav-link { min-height: 44px; }

  .has-tabbar .content { padding-bottom: 88px; }
  .tabbar {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
    background: var(--surface-raised); border-top: 1px solid var(--hairline);
    padding: 6px 4px calc(6px + env(safe-area-inset-bottom));
  }
  .tabbar-item {
    flex: 1; display: flex; flex-direction: column; align-items: center; gap: 3px;
    min-height: 48px; padding: 6px 2px; border-radius: var(--radius);
    color: var(--ink-muted); font-size: 12px; font-weight: 600; text-align: center;
  }
  .tabbar-item svg { width: 20px; height: 20px; }
  .tabbar-item.active { color: var(--accent-strong); }
  .tabbar-item.active svg { color: var(--accent); }
}

/* ---- D-11: a phone is 390px wide, and nothing may be wider ---- */
@media (max-width: 900px) {
  .content { padding: 18px 14px 60px; }
  /* Two-column layouts written inline (2fr 1fr, 1.3fr .7fr) collapse like the
     named grids do. !important because an inline style is the only thing
     that outranks it, and that inline style is exactly what is being undone. */
  .grid[style*="grid-template-columns"] { grid-template-columns: 1fr !important; }
}
@media (max-width: 640px) {
  .field-row { flex-direction: column; gap: 0; }
  .page-head { flex-direction: column; align-items: stretch; }
  .page-head > .flex-gap { flex-wrap: wrap; }
  /* Line items stack: the description on its own line, then qty x price and
     the amount underneath, rather than a five-column table squeezed to slivers. */
  .table-lines thead { display: none; }
  .table-lines tr { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px; padding: 9px 0; border-bottom: 1px solid var(--hairline); }
  .table-lines tr:last-child { border-bottom: none; }
  .table-lines td { display: inline-block; border: none; padding: 0; }
  .table-lines td:first-child { display: block; width: 100%; font-weight: 600; }
  .table-lines td:last-child { margin-left: auto; font-weight: 600; }
}

/* ---- D-12: the calendar on a phone, and each kind of event's colour ---- */
.cal-type-wedding { background: var(--accent-tint); color: var(--accent-strong); }
.cal-type-call { background: var(--info-tint); color: var(--info); }
.cal-type-payment { background: var(--danger-tint); color: var(--danger); }
.cal-type-loadin { background: var(--accent-tint); color: var(--accent-strong); }
.cal-type-other { background: var(--surface-sunken); color: var(--ink-muted); }

.cal-controls { display: flex; align-items: center; gap: 8px; }
.cal-month { padding: 0 6px; white-space: nowrap; }

/* The agenda exists only on a phone; the grid only off one. Both are in the
   page, so this needs no script and no second request. */
.calendar-agenda { display: none; }
.agenda-week { margin-bottom: 18px; }
.agenda-week-label { font-family: var(--font-sans); font-size: 12px; font-weight: 600;  color: var(--ink-muted); margin-bottom: 6px; }
.agenda-evt {
  display: grid; grid-template-columns: 64px 1fr auto; align-items: center; gap: 10px;
  padding: 12px 12px; margin-bottom: 6px; min-height: 48px;
  background: var(--surface-raised); border: 1px solid var(--hairline); border-radius: var(--radius);
}
.agenda-date { font-weight: 600; font-size: 12.5px; color: var(--ink-muted); white-space: nowrap; }
.agenda-title { font-weight: 600; font-size: 13.5px; min-width: 0; }
.agenda-evt .pill { font-size: 12px; }

@media (max-width: 640px) {
  .calendar-grid { display: none; }
  .calendar-agenda { display: block; }
  .cal-controls { width: 100%; justify-content: space-between; }
  .cal-controls .btn { min-height: 44px; padding: 0 16px; }
  .agenda-evt { grid-template-columns: 56px 1fr; }
  .agenda-evt .pill { grid-column: 2; justify-self: start; }
}

/* ---- D-14: what is waiting, beside the link that leads to it ---- */
.nav-badge {
  margin-left: auto; min-width: 20px; height: 20px; padding: 0 6px; border-radius: var(--radius-round);
  background: var(--accent-strong); color: var(--on-accent); font-size: 12px; font-weight: 600;
  display: inline-flex; align-items: center; justify-content: center; line-height: 1;
}

/* ---- D-15: the quick-jump box and its results ---- */
.nav-search { margin: 0 0 8px; }
.nav-search input[type=search] {
  background: rgba(255,255,255,0.07); border-color: rgba(255,255,255,0.12); color: var(--on-dark);
  font-size: 13px; padding: 8px 11px;
}
.nav-search input[type=search]::placeholder { color: var(--sidebar-muted); }
.nav-search input[type=search]:focus { background: rgba(255,255,255,0.11); border-color: var(--accent); box-shadow: none; }
.search-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 0; border-bottom: 1px solid var(--hairline);
}
.search-row:last-child { border-bottom: none; }
.search-row:hover { background: var(--surface); }
.search-row .pill { margin-left: auto; }

/* ---- D-16: breadcrumbs ---- */
.crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: 12px; color: var(--ink-muted); margin-bottom: 10px; }
.crumbs a:hover { color: var(--ink); text-decoration: underline; }
.crumbs [aria-current] { color: var(--ink); font-weight: 600; }
.crumb-sep { opacity: 0.5; }

/* ---- D-20: the brand block, drawn from the real logo or the pulse mark ---- */
.letterhead { display: inline-flex; align-items: center; gap: 10px; color: inherit; }
.letterhead-center { justify-content: center; }
.letterhead-words { display: flex; flex-direction: column; line-height: 1.15; }
.pulse-mark { width: 34px; height: 34px; flex: none; color: var(--accent); }
.brand-logo { display: block; max-height: 40px; max-width: 200px; width: auto; }
.sidebar .brand { padding: 0 8px 22px; }
.mobile-brand .letterhead-words { display: none; }
.mobile-brand .pulse-mark { width: 28px; height: 28px; }
.mobile-brand .brand-logo { max-height: 28px; max-width: 140px; }
.login-brand .letterhead { flex-direction: column; gap: 8px; }
.login-brand .pulse-mark { width: 52px; height: 52px; }
.login-brand .brand-logo { max-height: 56px; max-width: 240px; margin: 0 auto; }
.login-brand .brand-name { font-size: 22px; }
.public-letterhead { display: flex; flex-direction: column; align-items: center; gap: 4px; margin-bottom: 22px; text-align: center; }
.public-letterhead .brand-name { color: var(--ink); font-size: 18px; }
.public-letterhead .brand-logo { max-height: 56px; max-width: 260px; }
/* Settings -> Branding previews */
.brand-preview { display: flex; align-items: center; gap: 10px; min-height: 64px; padding: 10px 12px; margin-bottom: 8px; border: 1px solid var(--hairline); border-radius: var(--radius); background: var(--surface-raised); }
.brand-preview img { max-height: 48px; max-width: 220px; display: block; }
.brand-preview-dark { background: var(--sidebar-bg); color: var(--sidebar-text); }
.brand-preview-dark .muted { color: var(--sidebar-muted); }
.brand-preview-hero { padding: 0; overflow: hidden; }
.brand-preview-hero img { max-height: 160px; max-width: 100%; width: 100%; object-fit: cover; }
.brand-preview-empty .pulse-mark { width: 28px; height: 28px; }

/* ---- D-21: progress, in brand green, for the client portal ---- */
.progress { height: 6px; border-radius: var(--radius-sm); background: var(--surface-sunken); overflow: hidden; }
.progress-fill { height: 100%; border-radius: var(--radius-sm); background: var(--accent); transition: width .3s ease; }
.progress-row { display: grid; grid-template-columns: 1fr auto; gap: 4px 12px; align-items: center; padding: 8px 0; }
.progress-row .progress { grid-column: 1 / -1; }
.progress-label { font-weight: 600; font-size: 13.5px; }
.progress-value { font-size: 12px; color: var(--ink-muted); }
.progress-row.done .progress-label::before { content: '✓ '; color: var(--accent-strong); }

/* ---- D-22: the heartbeat rule ---- */
/* The website's signature detail: a hairline with one ECG blip in it. An
   inline SVG data URI in brand green, used sparingly -- under the dashboard
   title, on the login card, at the top of a proposal or pay page. Not on
   every card. */
.pulse-rule {
  height: 16px; margin: 6px 0 18px; opacity: 0.7;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 16' preserveAspectRatio='none'%3E%3Cpath d='M0 8H176l5-6 5 12 5-9 4 5h205' fill='none' stroke='%2300A160' stroke-width='1.5' stroke-linejoin='round' stroke-linecap='round'/%3E%3C/svg%3E") left center / 100% 16px no-repeat;
}
.pulse-rule-short { max-width: 220px; margin-left: auto; margin-right: auto; }

/* ---- D-25: the hero panel ---- */
.hero {
  position: relative; overflow: hidden; margin-bottom: 18px;
  border-radius: var(--radius); padding: 34px 28px 26px;
  background: var(--ink) center / cover no-repeat; color: var(--on-dark);
}
.hero-photo::before { content: ''; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(33,31,29,0.35), rgba(33,31,29,0.78)); }
.hero-inner { position: relative; max-width: 720px; }
.hero-eyebrow { color: var(--accent); }
.hero-title { color: var(--on-dark); font-size: 34px; line-height: 1.1; margin: 2px 0 6px; }
.hero-sub { font-size: 15px; color: rgba(255,255,255,0.8); }
.pulse-rule-hero { margin: 14px 0 0; max-width: 260px; opacity: 0.95; }
.hero .btn { margin-top: 14px; }
@media (max-width: 640px) { .hero { padding: 26px 18px 20px; border-radius: var(--radius); } .hero-title { font-size: 28px; } }
/* The login page, with a photo behind it. */
.login-wrap.login-hero { background-color: var(--ink); background-size: cover; background-position: center; }
.login-wrap.login-hero::before { content: ''; position: fixed; inset: 0; background: var(--scrim); }
.login-wrap.login-hero .login-card { position: relative; }

/* ---- D-30: the project header ---- */
/* One primary action; two secondary; everything else behind More. The stage
   sits under the title as a coloured pill that is really a <select>, so it
   reads as part of what the project IS rather than as a form field. */
.status-row { margin-top: 8px; }
.status-select-wrap { display: inline-block; }
.status-select {
  width: auto; display: inline-block; padding: 4px 30px 4px 12px; border-radius: var(--radius-round);
  border: 1px solid var(--status-color, var(--hairline));
  background: var(--surface-sunken);
  background: color-mix(in srgb, var(--status-color, var(--ink-muted)) 14%, var(--surface-raised));
  color: var(--ink); font-family: var(--font-sans); font-size: 12px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.08em; cursor: pointer;
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%2355504A' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 11px center; background-size: 10px 7px;
}
.status-select:focus { outline: 2px solid var(--accent-strong); outline-offset: 1px; }
.page-actions { flex-wrap: wrap; justify-content: flex-end; }
.more-menu .add-menu-panel form { margin-bottom: 6px; }
.menu-section-label { color: var(--ink-muted); margin: 10px 0 6px; }
.menu-section-label:first-child { margin-top: 0; }

/* ---- D-32 ---- */
.money-empty { padding: 10px 14px; border: 1px dashed var(--hairline); border-radius: var(--radius); }

/* ---- D-33: the pipeline board ---- */
/* A status's colour is a 4px bar on the column and a dot by the title; the
   title itself stays ink, because pale status colours failed contrast as
   text. */
.board-col { border-top: 4px solid var(--col-color, var(--hairline)); }
.board-col-title { color: var(--ink); display: inline-flex; align-items: center; gap: 6px; }
.board-col-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--col-color, var(--ink-muted)); flex: none; }
.board-col-count { white-space: nowrap; }
/* An empty column says so, rather than sitting as a blank beige box. */
.board-col-body:empty { min-height: 72px; border: 1px dashed var(--hairline); border-radius: var(--radius); position: relative; }
.board-col-body:empty::after { content: 'Drop here'; position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 12px; color: var(--ink-muted); opacity: 0.7; }
.board-card-chips { display: flex; flex-wrap: wrap; gap: 4px; margin: -2px 0 6px; }
.chip-xs { padding: 1px 7px; font-size: 12px; font-family: var(--font-sans); text-transform: uppercase; letter-spacing: 0.06em; }
.board-card-meta svg { width: 12px; height: 12px; vertical-align: -2px; margin-right: 4px; }
.board-filters { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 14px; }
.board-filters select, .board-filters input[type=search] { width: auto; min-width: 150px; padding: 7px 10px; font-size: 13px; }
.board-filters input[type=search] { flex: 1 1 180px; }
@media (max-width: 640px) { .board-filters select, .board-filters input[type=search] { width: 100%; } }

/* ---- D-34: the dashboard ---- */
a.stat { display: block; color: inherit; }
a.stat:hover { border-color: var(--accent); }
.needs-row { padding: 10px 0; border-bottom: 1px solid var(--hairline); }
.count-pill {
  display: inline-flex; align-items: center; justify-content: center; min-width: 22px; height: 22px;
  padding: 0 7px; margin-right: 8px; border-radius: var(--radius-round);
  background: var(--accent-tint); color: var(--accent-strong); font-size: 12px; font-weight: 600; vertical-align: -1px;
}

/* ---- D-35: settings, grouped ---- */
.settings-group { margin-bottom: 22px; }
.settings-group-title { color: var(--ink-muted); margin-bottom: 10px; }
.settings-card { display: flex; flex-direction: column; }
.settings-card p { flex: 1; }
.settings-status { font-size: 12px; font-weight: 600; margin-top: 8px; }

/* ---- D-36: the automation list ---- */
.group-row td { background: var(--surface-sunken); font-family: var(--font-sans); font-size: 12px; font-weight: 600; color: var(--ink-muted); padding: 6px 12px; }
.group-row:hover td { background: var(--surface-sunken); }
.stop-flag { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; margin-right: 3px; border-radius: var(--radius-sm); background: var(--surface-sunken); font-size: 12px; font-weight: 600; color: var(--ink-muted); cursor: help; }

/* ---- D-37: add-forms fold away ---- */
.add-form > summary { list-style: none; display: inline-flex; cursor: pointer; }
.add-form > summary::-webkit-details-marker { display: none; }
.add-form[open] > summary { margin-bottom: 8px; }
.add-form > summary svg { width: 13px; height: 13px; }

/* ---- D-38: social ---- */
/* Another company's brand colour is a dot, not a whole pill. */
.platform-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: none; }
.grid-tile-empty { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; width: 100%; height: 100%; padding: 8px; }
.grid-tile-empty .pulse-mark { position: absolute; width: 58%; height: 58%; opacity: 0.08; }
.grid-tile-empty-label { position: relative; font-family: var(--font-sans); font-size: 12px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-muted); }
.grid-tile-empty .grid-tile-text { position: relative; padding: 0; font-size: 12px; }
.inline-details { display: inline; }
.inline-details > summary { display: inline; cursor: pointer; color: var(--accent-strong); text-decoration: underline; }

/* ---- D-39: tables ---- */
tbody tr.pointer:hover { background: var(--surface); }
.money, td.money { text-align: right; font-variant-numeric: tabular-nums; }

/* ---- D-40: the couple's overview ---- */
.next-step { border-left: 4px solid var(--accent); }
.next-step-row { gap: 14px; flex-wrap: wrap; }
.team-row { display: flex; gap: 12px; align-items: center; }
.avatar-lg { width: 44px; height: 44px; font-size: 15px; }
a.progress-row { color: inherit; }
a.progress-row:hover .progress-label { color: var(--accent-strong); }

/* ---- D-41: the music planning journey ---- */
.journey-head .journey-pct { font-family: var(--font-display); font-size: 22px; color: var(--accent-strong); flex: none; margin-left: var(--space-3); }   /* never wrapped into the sentence beside it */
.journey { list-style: none; margin: 16px 0 0; padding: 0; }
.journey-step { margin-bottom: 8px; border: 1px solid var(--hairline); border-radius: var(--radius); background: var(--surface-raised); padding: 0 16px 0 0; }
.journey-step:hover { border-color: var(--accent); }
.journey-link { display: flex; align-items: center; gap: 14px; padding: 14px 0 14px 14px; color: inherit; }
.journey-num { width: 32px; height: 32px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; flex: none; background: var(--surface-sunken); color: var(--ink-muted); font-weight: 600; font-size: 13px; }
.journey-num svg { width: 16px; height: 16px; stroke-width: 3; }
.journey-step.done .journey-num { background: var(--accent); color: var(--on-dark); }
.journey-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.journey-title { font-weight: 600; font-size: 14.5px; }
.journey-count { font-size: 12px; font-weight: 600; color: var(--ink-muted); white-space: nowrap; }
.journey-step.done .journey-count { color: var(--accent-strong); }
.journey-segments { padding: 0 0 14px 60px; align-items: center; }
.chip-done { border-color: var(--accent-tint); background: var(--accent-tint); color: var(--accent-strong); }
.timeline-quiet .timeline-time { color: var(--ink-muted); }
@media (max-width: 640px) { .journey-segments { padding-left: 14px; } }

/* ---- D-42: the couple's forms and payments ---- */
.form-card-row { gap: 14px; flex-wrap: wrap; }
.form-card-done { opacity: 0.85; }
.pay-schedule { list-style: none; margin: 0; padding: 0; }
.pay-step { display: flex; align-items: center; gap: 14px; padding: 12px 0; border-bottom: 1px solid var(--hairline); }
.pay-step:last-child { border-bottom: none; }
.pay-dot { width: 26px; height: 26px; border-radius: 50%; border: 2px solid var(--hairline); display: inline-flex; align-items: center; justify-content: center; flex: none; color: var(--on-dark); }
.pay-dot svg { width: 14px; height: 14px; stroke-width: 3; }
.pay-step.done .pay-dot { background: var(--accent); border-color: var(--accent); }
.pay-step.next .pay-dot { border-color: var(--accent); }
.pay-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }

/* ---- D-43: the DJ's page and the music planning form's light room ---- */
.tonight-btn { font-size: 15px; padding: 14px 18px; margin-bottom: 18px; }
.event-card .eyebrow { margin-bottom: 2px; }
.rs-toggle {
  color: var(--rs-text); background: var(--rs-panel); border: 1px solid var(--rs-line); border-radius: var(--radius-round);
  padding: 7px 14px; font-size: 14px; font-family: inherit; cursor: pointer; margin-left: auto;
}
.runsheet.runsheet-light {
  --rs-bg: var(--surface-raised); --rs-panel: var(--surface); --rs-line: var(--hairline);
  --rs-text: var(--ink); --rs-dim: var(--ink-muted); --rs-accent: var(--accent-strong); --rs-red: var(--danger);
}
.runsheet .rs-danger { background: rgba(232,132,120,0.08); }
.runsheet.runsheet-light .rs-danger { background: var(--danger-tint); }
@media print { .rs-toggle { display: none; } }

/* ---- D-44: the public pages ---- */
/* Payment methods as tabs, in CSS alone: radio inputs carry the state. */
.pay-tabs { display: flex; flex-wrap: wrap; gap: 6px; }
.pay-tab-input { position: absolute; opacity: 0; pointer-events: none; }
.pay-tab { flex: 1 1 0; text-align: center; padding: 10px 12px; border: 1px solid var(--hairline); border-radius: var(--radius); font-weight: 600; font-size: 13.5px; cursor: pointer; background: var(--surface-raised); min-height: 44px; display: flex; align-items: center; justify-content: center; }
.pay-tab-input:checked + .pay-tab { background: var(--accent-strong); border-color: var(--accent); color: var(--on-accent); }
.pay-tab-input:focus-visible + .pay-tab { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
.pay-panels { flex-basis: 100%; }
.pay-panel { display: none; }
.pay-panel .card { margin: 10px 0 0 !important; }
#pay-tab-CARD:checked ~ .pay-panels .pay-panel-CARD,
#pay-tab-ZELLE:checked ~ .pay-panels .pay-panel-ZELLE,
#pay-tab-VENMO:checked ~ .pay-panels .pay-panel-VENMO { display: block; }
.sent-details > summary { list-style: none; }
.sent-details > summary::-webkit-details-marker { display: none; }
.sent-details[open] > summary { margin-bottom: 10px; }
.approved-hero { background: var(--accent-tint); border: 1px solid var(--accent); border-radius: var(--radius); padding: 24px 26px 18px; margin-bottom: 18px; color: var(--ink); }
.approved-hero .eyebrow { color: var(--accent-strong); }
.approved-title { font-size: 24px; margin: 4px 0 6px; }
.approved-hero .pulse-rule-hero { max-width: 220px; margin-top: 12px; }
.public-footer { text-align: center; margin-top: 28px; line-height: 1.8; }
.office-line a { color: var(--ink); font-weight: 600; }

/* ---- D-45: the login page ---- */
/* With a hero photo: the photograph fills the left, the card sits right.
   Without one: charcoal, the card centred, as before. */
.login-kicker { color: var(--accent-strong); margin-top: 6px; }
.login-card .letterhead { margin-bottom: 4px; }
@media (min-width: 900px) {
  .login-wrap.login-hero { justify-content: flex-end; padding-right: 8vw; }
  .login-wrap.login-hero::before { background: linear-gradient(90deg, rgba(33,31,29,0.25), rgba(33,31,29,0.7) 60%); }
}

/* ---- D-50: visible keyboard focus ---- */
/* Inputs already had a focus ring. Buttons, links, nav items, tabs and board
   cards had none, so a keyboard user could not tell where they were.
   :focus-visible, so a mouse click does not draw it. */
:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
.sidebar :focus-visible, .drawer :focus-visible { outline-color: var(--accent-tint); }

/* ---- D-51: tap targets ---- */
@media (max-width: 900px) {
  .btn, .nav-link, .icon-btn, .tab, .tabbar-item, .chip, .browse-chip, .az, .pay-tab { min-height: 44px; }
  .az { min-width: 40px; }
  .icon-btn { min-width: 44px; display: inline-flex; align-items: center; justify-content: center; }
  .btn-sm { padding-top: 8px; padding-bottom: 8px; }
}

/* ---- D-53: the empty state ---- */
.empty-state { text-align: center; padding: 34px 20px; color: var(--ink-muted); }
.empty-icon svg { width: 28px; height: 28px; opacity: 0.35; margin-bottom: 8px; }
.empty-illus { color: var(--ink-muted); opacity: 0.85; margin-bottom: 10px; }
.empty-illus svg { width: 64px; height: 64px; }
.empty-title { font-size: 13.5px; }
.empty-action { margin-top: 10px; }

/* ---- D-54: motion ---- */
/* Hovers stay at 120ms. The toast's slide-in and the card transitions go
   quiet for anyone who asked their system for less movement. */
@media (prefers-reduced-motion: reduce) {
  .toast, .segment-card, .progress-fill, .grid-tile, .journey-step { transition: none !important; }
  .toast { transform: none !important; }
}

/* ---- the render sweep: two classes that were used but never defined ---- */
.hero-charcoal { background-color: var(--ink); }   /* the hero with no photo: charcoal and the pulse rule (D-25) */
.form-card { padding: 16px 18px; }                 /* one card per form on the couple's Forms page (D-42) */

/* ---- Stream C: batch retire on Packages & Discounts ---- */
.check-col { width: 28px; padding-right: 0; }
.check-col input { width: auto; margin: 0; }
.bulk-bar { align-items: center; flex-wrap: wrap; }

/* ---- Stream E: the song request results ---- */
/* .result-list scrolls, and a scrolling box clips on both axes -- so with
   one result the "+" menu was sheared off at the bottom. Let it out while a
   menu is open; the list is short in exactly that case. */
.result-list:has(.add-menu[open]) { max-height: none; overflow: visible; }
.approval-preview pre { max-height: 320px; overflow: auto; background: var(--surface-2, var(--surface-raised)); padding: 10px 12px; border-radius: var(--radius-sm); }
.approval-item > summary { list-style: none; }
.approval-item > summary::-webkit-details-marker { display: none; }

/* ---- Stream G + D: boards fit the screen instead of scrolling sideways ---- */
/* Columns wrap into as many rows as they need, so the page scrolls down and
   never across. On a phone the columns stack, and the dropdown above them
   shows one stage at a time; with no JavaScript every stage stacks, which
   still beats a sideways scroll. */
.board { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); overflow-x: visible; align-items: start; }
.board-col { flex: none; min-width: 0; }
.board-col-title { min-width: 0; overflow-wrap: anywhere; }
.board.no-drag .board-card { cursor: pointer; }
.board.no-drag .board-col-body:empty::after { content: 'Nothing here yet'; }
.board-jump { display: none; }
@media (max-width: 700px) {
  .board { grid-template-columns: 1fr; }
  .board-jump { display: flex; gap: 10px; align-items: center; margin-bottom: 12px; }
  .board-jump select { flex: 1 1 auto; width: auto; min-width: 0; }
  .board.is-focused .board-col:not(.is-shown) { display: none; }
  .board-col-body:empty::after { content: 'Nothing here yet'; }
}

/* ---- Stream C + D: the proposal letterhead and the signature record ---- */
.proposal-contact { margin-top: 6px; line-height: 1.5; }
.signature-record code { font-size: 11px; }

/* ---- Stream C: the QR codes on a pay page ---- */
.pay-qr svg { max-width: 176px; width: 100%; height: auto; border: 1px solid var(--hairline); border-radius: var(--radius); }

/* ---- Stream A: adding media on its own full-width row, and the fetch warning ---- */
/* The add form used to live in a 132px tile, so a pasted URL was cut off after
   a dozen characters. It gets the width of the card: Dropbox button, URL box,
   Add, on one line; the box takes whatever is left. */
.media-add-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 12px; }
.media-add-form { display: flex; flex: 1 1 320px; gap: 8px; align-items: center; min-width: 0; margin: 0; }
.media-add-form input[type=url] { flex: 1 1 auto; min-width: 0; width: auto; }
.media-add-form .btn { flex: 0 0 auto; }
.media-chip { font-size: 11px; line-height: 1.3; padding: 4px 6px; border-top: 1px solid var(--hairline); cursor: help; }
.media-chip-bad { background: var(--danger-tint); color: var(--danger); font-weight: 600; }
.media-chip-unsure { background: var(--warning-tint); color: var(--warning); }
.dbx-more { display: flex; justify-content: center; padding: 10px 0 0; }
.dbx-more[hidden] { display: none; }

/* ---- Stream D: contract blanks that fit what goes in them ---- */
/* input[type=text] is width:100% app-wide and outranks .fill-inline, so say it with the attribute too. */
input[type=text].fill-inline[data-fill-grow] { width: auto; field-sizing: content; min-width: 14ch; max-width: 100%; box-sizing: border-box; }

/* ---- Stream H: linked (Google) calendars on the calendar page ---- */
.cal-feed { border-left: 3px solid currentColor; cursor: default; }
.cal-feed-slate { background: var(--surface-sunken); color: var(--ink-muted); }
.cal-feed-blue { background: var(--info-tint); color: var(--info); }
.cal-feed-green { background: var(--accent-tint); color: var(--accent-strong); }
.cal-feed-gold { background: var(--accent-tint); color: var(--accent-strong); }
.cal-feed-red { background: var(--danger-tint); color: var(--danger); }
.feed-row { border-top: 1px solid var(--hairline); padding: 14px 0; }
.feed-row:first-of-type { border-top: none; }

/* ---- Stream E: the three lists as buttons on the song's own row ---- */
.result-row { flex-wrap: wrap; }
.add-inline { display: flex; flex: 0 0 auto; gap: 6px; margin: 0; align-items: center; }
.add-inline-btn { white-space: nowrap; padding: 5px 10px; }
.add-inline-btn svg { width: 13px; height: 13px; }
.add-inline-dnp { color: var(--danger); }
.add-inline-dnp:hover { background: var(--danger-tint); border-color: var(--danger-tint); }
@media (max-width: 760px) {
  /* Still the song's own row: the buttons drop under its title, inside the same rule lines. */
  .add-inline { flex: 1 0 100%; min-width: 0; gap: 5px; }
  .add-inline-btn { flex: 1 1 0; min-width: 0; padding: 7px 2px; font-size: 11.5px; }
  #req-results .result-list { overflow-x: hidden; }
}

/* ---- Stream E: the grand entrance order ---- */
.entrance-list { list-style: none; margin: 0; padding: 0; }
.entrance-row { display: flex; align-items: center; gap: 10px; padding: 9px 4px; border-bottom: 1px solid var(--hairline); background: var(--surface-raised); }
.entrance-row:last-child { border-bottom: none; }
.entrance-row.is-dragging { opacity: 0.45; }
.entrance-num {
  flex: 0 0 26px; width: 26px; height: 26px; border-radius: 50%; background: var(--accent-tint); color: var(--accent-strong);
  display: inline-flex; align-items: center; justify-content: center; font-weight: 600; font-size: 12.5px;
}
.entrance-last { vertical-align: middle; margin-right: 6px; }
.entrance-grip { cursor: grab; color: var(--ink-muted); letter-spacing: -3px; user-select: none; }
.entrance-who { flex: 1; min-width: 0; }
.entrance-moves form { margin: 0; }
.entrance-moves .icon-btn[disabled] { opacity: 0.25; cursor: default; }
@media (max-width: 640px) {
  /* The name gets the whole line; the arrows go underneath it, inside the same row. */
  .entrance-grip { display: none; }
  .entrance-row { flex-wrap: wrap; row-gap: 2px; }
  .entrance-who { flex: 1 1 calc(100% - 40px); }
  .entrance-moves { flex: 1 0 100%; justify-content: flex-end; gap: 6px; }
}

/* ---- Stream H: what goes to which Google calendar ---- */
.route-row { display: grid; grid-template-columns: minmax(140px, 240px) 1fr; gap: 10px; align-items: center; margin-bottom: 6px; }
.route-row select { width: 100%; }
@media (max-width: 640px) { .route-row { grid-template-columns: 1fr; gap: 2px; margin-bottom: 10px; } }

/* ---- Stream D: a contract term the office has set and the signer cannot change ---- */
.fill-value.fill-locked { border-bottom-style: solid; white-space: nowrap; }

/* ---- Stream F: tables on a phone ---------------------------------------
   A table with five columns does not fit 375px, and scrolling a table
   sideways inside a page that scrolls down is miserable. So under 640px every
   table that has a header row stops being a grid: each row becomes a small
   card, the first cell its title, and every other cell a "Label ... value"
   line. The labels are the column headings, copied onto the cells by app.js
   (data-label); without JavaScript the cards still stack, just unlabelled.
   One rule for every table, so a new page gets it for free. Opt out with
   data-keep-table; .table-lines (proposal and invoice lines) has its own. */
@media (max-width: 640px) {
  table:has(> thead):not(.table-lines):not([data-keep-table]) { display: block; width: 100%; }
  table:has(> thead):not(.table-lines):not([data-keep-table]) > thead {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  table:has(> thead):not(.table-lines):not([data-keep-table]) > tbody,
  table:has(> thead):not(.table-lines):not([data-keep-table]) > tfoot { display: block; }
  table:has(> thead):not(.table-lines):not([data-keep-table]) > * > tr {
    display: block; padding: 10px 12px; border-bottom: 1px solid var(--hairline);
  }
  table:has(> thead):not(.table-lines):not([data-keep-table]) > * > tr:last-child { border-bottom: none; }
  table:has(> thead):not(.table-lines):not([data-keep-table]) > * > tr > td {
    display: flex; flex-wrap: wrap; align-items: baseline; justify-content: flex-end; gap: 4px 10px;
    width: auto; border: none; padding: 3px 0; text-align: right; overflow-wrap: anywhere; min-width: 0;
  }
  table:has(> thead):not(.table-lines):not([data-keep-table]) > * > tr > td[data-label]::before {
    content: attr(data-label); flex: 0 0 38%; margin-right: auto; text-align: left;
    font-family: var(--font-sans); font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em; color: var(--ink-muted);
  }
  /* The first cell is what the row IS: a name, a number, a title. */
  table:has(> thead):not(.table-lines):not([data-keep-table]) > * > tr > td:first-child {
    display: block; text-align: left; font-weight: 600; font-size: 14.5px; padding-bottom: 5px;
  }
  table:has(> thead):not(.table-lines):not([data-keep-table]) > * > tr > td:first-child::before { content: none; }
  /* A cell with no heading over it is the row's buttons; a spanning cell is a note or a total. */
  table:has(> thead):not(.table-lines):not([data-keep-table]) > * > tr > td:not([data-label]):not(:first-child) { justify-content: flex-start; text-align: left; padding-top: 6px; }
  table:has(> thead):not(.table-lines):not([data-keep-table]) > * > tr > td:empty { display: none; }
  table:has(> thead):not(.table-lines):not([data-keep-table]) > * > tr > td > input:not([type=checkbox]):not([type=radio]),
  table:has(> thead):not(.table-lines):not([data-keep-table]) > * > tr > td > select { flex: 1 1 140px; min-width: 0; }
  table:has(> thead):not(.table-lines):not([data-keep-table]) > * > tr > td audio { max-width: 100%; }
  /* A table with no header row (a short list, a label-and-value pair): the
     first cell takes the line, the rest follow underneath and wrap. */
  table:not(:has(> thead)):not(.table-lines):not([data-keep-table]),
  table:not(:has(> thead)):not(.table-lines):not([data-keep-table]) > tbody { display: block; width: 100%; }
  table:not(:has(> thead)):not(.table-lines):not([data-keep-table]) > tbody > tr {
    display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; padding: 10px 12px; border-bottom: 1px solid var(--hairline);
  }
  table:not(:has(> thead)):not(.table-lines):not([data-keep-table]) > tbody > tr:last-child { border-bottom: none; }
  table:not(:has(> thead)):not(.table-lines):not([data-keep-table]) > tbody > tr > td {
    display: block; border: none; padding: 0; min-width: 0; overflow-wrap: anywhere; width: auto !important;
  }
  table:not(:has(> thead)):not(.table-lines):not([data-keep-table]) > tbody > tr > td:first-child { flex: 1 0 100%; }
  table:not(:has(> thead)):not(.table-lines):not([data-keep-table]) > tbody > tr > td:empty { display: none; }
  .table-wrap { overflow-x: hidden; }
  /* What used to push a page wider than the phone: a grid column that would
     not shrink below its widest child, a pill that would not wrap, a button row that would not either. */
  .grid > * { min-width: 0; }
  .chip-list .pill, .pill { white-space: normal; max-width: 100%; }
  .flex-gap { flex-wrap: wrap; }
  .cal-controls { flex-wrap: wrap; row-gap: 6px; }
  code { overflow-wrap: anywhere; }
}

/* ---- Stream C: the two figures and two dates on a proposal ---- */
.pay-plan-row { display: flex; justify-content: space-between; align-items: baseline; gap: 6px 14px; flex-wrap: wrap; padding: 7px 0; border-bottom: 1px solid var(--hairline); }
.pay-plan-row:last-of-type { border-bottom: none; }

/* ---- Stream E: "Next: Ceremony ->" at the foot of each planning step ---- */
.plan-next { display: flex; justify-content: flex-end; margin: 14px 0 4px; }
.alert.flex-between { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }

/* ---- Stream D: the DJ's face on a couple's portal ---- */
.team-photo { width: 64px; height: 64px; border-radius: 50%; object-fit: cover; flex: 0 0 64px; border: 1px solid var(--hairline); }

/* ---- Stream H: what is on the job, on the music planning form ---- */
.rs-services { margin: 0; padding-left: 20px; line-height: 1.7; font-size: 15px; }

/* ---- Stream D: files on a wedding ---- */
.file-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--hairline); }
.file-row:last-of-type { border-bottom: none; }
.file-main { min-width: 0; overflow-wrap: anywhere; }

/* ---- Stream I: a text conversation on a project page ---- */
/* column-reverse around one child: the box opens scrolled to the newest message, with no script and the reading order intact */
.txt-thread { display: flex; flex-direction: column-reverse; max-height: 420px; overflow-y: auto; padding: 4px 2px; }
.txt-thread-in { display: flex; flex-direction: column; gap: 8px; }
.txt-thread-in > * { flex-shrink: 0; }
.txt-bubble { max-width: 82%; padding: 8px 12px; border-radius: var(--radius); font-size: 13.5px; line-height: 1.45; overflow-wrap: anywhere; }
.txt-in { align-self: flex-start; background: var(--surface-sunken); color: var(--ink); border-bottom-left-radius: 4px; }
.txt-out { align-self: flex-end; background: var(--accent-tint); color: var(--ink); border-bottom-right-radius: 4px; }
.txt-queued { border: 1px dashed var(--warning-line); background: var(--warning-tint); }
.txt-failed { border: 1px solid var(--danger-tint); }
.txt-meta { font-size: 11.5px; color: var(--ink-muted); margin-top: 3px; }
.txt-cancel { background: none; border: none; padding: 0; margin-left: 6px; color: var(--danger); font: inherit; font-weight: 600; cursor: pointer; text-decoration: underline; }
.txt-call { align-self: stretch; border-left: 3px solid var(--hairline); padding: 4px 0 4px 10px; }

/* ---- Round six, touches: the Thank-yous strip on a vendor's page ---- */
/* everything wraps: on a phone the note box and its buttons drop under the wedding's name instead of pushing the page wide */
.thanks-row { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 10px; padding: 10px 0; border-bottom: 1px solid var(--hairline); }
.thanks-row:last-of-type { border-bottom: none; }
.thanks-what { min-width: 0; flex: 1 1 220px; overflow-wrap: anywhere; }
.thanks-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; min-width: 0; }
.thanks-form { flex-wrap: wrap; min-width: 0; }
.thanks-form input[type="text"] { flex: 1 1 180px; min-width: 0; max-width: 100%; }
/* ---- Add-on offers: the couple's page (/offer/:token) ---- */
.addon-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px 16px; flex-wrap: wrap; padding: 14px 0; border-bottom: 1px solid var(--hairline); }
.addon-pick { display: flex; align-items: flex-start; gap: 12px; flex: 1 1 260px; min-width: 0; margin: 0; cursor: pointer; }
.addon-pick input { width: 22px; height: 22px; flex: 0 0 22px; margin-top: 2px; }
.addon-blurb { display: block; margin-top: 2px; font-weight: 400; overflow-wrap: anywhere; }
.addon-price { display: flex; align-items: center; gap: 8px; margin-left: 34px; white-space: nowrap; }
.addon-price select { width: auto; min-width: 72px; }
.addon-total-row { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; padding: 14px 0 6px; font-size: 16px; }
.addon-no { background: none; border: none; padding: 6px; color: var(--ink-muted); font: inherit; font-size: 13.5px; text-decoration: underline; cursor: pointer; }
/* ---- Round six, Spotify playlists: the preview's tick list, and the choice of list above it ---- */
.playlist-lists { border: 1px solid var(--hairline); border-radius: var(--radius); padding: 8px 12px; margin-left: 0; margin-right: 0; min-width: 0; }
.playlist-list-choice { display: flex; align-items: flex-start; gap: 8px; padding: 6px 0; margin: 0; cursor: pointer; font-size: 14px; font-weight: 400; color: var(--ink); }
.playlist-list-choice input { width: auto; margin-top: 3px; flex: 0 0 auto; }
/* No inner scroll box: on a phone its scrollbar is invisible, and songs below the fold would be added unread. */
.playlist-picks { border-top: 1px solid var(--hairline); }
.playlist-pick { display: flex; align-items: center; gap: 10px; padding: 9px 2px; margin: 0; border-bottom: 1px solid var(--hairline); cursor: pointer; font-size: 14px; font-weight: 400; color: var(--ink); }
.playlist-pick .pill { flex: 0 0 auto; }
.playlist-pick input { width: auto; flex: 0 0 auto; }
.playlist-pick-text { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.playlist-pick-on { cursor: default; color: var(--ink-muted); }
.playlist-pick-mark { flex: 0 0 auto; display: inline-flex; width: 16px; }
.playlist-pick-mark svg { width: 14px; height: 14px; }
.playlist-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
/* ---- R6: the DJ's post-event report (a thumb, the morning after) ---- */
.rpt-ask { display: block; text-decoration: none; color: inherit; border-color: var(--accent); margin-bottom: 14px; }
.rpt-form { max-width: 640px; }
.rpt-q { margin: 22px 0 8px; }
.rpt-q:first-of-type { margin-top: 8px; }
.rpt-label { display: block; font-weight: 600; font-size: 13px; margin: 12px 0 6px; }
.rpt-form textarea { width: 100%; font-size: 16px; /* under 16px an iPhone zooms the page on focus */ }
.rpt-scale { display: flex; flex-direction: column; gap: 8px; }
.rpt-scale-row { flex-direction: row; }
.rpt-scale-row .rpt-choice { flex: 1 1 0; min-width: 0; text-align: center; }
.rpt-scale-row .rpt-choice span { padding: 13px 6px; }
.rpt-choice { position: relative; display: block; cursor: pointer; }
.rpt-choice input { position: absolute; opacity: 0; inset: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.rpt-choice span { display: block; min-height: 48px; padding: 13px 16px; border: 1px solid var(--hairline); border-radius: var(--radius); background: var(--surface-raised); font-size: 15px; }
.rpt-choice input:checked + span { background: var(--accent-tint); border-color: var(--accent); font-weight: 600; }
.rpt-choice input:focus-visible + span { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
.rpt-submit { margin-top: 24px; min-height: 52px; font-size: 16px; }
.rpt-answer { padding: 8px 0; border-bottom: 1px solid var(--hairline); overflow-wrap: anywhere; }
.rpt-answer:last-of-type { border-bottom: none; }
.rpt-answer-label { font-size: 11.5px; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-muted); margin-bottom: 2px; }
.rpt-songs { margin: 0; padding-left: 20px; line-height: 1.7; }
.floor-plays { color: var(--accent-strong); }
/* ---- Lead sources: a month box (what a source cost, by the month) looks like every other box ---- */
input[type=month] {
  width: 100%; padding: 9px 11px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  font-size: 15px; font-family: inherit; background: var(--surface-raised); color: var(--ink);
}
/* ---- Round six: the final-details sign-off (the couple's read-through page) ---- */
.plan-nav-final { margin-left: auto; color: var(--accent-strong); }
.final-step { margin-top: 14px; border-left: 3px solid var(--accent); }
.final-step-done { border-left-color: var(--accent-strong); }
.final-step-row, .final-banner form { gap: 12px; flex-wrap: wrap; }
.final-banner { border-left: 3px solid var(--accent-strong); }
.final-row { display: flex; gap: 14px; padding: 7px 0; border-bottom: 1px solid var(--hairline); }
.final-row:last-child { border-bottom: none; }
.final-label { flex: 0 0 34%; max-width: 220px; }
.final-value { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.final-gap { margin: 8px 0 0; padding: 8px 11px; border-radius: var(--radius); background: var(--warning-tint); color: var(--warning); }
.final-entrance { margin: 0 0 8px 20px; line-height: 1.8; }
.final-list { padding: 8px 0; border-bottom: 1px solid var(--hairline); }
.final-list:last-of-type { border-bottom: none; }
.final-song { padding: 3px 0; overflow-wrap: anywhere; }
.final-confirm { border: 1px solid var(--accent); }
@media (max-width: 640px) {
  .plan-nav-final { margin-left: 0; }
  .final-row { flex-direction: column; gap: 2px; }
  .final-label { flex: none; max-width: none; }
}

/* ---- Visual refresh: the 44px display title does not fit a 375px screen ---- */
@media (max-width: 640px) { h1, .display { font: var(--text-display-phone); } }

/* ==== UI cleanup, phase 1 (21 September 2026): the shell, the tab bar, buttons, icons, utilities ==== */

/* The quick-jump's shortcut hint (item 1) */
.nav-search { position: relative; }
.nav-kbd { position: absolute; right: 9px; top: 50%; transform: translateY(-50%); font-family: var(--font-sans); font-size: 11px; color: var(--sidebar-muted); border: 1px solid var(--sidebar-rule); border-radius: var(--radius-sm); padding: 1px 5px; pointer-events: none; }

/* A tab row: tabs on the left, utility icon-buttons on the right, one hairline under both (item 3) */
.tabrow { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--space-2); border-bottom: 1px solid var(--hairline); margin-bottom: var(--space-3); }
.tabrow .tabs { border-bottom: none; margin-bottom: 0; flex: 1; min-width: 0; }
.tabrow .tab { margin-bottom: -1px; }
.tab-aside { display: flex; gap: var(--space-1); padding-bottom: 6px; flex: none; }
.tab-badge { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 5px; margin-left: 6px; border-radius: var(--radius-round); background: var(--accent-strong); color: var(--on-accent); font-size: 11px; font-weight: 600; line-height: 1; vertical-align: 1px; }
.tab.active .tab-badge { background: var(--accent-strong); }
/* The second row: one quiet strip, the chosen segment filled. Never the primary colour. */
.segmented { display: inline-flex; flex-wrap: wrap; gap: 2px; padding: 2px; margin-bottom: var(--space-3); border: 1px solid var(--hairline); border-radius: var(--radius-sm); background: var(--surface-raised); max-width: 100%; }
.segment { padding: 5px 12px; border-radius: var(--radius-sm); font-size: 13px; font-weight: 600; color: var(--ink-muted); white-space: nowrap; }
.segment:hover { color: var(--ink); }
.segment.active { background: var(--surface-sunken); color: var(--ink); }

/* Buttons that are an icon, and buttons that are barely there (item 4) */
.btn-icon { width: 32px; height: 32px; padding: 0; justify-content: center; flex: none; }
.btn-icon svg { width: 16px; height: 16px; }
.btn-icon.btn-sm { width: 28px; height: 28px; }
.btn-icon.btn-sm svg { width: 14px; height: 14px; }
.btn-ghost { border-color: transparent; background: transparent; color: var(--ink-muted); }
.btn-ghost:hover { background: var(--surface-sunken); color: var(--ink); border-color: transparent; }
.btn-ghost.btn-danger { color: var(--danger); }
.btn-ghost.btn-danger:hover { background: var(--danger-tint); }

/* "There is more over there": a chevron drawn by the stylesheet, so no page needs an import to say it (item 5) */
.link-more { display: inline-flex; align-items: center; gap: 1px; color: var(--accent-strong); font-weight: 600; font-size: 13px; white-space: nowrap; }
.link-more::after, .has-caret::after { content: ''; display: inline-block; width: 14px; height: 14px; background: currentColor; }
.link-more::after { -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 6 6 6-6 6'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 6 6 6-6 6'/%3E%3C/svg%3E") center / contain no-repeat; }
.has-caret { display: inline-flex; align-items: center; gap: 4px; }
.has-caret::after { -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") center / contain no-repeat; }
.icon-sm svg { width: 14px; height: 14px; }

/* A status dot: on (accent) or off (muted) */
.dot { display: inline-block; width: 8px; height: 8px; border-radius: var(--radius-round); background: var(--border); vertical-align: 1px; margin-right: 6px; }
.dot-ok { background: var(--accent); }
.dot-off { background: var(--border); }
.dot-warn { background: var(--warning-line); }
.dot-bad { background: var(--danger); }
.status-line { display: inline-flex; align-items: center; font-size: 12px; font-weight: 600; }

/* The stat tile's icon: top right, half-strength (item 6) */
.stat-icon { position: absolute; top: 12px; right: 12px; color: var(--ink-muted); opacity: 0.5; }
.stat-icon svg { width: 16px; height: 16px; }

/* Settings tiles: the icon in a tinted circle beside the title, one line of blurb, a dot for the status (item 6) */
.settings-card { display: flex; gap: 12px; align-items: flex-start; }
.settings-card > div { min-width: 0; }
.settings-card h3 { margin-bottom: 2px; }
.settings-card-icon { width: 36px; height: 36px; flex: none; border-radius: var(--radius-round); background: var(--surface-sunken); color: var(--ink-muted); display: inline-flex; align-items: center; justify-content: center; }
.settings-card:hover .settings-card-icon { background: var(--accent-tint); color: var(--accent-strong); }
.settings-status { margin-top: 6px; }

/* The phone tab bar for staff: a dot where something is waiting, and "More" opens the drawer (item 2) */
.tabbar-item { position: relative; }
.tabbar-dot { position: absolute; top: 6px; left: calc(50% + 8px); width: 8px; height: 8px; border-radius: var(--radius-round); background: var(--accent-strong); }

/* The illustrated empty state (item 7) */
.empty-state .illus-beat { stroke: var(--accent); }

/* The login page: a faint heartbeat the width of the screen, behind the card (item 7) */
.login-wrap { position: relative; overflow: hidden; }
.login-wrap::after { content: ''; position: absolute; left: 0; right: 0; top: 50%; height: 120px; transform: translateY(-50%); background: var(--accent); opacity: 0.16; pointer-events: none; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1400 120' preserveAspectRatio='none' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M0 60h520l24-36 40 84 30-60 18 30h768'/%3E%3C/svg%3E") center / 100% 100% no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1400 120' preserveAspectRatio='none' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M0 60h520l24-36 40 84 30-60 18 30h768'/%3E%3C/svg%3E") center / 100% 100% no-repeat; }
.login-wrap > * { position: relative; z-index: 1; }

/* Utilities, for what used to be written inline (item 9) */
.m-0 { margin: 0; } .my-1 { margin: 4px 0; } .mt-05 { margin-top: 4px; } .ml-auto { margin-left: auto; }
.w-100 { width: 100%; } .min-w-0 { min-width: 0; }
.max-w-xs { max-width: 220px; } .max-w-sm { max-width: 340px; } .max-w-md { max-width: 520px; } .max-w-lg { max-width: 720px; }
.wrap { flex-wrap: wrap; } .flex-1 { flex: 1; } .flex-2 { flex: 2; } .inline { display: inline; }
.align-end { align-items: end; } .align-start { align-items: flex-start; }
.gap-1 { gap: 4px; } .gap-2 { gap: 8px; } .gap-3 { gap: 16px; }
.text-right { text-align: right; } .text-md { font-size: 15px; }
.line-b { border-bottom: 1px solid var(--hairline); } .row-line { padding: 6px 0; border-bottom: 1px solid var(--hairline); }
/* The settings page: group titles are small and quiet, like the sidebar's (item 8) */
.settings-group-title { font-size: 11px; letter-spacing: 0.08em; }
/* On a phone the tab row scrolls sideways under the icon buttons rather than wrapping beneath them */
@media (max-width: 640px) { .tabrow .tabs { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; } .tabrow .tabs::-webkit-scrollbar { display: none; } .tabrow .tab { white-space: nowrap; } }

/* ---- UI cleanup phase 2: the Automation list ---- */
/* Stop conditions and "starts by itself" are small muted icons in a row; the tooltip and aria-label carry the words */
.flow-stops { display: inline-flex; align-items: center; gap: 6px; }
.flow-hint { display: inline-flex; align-items: center; cursor: help; vertical-align: -2px; }
.flow-trigger { display: inline-flex; align-items: center; gap: 6px; }
.flow-trigger .icon-sm { display: inline-flex; }
/* Active / Paused: a quiet pill with a dot and a word in sentence case */
.flow-state { text-transform: none; letter-spacing: 0; background: var(--surface-sunken); color: var(--ink); }
.flow-state .dot { margin-right: 0; }
/* ---- UI cleanup phase 2: social ---- */
/* The accounts as one line of handle chips at the end of the view tab row, with "Manage" to Settings -> Social. */
.social-accounts { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-1); }
.social-accounts .chip { display: inline-flex; align-items: center; gap: 6px; font-weight: 500; }
.social-accounts .link-more { margin-left: var(--space-1); }
/* On a phone the line sits above the tabs on its own row rather than squeezing them sideways. */
@media (max-width: 640px) {
  .tabrow:has(.social-accounts) { flex-wrap: wrap; }
  .tab-aside:has(.social-accounts) { flex-basis: 100%; order: -1; padding-bottom: var(--space-1); }
}
/* A tile with no media yet: a dashed ring the size of the thumbnail it stands in for, an image icon at 24px inside. */
.grid-tile.no-media { border: 1px dashed var(--border); background: var(--surface); }
.grid-tile-empty > svg { width: 24px; height: 24px; color: var(--ink-muted); flex: none; }
.grid-tile-empty-label { letter-spacing: 0; text-transform: none; font-weight: 500; }
/* The caption's first words stop above the status bar instead of running under it; two lines is enough to know which post this is. */
.grid-tile-empty { padding-bottom: 38px; }
.grid-tile-empty .grid-tile-text { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
@media (max-width: 640px) { .grid-tile-empty .grid-tile-text { display: none; } }
/* ---- UI cleanup phase 2: the Settings index ---- */
/* Six groups as a two-column list, each group one card of hairline-separated rows: icon, title and one line of
   blurb, a status word, a chevron. Half the height of the three-column tiles it replaces. */
.settings-list { columns: 2; column-gap: var(--space-3); }
.settings-list-group { padding: 0; margin: 0 0 var(--space-3); break-inside: avoid; display: block; }
.settings-list-group .settings-group-title { margin: 0; padding: 12px var(--space-3) 8px; border-bottom: 1px solid var(--hairline); }
.settings-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto; align-items: center; gap: 2px 12px; padding: 10px var(--space-3); color: inherit; text-decoration: none; }
.settings-row + .settings-row { border-top: 1px solid var(--hairline); }
.settings-row:hover { background: var(--surface-sunken); text-decoration: none; }
.settings-row:hover .settings-card-icon { background: var(--accent-tint); color: var(--accent-strong); }
.settings-row-body { display: flex; flex-direction: column; min-width: 0; }
.settings-row-title { font-weight: 600; }
.settings-row-status { text-align: right; max-width: 220px; }
.settings-row-status .status-line { text-align: left; align-items: flex-start; }
.settings-row-status .dot { margin-top: 4px; }
.settings-row-chevron { display: inline-flex; color: var(--ink-muted); }
.settings-row-chevron svg { width: 16px; height: 16px; }
@media (max-width: 900px) { .settings-list { columns: 1; } }
@media (max-width: 640px) {
  .settings-row { grid-template-columns: auto minmax(0, 1fr) auto; }
  .settings-row-status { grid-column: 2; grid-row: 2; text-align: left; max-width: none; margin-top: 2px; }
  .settings-row-chevron { grid-column: 3; grid-row: 1; }
  .settings-card-icon { grid-row: 1; }
}
/* ---- UI cleanup phase 2: Forms & Contracts (item 16) ---- */
/* The templates as one grouped list: a small heading per kind with its icon, hairline rows under it, and an empty
   kind as one quiet line. Replaces the six-column board. */
.tpl-group + .tpl-group { margin-top: var(--space-3); padding-top: var(--space-3); border-top: 1px solid var(--hairline); }
.tpl-group-head { display: flex; align-items: center; gap: 6px; }
.tpl-group-icon { display: inline-flex; }
.tpl-group-icon svg { width: 14px; height: 14px; color: var(--accent); }
.tpl-row { display: flex; align-items: center; gap: var(--space-2); padding: 8px 0; border-bottom: 1px solid var(--hairline); }
.tpl-rows .tpl-row:last-child { border-bottom: 0; padding-bottom: 2px; }
.tpl-name { flex: 1; min-width: 0; font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.tpl-name:hover { color: var(--accent-strong); }
.tpl-sig { display: inline-flex; color: var(--ink-muted); flex: none; }
.tpl-sig svg { width: 14px; height: 14px; }
.tpl-empty { margin: 0; padding: 2px 0; }
.tpl-note { margin: 8px 0 0; }
/* The "no business signature yet" line sits in the page head beside the primary button, and wraps under it on a phone */
.sig-status { gap: 10px; }
.sig-status .status-line { font-weight: 500; }
/* ---- UI cleanup phase 2: people & music (items 19 and 20) ---- */
/* A person as a face and a name: a 24px photo or initials circle, then the name (personChip in music.routes.js) */
.avatar-sm { width: 24px; height: 24px; font-size: 11px; }
img.avatar { object-fit: cover; }
.person-chip { display: inline-flex; align-items: center; gap: 8px; }
/* The music planning pages: the way back at the left, the sections as one quiet segmented strip beside it */
.plan-strip { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2) var(--space-3); margin-bottom: var(--space-3); }
.plan-strip .segmented { margin-bottom: 0; }
.plan-strip .plan-nav-home { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 600; }
.plan-strip .plan-nav-home svg { width: 14px; height: 14px; flex: none; }
/* ---- UI cleanup phase 2: the Money section (item 11) ---- */
/* One quiet line of figures under the tab row, in place of three stat tiles; the numbers in ink */
.money-strip { font-size: 13px; color: var(--ink-muted); margin: calc(-1 * var(--space-2)) 0 var(--space-3); }
.money-strip strong { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
/* The expenses filter: a year select that submits itself, and one toggle chip, filled when on */
.money-filter select { width: auto; }
.chip-on { background: var(--accent-tint); border-color: var(--accent-tint); color: var(--accent-strong); }
/* The "..." row menu: a <details> whose summary is an icon button, with a small panel under it */
.row-menu { position: relative; display: inline-block; text-align: left; }
.row-menu > summary { list-style: none; }
.row-menu > summary::-webkit-details-marker { display: none; }
.row-menu[open] > summary { background: var(--surface-sunken); }
.row-menu-panel { position: absolute; z-index: 30; top: calc(100% + 4px); right: 0; min-width: 200px; padding: 4px; background: var(--surface-raised); border: 1px solid var(--hairline); border-radius: var(--radius); box-shadow: var(--shadow-float); }
.row-menu-panel form { margin: 0; }
.row-menu-sub > summary { list-style: none; }
.row-menu-sub > summary::-webkit-details-marker { display: none; }
.row-menu-item { display: block; width: 100%; padding: 7px 10px; border: none; border-radius: var(--radius-sm); background: none; color: var(--ink); font: inherit; font-size: 13px; font-weight: 500; text-align: left; cursor: pointer; white-space: nowrap; }
.row-menu-item:hover { background: var(--surface-sunken); }
.row-menu-danger { color: var(--danger); }
.row-menu-danger:hover { background: var(--danger-tint); }
.row-menu-form { display: flex; flex-direction: column; gap: 6px; padding: 4px 10px 8px; }
.row-menu-form input[type=file] { font-size: 12px; max-width: 220px; }
.row-menu-form .btn { align-self: flex-start; }
/* A table box clips what hangs past its edge; while a row menu is open, let the panel out */
.table-wrap:has(.row-menu[open]) { overflow: visible; }
/* On a phone the row is a card and its cells stack: the menu button goes to the right edge, square for a thumb, and the panel opens under it inside the screen */
@media (max-width: 640px) {
  table:has(> thead):not(.table-lines):not([data-keep-table]) > * > tr > td.row-menu-cell:not([data-label]):not(:first-child) { justify-content: flex-end; }
  .row-menu > summary.btn-icon { width: 44px; height: 44px; }
  .row-menu-panel { max-width: calc(100vw - 48px); }
}
/* ---- UI cleanup phase 2: the Pipeline board, the Dashboard, the Calendar (items 13, 14, 18) ---- */
/* The board's filter selects submit themselves once app.js is running (which adds .js to <html>), so the Filter
   button is only for a page with no script. */
.js .autosubmit-btn { display: none; }
/* A dead stage's count of leads with no reason written down: a badge on that column's head, not a banner over the
   whole board. Warning on white is 4.85:1. */
.board-col-badge { margin-left: 0; background: var(--warning); color: var(--on-accent); text-decoration: none; }
.board-col-badge:hover { background: var(--danger); text-decoration: none; }
/* The calendar's month bar: a chevron either side of the month, and the key on the right as dots and words. */
.cal-monthbar { display: flex; align-items: center; justify-content: space-between; gap: 8px 16px; flex-wrap: wrap; margin-bottom: var(--space-3); }
.cal-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; font-family: var(--font-sans); font-size: 12px; color: var(--ink-muted); }
.cal-legend-item { display: inline-flex; align-items: center; white-space: nowrap; }
/* The dots read the same colours as the .cal-type-* and .cal-feed-* tiles above. */
.dot-cal-wedding, .dot-cal-loadin { background: var(--accent-strong); }
.dot-cal-call { background: var(--info); }
.dot-cal-payment { background: var(--danger); }
.dot-cal-other { background: var(--ink-muted); }
.dot-cal-feed-slate { background: var(--ink-muted); }
.dot-cal-feed-blue { background: var(--info); }
.dot-cal-feed-green, .dot-cal-feed-gold { background: var(--accent-strong); }
.dot-cal-feed-red { background: var(--danger); }
/* On a phone the month's chevrons are 44px squares, not 44px-tall bars (the earlier .cal-controls .btn rule pads them). */
@media (max-width: 640px) { .cal-controls .btn-icon { width: 44px; height: 44px; padding: 0; } }
/* ---- UI cleanup phase 2: the project page ---- */
/* Overview is two columns on a desk and one on a phone, like the inline 2fr 1fr it replaces */
.project-cols { grid-template-columns: 2fr 1fr; align-items: start; }
@media (max-width: 900px) { .project-cols { grid-template-columns: 1fr; } }
/* The one-line money summary under the header: where four tiles were */
.money-line { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; margin: -8px 0 var(--space-3); font-size: 14px; color: var(--ink-muted); }
.money-line strong { color: var(--ink); font-variant-numeric: tabular-nums; }
.money-line > span + span::before { content: '·'; color: var(--border); margin-right: 8px; }   /* each segment carries its own dot, so a wrap never strands one */
form.money-line { margin-bottom: var(--space-3); }
/* A task's tick box, and a note's row (were inline styles) */
.task-tick { width: 20px; height: 20px; padding: 0; display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--border); border-radius: var(--radius-sm); flex: none; }
.task-tick svg { width: 12px; height: 12px; }
.task-tick.is-done { background: var(--accent-strong); border-color: var(--accent-strong); color: var(--on-accent); }
.task-tick.is-done:hover { background: var(--accent-strong); color: var(--on-accent); }
.task-done { text-decoration: line-through; color: var(--ink-muted); }
.task-due { width: 150px; }
.note-row { padding: 8px 0; border-bottom: 1px solid var(--hairline); }

/* ---- Testing mode and the demo: the banner across the top of every page (src/lib/testingMode.js) ---- */
.mode-banner { padding: 8px var(--space-4); font-size: 13px; font-weight: 600; text-align: center; }
.mode-banner a { text-decoration: underline; text-underline-offset: 2px; color: inherit; font-weight: 600; }
.mode-testing { background: var(--warning-tint); color: var(--warning); border-bottom: 1px solid var(--warning-line); }
.mode-demo { background: var(--info-tint); color: var(--info); border-bottom: 1px solid var(--info); }
/* ---- The Pulse Planner logo (brand/pulse-planner-logo): the mark as an image, the words as text ---- */
.pp-mark { display: block; width: 40px; height: 40px; flex: none; }
.mobile-brand .pp-mark { width: 28px; height: 28px; }
.login-brand .pp-mark, .public-letterhead .pp-mark { width: 96px; height: 96px; margin: 0 auto; }
.public-letterhead .letterhead { flex-direction: column; gap: 8px; }
.brand-preview-empty .pp-mark { width: 28px; height: 28px; }

/* ---- Stream A: photos texted in (Social -> Photos) ---- */
.photos-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-3); }
.photos-bar .select-sm { max-width: 260px; }
.photo-group { margin-bottom: var(--space-4); }
.photo-group h4 { margin: 0 0 var(--space-2); font: var(--text-heading); }
.photo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: var(--space-2); }
.photo-tile { position: relative; display: flex; flex-direction: column; border: 1px solid var(--hairline); border-radius: var(--radius); background: var(--surface); overflow: hidden; cursor: pointer; }
.photo-tile:has(input:checked) { outline: 2px solid var(--accent); outline-offset: -2px; }
.photo-tile:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.photo-tile input { position: absolute; top: 8px; left: 8px; z-index: 1; width: 18px; height: 18px; margin: 0; accent-color: var(--accent); }
.photo-tile img, .photo-tile-blank { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; background: var(--surface-sunken); }
.photo-tile-blank { display: flex; align-items: center; justify-content: center; color: var(--ink-muted); }
.photo-tile-blank svg { width: 28px; height: 28px; }
.photo-tile-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 8px; padding: 6px 8px; }
.photo-tile-note { padding: 0 8px 8px; }
.photo-tile-dim { opacity: 0.7; cursor: default; }
@media (max-width: 640px) { .photo-grid { grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); } }

/* ---- Stream G: a stage on the board opens its automation ---- */
.board-col-flow { text-decoration: none; color: var(--ink); }
.board-col-flow:hover, .board-col-flow:focus-visible { color: var(--accent-strong); text-decoration: underline; }
.board-col-flow .icon-sm { color: var(--accent-strong); display: inline-flex; }
.board-col-flow .icon-sm svg { width: 13px; height: 13px; }

/* ---- Rehearsal seven: a link-more that is also a button keeps the button's colour; library rows wrap on a phone ---- */
.btn.link-more { color: var(--ink); }
.btn-gold.link-more, .btn-primary.link-more { color: var(--on-accent); }
@media (max-width: 640px) {
  .library-row { flex-wrap: wrap; }
  .library-row-info { flex-basis: 100%; }
}

/* ---- Stream A: the scheduled date fits its tile; destinations; media shape ---- */
/* A grid tile is a third of a column with a fixed height, and the meta bar is
   one flex row. "Sep 27, 2026, 12:00 PM" wrapped to three lines and collided
   with the pill beside it. The date is shortened where it is written; this
   stops whatever is left from wrapping into the picture. */
.grid-tile-meta .pill { flex: 0 0 auto; }
.grid-tile-when { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }

/* The account chips in the tab row are filters, so they read as links and the
   chosen one is marked. */
a.chip { text-decoration: none; color: inherit; }
a.chip:hover, a.chip:focus-visible { border-color: var(--accent); }
.chip-on { border-color: var(--accent); background: var(--accent-tint); color: var(--accent-strong); font-weight: 600; }

/* Where one post goes: one row per destination, its own caption under it. */
.dest-list { display: flex; flex-direction: column; gap: 10px; margin-top: 10px; }
.dest-row { border: 1px solid var(--hairline); border-radius: var(--radius-sm); padding: 8px 10px; }
.dest-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.dest-head form { display: inline-flex; margin: 0; }
.dest-caption { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; margin-top: 8px; }
.dest-caption textarea { width: 100%; }
.dest-add { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

/* How big it is and how long it runs, under its thumbnail. */
.media-shape { padding: 2px 4px 0; font-variant-numeric: tabular-nums; }

/* What the calendar can honestly say about the month's rhythm. */
.cadence-card p { line-height: 1.6; }

/* ---- Stream H: the run of show and the Do Not Play block on the music planning form ---- */
.rs-show-item { margin-top: 6px; font-size: 17px; }
.rs-dnp-songs { list-style: none; margin: 6px 0 0; padding: 0; }
.rs-dnp-songs li { padding: 5px 0; border-top: 1px solid var(--rs-line); font-size: 17px; }
.rs-dnp-songs li:first-child { border-top: 0; }

/* ---- Stream H: a printed music planning form has no dark page behind it ---- */
/* The music planning form asks for a dark canvas on screen (<meta name="color-scheme" content="dark">, dj.routes.js), and a
   browser printing it paints that canvas first -- near-black round the margins and behind every page break, however
   white the sheet itself is. On paper the whole page, not only the sheet, is light. */
@media print {
  html:has(body.runsheet), body.runsheet { color-scheme: light; background: var(--surface-raised); }
}

/* ---- Stream H: the DJ's report by voice ---- */
/* The Enter key's button: the real Send, kept first in the form and off the screen (not display:none, which some
   browsers skip when choosing it). */
.rpt-default-submit { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); border: 0; }
.rpt-voice-tip { margin-top: -4px; }
.rpt-night { margin: 4px 0 8px; padding: 12px 14px 14px; border: 1px solid var(--hairline); border-radius: var(--radius); background: var(--surface-raised); }
.rpt-night .rpt-label { margin-top: 0; }
/* The mic buttons are drawn by public/app.js, and only where the browser can listen. */
.rpt-mic-row { display: flex; align-items: center; justify-content: flex-end; gap: 8px; margin-top: 6px; }
.rpt-mic { display: inline-flex; align-items: center; gap: 6px; min-height: 40px; }
.rpt-mic svg { width: 16px; height: 16px; }
.rpt-mic[aria-pressed="true"] { color: var(--danger); border-color: var(--danger); background: var(--danger-tint); }
.rpt-mic-status { font-size: 13px; color: var(--ink-muted); }
.rpt-mic-status:empty { display: none; }

/* ---- Stream F (little changes, items 5-7): two-step sign-in ---- */
.two-step-steps { padding-left: 20px; }
.two-step-steps li { margin-bottom: 8px; }
.two-step-qr { margin: 8px 0; }
.two-step-qr svg { display: block; max-width: 100%; height: auto; }
.two-step-key { display: inline-block; word-break: break-all; font-size: 15px; letter-spacing: 0.04em; }
.two-step-codes { columns: 2; column-gap: 24px; padding-left: 24px; font-size: 16px; line-height: 1.9; }
.two-step-bigcode { font-size: 40px; letter-spacing: 0.12em; font-variant-numeric: tabular-nums; margin: 8px 0 12px; color: var(--ink); }
.two-step-late { color: var(--danger); }
@media print {
  .login-wrap { background: none !important; min-height: 0; }
  .login-card { box-shadow: none; width: auto; }
  .login-card .btn, .mode-banner { display: none !important; }
}

/* ---- Stream A, little changes round two: a photo's edit, and the other version (Social -> Photos, the post editor) ---- */
.photo-tile-edit { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; padding: 2px 6px 4px; }
.photo-tile-edit .muted { flex-basis: 100%; }
.media-extra { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin-top: 4px; }
/* ---- Streams J and I, little changes round two (item 3): the first-run checklist and the setup assistant ---- */
.setup-layout { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: 16px; align-items: start; }
@media (max-width: 900px) { .setup-layout { grid-template-columns: minmax(0, 1fr); } }
.setup-row { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 10px; padding: 10px 0; border-bottom: 1px solid var(--hairline); }
.setup-row:last-of-type { border-bottom: none; }
.setup-row-mark { flex: 0 0 22px; width: 22px; height: 22px; border-radius: 50%; border: 1px solid var(--hairline); display: inline-flex; align-items: center; justify-content: center; color: var(--accent-strong); }
.setup-row-done .setup-row-mark { background: var(--accent-tint); border-color: var(--accent-tint); }
.setup-row-mark svg { width: 14px; height: 14px; }
.setup-row-body { flex: 1 1 220px; min-width: 0; }
.setup-row-title { font-weight: 600; }
.setup-row-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.setup-row-actions form { display: inline; margin: 0; }
.setup-assistant textarea { width: 100%; }
.setup-thread { max-height: 460px; margin: 8px 0; }
.setup-say { white-space: pre-wrap; }
.setup-links { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.setup-proposal { border: 1px dashed var(--accent); border-radius: var(--radius); padding: 10px 12px; margin: 8px 0; background: var(--accent-tint); }
.setup-proposal-value { font-weight: 600; overflow-wrap: anywhere; white-space: pre-wrap; margin: 4px 0; }
.setup-proposal form { display: inline; margin: 0; }
.setup-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ---- Stream G: the contact picker (type to search; New Lead and "+ New project…") ---- */
.suggest-box { position: relative; }
.suggest-list { position: absolute; left: 0; right: 0; top: calc(100% - 22px); z-index: 30; margin: 0; padding: 4px; list-style: none; background: var(--surface-raised); border: 1px solid var(--border); border-radius: var(--radius); max-height: 280px; overflow-y: auto; }
.suggest-item { display: block; width: 100%; text-align: left; padding: 6px 8px; border: 0; background: transparent; color: var(--ink); border-radius: var(--radius-sm); cursor: pointer; font: inherit; }
.suggest-item:hover, .suggest-item:focus-visible { background: var(--accent-tint); }
.suggest-detail { display: block; font-size: 12px; color: var(--ink-muted); overflow-wrap: anywhere; }
.suggest-empty { padding: 6px 8px; font-size: 13px; color: var(--ink-muted); }

/* ---- Little changes round two (item 4): meetings -- the /meet/ page, a DJ's times, the Calls card ---- */
.meet-day { margin: 0 0 14px; }
.meet-day > .flex-gap { margin-top: 6px; }
.meet-booked { margin: 14px 0; }
.meet-week-row .field { margin-bottom: 8px; }
.meet-week-row input[type=time] { width: auto; }
.plain-list { list-style: none; margin: 0; padding: 0; }
.plain-list > li { padding: 4px 0; }
.text-danger { color: var(--danger); }

/* ---- Stream B: the approval queue stays inside its card, whatever is in it ---- */
/* A long word with no spaces -- an email address, a calendar entry, a held reason -- and a pill that would not wrap
   used to push Approve / Skip / Not available past the card's edge and the page sideways. The words wrap now, the
   buttons drop to their own line when there is no room beside them, and on a phone they sit under the words. */
.approval-item > summary { flex-wrap: wrap; gap: 8px 12px; }
.approval-item > summary > :first-child { flex: 1 1 320px; min-width: 0; overflow-wrap: anywhere; }
.approval-item > summary > .flex-gap { flex: 0 1 auto; flex-wrap: wrap; justify-content: flex-end; margin-left: auto; }
.approval-item .pill { white-space: normal; max-width: 100%; overflow-wrap: anywhere; border-radius: 12px; }
.approval-item .grid > * { min-width: 0; }
.approval-item .pre-wrap, .approval-preview > div { overflow-wrap: anywhere; }
/* A flow's own page: the steps and "When this runs" keep to their columns, and a step's line wraps a long word
   (a link, a merge field, an address) instead of pushing the row past its card. */
.flow-layout > * { min-width: 0; overflow-wrap: anywhere; }
.timeline-item > .flex-1 { min-width: 0; overflow-wrap: anywhere; }
.timeline-item .pill { white-space: normal; max-width: 100%; overflow-wrap: anywhere; }
.flow-desc { overflow-wrap: anywhere; }

/* ---- Packages & Discounts: the edit form opens as the row under the package being edited (25 September 2026) ---- */
tr.editing, tr.editing > td { background: var(--surface-sunken); } /* the row too: a flex cell does not fill the row's height */
tr.edit-row > td { padding: 14px 16px 18px; background: var(--surface-sunken); border-top: 0; }
tr.edit-row > td form { max-width: 720px; }

/* ---- Stream F: the email editor ---- */
/* One word-processor box everywhere an email is written (public/email-editor.js). The textarea underneath keeps the
   markup for a browser without JavaScript; this is what sits in front of it. Buttons are the app's own, and the box
   is an input: the same border, corners and focus ring as a textarea. */
.email-editor { position: relative; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-raised); }
.email-editor:focus-within { border-color: var(--accent-strong); }
.email-editor-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; padding: 6px 8px; border-bottom: 1px solid var(--hairline); background: var(--surface-sunken); border-radius: var(--radius-sm) var(--radius-sm) 0 0; }
.email-editor-group { display: inline-flex; align-items: center; gap: 2px; }
.email-editor-group-fields { margin-left: auto; gap: 6px; color: var(--ink-muted); }
.email-editor-group-fields svg { width: 16px; height: 16px; flex: none; }
.email-editor-btn { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; border: 1px solid transparent; border-radius: var(--radius-sm); background: transparent; color: var(--ink); cursor: pointer; font-family: var(--font-sans); font-size: 14px; }
.email-editor-btn:hover { background: var(--surface-raised); border-color: var(--hairline); }
.email-editor-btn[aria-pressed="true"] { background: var(--accent-tint); color: var(--accent-strong); border-color: var(--accent-tint); }
.email-editor-btn:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 1px; }
.email-editor-btn svg { width: 16px; height: 16px; }
.email-editor-btn .ee-b { font-weight: 600; }
.email-editor-btn .ee-i { font-style: italic; font-family: Georgia, serif; }
.email-editor-btn .ee-u { text-decoration: underline; }
.email-editor-fields { width: auto; max-width: 260px; padding: 5px 8px; font-size: 13px; border-color: var(--hairline); }
.email-editor-box { min-height: 220px; padding: 10px 12px; font-size: 15px; line-height: 1.6; color: var(--ink); overflow-wrap: anywhere; border-radius: 0 0 var(--radius-sm) var(--radius-sm); }
.email-editor-box:focus { outline: 2px solid var(--accent-strong); outline-offset: -2px; }
.email-editor-box.is-empty::before { content: attr(data-placeholder); color: var(--ink-muted); pointer-events: none; position: absolute; white-space: pre-line; }
.email-editor-box.is-missing { box-shadow: inset 0 0 0 2px var(--danger); }
.email-editor-box h2 { font: 600 1.25em/1.3 var(--font-sans); margin: 12px 0 4px; }
.email-editor-box ul, .email-editor-box ol { margin: 6px 0; padding-left: 22px; }
.email-editor-box a { color: var(--accent-strong); font-weight: 600; text-decoration: underline; }
.email-editor-box a[data-button] { display: inline-block; margin: 6px 0; padding: 8px 16px; background: var(--accent); color: var(--on-accent); border-radius: 6px; text-decoration: none; }
.email-editor-box img { max-width: 100%; height: auto; }
.email-editor-pop { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px 12px; padding: 10px 12px; border-top: 1px solid var(--hairline); background: var(--surface-sunken); }
.email-editor-pop[hidden] { display: none; } /* display: flex would otherwise win over the hidden attribute */
.email-editor-pop-field { display: flex; flex-direction: column; gap: 3px; flex: 1 1 200px; font: var(--text-caption); color: var(--ink-muted); }
.email-editor-pop-field input { padding: 7px 9px; font-size: 14px; }
.email-editor-pop-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; flex: 1 1 100%; }
/* The approval queue shows the email as the couple gets it, not the markup. */
.approval-email { margin-top: 6px; padding: 10px 12px; border: 1px solid var(--hairline); border-radius: var(--radius-sm); background: var(--surface-raised); max-height: 360px; overflow: auto; }
/* Settings -> Email: how the emails will read, in the chosen font. */
.email-font-sample { padding: 12px 14px; border: 1px solid var(--hairline); border-radius: var(--radius-sm); background: var(--surface-raised); line-height: 1.65; margin-bottom: var(--space-1); }
@media (max-width: 640px) {
  .email-editor-group-fields { margin-left: 0; flex: 1 1 100%; }
  .email-editor-fields { max-width: none; flex: 1; }
  .email-editor-box { font-size: 16px; /* under 16px an iPhone zooms the page on focus */ }
}

/* ---- Stream I: the setup assistant, docked beside the Automation pages and Settings -> Email ----
   The same panel as the first-run checklist's, as a collapsible box at the corner of a page whose own layout is
   somebody else's to change. Closed, it is one line; open, it is a scrolling card no taller than the window. On a
   phone it sits in the flow of the page instead, so it never covers the form it is there to help with. */
.assistant-dock { position: fixed; right: 16px; bottom: 16px; z-index: 35; width: 380px; max-width: calc(100vw - 32px); max-height: min(72vh, 640px); overflow: auto; margin: 0; box-shadow: var(--shadow-float); }
.assistant-dock:not([open]) { width: auto; overflow: visible; }
.assistant-dock-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; cursor: pointer; list-style: none; }
.assistant-dock-head::-webkit-details-marker { display: none; }
.assistant-dock-title { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; }
.assistant-dock-title svg { width: 16px; height: 16px; }
.assistant-dock:not([open]) .assistant-dock-hint { display: none; }
.assistant-dock-body { margin-top: var(--space-3); }
.setup-draft { border: 1px dashed var(--accent); border-radius: var(--radius); padding: 10px 12px; margin: 8px 0; background: var(--surface-raised); max-width: 100%; }
.setup-draft-body { white-space: pre-wrap; overflow-wrap: anywhere; font: inherit; font-size: 13px; line-height: 1.5; margin: 6px 0; max-height: 260px; overflow: auto; }
@media (max-width: 900px) {
  .assistant-dock { position: static; width: auto; max-width: none; max-height: none; box-shadow: none; margin-top: var(--space-4); }
}
/* ---- Stream G: a note keeps its line breaks; the website inquiry's answers are one line each (25 September 2026) ---- */
.note-body { white-space: pre-wrap; overflow-wrap: anywhere; }
.inquiry-answers { white-space: normal; }
.inquiry-answers-title { font-weight: 600; margin: 2px 0 6px; }
.inquiry-answer { display: grid; grid-template-columns: minmax(120px, 34%) 1fr; gap: 4px 12px; padding: 3px 0; border-top: 1px solid var(--hairline); font-size: 13.5px; }
.inquiry-answer:first-of-type { border-top: 0; }
.inquiry-q { color: var(--ink-muted); }
.inquiry-a { white-space: pre-wrap; overflow-wrap: anywhere; }
@media (max-width: 640px) { .inquiry-answer { grid-template-columns: 1fr; gap: 0; } .inquiry-q { font-size: 12px; } }

/* ---- Stream H: meeting notes (26 September 2026) -- the consent line on the booking page, and a transcript on the notes page ---- */
.meet-consent { border-left: 3px solid var(--accent); padding: 6px 10px; margin: 8px 0 12px; background: var(--surface-raised); }
.transcript-text { white-space: pre-wrap; overflow-wrap: anywhere; font: inherit; font-size: 13px; line-height: 1.55; max-height: 480px; overflow: auto; margin: 8px 0 0; }

/* ---- Stream J: the business's own colours (26 September 2026) -- the template tiles and the three pickers on Settings -> Branding ---- */
.theme-presets { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: var(--space-2); margin: var(--space-2) 0; }
.theme-tile { display: block; position: relative; border: 1px solid var(--hairline); border-radius: var(--radius); padding: 10px; cursor: pointer; background: var(--surface-raised); }
.theme-tile:has(input:checked) { border-color: var(--accent-strong); box-shadow: inset 0 0 0 1px var(--accent-strong); }
.theme-tile input { position: absolute; opacity: 0; pointer-events: none; }
.theme-swatches { display: flex; gap: 4px; margin-bottom: 6px; }
.theme-swatches span { flex: 1; height: 22px; border-radius: var(--radius-sm); border: 1px solid var(--hairline); }
.theme-tile-name { font-weight: 600; font-size: 13px; }
.theme-tile-words { font-size: 12px; color: var(--ink-muted); }
.theme-pickers { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.theme-pickers input[type=color] { width: 56px; height: 36px; padding: 2px; }

/* ---- Stream H: the welcome pulse (Brian, 26 September 2026) -- the line under "Good to see you" on the dashboard ---- */
/* Brian's own heartbeat: a hairline the width of the page with one full ECG beat -- a small rise, the spike, the dip,
   a small bump -- near the right end, traced from the picture he sent. Drawn as a mask over the accent colour rather
   than a green picture, so it follows the business's own colours; the stroke stays a hairline at any width. */
.pulse-welcome {
  height: 28px; margin: 4px 0 18px; opacity: 0.9; background-color: var(--accent);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2000 104' preserveAspectRatio='none'%3E%3Cpath d='M0 64H1628L1646 34 1655 100 1668 4 1680 66 1689 48 1697 64H2000' fill='none' stroke='black' stroke-width='1.6' stroke-linejoin='round' stroke-linecap='round' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E") left center / 100% 100% no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2000 104' preserveAspectRatio='none'%3E%3Cpath d='M0 64H1628L1646 34 1655 100 1668 4 1680 66 1689 48 1697 64H2000' fill='none' stroke='black' stroke-width='1.6' stroke-linejoin='round' stroke-linecap='round' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E") left center / 100% 100% no-repeat;
}

/* ---- Stream D: the way back from a public page (the pay page) for a signed-in couple, planner or the office ---- */
.public-way-back { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 600; color: var(--ink-muted); margin-bottom: 12px; }
.public-way-back:hover { color: var(--ink); }
.public-way-back svg { width: 14px; height: 14px; flex: none; }

/* ---- Stream D: a field never leaves its box on a phone (28 September 2026) ----
   Brian: "some of the boxes for the text fields are going outside the container box." Two things an iPhone does that
   a laptop does not. Safari zooms the page in when a field with text under 16px is tapped, and the zoomed field runs
   off the side of the screen; and its date and time boxes keep a width of their own whatever the container says.
   So on a phone every field's text is 16px, and a date or time box is drawn as an ordinary field. A field inside a
   row or a grid may also shrink below the width its contents ask for. */
input, select, textarea { max-width: 100%; min-width: 0; }
.field, .field-row > .field, .grid > *, .grid-2 > *, .grid-3 > * { min-width: 0; }
@media (max-width: 900px) {
  input[type=text], input[type=email], input[type=password], input[type=number], input[type=date], input[type=time],
  input[type=datetime-local], input[type=month], input[type=tel], input[type=url], input[type=search], input:not([type]),
  select, textarea { font-size: 16px; }
  input[type=date], input[type=time], input[type=datetime-local], input[type=month] {
    -webkit-appearance: none; appearance: none; display: block; min-height: 42px;
  }
  input[type=date]::-webkit-date-and-time-value, input[type=time]::-webkit-date-and-time-value,
  input[type=datetime-local]::-webkit-date-and-time-value, input[type=month]::-webkit-date-and-time-value { text-align: left; }
}
@media (max-width: 900px) {
  /* the few fields with a smaller size of their own, so tapping one never zooms the page either */
  .board-filters select, .board-filters input[type=search], .media-link-form input, .email-editor-pop-field input,
  textarea.mono, .row-menu-form input[type=file] { font-size: 16px; }
}

/* ---- Stream E: the song browse panel stays on the screen (the phone sweep, 28 September 2026) ----
   Each browse button opens a panel 300px wide hung from the button's own left edge, so on a phone the panel of any
   button but the first ran 70 to 200px off the right of the screen -- on the couple's Song Requests page, the DJ's
   and the library. On a phone the panel hangs from the BAR instead and is as wide as the bar. */
.browse-bar { position: relative; }
@media (max-width: 640px) {
  .browse-bar .browse-group, .browse-group { position: static; }
  .browse-bar .browse-panel, .browse-panel { left: 0; right: 0; width: auto; max-width: none; top: calc(100% + 6px); }
}

/* ---- Stream A: the Social calendar fits a phone ----
   Seven columns of 1fr are each as wide as their longest post title, which does not wrap, so a month with one long
   title made the whole page scroll sideways. A column may now be narrower than its contents; the title is cut short
   with an ellipsis, as it always was meant to be. */
.cal-grid { grid-template-columns: repeat(7, minmax(0, 1fr)); }
.cal-cell, .cal-head { min-width: 0; overflow: hidden; }
@media (max-width: 640px) {
  .cal-grid { gap: 2px; }
  .cal-head { letter-spacing: 0; font-size: 10px; padding: 2px 0; text-align: center; }
  .cal-cell { padding: 3px; min-height: 64px; }
  .cal-post { font-size: 10.5px; padding: 1px 3px; }
}

/* ---- Stream B: the held reason in the approval queue reads as a sentence (the showroom's third pass, 28 September 2026) ----
   A pill is a LABEL: capitals, tracked, one line. The reason a reply is held is a sentence with names and a day in
   it ("Held: they wrote to you ...; Lorenzo & Cedric are already on Saturday, October 3"), and in capitals it shouted.
   Sentence case, no tracking, and free to wrap on a narrow screen. */
.pill.pill-reason { text-transform: none; letter-spacing: 0; white-space: normal; text-align: left; font-weight: 500; line-height: 1.35; border-radius: var(--radius); }

/* ---- Stream A: video reels (Brian, 28 September 2026) ----
   A clip on the Photos & video tab says it is one, and how long it runs, over its still; and under each event's
   pictures, the reels made from its clips. */
.photo-tile-clip { position: absolute; top: 8px; right: 8px; z-index: 1; padding: 1px 6px; border-radius: var(--radius-sm); background: var(--ink); color: var(--surface); }
.reel-strip { margin-top: var(--space-2); padding: var(--space-2) var(--space-3); border: 1px solid var(--hairline); border-radius: var(--radius); background: var(--surface); }
.reel-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); padding-top: var(--space-2); margin-top: var(--space-2); border-top: 1px solid var(--hairline); }
.reel-thumb { display: block; width: 45px; height: 80px; flex: none; object-fit: cover; border-radius: var(--radius-sm); background: var(--surface-sunken); }
.reel-thumb-blank { display: flex; align-items: center; justify-content: center; color: var(--ink-muted); }
.reel-thumb-blank svg { width: 20px; height: 20px; }
.reel-words { flex: 1 1 220px; min-width: 0; overflow-wrap: anywhere; }

/* ---- Stream A: the order of a reel's clips (Brian, 29 September 2026) ----
   One row per clip, numbered as it will play, that can be dragged. */
.reel-order { list-style: none; margin: 0; padding: 0; }
.reel-order-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); padding: var(--space-2) 0; border-top: 1px solid var(--hairline); cursor: grab; }
.reel-order-row:first-child { border-top: 0; }
.reel-order-row.dragging { opacity: 0.5; }
.reel-order-num { flex: none; width: 28px; text-align: center; font-family: var(--font-display); font-size: 20px; }

/* ---- Stream H: video services (29 September 2026) ----
   The numbered setup steps on Settings -> Meetings -> Video services: room to read, and an address that wraps. */
.setup-steps { margin: var(--space-2) 0 0 18px; padding: 0; line-height: 1.7; }
.setup-steps code { overflow-wrap: anywhere; }
.setup-steps ul { margin: 4px 0 4px 18px; padding: 0; }

/* ---- Stream J: the sign-in pages (Brian, 30 September 2026) ----
   Light, the business's own colours, one card in the middle -- never the charcoal, the pulse line or a card pushed
   to one side. With "your hero photo behind it" the photo is faded under a wash of the page colour, so the card and
   its words read on any picture. */
.signin-body { margin: 0; background: var(--surface); }
.signin { position: relative; min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px; padding: 32px 16px; background: var(--surface); }
.signin-backdrop { position: fixed; inset: 0; background-position: center; background-size: cover; background-repeat: no-repeat; opacity: 0.22; pointer-events: none; z-index: 0; }
.signin-photo::after { content: ''; position: fixed; inset: 0; background: linear-gradient(180deg, var(--surface) 0%, transparent 40%, transparent 60%, var(--surface) 100%); opacity: 0.6; pointer-events: none; }
.signin > *:not(.signin-backdrop) { position: relative; z-index: 1; }
.signin-card { width: 100%; max-width: 400px; background: var(--surface-raised); border: 1px solid var(--hairline); border-radius: var(--radius); padding: 34px 30px 30px; box-shadow: var(--shadow-float); }
.signin-brand { text-align: center; margin-bottom: 20px; }
.signin-brand .letterhead { flex-direction: column; gap: 8px; }
.signin-brand .brand-logo { max-height: 64px; max-width: 260px; margin: 0 auto; }
.signin-brand .pp-mark { width: 72px; height: 72px; margin: 0 auto; }
.signin-brand .brand-name { font-size: 22px; color: var(--ink); }
.signin-brand .brand-sub { color: var(--ink-muted); }
.signin-name { font-family: var(--font-display); font-size: 22px; line-height: 1.2; margin-top: 10px; }
.signin-welcome { margin: 8px 0 0; color: var(--ink-muted); font-size: 15px; line-height: 1.45; }
.signin-kicker { color: var(--accent-strong); margin-top: 14px; }
.signin-foot { margin: 0; text-align: center; }
@media (max-width: 480px) { .signin { padding: 20px 12px; justify-content: flex-start; } .signin-card { padding: 26px 20px 24px; } }
@media print { .signin { min-height: 0; background: none; } .signin-card { box-shadow: none; border: 0; } .signin-backdrop, .signin-photo::after { display: none; } }
