/* ----------------------------------------------------------------------
 * app.css — operator-facing screens.
 * Reads tokens.css for every colour and measurement; no raw hex here.
 * ---------------------------------------------------------------------- */

@import url("tokens.css");

*, *::before, *::after { box-sizing: border-box; }

body {
    margin: 0;
    /* This is a desktop screenshare tool — the operator runs it full-screen
       with a prospect watching. Below this the row layout stops being
       readable, so scroll rather than reflow into something worse. */
    min-width: 1300px;
    font-family: var(--font-body);
    font-weight: var(--weight-body);
    color: var(--color-text);
    background: var(--color-soft);
    font-size: 15px;
    line-height: 1.5;
}

h1, h2, h3, th {
    font-family: var(--font-heading);
    font-weight: var(--weight-heading);
    color: var(--color-primary);
    margin: 0;
}

a { color: var(--color-link); }

/* --- Chrome ------------------------------------------------------- */
.masthead {
    background: var(--color-primary);
    border-bottom: var(--border-accent);
    padding: var(--space-3) var(--space-4);
    display: flex;
    align-items: center;
    gap: var(--space-3);
}
.masthead__mark { display: flex; align-items: center; }
.masthead__title { color: #fff; font-size: 15px; font-weight: var(--weight-heading); }
.masthead__spacer { flex: 1; }
.masthead a { color: rgba(255,255,255,.72); text-decoration: none; font-size: 13px; }
.masthead a:hover { color: var(--color-accent); }

.wrap { max-width: 1560px; margin: 0 auto; padding: var(--space-5) var(--space-4); }

.page-head {
    display: flex;
    align-items: flex-end;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
}
.page-head h1 { font-size: 26px; }
.page-head p { margin: var(--space-1) 0 0; color: var(--color-muted); font-size: 14px; }
.page-head__spacer { flex: 1; }

/* --- Surfaces ----------------------------------------------------- */
.card {
    background: var(--color-surface);
    border: var(--border-subtle);
    border-top: var(--border-accent);
    padding: var(--space-4);
}
/* Vertical spacing for STACKED cards in normal flow. Grid/flex containers
   that hold cards must reset this — it lands on every item but the first and
   drops the rest (see `.clusters .card` and `.price-bands .card`). Use the
   container's own `gap` there, not this. */
.card + .card { margin-top: var(--space-3); }
.card__title { font-size: 15px; margin-bottom: var(--space-3); }

/* --- Buttons ------------------------------------------------------ */
.btn {
    display: inline-block;
    font-family: var(--font-heading);
    font-weight: var(--weight-heading);
    font-size: 13px;
    letter-spacing: .02em;
    padding: 9px 16px;
    border: 2px solid var(--color-primary);
    background: var(--color-primary);
    color: #fff;
    text-decoration: none;
    cursor: pointer;
    border-radius: var(--radius);
}
.btn:hover { background: var(--color-accent); border-color: var(--color-accent); color: var(--color-primary); }
.btn--ghost { background: transparent; color: var(--color-primary); }
.btn--ghost:hover { background: var(--color-primary); color: #fff; border-color: var(--color-primary); }
.btn--small { padding: 5px 10px; font-size: 12px; }

/* --- Tables ------------------------------------------------------- */
.table { width: 100%; border-collapse: collapse; }
.table th {
    text-align: left;
    font-size: 11px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--color-muted);
    padding: 0 var(--space-3) var(--space-2);
    border-bottom: var(--border-subtle);
    white-space: nowrap;
}
.table td { padding: var(--space-3); border-bottom: var(--border-subtle); vertical-align: top; }
.table tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: var(--color-soft); }

.client-name {
    font-family: var(--font-heading);
    font-weight: var(--weight-heading);
    color: var(--color-primary);
    font-size: 15px;
    text-decoration: none;
}
.client-name:hover { color: var(--color-accent); }
.client-meta { color: var(--color-muted); font-size: 13px; margin-top: 2px; }

.session-date { font-weight: var(--weight-heading); color: var(--color-primary); }
.session-rel { color: var(--color-muted); font-size: 13px; }
.session-rel--soon { color: var(--color-stale, #c98a00); font-weight: var(--weight-heading); }

/* --- Readiness ---------------------------------------------------- */
.ready { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.ready__item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    padding: 3px 9px;
    border: 1px solid var(--color-line);
    color: var(--color-muted);
    background: var(--color-soft);
    white-space: nowrap;
}
.ready__item::before { content: "○"; font-size: 11px; }
.ready__item--yes {
    color: var(--delta-up);
    border-color: var(--delta-up);
    background: transparent;
}
.ready__item--yes::before { content: "●"; }
.ready__item--warn {
    color: var(--band-average);
    border-color: var(--band-average);
    background: transparent;
}
.ready__item--warn::before { content: "!"; font-weight: 700; }

/* --- Badges ------------------------------------------------------- */
.badge {
    display: inline-block;
    font-size: 11px;
    letter-spacing: .06em;
    text-transform: uppercase;
    font-weight: var(--weight-heading);
    padding: 3px 8px;
    border: 1px solid currentColor;
}
.badge--new      { color: var(--color-accent); }
.badge--draft    { color: var(--band-average); }
.badge--complete { color: var(--delta-up); }

.flag {
    display: block;
    font-size: 12px;
    color: var(--band-average);
    margin-top: var(--space-2);
}

/* --- Forms -------------------------------------------------------- */
label { display: block; font-size: 12px; text-transform: uppercase; letter-spacing: .06em; color: var(--color-muted); margin-bottom: var(--space-1); }
input[type=text], input[type=password], input[type=email], input[type=number], input[type=date], input[type=datetime-local], input[type=tel], select, textarea {
    width: 100%;
    padding: 9px 10px;
    border: var(--border-subtle);
    border-radius: var(--radius);
    font-family: var(--font-body);
    font-size: 15px;
    color: var(--color-text);
    background: #fff;
}
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--color-accent); }
/* Stacked fields in normal flow. As with `.card + .card`, a flex/grid row of
   fields must reset this — it lands on every field but the first. */
.field + .field { margin-top: var(--space-3); }
.field-row { display: flex; gap: var(--space-3); }
.field-row > * { flex: 1; }
.field-row > .field { margin-top: 0; }   /* the row's gap does the spacing */

/* --- Login -------------------------------------------------------- */
.login { min-height: 100vh; display: grid; place-items: center; background: var(--color-primary); }
.login__box { width: 340px; background: #fff; padding: var(--space-5) var(--space-4); border-top: 4px solid var(--color-accent); }
.login h1 { font-size: 20px; margin: var(--space-2) 0 var(--space-4); }
.login .btn { width: 100%; margin-top: var(--space-3); }

.alert { border-left: 3px solid var(--band-low); background: #fff; padding: var(--space-2) var(--space-3); font-size: 13px; margin-bottom: var(--space-3); }

.empty { text-align: center; padding: var(--space-5); color: var(--color-muted); }
.muted { color: var(--color-muted); }
.nowrap { white-space: nowrap; }

/* --- Logo ---------------------------------------------------------
 * One source file (img/luminus-logo-svg.svg), inlined with
 * fill="currentColor" so each context sets the colour: white on the navy
 * masthead, brand navy on the white login card. Height drives the size —
 * the mark is roughly 2:1 — so `width: auto` keeps it undistorted.
 * ------------------------------------------------------------------ */
.logo { display: block; width: auto; }
/* Stays white on hover — the mark is the brand, not a link affordance. */
.logo--masthead { height: 26px; color: #fff; }
.logo--login { height: 42px; color: var(--color-primary); margin-bottom: var(--space-4); }

/* --- Wizard ------------------------------------------------------- */
.wrap--wide { max-width: 1560px; }

/* Full-width bar directly under the app header, the way the exported
   document carries its section run. */
.wizard-nav { background: var(--color-surface); border-bottom: var(--border-subtle); }
.wizard-nav__inner {
    max-width: 1560px;
    margin: 0 auto;
    padding: 0 var(--space-4);
    display: flex;
    gap: 2px;
    flex-wrap: wrap;
}
.wizard-nav__step {
    border-bottom: 0;
    font-family: var(--font-heading);
    font-size: 12px;
    letter-spacing: .04em;
    text-transform: uppercase;
    text-decoration: none;
    color: var(--color-muted);
    background: #fff;
    border: var(--border-subtle);
    padding: 8px 14px;
}
.wizard-nav__step:hover { color: var(--color-primary); border-color: var(--color-accent); }
.wizard-nav__step.is-current {
    color: #fff;
    background: var(--color-primary);
    border-color: var(--color-primary);
}
.wizard-nav__step.is-pending { opacity: .55; }

/* --- Document band: what the PDF page header will carry ---------------
 * Pinned to the top, so the client and the period stay visible while working
 * down a long tab. It has to sit above the content it scrolls over, and its
 * background has to stay opaque for that to hold. */
.doc-head {
    position: sticky;
    top: 0;
    z-index: 20;
    background: var(--color-surface);
    border-bottom: var(--border-subtle);
}
.doc-head__inner {
    max-width: 1560px;
    margin: 0 auto;
    padding: var(--space-3) var(--space-4);
    display: flex;
    align-items: center;
    gap: var(--space-3);
}
.doc-head__spacer { flex: 1; }
.doc-head__period {
    font-family: var(--font-heading);
    font-weight: var(--weight-heading);
    font-size: 14px;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--color-muted);
}
.logo--doc { height: 26px; color: var(--color-primary); }

/* PLACEHOLDER client mark — one stand-in file for every client until a real
   logo can be uploaded per blueprint. Height-driven so a logo of any aspect
   sits on the same baseline as the Luminus mark opposite it. */
.client-mark { display: flex; align-items: center; gap: var(--space-3); }
.client-mark__logo { display: block; height: 32px; width: auto; max-width: 220px; object-fit: contain; }
.client-mark__name {
    font-family: var(--font-heading);
    font-weight: var(--weight-heading);
    font-size: 17px;
    color: var(--color-primary);
}

/* --- Step heading ---------------------------------------------------- */
.page-title { margin-bottom: var(--space-4); }
.page-title h1 { font-size: 26px; }
.page-title p { margin: var(--space-2) 0 0; color: var(--color-muted); font-size: 14px; }

.notice {
    background: #fff;
    border-left: 3px solid var(--band-average);
    padding: var(--space-3);
    font-size: 13px;
    margin: 0 0 var(--space-3);
}
.notice code { background: var(--color-soft); padding: 1px 4px; }

/* --- Split: params left, forecast right --------------------------- */
.split { display: grid; grid-template-columns: minmax(0, 1fr) 470px; gap: var(--space-3); align-items: start; }

.split__panel { position: sticky; top: var(--space-3); }

.card__hint {
    font-family: var(--font-body);
    font-weight: var(--weight-body);
    font-size: 12px;
    text-transform: none;
    letter-spacing: 0;
    color: var(--color-muted);
    margin-left: var(--space-2);
}

/* --- Param rows --------------------------------------------------- */
/* Border on the TOP of each row, so the first one is separated from the box
   title and its collapse toggle, and the list closes without a trailing rule. */
.row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) 0;
    border-top: var(--border-subtle);
}
.row__inputs { margin-left: auto; display: flex; gap: var(--space-2); }

.check { display: flex; align-items: center; gap: var(--space-2); margin: 0; text-transform: none; letter-spacing: 0; font-size: 15px; color: var(--color-primary); font-family: var(--font-heading); font-weight: var(--weight-heading); cursor: pointer; }
.check input { width: 16px; height: 16px; accent-color: var(--color-accent); cursor: pointer; }

.mini { font-size: 10px; letter-spacing: .06em; text-transform: uppercase; color: var(--color-muted); margin: 0; }
.mini input { width: 92px; padding: 6px 8px; font-size: 14px; margin-top: 2px; text-align: right; font-variant-numeric: tabular-nums; }
.mini input:disabled { background: var(--color-soft); color: var(--color-muted); cursor: not-allowed; }

.hint { font-size: 12px; color: var(--color-muted); margin: var(--space-1) 0 0; }

/* --- Forecast panel ----------------------------------------------- */
.panel { background: var(--color-surface); border: var(--border-subtle); border-top: var(--border-accent); }
.panel__headline { background: var(--color-primary); padding: var(--space-4); }
.headline__label { display: block; font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--color-accent); }
.headline__value { display: block; font-family: var(--font-heading); font-weight: var(--weight-heading); font-size: 34px; line-height: 1.1; color: #fff; margin: 4px 0; }
.headline__note { display: block; font-size: 12px; color: rgba(255,255,255,.62); }

.panel__section { padding: var(--space-3) var(--space-4) var(--space-4); border-top: var(--border-subtle); }
.panel__title { font-size: 12px; letter-spacing: .08em; text-transform: uppercase; color: var(--color-muted); margin-bottom: var(--space-2); }

.table--forecast { margin: var(--space-3) 0 0; }
.table--forecast th, .table--forecast td { padding: 8px var(--space-4); }
.table--compact th, .table--compact td { padding: 6px 0; font-size: 13px; }
.num { text-align: right; font-variant-numeric: tabular-nums; }
.strong { font-weight: var(--weight-heading); color: var(--color-primary); }

.delta { font-weight: var(--weight-heading); }
.delta--up   { color: var(--delta-up); }
.delta--down { color: var(--delta-down); }
.delta--flat { color: var(--delta-flat); }

.stats { margin: 0; }
.stats > div { display: flex; justify-content: space-between; padding: 5px 0; font-size: 13px; }
.stats dt { color: var(--color-muted); margin: 0; }
.stats dd { margin: 0; font-variant-numeric: tabular-nums; }
.stats__total { border-top: var(--border-subtle); margin-top: var(--space-2); padding-top: var(--space-2) !important; font-weight: var(--weight-heading); }
.stats__total dt, .stats__total dd { color: var(--color-primary); font-size: 15px; }

.saved { font-size: 12px; color: var(--color-muted); text-align: right; margin: var(--space-2) 0 0; min-height: 1.2em; }
.saved.is-busy { color: var(--color-accent); }
.delta--new  { color: var(--color-accent); font-size: 12px; text-transform: uppercase; letter-spacing: .06em; }

/* --- Assessment questions ------------------------------------------ */
.question__label { font-size: 16px; margin-bottom: var(--space-1); }
.question__prompt { font-size: 13px; color: var(--color-muted); margin: 0 0 var(--space-3); max-width: 62ch; }
.question__notes-label { margin-top: var(--space-3); }
.question textarea { font-size: 14px; }

/* Segmented control: three mutually exclusive ratings, one visible choice. */
.segmented { display: inline-flex; border: 2px solid var(--color-line); }
.segmented__option { position: relative; margin: 0; }
.segmented__option input {
    position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer;
}
.segmented__option span {
    display: block;
    font-family: var(--font-heading);
    font-weight: var(--weight-heading);
    font-size: 13px;
    letter-spacing: .04em;
    padding: 8px 22px;
    color: var(--color-muted);
    background: #fff;
    cursor: pointer;
    user-select: none;
}
.segmented__option + .segmented__option span { border-left: 2px solid var(--color-line); }
.segmented__option input:hover + span { color: var(--color-primary); }
.segmented__option input:focus-visible + span { outline: 2px solid var(--color-accent); outline-offset: -2px; }
.segmented__option--low     input:checked + span { background: var(--band-low);     color: #fff; }
.segmented__option--average input:checked + span { background: var(--band-average); color: #fff; }
.segmented__option--high    input:checked + span { background: var(--band-high);    color: #fff; }

.step-actions { display: flex; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-3); }

/* --- Score panel --------------------------------------------------- */
.headline__of { font-size: 16px; color: rgba(255,255,255,.5); font-weight: var(--weight-body); margin-left: 2px; }

.meter + .meter { margin-top: var(--space-2); }
.meter__head { display: flex; justify-content: space-between; font-size: 13px; margin-bottom: 3px; }
.meter.is-current .meter__head { font-weight: var(--weight-heading); color: var(--color-primary); }
.meter__value { font-variant-numeric: tabular-nums; }
.meter__track { height: 6px; background: var(--color-soft); }
.meter__fill { height: 100%; transition: width .18s ease-out; }
.meter__fill--low     { background: var(--band-low); }
.meter__fill--average { background: var(--band-average); }
.meter__fill--high    { background: var(--band-high); }

.band {
    display: inline-block;
    font-family: var(--font-heading);
    font-weight: var(--weight-heading);
    font-size: 11px;
    letter-spacing: .08em;
    text-transform: uppercase;
    padding: 3px 10px;
    color: #fff;
}
.band--low { background: var(--band-low); }
.band--average { background: var(--band-average); }
.band--high { background: var(--band-high); }
.band--none { background: var(--color-muted); }
.band--fixed { width: 96px; padding: 7px 0; font-size: 12px; text-align: center; }

.total-band { display: flex; align-items: center; justify-content: space-between; }
.total-band__score { font-family: var(--font-heading); font-weight: var(--weight-heading); font-size: 26px; color: var(--color-primary); }
.total-band .headline__of { color: var(--color-muted); font-size: 14px; }

/* --- Snapshot: the reveal -------------------------------------------
 * Built live in front of a prospect. No numbers anywhere — the score is the
 * underlying metric that decides a bar's colour and length, not something
 * anyone should be reading off the screen. Gaps are meant to be seen as
 * shapes against the gridlines.
 *
 * Plain CSS, so all five charts carry into the PDF export unchanged.
 * -------------------------------------------------------------------- */

/* Real 3D boxes, not shaded flats.
 *
 * Each bar is the FRONT face; a skewed pseudo-element gives it a TOP face and
 * another gives it a SIDE face, both projected up-and-right at 45 degrees.
 * The two faces take the bar's own colour and are lightened / darkened with a
 * filter, so adding a new band colour needs no extra rules here.
 *
 * The bars then stand on a faint grey plane, which is what stops them looking
 * like they are floating and gives the depth somewhere to land. */
.hchart, .vcluster { --bar-depth: 9px; }
.hchart-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-4); }
.hchart__title { font-size: 20px; }

.hbar, .vbar__fill { position: relative; z-index: 1; }

.hbar::before, .vbar__fill::before,
.hbar::after,  .vbar__fill::after {
    content: '';
    position: absolute;
}

/* The face TOWARDS the viewer keeps the pure band colour — it is the largest
   surface and the one carrying the reading. The other two are washed with
   white or black rather than brightness-filtered: multiplying the channels
   makes a colour more saturated as well as lighter, so the top face ended up
   looking more vivid than the front instead of paler than it. */
.hbar::before, .vbar__fill::before,
.hbar::after,  .vbar__fill::after {
    background-color: inherit;
}

/* Top face: the bar's width, pushed up and sheared right. Lighter. */
.hbar::before, .vbar__fill::before {
    left: 0;
    top: calc(var(--bar-depth) * -1);
    width: 100%;
    height: var(--bar-depth);
    transform: skewX(-45deg);
    transform-origin: bottom left;
    background-image: linear-gradient(rgba(255, 255, 255, .42), rgba(255, 255, 255, .42));
}

/* Side face: the bar's height, pushed right and sheared up. Darker. */
.hbar::after, .vbar__fill::after {
    top: 0;
    right: calc(var(--bar-depth) * -1);
    width: var(--bar-depth);
    height: 100%;
    transform: skewY(-45deg);
    transform-origin: left top;
    background-image: linear-gradient(rgba(0, 0, 0, .34), rgba(0, 0, 0, .34));
}

/* ---- Top chart: the four phases against each other ------------------ */
.hchart { display: grid; grid-template-columns: 116px minmax(0, 1fr); gap: var(--space-4); align-items: stretch; }

.hchart__labels, .hchart__plot { display: flex; flex-direction: column; justify-content: center; gap: var(--space-3); }
.hchart__name { display: flex; align-items: center; height: 26px; font-family: var(--font-heading); font-weight: var(--weight-heading); font-size: 14px; color: var(--color-primary); }

/* Gridlines live on the plot, not on each row, so they run unbroken behind
   all four bars. Steps at 25 / 50 / 75 / 100%. */
.hchart__plot {
    background-image: repeating-linear-gradient(
        to right,
        transparent 0,
        transparent calc(25% - 1px),
        rgba(1, 0, 49, .14) calc(25% - 1px),
        rgba(1, 0, 49, .14) 25%
    );
}
.hchart__plot { position: relative; }
/* The wall the horizontal bars emerge from. */
.hchart__plot::before {
    content: '';
    position: absolute;
    left: calc(var(--bar-depth) * -1);
    top: 0;
    width: calc(var(--bar-depth) * 1.5);
    height: 100%;
    background: rgba(1, 0, 49, .09);
    border-left: 1px solid rgba(1, 0, 49, .22);
    transform: skewY(-45deg);
    transform-origin: left bottom;
    z-index: 0;
}
.hchart__row { display: flex; align-items: center; height: 26px; position: relative; z-index: 1; }

.hbar {
    display: block;
    height: 100%;
    min-width: 5px;
    transition: width .2s ease-out;
}
.hbar--low { background-color: var(--band-low); }
.hbar--average { background-color: var(--band-average); }
.hbar--high { background-color: var(--band-high); }

/* ---- The four phases side by side ----------------------------------- */
.clusters { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-3); margin-top: var(--space-3); align-items: stretch; }

/* The generic `.card + .card` margin applies to cards 2-4 but not the first,
   which pushed three of them down and left the first stretching taller to
   fill the row. It also out-specifies a plain `.phase` rule, so the reset has
   to match on two classes. */
.clusters .card { margin-top: 0; }

.phase { display: flex; flex-direction: column; }
/* Reserved so a title that wraps to two lines cannot drop this card's chart
   below its neighbours' — the four charts must share one baseline. */
.phase__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-2); min-height: 52px; }
.phase__head h2 { font-size: 20px; line-height: 1.25; }
.phase__head .band { flex-shrink: 0; }
.phase__blurb { font-size: 12px; line-height: 1.45; color: var(--color-muted); margin: var(--space-1) 0 var(--space-4); min-height: 52px; }

/* Vertical clusters. Taller than they need to be, deliberately: with only
   three possible values the extra height is what makes the difference between
   a Low and a High register as a gap rather than a step. */
.vcluster {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    gap: 9px;
    height: 210px;
    align-items: end;
    margin-bottom: 104px;
    position: relative;
    /* Asymmetric on purpose: the diagonal labels run down-LEFT from each
       column, so the left needs clearance and the right barely any. Padding
       both sides equally just threw away plot width. */
    padding: 0 6px 0 30px;
    background-origin: content-box;
    background-clip: content-box;
    /* Room for the top faces of full-height bars to project above the plot. */
    margin-top: 14px;
    /* Steps at 20 / 40 / 60 / 80 / 100%, measured from the baseline. */
    background-image: repeating-linear-gradient(
        to top,
        transparent 0,
        transparent calc(20% - 1px),
        rgba(1, 0, 49, .14) calc(20% - 1px),
        rgba(1, 0, 49, .14) 20%
    );
}
/* The floor the columns stand on. */
.vcluster::after {
    content: '';
    position: absolute;
    left: calc(var(--bar-depth) * -1.6);
    bottom: 0;
    width: calc(100% + var(--bar-depth) * 3);
    height: calc(var(--bar-depth) * 1.5);
    background: rgba(1, 0, 49, .09);
    border-bottom: 1px solid rgba(1, 0, 49, .22);
    transform: skewX(-45deg);
    transform-origin: bottom left;
    z-index: 0;
}
.vbar { position: relative; height: 100%; display: flex; align-items: flex-end; justify-content: center; z-index: 1; }

/* A Low answer scores zero. Without a floor its column would vanish and read
   as unanswered rather than as a deliberate Low. */
.vbar__fill {
    display: block;
    width: 78%;
    min-height: 5px;
    transition: height .2s ease-out;
}
.vbar__fill--low { background-color: var(--band-low); }
.vbar__fill--average { background-color: var(--band-average); }
.vbar__fill--high { background-color: var(--band-high); }
.vbar__fill--unanswered { min-height: 0; }
.vbar__fill--unanswered::before,
.vbar__fill--unanswered::after { display: none; }

.vbar__label {
    position: absolute;
    top: calc(100% + 7px);
    right: 50%;
    transform: rotate(-45deg);
    transform-origin: top right;
    white-space: nowrap;
    font-size: 11px;
    line-height: 1;
    color: var(--color-muted);
}

/* Anchored to the chart above, NOT pushed to the foot of the card.
   `margin-top: auto` bottom-aligned them, so four notes of different lengths
   started at four different heights — the slack now falls at the bottom of
   the shorter cards instead, and all four Notes begin on one line. */
.phase__notes { border-top: var(--border-subtle); padding-top: var(--space-3); margin-top: var(--space-2); }
.phase__notes-label { display: block; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--color-muted); margin-bottom: var(--space-2); }
.phase__notes p { margin: 0 0 var(--space-3); font-size: 13px; line-height: 1.5; }


/* Question-first: the sheet asks the question and keeps the keyword in a
   trailing scoring column. Match that — the operator reads these aloud. */
.question__ask { font-size: 19px; line-height: 1.35; margin-bottom: var(--space-2); max-width: 60ch; }
.question__helper { font-size: 14px; color: var(--color-muted); margin: 0 0 var(--space-3); max-width: 66ch; }
.page-head__client { font-size: 13px; color: var(--color-muted); margin-right: var(--space-3); }

/* --- Assessment: the sheet's row-by-row tab ------------------------
 * Question/Description | Rating | Notes, worked down one row at a time on a
 * screenshare. No scores anywhere on this screen — see views/steps/assessment.
 * ------------------------------------------------------------------ */
.card--flush { padding: 0; }

.assess__head,
.assess__row {
    display: grid;
    /* Notes takes a fixed 40% of the row; the rating square is fixed; the
       question absorbs everything left, so it gets the benefit of a wider
       screen rather than the notes field growing without limit. */
    grid-template-columns: minmax(0, 1fr) 172px 40%;
    gap: var(--space-4);
}

.assess__head {
    min-height: 0;
    padding: var(--space-3) var(--space-4);
    background: var(--color-primary);
    font-family: var(--font-heading);
    font-weight: var(--weight-heading);
    font-size: 11px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: #fff;
}

.assess__row {
    /* Tighter top and bottom than the sides — the row is wide, and the space
       that helps it read is between the columns, not above and below. */
    padding: var(--space-3) var(--space-4);
    border-bottom: var(--border-subtle);
    align-items: stretch;
    /* Lowered with the padding: at 148px it was holding the old row height and
       the padding change would have done nothing. Still enough to keep the
       rating square from collapsing behind a one-line question. */
    min-height: 118px;
}
.assess__row:last-child { border-bottom: 0; }

/* Banding on alternate rows, matching the Questionnaire. `odd` because the
   header is the first child, so the questions sit at child positions 2 through
   6 and the odd ones are the 2nd and 4th questions. Before :hover so hovering
   still reads over it. */
.assess__row:nth-child(odd) { background: rgba(1, 0, 49, .028); }
.assess__row:hover { background: var(--color-soft); }

.assess__ask {
    font-family: var(--font-heading);
    font-weight: var(--weight-heading);
    color: var(--color-primary);
    font-size: 21px;
    line-height: 1.3;
    letter-spacing: -0.01em;
    margin: 0 0 var(--space-2);
}
/* Body face, lighter, looser — the question is read aloud, the description is
   the operator's prompt to expand on it. They should not look alike. */
.assess__helper {
    font-family: var(--font-body);
    font-weight: var(--weight-body);
    font-size: 15px;
    line-height: 1.5;
    color: var(--color-muted);
    margin: 0;
}
.assess__notes textarea { font-size: 14px; height: 100%; min-height: 92px; resize: vertical; }

/* Vertical rating stack: High at the top, Low at the bottom. */
/* Rating control: a native <select> styled as a full-height square.
 *
 * Still a dropdown, so the three options are not all on screen framing the
 * answer before it is given — the prospect sees one box, not a green-good /
 * red-bad ladder. The colour only lands once a rating has been chosen; until
 * then it reads as a neutral grey square, obvious when scanning the tab.
 *
 * appearance:none strips the native chrome. The colour class is set by the
 * server on load and re-synced by live-panel.js on change.
 */
.assess__rating { display: flex; }

.rating-select {
    flex: 1;
    width: 100%;
    appearance: none;
    -webkit-appearance: none;
    border: 0;
    border-radius: var(--radius);
    font-family: var(--font-heading);
    font-weight: var(--weight-heading);
    font-size: 20px;
    letter-spacing: .04em;
    text-align: center;
    text-align-last: center;   /* Safari/Firefox centre the closed value */
    cursor: pointer;
    /* Neutral grey while unanswered — present enough to show the row is
       waiting on an answer, without the weight of a filled black block. */
    background: var(--color-muted);
    color: rgba(255, 255, 255, .75);
    transition: background .12s ease-out, color .12s ease-out;
}
.rating-select:hover  { color: #fff; }
.rating-select:focus  { outline: 2px solid var(--color-accent); outline-offset: -2px; }
.rating-select option { font-size: 15px; color: var(--color-text); background: #fff; }

.rating-select.is-high    { background: var(--band-high);    color: #fff; }
.rating-select.is-average { background: var(--band-average); color: #fff; }
.rating-select.is-low     { background: var(--band-low);     color: #fff; }

.summary-notes { margin-top: var(--space-3); }
.summary-notes textarea { font-size: 14px; }

.step-actions { align-items: center; }
.step-actions .saved { margin: 0 auto 0 0; text-align: left; }

.btn { white-space: nowrap; }
.page-head__client { white-space: nowrap; }

/* --- Questionnaire: revalidating what the prospect submitted ----------
 * Built around the answers. Every figure is editable in place with a note
 * beside it, matching the sheet's tab so the operator reads down the same
 * rows they always have.
 * -------------------------------------------------------------------- */
.qcard + .qcard { margin-top: var(--space-3); }
/* Sized with the Snapshot's phase titles rather than the generic 15px card
   title — these head a whole table, and at 15px they sat below the weight of
   the rows underneath them. */
.qcard__title { padding: var(--space-4) var(--space-4) var(--space-3); margin: 0; font-size: 20px; }
.qcard__title .card__hint { font-size: 13px; }
/* In a normal (padded) card the flush title padding would stack on the card's
   own padding — a gap above the title. Drop it there; the card supplies the
   inset, and a normal bottom margin sits the fields below. */
.card:not(.card--flush) > .qcard__title { padding: 0; margin-bottom: var(--space-3); }

/* One height for every field in the row, taken from the notes field, which is
   the tallest because it carries two rows of prose. Sharing a variable is what
   keeps the n/a blocks from drifting out of line with the inputs again. */
.qtable { --field-h: 46px; }
.qtable__head, .qtable__row { display: grid; gap: var(--space-2); align-items: stretch; }
/* Notes is a fixed width in all three tables, so its edges line up. The lead
   table fills its row with four value columns; the sales and retention tables
   carry fewer, so they take an empty spacer column that pushes their fields
   right to meet Notes rather than leaving their labels stranded in an
   over-wide first column. */
.qtable { --label-w: 320px; --notes-w: 520px; }
.qspacer { display: block; }

/* The lead table carries four value columns, so it is the one that runs out of
   room first. Its label absorbs slack at full width and gives it back as the
   window narrows, and Notes may shrink rather than push the table past the
   card edge. */
.qtable--lead .qtable__head, .qtable--lead .qtable__row {
    grid-template-columns: minmax(240px, 1fr) repeat(4, 132px) minmax(360px, var(--notes-w));
}
/* Wider than the marketing tables because the revenue dropdown holds a phrase
   rather than a figure. Everything in this box then matches that width — a
   column of fields reading as one set matters more here than matching the
   width used in a separate table. */
.qtable--sales .qtable__head, .qtable--sales .qtable__row {
    grid-template-columns: var(--label-w) 1fr 156px var(--notes-w);
}
.qtable--sales .qcell input { max-width: none; }
.qtable--retention .qtable__head, .qtable--retention .qtable__row {
    grid-template-columns: var(--label-w) 1fr repeat(2, 132px) var(--notes-w);
}

.qtable__head {
    padding: var(--space-2) var(--space-4);
    background: var(--color-primary);
    font-family: var(--font-heading);
    font-weight: var(--weight-heading);
    font-size: 11px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #fff;
    align-items: center;
}
.qtable__head .num { text-align: center; }

.qtable__row { padding: var(--space-2) var(--space-4); border-bottom: var(--border-subtle); }
.qtable__row:last-child { border-bottom: 0; }

/* Banding on alternate rows, to help the eye track across a wide row.
   `odd` rather than `even`: the header is the first child, so the rows sit at
   child positions 2, 3, 4, 5 and it is the odd ones that are the 2nd and 4th
   rows of data. Declared before :hover so hovering still reads over it. */
.qtable__row:nth-child(odd) { background: rgba(1, 0, 49, .028); }
.qtable__row:hover { background: var(--color-soft); }

.qchannel { display: flex; align-items: center; }
.qchannel__name { font-family: var(--font-heading); font-weight: var(--weight-heading); font-size: 15px; color: var(--color-primary); }

.qmetric { display: flex; flex-direction: column; justify-content: center; gap: 2px; padding: var(--space-1) 0; }
.qmetric__q { font-family: var(--font-heading); font-weight: var(--weight-heading); font-size: 15px; color: var(--color-primary); }
.qmetric__help { font-size: 12px; color: var(--color-muted); font-style: italic; }

/* Every value field is the same size. The $ and % live inside the field,
   applied by field-format.js, rather than as separate affixes that made each
   column a different width. */
.qcell { display: flex; align-items: center; justify-content: center; margin: 0; }
.qcell input, .qcell select {
    width: 100%;
    max-width: 132px;
    height: var(--field-h);
    padding: 0 10px;
    font-family: var(--font-body);
    font-size: 17px;
    color: var(--color-primary);
    border: var(--border-subtle);
    background: #fff;
    text-align: center;
    font-variant-numeric: tabular-nums;
}
/* The native arrow occupies space inside the field, so centred text ends up
   sitting left of centre against the plain inputs beneath it. Drawing the
   chevron as a background and padding both sides equally puts the text back on
   the true centre line. */
.qcell select {
    max-width: none;
    font-size: 15px;
    text-align-last: center;
    appearance: none;
    -webkit-appearance: none;
    padding: 0 22px;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath fill='%236b7785' d='M0 0h10L5 6z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 7px center;
}
.qcell input:focus, .qcell select:focus { outline: none; border-color: var(--color-accent); }

/* A metric that doesn't apply to a channel (organic has no CTR/CPC): hold the
   column's width so the row stays aligned, but show a muted dash, not a field. */
.qcell--na { color: var(--color-muted); font-size: 17px; }

/* Notes stay at reading size — they are prose, not figures. */
/* Centred like every other field. Left on `stretch` the textarea kept its
   fixed height and fell back to the top of the cell, which only showed once a
   wrapping label made a row taller than one field — the sales metrics. */
.qcell--notes { align-items: center; justify-content: stretch; }
.qcell--notes textarea {
    width: 100%;
    padding: 6px 8px;
    font-family: var(--font-body);
    font-size: 13px;
    color: var(--color-text);
    border: var(--border-subtle);
    background: #fff;
    resize: vertical;
    height: var(--field-h);
    min-height: var(--field-h);
}
.qcell--notes textarea:focus { outline: none; border-color: var(--color-accent); }

/* Sized and boxed exactly like an input, so a locked cell reads as a field
   that cannot be typed in rather than as a block floating above the row. */
.qcell--na {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    max-width: 132px;
    height: var(--field-h);
    align-self: center;
    background: var(--color-soft);
    border: var(--border-subtle);
    color: var(--color-muted);
    font-size: 13px;
    letter-spacing: .04em;
}

/* --- Blueprint: collapsible parameter boxes --------------------------
 * <details> rather than a scripted toggle: it collapses with no JavaScript,
 * and — crucially — the fields inside stay in the DOM while closed, so a
 * collapsed box still posts its values and still counts in the forecast.
 * -------------------------------------------------------------------- */
.param-box > summary {
    position: relative;
    padding-right: 40px;
    cursor: pointer;
    list-style: none;
    user-select: none;
    /* Set with the assessment questions: these head the equivalent block of
       the exercise and were sitting two sizes below them.
       Weight and colour are restated because <summary> is not covered by the
       h1/h2/h3 rule the old <h2> title inherited from — converting these boxes
       to <details> had quietly dropped them to body weight and body colour. */
    font-family: var(--font-heading);
    font-weight: var(--weight-heading);
    color: var(--color-primary);
    font-size: 21px;
    line-height: 1.3;
    letter-spacing: -0.01em;
}
.param-box > summary .card__hint { font-size: 13px; }
.param-box > summary::-webkit-details-marker { display: none; }
.param-box > summary:hover { color: var(--color-accent); }

/* The toggle: a plus that becomes a minus by rotating one of its two bars. */
.param-box > summary::before,
.param-box > summary::after {
    content: '';
    position: absolute;
    right: 4px;
    top: 50%;
    width: 14px;
    height: 2px;
    background: var(--color-primary);
    transition: transform .15s ease-out;
}
.param-box > summary::before { transform: translateY(-50%); }
.param-box > summary::after  { transform: translateY(-50%) rotate(90deg); }
.param-box[open] > summary::after { transform: translateY(-50%) rotate(0deg); }
.param-box > summary:hover::before,
.param-box > summary:hover::after { background: var(--color-accent); }

/* --- Blueprint headline: two metrics, then the plain-English line ---- */
.headline-pair { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.headline-metric { text-align: center; }
.headline-metric .headline__label { display: block; font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--color-accent); }
.headline-metric .headline__value { display: block; font-family: var(--font-heading); font-weight: var(--weight-heading); font-size: 30px; line-height: 1.1; color: #fff; margin-top: 4px; }

.panel__headline .headline__note {
    margin: var(--space-3) 0 0;
    padding-top: var(--space-3);
    border-top: 1px solid rgba(255, 255, 255, .22);
    text-align: center;
    font-size: 13px;
    color: rgba(255, 255, 255, .72);
}

/* A row the practice is not buying steps back: dimmed, with its figures
   hidden. `visibility` rather than `display` so the row keeps its height and
   the ticked rows above and below stay on their grid. */
.row.is-off .check span { color: var(--color-muted); font-weight: var(--weight-body); }
.row.is-off .check input { opacity: .5; }
.row.is-off .row__inputs { visibility: hidden; }
.row .check span, .row .row__inputs { transition: opacity .12s ease-out, color .12s ease-out; }
/* A figure the operator reads rather than sets — sized like the inputs beside
   it so the row still scans as one line. */
.mini--static { display: block; }
.mini__value { display: block; width: 92px; padding: 6px 8px; margin-top: 2px; font-size: 14px; text-align: right; color: var(--color-primary); font-variant-numeric: tabular-nums; }
/* A field that does not apply to this row. Hidden rather than removed so the
   management fields either side of it stay on one line down the column. */
.mini--void { visibility: hidden; }
/* Full-width prose at the foot of a parameter box. */
.box-notes { margin-top: var(--space-3); }
.box-notes textarea {
    width: 100%;
    padding: 8px 10px;
    font-family: var(--font-body);
    font-size: 14px;
    line-height: 1.5;
    color: var(--color-text);
    border: var(--border-subtle);
    background: #fff;
    resize: vertical;
}
.box-notes textarea:focus { outline: none; border-color: var(--color-accent); }

/* Industry benchmark table — same field styling as the Questionnaire. */
.qtable--bench .qtable__head, .qtable--bench .qtable__row {
    grid-template-columns: minmax(220px, 1fr) 132px 132px 132px;
}
.btn--danger { color: var(--band-low); border-color: var(--band-low); }
.btn--danger:hover { background: var(--band-low); border-color: var(--band-low); color: #fff; }

/* Pricing overview cards. The generic `.card + .card` margin lands on the 2nd
   and 3rd grid items but not the first, dropping them 16px — the same hazard
   as the Snapshot clusters. Zero it inside the grid; `gap` does the spacing. */
.price-bands { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-3); align-items: start; }
.price-bands .card { margin-top: 0; }
.price-band__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-2); margin-bottom: var(--space-3); }
.price-band__head h2 { font-size: 17px; margin-bottom: var(--space-2); }
.price-band .stats { margin-top: var(--space-2); }

/* Header gear — inherits the masthead link colour and hover. */
.masthead__icon { display: inline-flex; align-items: center; }
.masthead__icon svg { display: block; }

/* A .table sitting flush in a card would butt its header right against the
   accent top border — give the header row breathing room from it. */
.card--flush .table thead th { padding-top: var(--space-3); }
.login__hint { font-size: 13px; color: var(--color-muted); margin: 0 0 var(--space-3); }
.assignee { color: var(--color-primary); font-weight: var(--weight-heading); }

/* Assignee checkboxes on the Questionnaire. */
.assignees { padding: 0 var(--space-4) var(--space-4); display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); }
.assignee-check { display: flex; align-items: center; gap: var(--space-2); margin: 0; cursor: pointer; font-family: var(--font-heading); font-weight: var(--weight-heading); font-size: 15px; color: var(--color-primary); }
.assignee-check input { width: 16px; height: 16px; accent-color: var(--color-accent); cursor: pointer; }
.assignee-check__role { font-family: var(--font-body); font-weight: var(--weight-body); font-size: 12px; color: var(--color-muted); text-transform: uppercase; letter-spacing: .04em; }

/* Blueprint settings panel. */
.settings-subhead { font-size: 13px; letter-spacing: .04em; text-transform: uppercase; color: var(--color-muted); margin: var(--space-4) 0 var(--space-2); }

/* Readiness toggles (Paid / Questionnaire) on the settings Pipeline card. */
.check-row { display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-5); }
.check-item { display: flex; align-items: center; gap: var(--space-2); margin: 0; cursor: pointer; font-family: var(--font-heading); font-weight: var(--weight-heading); font-size: 15px; color: var(--color-primary); }
.check-item input { width: 16px; height: 16px; accent-color: var(--color-accent); cursor: pointer; }
.check-item__hint { font-family: var(--font-body); font-weight: var(--weight-body); font-size: 12px; color: var(--color-muted); text-transform: none; letter-spacing: 0; }
/* Review flags read as a short paragraph each, so stack them and let the
   hint wrap under its label rather than trailing it on one line. */
.check-row--stack { flex-direction: column; gap: var(--space-3); }
.check-item--flag { align-items: flex-start; max-width: 720px; }
.check-item--flag input { margin-top: 3px; flex: none; }
.check-item--flag .check-item__hint { display: block; margin-top: 2px; line-height: 1.4; }

.check-item__action { display: flex; align-items: center; gap: var(--space-3); padding-left: 24px; }
.check-item__action .check-item__hint { font-size: 12px; color: var(--color-muted); }

/* A card that needs the operator's attention before the list below it. */
.card--attention { border-top-color: var(--band-average); }
.card--attention select { width: auto; min-width: 240px; height: 32px; padding: 0 28px 0 10px; font-size: 13px; }

/* Dashboard row actions: buttons and inline POST forms sit on one line. */
.row-actions { display: flex; gap: var(--space-2); align-items: center; }
.row-actions form { margin: 0; }
.flag a { color: inherit; text-decoration: underline; }
.logo-preview { padding: var(--space-2) 0; }
.logo-preview img { height: 40px; width: auto; max-width: 240px; }

/* Blueprint settings gear on the wizard nav row. */
.wizard-nav__spacer { flex: 1; }
.wizard-nav__gear {
    display: inline-flex;
    align-items: center;
    padding: 8px 12px;
    color: var(--color-muted);
    border: var(--border-subtle);
    background: #fff;
}
.wizard-nav__gear:hover { color: var(--color-primary); border-color: var(--color-accent); }
.wizard-nav__gear.is-current { color: #fff; background: var(--color-primary); border-color: var(--color-primary); }
.wizard-nav__gear svg { display: block; }

/* Admin assignees are locked on — checked and greyed, can't be unassigned. */
.assignee-check--locked { color: var(--color-muted); cursor: default; }
.assignee-check--locked input { accent-color: var(--color-muted); cursor: not-allowed; }

/* Sign in with Google (login page). White, bordered, the G mark at left — the
   familiar shape, in the app's geometry. */
.btn--google { display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%; background: #fff; color: var(--color-primary); border: var(--border-subtle); }
.btn--google:hover { background: var(--color-soft); border-color: var(--color-accent); color: var(--color-primary); }
.login__or { display: flex; align-items: center; gap: var(--space-2); margin: var(--space-3) 0; color: var(--color-muted); font-size: 12px; text-transform: uppercase; letter-spacing: .06em; }
.login__or::before, .login__or::after { content: ''; flex: 1; border-top: var(--border-subtle); }
