/* Sales Intellect - CORE styles (2026-08-26).
 * Loaded by EVERY layout, public pages included: Bootstrap variable overrides,
 * typography, buttons, forms, cards, flash/toast, the public form page, the
 * public booking page, the Intellect (default) theme and the auth screens.
 * Anything only a signed-in member sees belongs in interface.css; the
 * Ocean/Forest/Midnight themes in themes.css. Keep this one small - it is the
 * render-blocking stylesheet on the sign-in page. */
/* Sales Intellect — application styles
 *
 * Warm-slate editorial theme: warm off-white canvas, near-black text,
 * neutral stone palette, Fraunces serif headings, Inter sans body.
 * Overrides Bootstrap 5.3 CSS variables in :root so most components
 * (buttons, cards, inputs, alerts) pick up the new look automatically.
 */

/* ---- Bootstrap variable overrides -------------------------------- */
:root {
    /* Sans + serif stacks. Fraunces gives headings an editorial feel. */
    --bs-font-sans-serif: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto,
                          'Helvetica Neue', Arial, sans-serif;
    --is-font-serif:      'Fraunces', 'Iowan Old Style', 'New York', Georgia,
                          'Times New Roman', serif;

    /* Warm off-white canvas, cream-tinted cards, stone borders. */
    --bs-body-bg:        #faf8f3;
    --bs-body-color:     #1c1917;
    --bs-emphasis-color: #18181b;
    --bs-secondary-color: #6b6660;
    --bs-tertiary-color:  #a8a29e;
    --bs-tertiary-bg:     #f2efe8;

    /* Goal-pill status colours (campaign board).
     *
     * These live on the PILL, never on the table cell: a whole cell washed
     * green or red turns the board into a block of colour and drowns out the
     * contact beside it. The pill carries the status; the cell stays paper.
     * Each theme redefines the four pairs below and inherits everything else.
     * "Not yet" states (due later, any-time, waiting on a prerequisite) use
     * the theme's own tertiary tokens, so they read as quiet by construction. */
    --goal-done-bg:    #e7f3ea;  --goal-done-fg:    #14532d;
    --goal-notdone-bg: #fee2e2;  --goal-notdone-fg: #b91c1c;
    --goal-todo-bg:    #fdf1d8;  --goal-todo-fg:    #854d0e;
    --goal-overdue-bg: #fbe6e1;  --goal-overdue-fg: #7f1d1d;

    --bs-border-color:             #e7e3d8;
    --bs-border-color-translucent: rgba(28, 25, 23, .08);
    --bs-border-radius:    .375rem;
    --bs-border-radius-sm: .25rem;
    --bs-border-radius-lg: .5rem;

    /* Near-black primary — buttons, links, focus rings. */
    --bs-primary:     #292524;
    --bs-primary-rgb: 41, 37, 36;
    --bs-link-color:        #292524;
    --bs-link-color-rgb:    41, 37, 36;
    --bs-link-hover-color:  #57534e;

    /* Subtle warm secondary for ghost buttons. */
    --bs-secondary:     #78716c;
    --bs-secondary-rgb: 120, 113, 108;

    /* Backwards-compat with the legacy custom var some code still reads. */
    --is-accent: #292524;
    --is-accent-soft: rgba(41, 37, 36, .08);
    /* Text that sits ON --is-accent. White is right for four of the five
       themes, whose accents are dark; Midnight's accent is a light indigo,
       where white reaches only 2.98:1. Any rule filling with --is-accent must
       take its text from here rather than assuming #fff. */
    --is-accent-contrast: #ffffff;
    --is-warm-bg: #faf8f3;

    /* The theme's dark tone, used by the "Always use dark header" preference
       (.header-dark below). Every theme MUST define this — a theme without one
       falls back to this warm-slate value and will look off-palette. It has to
       be dark enough for white text and the on-dark logo to sit on it. */
    --is-header-dark: #292524;   /* near-black stone */

    /* Height of the pinned top navbar. Anything that has to sit clear of it
       (sticky sidebars, in-page anchor targets) offsets by this, so the bar's
       size lives in exactly one place. Matches brand logo 30px + brand padding
       .5rem + navbar padding 1rem + 1px border. */
    --is-navbar-h: 55px;
}

html, body {
    font-family: var(--bs-font-sans-serif);
}
body {
    background-color: var(--bs-body-bg);
    color: var(--bs-body-color);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-feature-settings: "ss01", "cv11"; /* nicer Inter forms */
}

/* Serif headings — editorial accent on top-of-page titles. */
h1, h2, h3, h4, h5,
.h1, .h2, .h3, .h4, .h5 {
    font-family: var(--is-font-serif);
    font-weight: 600;
    letter-spacing: -0.015em;
    color: var(--bs-emphasis-color);
}
h6, .h6 { /* keep h6 in sans — used in card titles as a label */
    font-family: var(--bs-font-sans-serif);
    font-weight: 600;
    letter-spacing: 0;
}

/* Inputs / forms / focus rings. */
.form-control, .form-select {
    border-color: var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    background-color: #ffffff;
}
.form-control:focus, .form-select:focus {
    border-color: #57534e;
    box-shadow: 0 0 0 .2rem rgba(41, 37, 36, .12);
}
.form-control::placeholder { color: var(--bs-tertiary-color); }

/* ---- Buttons ------------------------------------------------------ */
.btn {
    --bs-btn-border-radius: var(--bs-border-radius);
    font-weight: 500;
    letter-spacing: .005em;
}
.btn-primary {
    --bs-btn-bg:         #292524;
    --bs-btn-border-color: #292524;
    --bs-btn-hover-bg:   #1c1917;
    --bs-btn-hover-border-color: #1c1917;
    --bs-btn-active-bg:  #18181b;
    --bs-btn-active-border-color: #18181b;
    --bs-btn-color:      #faf8f3;
    --bs-btn-hover-color: #ffffff;
    /* Disabled state: muted warm stone instead of Bootstrap's blue. */
    --bs-btn-disabled-bg:           #d6d3c9;
    --bs-btn-disabled-border-color: #c7c2b3;
    --bs-btn-disabled-color:        #78716c;
}
/* Skip Bootstrap's extra .65 opacity fade on disabled — our disabled colour
   tokens above are already muted enough to read as inactive. */
.btn-primary:disabled,
.btn-primary.disabled { opacity: 1; }
.btn-outline-primary {
    --bs-btn-color:        #292524;
    --bs-btn-border-color: #d6d3c9;
    --bs-btn-hover-bg:     #f2efe8;
    --bs-btn-hover-border-color: #292524;
    --bs-btn-hover-color:  #292524;
    --bs-btn-active-bg:    #292524;
    --bs-btn-active-border-color: #292524;
    --bs-btn-active-color: #ffffff;
}
.btn-outline-secondary {
    --bs-btn-color:        #57534e;
    --bs-btn-border-color: #e0dccf;
    --bs-btn-hover-bg:     #f2efe8;
    --bs-btn-hover-color:  #1c1917;
    --bs-btn-hover-border-color: #c7c2b3;
}
.btn-success {
    --bs-btn-bg:         #15803d;
    --bs-btn-border-color: #15803d;
    --bs-btn-hover-bg:   #166534;
    --bs-btn-hover-border-color: #166534;
}

/* Subtle pill chips for badges that read as labels. */
.badge {
    font-weight: 500;
    letter-spacing: .01em;
    border-radius: 999px;
    padding: .25em .6em;
}

/* ---- Cards -------------------------------------------------------- */
.card {
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-lg);
    background-color: #ffffff;
    box-shadow: 0 1px 0 rgba(28, 25, 23, .025);
}
.card-header {
    background-color: #ffffff !important;
    border-bottom-color: var(--bs-border-color);
    font-weight: 500;
}
.card-footer {
    background-color: #ffffff !important;
    border-top-color: var(--bs-border-color);
}
/* The organisation's logo beside the dashboard greeting: capped so a tall
   mark sits level with the two-line title, never a banner. */
.home-org-logo { max-height: 3.5rem; max-width: 14rem; width: auto; height: auto; object-fit: contain; }

.mode-card {
    transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
    color: var(--bs-emphasis-color);
}
.mode-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 22px rgba(28, 25, 23, .06);
    border-color: #c7c2b3;
}

/* ---- Tables ------------------------------------------------------- */
.table {
    --bs-table-bg: transparent;
    --bs-table-color: var(--bs-body-color);
    --bs-table-border-color: var(--bs-border-color);
    --bs-table-hover-bg: rgba(41, 37, 36, .035);
    --bs-table-striped-bg: rgba(41, 37, 36, .02);
}
.table > :not(caption) > * > * {
    border-bottom-color: var(--bs-border-color);
}
.table-light, .table-light > th, .table-light > td {
    --bs-table-bg: #f5f1e8;
    --bs-table-color: #57534e;
}
.table > thead th {
    font-weight: 500;
    text-transform: none;
    letter-spacing: 0;
    color: #57534e;
}

/* ---- Public form page -------------------------------------------- */
.salesint-form-wrap { max-width: 720px; margin: 0 auto; }

/* Row rhythm. Was .25rem, which on a form of single-field rows left barely
   four pixels between one answer and the next — and the embed had been on 1rem
   all along, so the hosted form and the embedded one did not match. Same
   number in both places now; the embed's copy lives in
   PublicFormController::embedCss(). */
.salesint-row { margin-bottom: 1rem; }

/* The submit is the end of the form and a deliberate act, not another field,
   so it gets a clear break rather than the row rhythm.
 *
 * On the row rather than on the button, via :has(), so a submit that shares a
 * row with a field still lines up with it instead of being pushed down on its
 * own. Where :has() is unsupported the rule is simply skipped and the form
 * falls back to normal row spacing — no layout breaks. */
.salesint-row:has(.salesint-submit-wrap) {
    margin-top: 1.75rem;
    margin-bottom: 1.25rem;
}

/* A row whose whole content is hidden fields. The inputs inside are
   display:none of their own accord, but the row would still bring a gutter's
   worth of margin with it — a gap on the page where the visitor sees nothing
   to explain it. The row element itself stays in the document so a "show only
   if" rule still has something to act on; the embed's copy of this rule lives
   in PublicFormController::embedCss(). */
.salesint-row--novisual { display: none; }

.salesint-required { color: var(--bs-danger); }

/* The upload field's ticked file kinds, in the designer's settings panel. Ten
   checkboxes on the standard .form-check margin is a column of air; tightened
   here rather than in checkControl(), which every other setting also uses. */
.form-upload-types { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 .5rem; }
.form-upload-types .form-check { margin-bottom: .1rem; }
.form-range-value { min-width: 4.5rem; text-align: right; }

/* ---- File upload drop zone (public form) --------------------------
 *
 * The hosted page's version: themed, unlike the embed's, which ships a bare
 * layout-only copy in PublicFormController::embedCss() because on somebody
 * else's site the colours are theirs to choose.
 *
 * The file input covers the whole zone at zero opacity rather than being hidden
 * away. That is what makes a click anywhere on it open the picker and a file
 * dropped on it register, with no JavaScript involved at all — the script only
 * adds the running list, per-file removal and the checks. */
.salesint-dropzone {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .15rem;
    text-align: center;
    padding: 1.5rem 1rem;
    border: 2px dashed var(--bs-border-color);
    border-radius: var(--bs-border-radius-lg);
    background-color: var(--bs-body-bg);
    color: var(--bs-secondary-color);
    cursor: pointer;
    transition: border-color .15s ease, background-color .15s ease, color .15s ease;
}
.salesint-dropzone:hover,
.salesint-dropzone:focus-within,
.salesint-dropzone.is-dragging {
    border-color: var(--is-accent, var(--bs-primary));
    background-color: var(--is-accent-soft, var(--bs-tertiary-bg));
    color: var(--bs-body-color);
}
.salesint-dropzone.is-invalid { border-color: var(--bs-danger); }
.salesint-dropzone-icon { font-size: 1.4rem; line-height: 1; }
.salesint-dropzone-text { font-size: .9rem; }
.salesint-dropzone-hint { font-size: .78rem; opacity: .8; }
.salesint-file-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}
/* A file input covering the zone would swallow a drop meant for the list once
   files are showing; the list sits outside the zone, so it does not. */
.salesint-file-list { list-style: none; margin: .5rem 0 0; padding: 0; }
.salesint-file-list:empty { display: none; }
.salesint-file {
    display: flex;
    align-items: center;
    gap: .5rem;
    font-size: .82rem;
    background-color: var(--bs-tertiary-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    padding: .25rem .5rem;
    margin-bottom: .3rem;
}
.salesint-file-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.salesint-file-size { flex: 0 0 auto; color: var(--bs-secondary-color); }
.salesint-file-remove {
    flex: 0 0 auto;
    background: none;
    border: 0;
    padding: 0 .15rem;
    line-height: 1;
    font-size: 1.05rem;
    color: var(--bs-secondary-color);
    cursor: pointer;
}
.salesint-file-remove:hover { color: var(--bs-danger); }
/* Said after a re-render, which cannot put files back into an input. Amber
   rather than red: nothing is wrong yet, but something needs doing again. */
.salesint-refile { color: var(--bs-warning-text-emphasis, #997404); }

/* The honeypot. Off-screen rather than display:none — a bot reading the DOM
   skips what is hidden, and the point is that it fills this in.
   The embed ships its own copy of this rule inside embed.js, because on
   somebody else's site there is no stylesheet of ours to rely on. */
.salesint-hp {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* ---- Modals & offcanvas ------------------------------------------ */
.modal-content, .offcanvas {
    background-color: #ffffff;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-lg);
    box-shadow: 0 24px 48px rgba(28, 25, 23, .12);
}
.modal-header, .offcanvas-header { border-bottom-color: var(--bs-border-color); }
.modal-footer { border-top-color: var(--bs-border-color); }
.modal-title, .offcanvas-title {
    font-family: var(--is-font-serif);
    font-weight: 600;
}

/* ---- Flash messages ---- */
.flash-stack { position: relative; }
.alert {
    border-radius: var(--bs-border-radius);
    border-width: 1px;
}

/* ---- Toast stack ---------------------------------------------------
   One column, anchored to the bottom-right. Toasts used to pin themselves
   individually to that corner, so two raised by the same action landed on top
   of one another — a "Saved" message hidden underneath a warning about the
   same save. The container is pinned instead; it grows upwards as toasts are
   added, newest nearest the corner. */
#appToastStack {
    position: fixed;
    bottom: 1rem;
    right: 1rem;
    z-index: 1080;
    display: flex;
    flex-direction: column;
    gap: .5rem;
    max-width: min(24rem, calc(100vw - 2rem));
    pointer-events: none;      /* the gaps between toasts stay click-through */
}
#appToastStack > .toast {
    pointer-events: auto;
    min-width: 18rem;
}

/* ---- Public booking page (/meetwith/...) -------------------------- */
.public-page { background: var(--bs-body-bg); min-height: 100vh; }

.bk-day-strip {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: .35rem;
}
.bk-day-cell {
    background: #fff;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-sm);
    padding: .5rem .25rem;
    cursor: pointer;
    text-align: center;
    transition: border-color .12s ease, background-color .12s ease;
}
.bk-day-cell:hover { border-color: var(--bs-primary); }
.bk-day-cell.is-selected {
    border-color: var(--bs-primary);
    background: var(--is-accent-soft);
}
.bk-day-cell.is-today .bk-day-cell-num {
    color: var(--bs-primary);
    font-weight: 700;
}
.bk-day-cell.is-empty {
    opacity: .3;
    background: var(--bs-tertiary-bg);
    color: var(--bs-tertiary-color);
}
.bk-day-cell.is-empty:hover { border-color: var(--bs-border-color); }
.bk-day-cell-weekday { font-size: .72rem; color: var(--bs-secondary-color); text-transform: uppercase; }
.bk-day-cell-num     { font-size: 1.4rem; font-weight: 600; line-height: 1.1; }
.bk-day-cell-month   { font-size: .72rem; color: var(--bs-secondary-color); }

.bk-slot-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: .5rem;
}
.bk-slot-btn {
    background: #fff;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius-sm);
    padding: .5rem;
    text-align: center;
    cursor: pointer;
    transition: border-color .12s ease, background-color .12s ease, transform .08s ease;
}
.bk-slot-btn:hover {
    border-color: var(--bs-primary);
    background: var(--is-accent-soft);
}
.bk-slot-btn:active { transform: translateY(1px); }
.bk-slot-time { font-weight: 600; }
.bk-slot-btn.is-current {
    border-color: var(--bs-primary);
    background: var(--is-accent-soft);
    cursor: default;
}
.bk-slot-current-tag {
    font-size: .65rem;
    color: var(--bs-primary);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .03em;
    margin-top: .1rem;
}

.bk-tz-row {
    display: block;
    width: 100%;
    padding: .35rem .5rem;
    border: 0;
    background: transparent;
    text-align: left;
    border-radius: var(--bs-border-radius-sm);
    font-size: .9rem;
}
.bk-tz-row:hover { background: var(--bs-tertiary-bg); }

/* "Powered by Sales Intellect" call-out under the booking form. Built purely
   on theme variables so it works on whichever theme the host picked for their
   public page (including midnight) with no per-theme overrides. */
/* One row: our lockup on the left, the credit line on the right. The page
   belongs to the organisation whose logo is at the top of it, so this is a
   credit, not a pitch — it was a bordered block with a headline, a paragraph
   and a call-to-action button competing with the booking form above it. */
.bk-promo {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-top: 2.5rem;
    padding-top: 1rem;
    /* A rule rather than a box — it separates without enclosing. */
    border-top: 1px solid var(--bs-border-color);
}
.bk-promo-brand {
    display: inline-flex;
    flex: 0 0 auto;
}
.bk-promo-brand img {
    height: 22px;
    width: auto;
    max-width: 100%;
}
.bk-promo-lead {
    margin: 0;
    margin-left: auto;      /* right-aligned even when the row wraps */
    text-align: right;
    font-size: .8125rem;
    line-height: 1.5;
    color: var(--bs-secondary-color);
}
.bk-promo-lead a {
    color: var(--bs-emphasis-color);
    font-weight: 600;
    text-decoration: none;
}
.bk-promo-lead a:hover { text-decoration: underline; }

/* The host organisation's own logo, above their booking form. Contained
   rather than stretched: logos arrive at every aspect ratio, and one drawn to
   the full width of its column would tower over the heading beside it. */
.bk-org-logo {
    display: block;
    max-width: 100%;
    max-height: 96px;
    width: auto;
    object-fit: contain;
}
@media (max-width: 575.98px) {
    /* Stacked: the logo goes back to leading the page, centred over the words
       rather than sitting off to one side of nothing. */
    .bk-public-header--branded { text-align: center; }
    .bk-org-logo { margin: 0 auto; }
    .bk-promo { justify-content: center; }
    .bk-promo-lead { margin-left: 0; text-align: center; }
}

/* The logo preview on /admin/organisation. */
.org-logo-preview {
    max-width: 220px;
    max-height: 90px;
    object-fit: contain;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--bs-border-radius);
    background-color: var(--bs-tertiary-bg);
    padding: .35rem .5rem;
}

/* Responsive: stack panes vertically on small screens. */
@media (max-width: 992px) {
    .calendar-layout { flex-direction: column; }
    [data-mode="dual"] .cal-pane-month,
    [data-mode="dual"] .cal-pane-day,
    [data-mode="tri"]  .cal-pane-month,
    [data-mode="tri"]  .cal-pane-day,
    [data-mode="tri"]  .cal-pane-entry { flex: 1 1 auto; max-width: 100%; }
    [data-mode="dual"] .cal-pane-entry { display: none; }
}

/* ---- Theme: Intellect (default) ----------------------------------
 * The Sales Intellect brand system: brand blues as anchors, soft blue tints
 * and neutrals for everyday surfaces, calm accents. Deliberately no amber —
 * in a CRM full of statuses it competes with real alerts, so "todo"/"on hold"
 * use Lilac and alerts use Rose.
 *
 * Source of truth: newfiles/claude-sales-intellect-crm-system-v3.html
 *   brand   light-blue #00c8ff · dark-blue #004499 · bg-blue #00317c
 *   tints   blue-50 #eef6fd · blue-100 #d9ecfa · blue-200 #b3d7f2
 *   neutral ink #1a2230 · graphite #45505f · slate #6b7686 · mist #e4e9f0
 *           cloud #f0f3f7 · paper #f7f9fc
 *   accents teal #17a2a8 · sage #4fb286 · lilac #7c83db · rose #e06c78
 *
 * Per the system's working rules the app canvas stays Paper/White with Dark
 * Blue as the single primary action — the navbar is therefore light, which is
 * also why this theme uses the on-light logo (see Theme::isDark).
 */
.theme-intellect {
    /* Goal-pill status — see :root for why these are pill-only. */
    --goal-done-bg: #e6f6f2;  --goal-done-fg: #0d7a5f;
    --goal-notdone-bg: #fbeef0;  --goal-notdone-fg: #ba4150;
    --goal-todo-bg: #eef0fb;  --goal-todo-fg: #4b52b3;
    --goal-overdue-bg: #f7dfe3;  --goal-overdue-fg: #a3323f;

    /* The system specifies one Segoe UI display/body stack — no serif. */
    --bs-font-sans-serif: 'Segoe UI', system-ui, -apple-system, 'Helvetica Neue',
                          Arial, sans-serif;
    --is-font-serif:      'Segoe UI', 'Helvetica Neue', Arial, sans-serif;

    --bs-body-bg:         #f7f9fc;  /* paper */
    --bs-body-color:      #1a2230;  /* ink */
    --bs-emphasis-color:  #004499;  /* dark blue — "headings, key structure" */
    --bs-secondary-color: #45505f;  /* graphite */
    --bs-tertiary-color:  #6b7686;  /* slate */
    --bs-tertiary-bg:     #f0f3f7;  /* cloud */

    --bs-border-color:             #e4e9f0;  /* mist / stroke */
    --bs-border-color-translucent: rgba(26, 34, 48, .08);
    --bs-border-radius:    .5rem;   /* --r-sm 8px  */
    --bs-border-radius-sm: .375rem;
    --bs-border-radius-lg: .75rem;  /* --r 12px    */

    --bs-primary:     #004499;
    --bs-primary-rgb: 0, 68, 153;
    --bs-link-color:       #004499;
    --bs-link-color-rgb:   0, 68, 153;
    --bs-link-hover-color: #0052b8;

    --bs-secondary:     #6b7686;
    --bs-secondary-rgb: 107, 118, 134;

    /* Focus rings: light blue at ~16% — on-brand and visible for keyboard users. */
    --bs-focus-ring-color: rgba(0, 200, 255, .16);

    --is-accent: #004499;
    --is-accent-soft: #eef6fd;  /* blue-50 — the system's hover fill */
    --is-warm-bg: #f7f9fc;
    /* BG Blue. The design system reserves this exact colour for "header bars,
       deep gradients, sidebars" — so it is literally what a dark header wants. */
    --is-header-dark: #00317c;
}
.theme-intellect .btn-primary {
    --bs-btn-bg:         #004499;
    --bs-btn-border-color: #004499;
    --bs-btn-hover-bg:   #0052b8;
    --bs-btn-hover-border-color: #0052b8;
    --bs-btn-active-bg:  #00317c;
    --bs-btn-active-border-color: #00317c;
    --bs-btn-color:      #ffffff;
    --bs-btn-hover-color: #ffffff;
    --bs-btn-disabled-bg:           #cdd6e2;
    --bs-btn-disabled-border-color: #cdd6e2;
    --bs-btn-disabled-color:        #6b7686;
}
.theme-intellect .btn-outline-primary {
    --bs-btn-color:        #004499;
    --bs-btn-border-color: #cdd6e2;  /* stroke-strong */
    --bs-btn-hover-bg:     #eef6fd;
    --bs-btn-hover-border-color: #004499;
    --bs-btn-hover-color:  #004499;
    --bs-btn-active-bg:    #004499;
    --bs-btn-active-border-color: #004499;
    --bs-btn-active-color: #ffffff;
}
.theme-intellect .btn-outline-secondary {
    --bs-btn-color:        #45505f;
    --bs-btn-border-color: #cdd6e2;
    --bs-btn-hover-bg:     #f0f3f7;
    --bs-btn-hover-color:  #1a2230;
    --bs-btn-hover-border-color: #6b7686;
}
/* Soft destructive: rose outline, filled only on confirm. */
.theme-intellect .btn-danger {
    --bs-btn-bg:         #e06c78;
    --bs-btn-border-color: #e06c78;
    --bs-btn-hover-bg:   #c9525f;
    --bs-btn-hover-border-color: #c9525f;
    --bs-btn-color:      #ffffff;
}
.theme-intellect .btn-outline-danger {
    --bs-btn-color:        #c04552;
    --bs-btn-border-color: #f0cdd1;
    --bs-btn-hover-bg:     #fbeef0;
    --bs-btn-hover-color:  #c04552;
    --bs-btn-hover-border-color: #e06c78;
}
.theme-intellect .btn-success {
    --bs-btn-bg:         #4fb286;
    --bs-btn-border-color: #4fb286;
    --bs-btn-hover-bg:   #3f9d74;
    --bs-btn-hover-border-color: #3f9d74;
    --bs-btn-color:      #ffffff;
    --bs-btn-hover-color: #ffffff;
}
.theme-intellect .app-navbar {
    background-color: rgba(247, 249, 252, .85);
    border-bottom-color: #e4e9f0;
}
.theme-intellect .app-navbar .nav-link { color: #45505f; }
.theme-intellect .form-control:focus,
.theme-intellect .form-select:focus {
    border-color: #00c8ff;
    box-shadow: 0 0 0 3px rgba(0, 200, 255, .16);
}
/* Status colours — sage / rose / lilac. No amber, by design. */
.theme-intellect .history-pill--created     { background: #e6f6f2; color: #0d7a5f; border-color: #c4e8dc; }
.theme-intellect .history-pill--rescheduled { background: #eef6fd; color: #004499; border-color: #b3d7f2; }
.theme-intellect .history-pill--cancelled   { background: #fbeef0; color: #c04552; border-color: #f0cdd1; }
.theme-intellect .history-pill--note        { background: #eef0fb; color: #4b52b3; border-color: #d5d8f3; }
.theme-intellect .table {
    --bs-table-hover-bg:   rgba(0, 49, 124, .035);
    --bs-table-striped-bg: rgba(0, 49, 124, .02);
}
.theme-intellect .table-light,
.theme-intellect .table-light > th,
.theme-intellect .table-light > td {
    --bs-table-bg:    #f0f3f7;
    --bs-table-color: #45505f;
}
.theme-intellect .table > thead th { color: #45505f; }
.theme-intellect .nav-tabs .badge {
    background-color: #d9ecfa !important;
    color: #004499 !important;
}
/* The auth canvas now lives in the .auth-split rules further down. */

/* Preview: Intellect (default) — swatch for the Settings theme picker.
   Mirrors .theme-preview-* above: navbar tint, canvas, sidebar, text lines. */
.theme-preview-intellect .tp-navbar {
    background: rgba(0, 68, 153, .85);
}
.theme-preview-intellect .tp-navbar::before {
    background: #f7f9fc;
}
.theme-preview-intellect .tp-sidebar {
    background: #eef6fd;
}
.theme-preview-intellect .tp-content {
    background: #f7f9fc;
}
.theme-preview-intellect .tp-line {
    background: #cdd6e2;
}

/* ---- Auth split (sign in / setup / invites) -----------------------
 * Two 50/50 panes: product summary left, form right. Below 820px it stacks
 * and the hero degrades to a slim banner so the form stays above the fold.
 *
 * Colours come from the active theme's variables rather than hard-coded brand
 * hexes, so this survives a change of default theme; .theme-intellect then
 * layers the brand's soft blue wash over the top.
 *
 * The hero is deliberately LIGHT: it carries the on-light logo, which is dark
 * artwork and would disappear on a dark panel.
 */
.auth-page { margin: 0; }
.auth-split {
    display: flex;
    min-height: 100vh;
    min-height: 100dvh;
}
.auth-split > section { flex: 1 1 50%; }

.auth-hero {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 3rem;
    color: var(--bs-body-color);
    background: linear-gradient(150deg, var(--bs-tertiary-bg) 0%, var(--bs-body-bg) 100%);
    border-right: 1px solid var(--bs-border-color);
}
.auth-hero-inner { max-width: 30rem; width: 100%; }
.auth-logo {
    display: block;
    width: min(360px, 85%);
    height: auto;
    margin-bottom: 2.5rem;
}
.auth-headline {
    font-size: clamp(1.7rem, 3.2vw, 2.6rem);
    line-height: 1.12;
    font-weight: 700;
    letter-spacing: -0.02em;
    margin: 0 0 1rem;
    color: var(--bs-emphasis-color);
}
.auth-sub {
    font-size: 1.02rem;
    line-height: 1.6;
    color: var(--bs-secondary-color);
    margin: 0 0 2rem;
}
.auth-points {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    gap: .75rem;
}
/* Two flex children only: the tick, and ONE element holding all the text.
   Every child of a flex container is a flex item, so bare text beside a <strong>
   splits into separate items — each getting the gap above, and each laying out
   on its own instead of wrapping as one paragraph. That is why the bullet text
   must stay wrapped in .auth-point-text, however tempting it looks to drop it. */
.auth-points li {
    display: flex;
    align-items: flex-start;
    gap: .6rem;
    font-size: .98rem;
    line-height: 1.5;
    color: var(--bs-body-color);
}
/* The single text child of a flex bullet — min-width:0 lets it wrap rather
   than force the row wider than the panel. */
.auth-point-text,
.auth-steps-text { min-width: 0; }
.auth-tick {
    flex: none;
    width: 1.25rem;
    height: 1.25rem;
    border-radius: 50%;
    background: var(--bs-primary);
    color: #fff;
    display: grid;
    place-items: center;
    font-size: .7rem;
    margin-top: .15rem;
}

/* Bold names inside a bullet. The list is scanned before it is read, so the
   feature's name carries the weight and the sentence around it does not. */
.auth-points strong { font-weight: 600; color: var(--bs-emphasis-color); }

/* ---- "How it works" block, hero side (register page) ------------------
   Sits under the bullet list and, unlike the bullets, STAYS on mobile: what
   happens after someone hits Send is the question the form has to answer, so
   it cannot be the thing that gets hidden at 820px. The .theme-intellect block
   below re-tints it for the navy hero. */
.auth-steps {
    margin-top: 2rem;
    padding: 1.1rem 1.2rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .7rem;
    background: var(--bs-tertiary-bg);
}
.auth-steps-title {
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
    margin: 0 0 .85rem;
    color: var(--bs-secondary-color);
}
.auth-steps-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    gap: .75rem;
    counter-reset: auth-step;
}
/* Two flex children only — same rule as .auth-points li, see the note there. */
.auth-steps-list li {
    display: flex;
    align-items: flex-start;
    gap: .65rem;
    font-size: .92rem;
    line-height: 1.45;
    color: var(--bs-body-color);
}
/* Numbers rather than ticks: the ticks above mean "feature", and reusing them
   here would read as three more features instead of three steps in order. */
.auth-steps-list li::before {
    counter-increment: auth-step;
    content: counter(auth-step);
    flex: none;
    width: 1.35rem;
    height: 1.35rem;
    border-radius: 50%;
    border: 1px solid var(--bs-primary);
    color: var(--bs-primary);
    font-size: .72rem;
    font-weight: 700;
    display: grid;
    place-items: center;
    margin-top: .1rem;
}

/* ---- Call to action, PANEL side ---------------------------------------
   The registration invitation under the sign-in card. It lives in the right column,
   not the hero, because it is an offer aimed at the person already looking at
   the form — and because the hero's bullets vanish below 820px, which would
   hide it from every phone.

   The large margin-top is load-bearing: without a clear gap this reads as part
   of the sign-in card above it, and "Register" starts to look like a second
   submit button for the same form. */
.auth-cta {
    /* Mirrors --mk-accent / --mk-navy-deep in marketing.css - keep the pairs equal. */
    --auth-accent: #00c8ff;
    --auth-navy-deep: #001c47;
    margin-top: 2.75rem;
    padding: 1.15rem 1.25rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .7rem;
    background: var(--bs-tertiary-bg);
}
.auth-cta-badge {
    display: inline-block;
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
    padding: .2rem .5rem;
    border-radius: .35rem;
    background: var(--auth-accent);
    color: var(--auth-navy-deep);
    margin-bottom: .6rem;
}
/* The register button: cyan on deep navy, the same pair marketing.css uses for
   its accent (--mk-accent / --mk-navy-deep), so the offer reads as a step
   toward /how-we-help rather than as another sign-in button. */
.auth-cta-btn {
    display: block;
    width: 100%;
    padding: .55rem 1rem;
    border: 0;
    border-radius: var(--bs-border-radius);
    background: var(--auth-accent);
    color: var(--auth-navy-deep);
    font-weight: 700;
    text-align: center;
    text-decoration: none;
    transition: filter .15s ease;
}
.auth-cta-btn:hover, .auth-cta-btn:focus-visible { background: var(--auth-accent); color: var(--auth-navy-deep); filter: brightness(1.08); }
.auth-cta-title {
    font-size: 1.02rem;
    font-weight: 600;
    margin: 0 0 .35rem;
    color: var(--bs-emphasis-color);
}
.auth-cta-text {
    margin: 0 0 .9rem;
    font-size: .9rem;
    line-height: 1.55;
    color: var(--bs-secondary-color);
}
.auth-cta-text strong { color: var(--bs-emphasis-color); font-weight: 600; }
/* Variant with no button — a reminder, not an offer, so it needs less weight
   and no bottom gap under its only paragraph. */
.auth-cta--quiet {
    margin-top: 1.5rem;
    padding: .85rem 1rem;
    text-align: center;
}
.auth-cta--quiet .auth-cta-text { font-size: .86rem; }

/* ---- Phone number + who builds this ------------------------------------
   partials/auth_contact.php, under the last card in the right column of
   /login and /register. A hairline above it rather than a box: it is a
   footnote to the column, not a fourth thing to read. */
.auth-contact {
    margin-top: 1.75rem;
    padding-top: 1.15rem;
    border-top: 1px solid var(--bs-border-color);
    text-align: center;
}
.auth-contact-call {
    margin: 0 0 .35rem;
    font-size: .92rem;
    color: var(--bs-secondary-color);
}
.auth-contact-call a {
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;   /* a phone number broken across two lines is unreadable */
}
.auth-contact-call a:hover { text-decoration: underline; }
.auth-contact-by { margin: 0; font-size: .8rem; color: var(--bs-secondary-color); }

/* ---- Two-up form fields (register) -------------------------------------
   The rows' vertical spacing still comes from each field's .mb-3, so only the
   column gap belongs here. Anything that must span both columns takes
   .auth-form-full. */
.auth-form-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 1rem;
}
.auth-form-grid > .auth-form-full { grid-column: 1 / -1; }
@media (max-width: 520px) {
    .auth-form-grid { grid-template-columns: 1fr; }
}

/* ---- Registration thank-you ------------------------------------------- */
.auth-thanks-icon {
    width: 3rem;
    height: 3rem;
    margin: 0 auto 1rem;
    border-radius: 50%;
    background: var(--bs-primary);
    color: #fff;
    display: grid;
    place-items: center;
    font-size: 1.5rem;
}
.auth-thanks-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    gap: .6rem;
}
/* Same two-children rule as .auth-points li — see the note there. */
.auth-thanks-list li {
    display: flex;
    align-items: flex-start;
    gap: .6rem;
    font-size: .9rem;
    line-height: 1.5;
    color: var(--bs-body-color);
}
/* .auth-tick is a hero component, and .theme-intellect re-tints it further down
   this file for the navy panel — light blue on dark. On this light card it needs
   the untinted brand fill back, so the selector carries one extra class to win
   on specificity rather than on source order. */
.auth-thanks-list li .auth-tick {
    background: var(--bs-primary);
    color: #fff;
}

.auth-panel {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 3rem;
    background: var(--bs-body-bg);
}
.auth-panel-inner { max-width: 26rem; width: 100%; }
/* The form card on sign-in and register: the same deep, soft shadow and 1rem
   radius as the .mk-art boxes on /how-we-help, so the two pages read as one
   site. Overrides the flat .card rule above (the app's cards stay flat). */
.auth-card-inner {
    border: 1px solid #dfe7f1;
    border-radius: 1rem;
    box-shadow: 0 24px 50px rgba(0, 40, 96, .12);
}
/* The register page only — its form is two columns wide (see the view). */
.auth-panel-inner--wide { max-width: 30rem; }

/* Brand hero — deep navy gradient, bg-blue → dark-blue. The design system
   reserves BG Blue for "header bars, deep gradients, sidebars", which is
   exactly this panel.
   Because it is dark, everything on it inverts: the layout uses the on-DARK
   logo (see layouts/auth.php) and the text colours below. Change the gradient
   back to a light one and these all have to come with it, or the panel goes
   white-on-white. */
.theme-intellect .auth-hero {
    background: linear-gradient(150deg, #00317c 0%, #004499 100%);
    border-color: rgba(255, 255, 255, .12);
    color: #ffffff;
}
.theme-intellect .auth-headline  { color: #ffffff; }
.theme-intellect .auth-sub       { color: #b3d7f2; }  /* blue-200 */
.theme-intellect .auth-points li { color: #d9ecfa; }  /* blue-100 */
.theme-intellect .auth-tick {
    background: #00c8ff;  /* light blue — the system's accent/active colour */
    color: #00317c;
}
.theme-intellect .auth-points strong { color: #ffffff; }
.theme-intellect .auth-steps {
    border-color: rgba(255, 255, 255, .18);
    background: rgba(255, 255, 255, .07);
}
.theme-intellect .auth-steps-title      { color: #b3d7f2; }  /* blue-200 */
.theme-intellect .auth-steps-list li    { color: #d9ecfa; }  /* blue-100 */
.theme-intellect .auth-steps-list li::before {
    border-color: #00c8ff;
    color: #00c8ff;  /* light blue — the system's accent/active colour */
}

@media (max-width: 820px) {
    .auth-split { flex-direction: column; }
    .auth-hero {
        padding: 2.25rem 1.5rem;
        border-right: 0;
        border-bottom: 1px solid var(--bs-border-color);
    }
    .auth-hero-inner { max-width: 34rem; margin: 0 auto; }
    .auth-logo { margin-bottom: 1.5rem; width: min(300px, 75%); }
    .auth-headline { font-size: 1.6rem; }
    .auth-sub { margin-bottom: 0; }
    .auth-points { display: none; }  /* keep the form above the fold */
    /* The steps stay — with the bullets gone they follow .auth-sub directly,
       so they need a smaller gap than the desktop 2rem. */
    .auth-steps { margin-top: 1.25rem; }
    .auth-panel { padding: 2.25rem 1.5rem; }
    .auth-panel-inner { margin: 0 auto; }
}

/* ---- Video hero (sign in only) ---------------------------------------
 * partials/auth_hero_home.php. The film is BACKGROUND: it sits under a scrim,
 * carries no information, and the panel has to be a finished design without it
 * — below 820px and under prefers-reduced-motion the src is never attached at
 * all (see the partial), so what is left is the navy gradient the other heroes
 * already use.
 *
 * Three layers, stacked explicitly rather than by source order: film (0),
 * scrim (1), content (2). The section keeps its .theme-intellect gradient as
 * the paint underneath, which is what shows before the first frame arrives.
 *
 * These rules come AFTER the .theme-intellect block above on purpose: the
 * colours there are the same specificity, so this file's order is what makes
 * the white type win. Moving this block up turns the copy pale blue again.
 */
.auth-hero--video {
    position: relative;
    overflow: hidden;
}
.auth-hero-video {
    position: absolute;
    inset: 0;
    z-index: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border: 0;
    /* Faded in on loadeddata so the gradient hands over to the film instead of
       cutting to a black frame. */
    opacity: 0;
    transition: opacity .8s ease;
}
.auth-hero-video.is-ready { opacity: 1; }

/* The footage is bright, colourful and moving; white type straight onto it is
   unreadable about a third of the way through the loop. Heavier at the top-left
   and bottom, which is where the logo and the button sit. */
.auth-hero-scrim {
    position: absolute;
    inset: 0;
    z-index: 1;
    background:
        linear-gradient(150deg, rgba(0, 22, 58, .88) 0%, rgba(0, 40, 96, .66) 45%, rgba(0, 12, 34, .88) 100%),
        radial-gradient(120% 90% at 20% 20%, rgba(0, 0, 0, .35), transparent 60%);
}
.auth-hero--video .auth-hero-inner {
    position: relative;
    z-index: 2;
}

/* Everything on the film is white with a soft shadow — the shadow is what keeps
   it legible over a bright frame, so it is not decoration and should not be
   tuned away. */
.auth-hero--video .auth-headline,
.auth-hero--video .auth-sub {
    color: #ffffff;
    text-shadow: 0 2px 14px rgba(0, 0, 0, .55), 0 1px 3px rgba(0, 0, 0, .45);
}
.auth-hero--video .auth-sub { opacity: .95; }
.auth-hero--video .auth-logo {
    filter: drop-shadow(0 3px 12px rgba(0, 0, 0, .5));
}

/* The register hero's "How it works" block, on film. The translucent white it
   uses over the flat gradient disappears over moving footage, so on a video
   hero it becomes a dark pane of its own — blurred where the browser can, and
   still opaque enough where it cannot. */
.auth-hero--video .auth-steps {
    background: rgba(0, 18, 46, .52);
    border-color: rgba(255, 255, 255, .26);
    backdrop-filter: blur(7px);
    box-shadow: 0 12px 34px rgba(0, 0, 0, .3);
}
.auth-hero--video .auth-steps-title { color: #cfe6fb; }
.auth-hero--video .auth-steps-list li { color: #ffffff; }

/* One quiet line under the steps, for somebody not ready to fill the form in.
   Deliberately not a button: the button on this screen is Send. */
.auth-hero-aside {
    margin: 1.25rem 0 0;
    font-size: .88rem;
    color: #cfe6fb;
    text-shadow: 0 1px 6px rgba(0, 0, 0, .5);
}
.auth-hero-aside a {
    color: #ffffff;
    font-weight: 600;
    text-decoration-color: rgba(255, 255, 255, .5);
    text-underline-offset: .2em;
}
.auth-hero-aside a:hover { color: #9ee4ff; }

.auth-hero-actions { margin-top: 2.25rem; }
/* Not a .btn: the auth screens' buttons are the form's, and this one has to
   read as the only thing to press on a moving background. Solid white, brand
   navy text, lifted off the film by its shadow. */
.auth-hero-btn {
    display: inline-flex;
    align-items: center;
    gap: .55rem;
    padding: .8rem 1.4rem;
    border-radius: .65rem;
    background: #ffffff;
    color: #00317c;
    font-weight: 600;
    font-size: 1rem;
    text-decoration: none;
    box-shadow: 0 10px 28px rgba(0, 0, 0, .38);
    transition: transform .18s ease, box-shadow .18s ease, background-color .18s ease;
}
.auth-hero-btn:hover,
.auth-hero-btn:focus-visible {
    background: #f2f8ff;
    color: #00317c;
    transform: translateY(-2px);
    box-shadow: 0 14px 34px rgba(0, 0, 0, .45);
}
.auth-hero-btn i { transition: transform .18s ease; }
.auth-hero-btn:hover i { transform: translateX(3px); }

@media (max-width: 820px) {
    /* No film down here (the partial never attaches it), so this is only about
       the gradient banner keeping its proportions. */
    .auth-hero-actions { margin-top: 1.5rem; }
    .auth-hero-btn { font-size: .95rem; padding: .7rem 1.1rem; }
}
@media (prefers-reduced-motion: reduce) {
    .auth-hero-video { transition: none; }
    .auth-hero-btn { transition: none; }
    .auth-hero-btn:hover { transform: none; }
}

