/*
 * ai-logline.css
 *
 * The AI logline panel on the script summary card.
 *
 * Deliberately small. The button is .btn .btn-outline from global.css and the
 * heading is .script-section-label from dashboard.css, so nothing here restyles
 * a control that already has a style -- these rules only lay the panel out and
 * dress the result list, using the same variables as the card around it.
 *
 * Namespaced .ai- throughout, like .sb- and .sc- before it, so it can be loaded
 * on any dashboard page without reaching into anything else.
 */

.ai-logline-panel {
    margin-bottom: 14px;
}

.ai-logline-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}

/* The result list -------------------------------------------------------- */

.ai-logline-result {
    margin-top: 12px;
}

.ai-logline-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.ai-logline-item {
    border: 1px solid var(--border);
    border-radius: 6px;
    background: #fff;
    padding: 12px 14px;
}

/* The angle -- Classic, Hook-forward, Marketable. Same treatment as the other
   small labels on this card, so the three options read as a set. */
.ai-logline-angle {
    font-size: 13px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-blue);
    margin-bottom: 4px;
}

.ai-logline-text {
    font-size: 18px;
    line-height: 1.35;
    color: var(--text-soft);
}

.ai-logline-foot {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 8px;
}

.ai-logline-foot .ai-wordcount {
    font-size: 13px;
    color: var(--text-muted);
}

/* The two buttons inside a result. Quieter than .btn: they sit inside a card
   that already has a primary action at the top of it. */
.ai-logline-foot button {
    font-family: 'Cabin Condensed', sans-serif;
    font-size: 13px;
    font-weight: 600;
    padding: 4px 12px;
    border-radius: 5px;
    border: 1px solid var(--border);
    background: var(--bg-light);
    color: var(--text-soft);
    cursor: pointer;
    transition: all 0.2s;
}

.ai-logline-foot button:hover {
    border-color: var(--primary);
    color: var(--primary);
}

/* Why this version says what it says. Set back and smaller: it is the reasoning
   behind the option, not the option. */
.ai-logline-why {
    margin-top: 8px;
    padding-left: 10px;
    border-left: 2px solid var(--border);
    font-size: 14px;
    line-height: 1.45;
    color: var(--text-muted);
}

/* Supporting lines ------------------------------------------------------- */

.ai-meta {
    font-size: 14px;
    color: var(--text-muted);
    margin: 0 0 10px;
}

.ai-readback,
.ai-notes {
    margin-top: 12px;
    padding: 10px 12px;
    border-radius: 6px;
    background: var(--bg-light);
    font-size: 14px;
    line-height: 1.45;
    color: var(--text-soft);
}

.ai-cached-note {
    font-size: 13px;
    color: var(--text-muted);
    margin: 0 0 10px;
}

.ai-cached-note a {
    color: var(--primary);
    cursor: pointer;
}

/* Said once, quietly, and always -- the script is leaving the building and the
   writer is entitled to know that without having to go looking for it. */
.ai-disclaimer {
    margin-top: 12px;
    font-size: 12px;
    line-height: 1.4;
    color: var(--text-muted);
}

/* States ----------------------------------------------------------------- */

.ai-working {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 14px 0;
    font-size: 15px;
    color: var(--text-muted);
}

.ai-error {
    margin-top: 10px;
    padding: 10px 12px;
    border-radius: 6px;
    border: 1px solid var(--border);
    background: var(--bg-light);
    font-size: 14px;
    color: var(--text-soft);
}

@media (max-width: 700px) {
    .ai-logline-head {
        align-items: flex-start;
        flex-direction: column;
    }
}

/* The writer's own logline, judged ---------------------------------------
   Sits above the alternatives: it is what they already have, and the three
   below only mean something once you know what is wrong with this one. */

.ai-yours {
    margin: 0 0 14px;
    padding: 12px 14px;
    border: 1px solid var(--border);
    border-left: 3px solid var(--color-blue);
    border-radius: 6px;
    background: var(--bg-light);
}

.ai-yours-head {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    font-size: 13px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-blue);
    margin-bottom: 6px;
}

/* Verdict and accuracy chips. The class is chosen from a whitelist server-side
   -- never from the model's own string -- so these three are the only ones
   that can appear, plus the neutral fallback. */
.ai-verdict,
.ai-accuracy {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.ai-verdict-strong {
    background: #d7f5e3;
    color: #1a7f4b;
}

.ai-verdict-workable {
    background: #fdf0d5;
    color: #8a6100;
}

.ai-verdict-needs-work {
    background: #fde0e0;
    color: #a02a2a;
}

.ai-verdict-neutral {
    background: #e5e5e5;
    color: var(--text-soft);
}

.ai-accuracy {
    background: #fff;
    border: 1px solid var(--border);
    color: var(--text-muted);
    text-transform: none;
    letter-spacing: 0;
    font-weight: 600;
}

.ai-yours-note,
.ai-yours-keep {
    margin: 0 0 4px;
    font-size: 14px;
    line-height: 1.45;
    color: var(--text-soft);
}

.ai-yours-keep {
    color: var(--text-muted);
}

/* What each alternative does that the writer's does not. Distinct from
   .ai-logline-why: that is why this version exists at all, this is the
   comparison, and they answer different questions. */
.ai-logline-vs {
    margin-top: 6px;
    padding-left: 10px;
    border-left: 2px solid var(--color-blue);
    font-size: 14px;
    line-height: 1.45;
    color: var(--text-soft);
}

.ai-logline-vs strong {
    color: var(--color-blue);
}

/* A result generated from a script or a logline that has since changed. Shown
   rather than hidden -- it is still the writer's work -- but it has to say so,
   or it silently describes a logline they have already rewritten. */
.ai-cached-stale {
    padding: 6px 10px;
    border-radius: 5px;
    background: #fdf0d5;
    color: #8a6100;
}

.ai-cached-stale a {
    color: #8a6100;
    text-decoration: underline;
}

/* For television: what the model reads the SHOW as. The loglines above it are
   selling the series, so this is the premise they are built on -- and the
   confidence note matters, because one episode is thin evidence for a series. */
.ai-series {
    margin: 0 0 12px;
    padding: 10px 14px;
    border: 1px dashed var(--border);
    border-radius: 6px;
}

.ai-series-head {
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
    margin-bottom: 4px;
}

.ai-series-engine {
    margin: 0;
    font-size: 16px;
    line-height: 1.4;
    color: var(--text-soft);
}

.ai-series-foot {
    margin: 6px 0 0;
    font-size: 12px;
    color: var(--text-muted);
}

/* Shown where the Regenerate link would be, while the daily limit is in force.
   A link that always refuses is worse than no link. */
.ai-cooldown {
    color: var(--text-muted);
}

/* The collapsed line, and the history ------------------------------------
   What a writer returning to a script sees first: one small line saying the
   work exists and when it was done. The result is in the page underneath it,
   folded away, so opening it costs nothing. */

.ai-logline-summary {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    margin-top: 8px;
}

.ai-summary-toggle,
.ai-history-open {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 0;
    border: none;
    background: none;
    cursor: pointer;
    font-family: 'Cabin Condensed', sans-serif;
    font-size: 13px;
    color: var(--text-muted);
    transition: color 0.2s;
}

.ai-summary-toggle:hover,
.ai-history-open:hover {
    color: var(--primary);
}

.ai-summary-chevron,
.ai-history-chevron {
    font-size: 11px;
    transition: transform 0.2s;
}

.ai-history-open {
    color: var(--color-blue);
}

/* The dialog ------------------------------------------------------------- */

.ai-history {
    padding: 4px 2px;
}

.ai-history-title {
    margin: 0 0 2px;
    font-size: 20px;
    color: var(--color-blue);
}

.ai-history-sub {
    margin: 0 0 14px;
    font-size: 13px;
    color: var(--text-muted);
}

.ai-history-entry {
    border-top: 1px solid var(--border);
    padding: 10px 0;
}

/* The set that still matches the script as it stands. */
.ai-history-entry.is-current {
    border-left: 3px solid var(--color-blue);
    padding-left: 10px;
}

.ai-history-toggle {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 0;
    border: none;
    background: none;
    cursor: pointer;
    text-align: left;
    font-family: 'Cabin Condensed', sans-serif;
}

.ai-history-when {
    font-size: 15px;
    font-weight: 600;
    color: var(--text-soft);
}

.ai-history-count {
    font-size: 13px;
    color: var(--text-muted);
}

.ai-history-badge {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 2px 8px;
    border-radius: 10px;
    background: var(--primary-dim, #eef0ff);
    color: var(--primary);
}

.ai-history-body {
    padding-top: 6px;
}

/* The story extract ------------------------------------------------------
   Folded away by default: it is a page of analysis on a card whose job is the
   script. The bar is always visible so the writer knows it exists. */

.ai-extract-offer {
    margin-top: 10px;
    padding: 12px 14px;
    border: 1px dashed var(--border);
    border-radius: 6px;
    font-size: 14px;
    line-height: 1.5;
    color: var(--text-soft);
}

.ai-extract-offer p {
    margin: 0 0 10px;
}

.ai-extract-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 10px;
}

.ai-extract-toggle,
.ai-reanalyze {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 0;
    border: none;
    background: none;
    cursor: pointer;
    font-family: 'Cabin Condensed', sans-serif;
    font-size: 13px;
    color: var(--text-muted);
    transition: color 0.2s;
}

.ai-extract-toggle:hover,
.ai-reanalyze:hover {
    color: var(--primary);
}

.ai-extract-panel {
    margin-top: 10px;
}

/* An out-of-date breakdown is not a warning.
 *
 * This was amber on amber -- the palette this file uses for things that went
 * wrong (.cv-verdict--consider, the error notes at 223 and 280) -- and it was
 * raised by a single comma, because a hash cannot tell a comma from a rewrite.
 * A writer who sees a caution strip every time they touch their own script
 * learns to stop touching it, which is the opposite of the point.
 *
 * So: grey, a hairline instead of a fill, and the same muted tone as the pass
 * verdict. It is still there, still first, still noticed. It just is not
 * shouting, because nothing here is broken -- the panel below it works, and the
 * note is an offer to refresh it whenever the changes have earned it.
 */
.ai-extract-stale {
    margin-bottom: 12px;
    padding: 8px 12px;
    border-radius: 6px;
    background: #f7f8f9;
    border: 1px solid #e6e8ea;
    color: #5b6167;
    font-size: 13px;
    line-height: 1.45;
}

.ai-extract-stale i {
    margin-right: 5px;
    color: #99a0a7;
}

/* Boxed, like a coverage category ---------------------------------------------

   These were a flat run of small headings with paragraphs under them, which
   on a reading of fifteen fields gave the eye nothing to stop at -- Story ran
   into Character ran into Structure, and the writer had to read the labels to
   find out where they were.

   Same box as .cv-cat on the coverage report, on purpose: the two are read by
   the same person on the same page, and a report that looks like a different
   product for being a different feature is just harder to use. */
.ai-x-section,
.ai-x-list {
    margin-bottom: 12px;
    padding: 14px 16px;
    border: 1px solid var(--border, #e6e6e6);
    border-radius: 6px;
    background: #fcfcfc;
}

/* A heading now, not a label on a paragraph. 1.2rem and uppercase is what
   .cv-cat-name settled on for the same job. */
.ai-x-section-title {
    margin: 0 0 10px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border, #ececec);
    font-size: 1.2rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--color-blue);
}

/* Label above value, with air between fields.

   8px was fine when the whole section was small; inside a box with a rule
   under its heading, the fields need to be told apart from each other as well
   as from the heading. The last one drops its margin so the box does not end
   with a gap. */
.ai-x-field {
    margin-bottom: 12px;
}

.ai-x-section .ai-x-field:last-child { margin-bottom: 0; }

/* The subheading. Uppercase and small against a 1.2rem section title, so the
   two never compete: one names the section, the other names the field. */
.ai-x-label {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--text-muted);
    margin-bottom: 3px;
}

/* A field the writer changed says so, and offers the way back. */
.ai-x-edited {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 1px 6px;
    border-radius: 8px;
    background: var(--bg-light);
    color: var(--text-soft);
}

.ai-x-revert,
.ai-x-promote {
    padding: 1px 8px;
    border: 1px solid var(--border);
    border-radius: 5px;
    background: #fff;
    cursor: pointer;
    font-family: 'Cabin Condensed', sans-serif;
    font-size: 11px;
    color: var(--text-muted);
    transition: all 0.2s;
}

.ai-x-revert:hover,
.ai-x-promote:hover {
    border-color: var(--primary);
    color: var(--primary);
}

/* contenteditable, not an input: the card is a reading surface, and a page of
   boxes reads as a form to fill in rather than an analysis to correct. */
/* Reads as prose, and still says it is editable on hover. The negative left
   margin puts the text back on the box's own left edge, so the padding that
   exists for the hover outline does not indent every value by 10px. */
.ai-x-value {
    margin-left: -10px;
    padding: 3px 10px;
    border: 1px solid transparent;
    border-radius: 5px;
    font-size: 1.05rem;
    line-height: 1.55;
    color: var(--text-soft);
    transition: all 0.15s;
}

.ai-x-value:hover {
    border-color: var(--border);
    background: #fff;
}

.ai-x-value:focus {
    outline: none;
    border-color: var(--primary);
    background: #fff;
}

.ai-x-list {
    margin-bottom: 14px;
}

.ai-x-list ul {
    margin: 0;
    padding-left: 18px;
    font-size: 14px;
    line-height: 1.5;
    color: var(--text-soft);
}

.ai-x-page {
    font-size: 11px;
    color: var(--text-muted);
}

.ai-x-chip {
    display: inline-block;
    margin: 0 4px 4px 0;
    padding: 2px 10px;
    border-radius: 10px;
    background: var(--bg-light);
    font-size: 13px;
    color: var(--text-soft);
}

.ai-x-confidence {
    padding: 10px 12px;
    border-radius: 6px;
    background: var(--bg-light);
    font-size: 13px;
    line-height: 1.5;
    color: var(--text-soft);
}

/* Feedback --------------------------------------------------------------- */

.ai-logline-vote {
    display: inline-flex;
    gap: 4px;
    margin-left: auto;
}

.ai-logline-vote button {
    padding: 4px 10px;
    border: 1px solid var(--border);
    border-radius: 5px;
    background: #fff;
    cursor: pointer;
    font-size: 12px;
    color: var(--text-muted);
    transition: all 0.2s;
}

.ai-logline-vote button:hover {
    border-color: var(--primary);
    color: var(--primary);
}

.ai-logline-vote button.is-on {
    border-color: var(--color-blue);
    background: var(--bg-light);
    color: var(--color-blue);
}

/* .ai-reason, .ai-reason-input, .ai-reason-send and .ai-reason-thanks are
   defined further down, where the note box became a label above a growing
   textarea above a button. They used to live here as a single flex row, and
   leaving that behind kept the label on the same line as the field. */

/* A column now: the standing note sits above the button, full width, and the
   button and its hint stay a row of their own. */
.ai-refine-row {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
    margin-top: 14px;
}

.ai-refine-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}

.ai-refine-hint {
    font-size: 12px;
    color: var(--text-muted);
}

/* The standing note ------------------------------------------------------

   Shaped like .ai-reason on purpose. It asks the same kind of thing -- tell
   us what you think -- and a writer who has met one of these boxes under a
   logline should recognise this one without being taught it twice. What it
   does not have is a Save button: this one saves itself. */
.ai-note {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    width: 100%;
}

.ai-note .grow-wrap {
    width: 100%;
}

.ai-note-ask {
    display: block;
    margin-bottom: 4px;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--text-dark, #222);
}

.ai-note-optional {
    font-weight: 400;
    font-style: italic;
    color: var(--text-soft, #6b6b6b);
}

.ai-note .grow-wrap>textarea,
.ai-note .grow-wrap::after {
    font-size: 0.92rem;
    line-height: 1.45;
    padding: 6px 9px;
    border-radius: 6px;
    font-family: inherit;
    min-height: 2.6em;
}

.ai-note .grow-wrap>textarea:focus {
    outline: none;
    border-color: var(--logo-green, #2e7d5b);
}

/* Holds its line whether or not it has anything to say, so the button below
   does not jump when a save reports back. */
.ai-note-state {
    display: block;
    min-height: 1.1em;
    margin-top: 4px;
    font-size: 12px;
    font-style: italic;
    color: var(--text-muted);
}

/* Refine's read-back of the writer's notes. First thing in the result, because
   somebody who has just rated three loglines wants to see their notes landed. */
.ai-responding {
    margin: 0 0 12px;
    padding: 10px 12px;
    border-left: 3px solid var(--color-blue);
    border-radius: 4px;
    background: var(--bg-light);
    font-size: 14px;
    line-height: 1.45;
    color: var(--text-soft);
}

/* The structure pass, running quietly beside the analysis bar. */
.ai-mapping {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin-left: auto;
    font-size: 12px;
    color: var(--text-muted);
}

/* Credits ---------------------------------------------------------------- */

.ai-logline-actions {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-left: auto;
}

.ai-credit-pill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    border: 1px solid var(--border, #d8d8d8);
    border-radius: 999px;
    font-size: 0.9rem;
    line-height: 1.6;
    color: var(--text-muted, #6b6b6b);
    white-space: nowrap;
}

.ai-credit-pill i {
    font-size: 0.72rem;
    opacity: 0.75;
}

/* The price confirmation ------------------------------------------------- */

.ai-quote-parts {
    list-style: none;
    margin: 0 0 12px;
    padding: 0;
    text-align: left;
}

/* No rules between the rows.

   Each line item can carry a note under it, and a border fell between the two
   -- so 'Read and analyse the script' and the sentence explaining why it is on
   the bill read as two separate charges. The rule under .ai-quote-total is the
   only division this list needs: everything above it is what you are buying,
   and the thing below is what it comes to. */
.ai-quote-parts li {
    display: flex;
    justify-content: space-between;
    gap: 16px;
    padding: 5px 0;
}

.ai-quote-total {
    margin: 0;
}

/* Said above the price when the writer has rated loglines without saying why.
   Left-aligned against the dialog's centred text on purpose: it is two
   sentences of explanation, and centred prose is read as a headline. */
.ai-brief-thin {
    margin: 0 0 10px;
    text-align: left;
    font-size: 0.92rem;
    line-height: 1.5;
    color: var(--text-soft, #6b6b6b);
}

.ai-brief-thin+.ai-quote-total {
    padding-top: 10px;
    border-top: 1px solid var(--border, #e6e6e6);
}

/* The fallback shape, for a quote with no line items to hang a note on.
   No rule of its own: it drew one above itself, which put the note below a
   border and made it read as a second total rather than as a caution. */
.ai-quote-warning {
    margin: 12px 0 0;
    font-size: 0.9em;
    color: var(--text-muted, #6b6b6b);
}

/* And the usual shape: an aside like the others, but the one that says what
   you are about to lose. Darker than a plain note and not italic, because it
   is a caution rather than a footnote. */
.ai-quote-parts li.ai-quote-warn-note {
    padding-top: 6px;
    font-style: normal;
    color: var(--text-dark, #444);
}

/* The credits page ------------------------------------------------------- */

.credit-summary {
    padding: 10px;
}

.credit-figure {
    display: flex;
    align-items: baseline;
    gap: 10px;
}

.credit-figure-value {
    font-size: 2.4rem;
    font-weight: 700;
    line-height: 1;
    color: var(--logo-green, #2e7d5b);
}

.credit-figure-label {
    font-size: 0.95rem;
    color: var(--text-soft, #6b6b6b);
}

.credit-split {
    margin: 10px 0 0;
    font-size: 0.92rem;
    color: var(--text-soft, #6b6b6b);
}

.credit-actions {
    margin-top: 16px;
}

.credit-pager {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    padding: 14px 0 4px;
}

.credit-pager:empty {
    display: none;
}

.credit-pager-label {
    font-size: 0.9rem;
    color: var(--text-soft, #6b6b6b);
}

a.ai-credit-pill {
    text-decoration: none;
}

a.ai-credit-pill:hover {
    border-color: var(--logo-green, #2e7d5b);
    color: var(--logo-green, #2e7d5b);
}

/* Choosing a credit pack ------------------------------------------------- */

.credit-pack-intro {
    margin: 0 0 16px;
    font-size: 0.92rem;
    color: var(--text-soft, #6b6b6b);
}

.credit-pack {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    width: 100%;
    margin-bottom: 10px;
    padding: 14px 16px;
    border: 1px solid var(--border, #d8d8d8);
    border-radius: 8px;
    background: var(--bg-white, #fff);
    cursor: pointer;
    text-align: left;
    transition: border-color .15s, background .15s;
}

.credit-pack:hover:not(:disabled) {
    border-color: var(--logo-green, #2e7d5b);
    background: var(--bg-light, #f7f7f7);
}

.credit-pack:disabled {
    opacity: 0.55;
    cursor: default;
}

.credit-pack-main {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.credit-pack-credits {
    font-weight: 600;
    font-size: 1.05rem;
}

.credit-pack-rate,
.credit-pack-price {
    font-size: 0.88rem;
    color: var(--text-soft, #6b6b6b);
}

.credit-pack-price {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--logo-green, #2e7d5b);
    white-space: nowrap;
}

/* AI Extras widget --------------------------------------------------------
   The tab chrome is the site's own (.nav-tabs / .tab-pane, as used by Script
   Elements and Attachments/Media). Only the inside of a pane needs anything. */

.ai-extras {
    margin-bottom: 18px;
}

.ai-extras .ai-credit-pill {
    margin-left: auto;
}

/* The row the Generate and Review buttons sit in.

   No padding at the top. The tab pane already opens with its own space, so
   12px more here pushed the buttons a clear line further down than anything
   above them warranted -- two rules each doing a bit of the same job, which
   is how a gap ends up bigger than either author intended. */
.ai-tab-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    /* Nothing above -- the tab pane opens the space there -- and room below,
       because the panels that follow are bordered boxes. Butted up against
       one, a button reads as part of its header rather than as the thing
       that made it. The 4px this replaces was doing nothing visible. */
    padding: 0;
    margin-bottom: 14px;
}

.ai-tab-foot {
    padding: 10px 0 4px;
    border-top: 1px solid var(--border, #e6e6e6);
    margin-top: 12px;
}

.ai-tab-empty {
    margin: 0;
    padding: 22px 4px;
    text-align: center;
    color: var(--text-soft, #6b6b6b);
    font-size: 0.95rem;
}

/* The analysis is the tab's whole content now, so it no longer hides itself
   behind a chevron -- the tab is the disclosure. */
.ai-extras .ai-extract-panel {
    padding-top: 4px;
}

.ai-extract-note {
    font-size: 0.85rem;
    color: var(--text-soft, #6b6b6b);
    font-style: italic;
}

/* An edited logline ------------------------------------------------------- */

.ai-logline-text[contenteditable] {
    border-radius: 4px;
    padding: 2px 4px;
    margin: -2px -4px;
    outline: none;
    transition: background .15s, box-shadow .15s;
}

.ai-logline-text[contenteditable]:hover {
    background: var(--bg-light, #f7f7f7);
}

.ai-logline-text[contenteditable]:focus {
    background: var(--bg-white, #fff);
    box-shadow: 0 0 0 2px var(--logo-green, #2e7d5b);
}

.ai-logline-edited {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 4px;
    font-size: 0.78rem;
    font-style: italic;
    color: var(--text-soft, #6b6b6b);
}

.ai-logline-revert {
    border: 0;
    background: none;
    padding: 0 2px;
    cursor: pointer;
    color: var(--text-soft, #6b6b6b);
    font-size: 0.78rem;
}

.ai-logline-revert:hover {
    color: var(--logo-green, #2e7d5b);
}

/* Telling us why ---------------------------------------------------------- */

.ai-reason {
    /* A column: the question, then the field, then the button. Explicit
       rather than relying on block flow, so this cannot be quietly turned
       back into a row by a rule defined above it. */
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    margin-top: 10px;
    width: 100%;
}

.ai-reason .grow-wrap {
    width: 100%;
}

.ai-reason-ask {
    display: block;
    margin-bottom: 4px;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--text-dark, #222);
}

.ai-reason-optional {
    font-weight: 400;
    font-style: italic;
    color: var(--text-soft, #6b6b6b);
}

/* The wrapper is css/dashboard.css's .grow-wrap. Only the size is overridden
   here -- this sits inside a logline, not in a dialog. */
.ai-reason .grow-wrap>textarea,
.ai-reason .grow-wrap::after {
    font-size: 0.92rem;
    line-height: 1.45;
    padding: 6px 9px;
    border-radius: 6px;
    font-family: inherit;
    min-height: 2.2em;
}

.ai-reason .grow-wrap>textarea:focus {
    outline: none;
    border-color: var(--logo-green, #2e7d5b);
}

.ai-reason-send {
    margin-top: 6px;
    padding: 4px 14px;
    border: 1px solid var(--border, #d8d8d8);
    border-radius: 6px;
    background: var(--bg-white, #fff);
    font-size: 0.85rem;
    cursor: pointer;
}

.ai-reason-send:hover {
    border-color: var(--logo-green, #2e7d5b);
    color: var(--logo-green, #2e7d5b);
}

.ai-reason-thanks {
    font-size: 0.85rem;
    font-style: italic;
    color: var(--text-soft, #6b6b6b);
}

/* Choosing the angles ----------------------------------------------------- */



/* Choosing a style, in the Generate dialog -------------------------------- */

.ai-angle-intro {
    margin: 0 0 10px;
    text-align: left;
    font-size: 0.95rem;
}

.ai-angle-choices {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 16px;
    text-align: left;
}

.ai-angle-choice {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 12px;
    border: 1px solid var(--border, #d8d8d8);
    border-radius: 8px;
    cursor: pointer;
    transition: border-color .15s, background .15s;
}

.ai-angle-choice:hover {
    background: var(--bg-light, #f7f7f7);
}

/* :has is what lets the whole row respond to its own radio. Where it is not
   supported the rows simply stay plain, which is a smaller loss than wiring
   a class up in script. */
.ai-angle-choice:has(input:checked) {
    border-color: var(--logo-green, #2e7d5b);
    background: var(--bg-light, #f7f7f7);
}

.ai-angle-choice input {
    margin-top: 3px;
    flex: none;
}

.ai-angle-choice-body {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.ai-angle-choice-label {
    font-weight: 600;
    font-size: 0.95rem;
}

.ai-angle-choice-blurb {
    font-size: 0.85rem;
    color: var(--text-soft, #6b6b6b);
}

/* Guidance, asked in the same dialog as the style ------------------------

   A plain textarea rather than a .grow-wrap: this one sits in a dialog that
   sizes itself to its content, and a field that grows as it is typed into
   would move the Generate button down the screen under the writer's cursor.
   Three rows, and it scrolls. */
.ai-angle-note-ask {
    display: block;
    margin: 16px 0 4px;
    text-align: left;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text-dark, #222);
}

.ai-angle-note-optional {
    font-weight: 400;
    font-style: italic;
    color: var(--text-soft, #6b6b6b);
}

textarea.ai-angle-note {
    display: block;
    width: 100%;
    box-sizing: border-box;
    padding: 8px 10px;
    border: 1px solid var(--border, #d8d8d8);
    border-radius: 8px;
    font-family: inherit;
    font-size: 0.92rem;
    line-height: 1.45;
    resize: vertical;
}

textarea.ai-angle-note:focus {
    outline: none;
    border-color: var(--logo-green, #2e7d5b);
}

/* Says the note outlives this dialog, which is the part a writer would not
   otherwise guess: it reads like a field on a form, and it is a setting. */
/* The gap between the note and the price lives here rather than on the price
   itself: the analyse dialog shows the same price line with no note above it,
   and spacing it from there would open a hole at the top of that one. */
.ai-angle-note-hint {
    margin: 4px 0 24px;
    text-align: left;
    font-size: 12px;
    font-style: italic;
    color: var(--text-muted);
}

/* And less between the price and the buttons than SweetAlert's own 1.25em.
   The total is the last thing read before deciding, so it belongs with the
   button that acts on it rather than floating between the two. */
.ai-quote-popup .swal2-actions {
    margin-top: 10px;
}

/* Said above the price when a script is short for its format. Amber rather
   than red: it is a caution about what the answer will be like, not a refusal
   -- the refusals never reach a dialog at all. */
.ai-length-warn {
    margin: 0 0 12px;
    padding: 8px 10px;
    border-radius: 6px;
    background: var(--bg-warning-soft, #fdf6e3);
    border: 1px solid var(--warning, #e0b84c);
    text-align: left;
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--text-dark, #333);
}

.ai-length-warn i {
    margin-right: 6px;
    color: var(--warning, #c9971f);
}

/* A read on the writer's own logline -------------------------------------- */

.ai-review-out:empty {
    display: none;
}

.ai-review {
    margin-bottom: 14px;
    padding: 14px;
    border: 1px solid var(--border, #e2e2e2);
    border-radius: 10px;
    background: var(--bg-white, #fff);
}

/* The answer first. A writer asked one question and it should not be below a
   table of criteria they have to read down to find it. */
.ai-review-verdict {
    padding-left: 12px;
    border-left: 4px solid var(--border, #d8d8d8);
}

.ai-review-verdict.is-yes {
    border-left-color: var(--logo-green, #2e7d5b);
}

.ai-review-verdict.is-maybe {
    border-left-color: var(--warning, #e0b84c);
}

.ai-review-verdict.is-no {
    border-left-color: var(--danger, #b4462f);
}

.ai-review-badge {
    display: inline-block;
    margin-bottom: 4px;
    font-size: 1.05rem;
    font-weight: 700;
}

.is-yes .ai-review-badge {
    color: var(--logo-green, #2e7d5b);
}

.is-maybe .ai-review-badge {
    color: var(--warning, #b8901f);
}

.is-no .ai-review-badge {
    color: var(--danger, #b4462f);
}

.ai-review-summary {
    margin: 0;
    font-size: 0.95rem;
    line-height: 1.55;
}

.ai-review-reads {
    margin: 12px 0 0;
    font-size: 0.9rem;
}

.ai-review-mismatch {
    display: block;
    margin-top: 4px;
    color: var(--warning, #b8901f);
}

/* One thing to keep, one thing to change. */
.ai-review-headline {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin: 14px 0;
}

@media (max-width: 620px) {
    .ai-review-headline {
        grid-template-columns: 1fr;
    }
}

.ai-review-keep,
.ai-review-fix {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 10px;
    border-radius: 8px;
    background: var(--bg-light, #f7f7f7);
    font-size: 0.9rem;
    line-height: 1.5;
}

.ai-review-keep strong {
    color: var(--logo-green, #2e7d5b);
}

.ai-review-fix strong {
    color: var(--danger, #b4462f);
}

.ai-review-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.ai-review-item {
    display: grid;
    grid-template-columns: 8.5rem 5.5rem 1fr;
    gap: 10px;
    align-items: baseline;
    padding: 8px 0;
    border-top: 1px solid var(--border, #eee);
    font-size: 0.9rem;
    line-height: 1.5;
}

@media (max-width: 620px) {
    .ai-review-item {
        grid-template-columns: 1fr;
        gap: 2px;
    }
}

.ai-review-crit {
    font-weight: 600;
}

.ai-review-rating {
    font-size: 0.8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .02em;
}

.ai-review-rating.is-strong {
    color: var(--logo-green, #2e7d5b);
}

.ai-review-rating.is-adequate {
    color: var(--text-muted, #8a8a8a);
}

.ai-review-rating.is-weak {
    color: var(--danger, #b4462f);
}

.ai-review-missing {
    margin-top: 12px;
    font-size: 0.9rem;
    line-height: 1.5;
}

.ai-review-missing ul {
    margin: 4px 0 0;
    padding-left: 18px;
}

/* The basis of the whole read, said plainly: a writer who assumes otherwise
   would take "would pass" as a verdict on their screenplay. */
.ai-review-scope {
    margin: 14px 0 0;
    font-size: 12px;
    line-height: 1.5;
    color: var(--text-muted, #8a8a8a);
}

/* The two rewrites --------------------------------------------------------

   Copy, never adopt. The visual difference between them is the whole point:
   one is the writer's own sentence rebuilt, the other is fiction that happens
   to be well shaped, and they must not read as two versions of one thing. */
.ai-rw {
    margin-top: 14px;
    padding: 12px;
    border-radius: 8px;
    border: 1px solid var(--border, #e2e2e2);
}

.ai-rw-tight {
    background: var(--bg-light, #f7f7f7);
}

/* Dashed and tinted: it looks provisional because it is. */
.ai-rw-made {
    background: var(--bg-warning-soft, #fdf9ef);
    border-style: dashed;
    border-color: var(--warning, #e0b84c);
}

.ai-rw-head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 6px;
    font-size: 0.9rem;
}

.ai-rw-tag {
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--bg-white, #fff);
    border: 1px solid var(--border, #d8d8d8);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--text-muted, #8a8a8a);
}

.ai-rw-tag.is-warn {
    border-color: var(--warning, #e0b84c);
    color: var(--warning, #b8901f);
}

.ai-rw-text {
    margin: 0 0 6px;
    font-size: 1rem;
    line-height: 1.5;
    color: var(--text-dark, #222);
}

.ai-rw-why {
    margin: 0 0 8px;
    font-size: 0.85rem;
    line-height: 1.5;
    color: var(--text-soft, #6b6b6b);
}

.ai-rw-warn {
    margin: 0 0 8px;
    font-size: 0.85rem;
    line-height: 1.5;
    font-weight: 600;
    color: var(--text-dark, #333);
}

.ai-rw-warn i {
    margin-right: 5px;
    color: var(--warning, #c9971f);
}

.ai-rw-invented {
    margin-bottom: 8px;
    font-size: 0.85rem;
    line-height: 1.45;
    color: var(--text-soft, #6b6b6b);
}

.ai-rw-invented ul {
    margin: 3px 0 0;
    padding-left: 18px;
}

.ai-rw-copy {
    padding: 3px 12px;
    border: 1px solid var(--border, #d8d8d8);
    border-radius: 6px;
    background: var(--bg-white, #fff);
    font-size: 0.82rem;
    cursor: pointer;
}

.ai-rw-copy:hover {
    border-color: var(--logo-green, #2e7d5b);
    color: var(--logo-green, #2e7d5b);
}

/* The collapsible sections ------------------------------------------------

   One shape for all three long answers -- the story analysis, the suggested
   loglines, the logline review. They are the same kind of thing to a reader
   and any difference between them would only be noise. */
.ai-panel {
    display: block;
    margin-bottom: 14px;
    border: 1px solid var(--border, #e2e2e2);
    border-radius: 10px;
    overflow: hidden;
}

.ai-panel-head {
    display: flex;
    align-items: baseline;
    gap: 10px;
    width: 100%;
    padding: 10px 12px;
    border: 0;
    background: var(--bg-light, #f6f6f6);
    text-align: left;
    cursor: pointer;
    font-family: inherit;
}

/* A head with a control beside it.

   Three things on one bar, in reading order: the title, the control that
   belongs to this section, then the answer in miniature pushed to the far
   right. The control cannot be inside the head -- it is a checkbox and the
   head is a <button> -- so all three are siblings here and the row is what
   makes them a line.

   center, not baseline: the switch is a drawn track rather than text and has
   no baseline worth aligning to, so matching baselines is what made it sit
   low against the words either side of it. */
.ai-panel-headrow {
    display: flex;
    align-items: center;
    gap: 12px;
    background: var(--bg-light, #f6f6f6);
    cursor: pointer;
}

/* Sized to its own contents, so the control sits directly after the title
   instead of being pushed across a button that had stretched to fill the bar.

   AND THEREFORE NOT THE THING THAT LIGHTS UP

   A full-width head painted its own hover and the whole bar responded. Shrunk
   to its contents it darkened the words 'Coverage Sep 6, 2026' and nothing
   else, which reads as a bug: the bar is clickable end to end -- see the
   .ai-panel-headrow branch in js/ai-logline.js -- so a highlight covering a
   third of it describes something that is not true.

   The button goes transparent in here and the row paints both states, so the
   highlight matches the click target exactly.

   Kept as a <button> rather than swapped for a div with an onclick, which was
   the other way to fix this. The hover is a styling problem and this is a
   styling answer; changing the element would trade it for a control that
   cannot be tabbed to or fired with Enter, and getting those back means a
   tabindex, a role and a keydown handler -- three things to keep working in
   place of one line. */
.ai-panel-headrow>.ai-panel-head {
    /* width:auto beats the base rule's width:100%, which is the whole of why
       this needs saying. flex:0 1 auto resolves its basis from width, so a
       button still asking for 100% took the entire bar however little text was
       in it -- shoving the switch to the far right and squeezing the verdict
       until it ellipsised. Sized to its content, the three parts sit in reading
       order with the room going to the verdict, which is what needs it. */
    width: auto;
    flex: 0 1 auto;
    min-width: 0;
    align-items: center;
    padding-right: 0;
    background: transparent;
}

.ai-panel-headrow>.ai-panel-head:hover {
    background: transparent;
}

.ai-panel-headrow:hover {
    background: var(--bg-hover, #efefef);
}


/* Outside the button in this arrangement, so it needs the stretch and the
   right-hand padding the button used to give it. */
.ai-panel-headrow>.ai-panel-meta {
    flex: 1 1 auto;
    padding-right: 12px;
}

/* Never squeezed by the line beside it, and never the thing that wraps.

   Its own cursor, because it is the one stretch of the bar that toggles
   nothing and must not offer the pointer that says it does. The switch inside
   sets pointer on itself, which beats this inherited one. */
.ai-panel-aside {
    flex: none;
    display: flex;
    align-items: center;
    cursor: default;
}

/* The switch was drawn for a stacked block, where it needs room above it.
   On one line with everything else that margin is what drops it below the
   text it is supposed to be level with. */
.ai-panel-aside .mk-switch {
    margin-top: 0;
}

.ai-panel-aside .mk-switch-text {
    font-size: 14px;
    white-space: nowrap;
}

.ai-panel-head:hover {
    background: var(--bg-hover, #efefef);
}

.ai-panel-chevron {
    flex: none;
    font-size: 0.8rem;
    color: var(--text-muted, #8a8a8a);
}

.ai-panel-title {
    font-weight: 700;
    font-size: 0.95rem;
    color: var(--text-dark, #222);
}

/* Coverage titles carry a date -- 'Coverage Sep 6, 2026' -- which is what
   tells one report from another in a stack, so they are worth a size the eye
   lands on. Scoped to this panel rather than raised for all of them: the
   analysis and logline panels are one to a card and their titles have nothing
   to distinguish. */
.ai-panel[data-panel^="coverage"] .ai-panel-title {
    font-size: 1.1rem;
    white-space: nowrap;
}

/* The answer in miniature, kept visible when the panel is shut so a closed
   section still says something. Pushed right, and first to go on a narrow
   screen -- the title is what has to survive. */
.ai-panel-meta {
    flex: 1;
    text-align: right;
    font-size: 0.82rem;
    color: var(--text-muted, #8a8a8a);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ai-panel-body {
    padding: 12px;
}

/* The contents already carried their own outside margin, which doubles up
   inside a bordered panel. */
.ai-panel-body>.ai-logline-result,
.ai-panel-body>.ai-review,
.ai-panel-body>.ai-extract {
    margin-bottom: 0;
}

/* The review keeps its own padding inside the panel -- its contents sit flush
   against the edge without it. The border goes, because the panel already
   draws one and two nested boxes read as two things. */
.ai-panel-body>.ai-review {
    padding: 10px;
    border: 0;
}

/* A review of a logline the writer has since changed. */
.ai-review-stale {
    margin: 0 0 12px;
    padding: 8px 10px;
    border-radius: 6px;
    background: var(--bg-light, #f6f6f6);
    font-size: 0.88rem;
    line-height: 1.5;
    color: var(--text-soft, #6b6b6b);
}

.ai-review-stale i {
    margin-right: 6px;
}

/* The line under the "place them all" question that says what will be lost. */
.ai-place-note {
    margin: 10px 0 0;
    font-size: 0.88rem;
    line-height: 1.5;
    color: var(--text-soft, #6b6b6b);
}

.ai-angle-choice-label em {
    font-weight: 400;
    font-style: normal;
    color: var(--text-muted, #8a8a8a);
}

/* The droppable line item ------------------------------------------------- */

.ai-quote-pick label {
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    margin: 0;
}

.ai-quote-pick input {
    flex: none;
    cursor: pointer;
}

/* Unticked, the row says what it would have cost rather than disappearing --
   the writer needs to see what they turned off, and what turning it back on
   would add.

   Greyed and nothing else. The strike through the number said the same thing
   the fading already said, twice, and read as a price that had been cancelled
   rather than one not being charged yet. */
.ai-quote-pick:has(input:not(:checked)) {
    opacity: .55;
}

/* A total, once there is a list above it to total up. */
.ai-quote-parts+.ai-quote-total {
    margin-top: 10px;
    padding-top: 10px;
    border-top: 2px solid var(--border, #e6e6e6);
    font-weight: 600;
}

/* The Analysis tab's actions ---------------------------------------------- */

/* Buttons, not links. These sit alone on a bar with nothing else on it, so a
   borderless label with only a colour change on hover read as text that
   happened to be clickable -- and with the note beside them empty, the
   space-between pushed the first one into the middle of the tab. */
.ai-extract-bar {
    justify-content: flex-start;
}

.ai-extract-note {
    flex: 1;
}

.ai-extract-actions {
    display: flex;
    gap: 8px;
    margin-left: auto;
}

.ai-extract-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 12px;
    border: 1px solid var(--border, #d8d8d8);
    border-radius: 6px;
    background: var(--bg-white, #fff);
    cursor: pointer;
    font-family: 'Cabin Condensed', sans-serif;
    font-size: 13px;
    color: var(--text-muted, #8a8a8a);
    transition: color .15s, border-color .15s, background .15s;
}

.ai-extract-btn:hover {
    background: var(--bg-light, #f6f6f6);
    border-color: var(--primary, #2e7d5b);
    color: var(--primary, #2e7d5b);
}

.ai-extract-btn:disabled {
    opacity: .6;
    cursor: default;
}

/* The structure choice as a section of its own is now the layout dialog's
   alone -- the analyse dialog asks it under the checkbox it belongs to, as
   .ai-quote-opt. Nothing greys this one: the layout dialog is buying the
   layout and nothing else, so the question can never be moot. The .is-off
   and .ai-shape-off rules that handled that went with it. */

/* The cost column ---------------------------------------------------------

   'credits' rides along with the number so the word wraps and aligns with it
   rather than being stranded on its own. nowrap because "8 / credits" over two
   lines in a two-column row looks like a fault. */
.ai-quote-cost {
    flex: none;
    white-space: nowrap;
    color: var(--text-muted, #8a8a8a);
}

.ai-quote-cost b {
    color: var(--text-dark, #222);
}

/* What happens if you say no to the optional line. A row of the same list, so
   it sits under the thing it is about -- but with no rule above it and no
   price, because it is not a charge.

   QUALIFIED WITH THE LIST, AND IT HAS TO BE

   .ai-quote-parts li is a class and a type, which outweighs a bare class --
   so every property the two share was being decided by the row rule and not
   by this one. The display went back to flex, and the 26px indent that ties
   the note to the checkbox above it was replaced by the row's 5px 0. It read
   as a rule that did nothing, because most of it did nothing.

   No vertical padding and a tighter line: two of these now sit in the
   analyse dialog, and the height they cost is height the buttons lose. */
.ai-quote-parts li.ai-quote-aside {
    display: block;
    padding: 0 0 4px 26px;
    font-size: 0.85rem;
    font-style: italic;
    line-height: 1.3;
    color: var(--text-muted, #8a8a8a);
}

/* Qualified with the list, because .ai-quote-parts li is more specific than a
   bare class and was winning wherever this sat in the file. */
.ai-quote-parts li.ai-quote-pick {
    padding-bottom: 2px;
}

/* What is behind a tab, on the tab ---------------------------------------- */

/* What is behind a tab, on the tab ----------------------------------------

   THE ALIGNMENT IS THE LAYOUT'S JOB, NOT THE ICON'S

   A FontAwesome glyph sitting inline never lines up with the text beside it:
   it carries its own baseline and its own line-height, and nudging it with
   vertical-align or a top offset only holds until somebody changes the font
   size. Making the tab a flex row instead puts the label and the badge on one
   centre line and keeps them there -- and the gap replaces the badge's left
   margin, which is what was pushing it too far right. */
/* gap:0 on purpose.

   The icon carries margin-right:5px and the count carries margin-left:5px,
   both deliberate and both documented where they are set. The gap was adding
   6px on top of each, so a tab's icon, its label and its tick sat 11px apart
   and stopped reading as one thing -- three items in a row rather than one
   tab with a name. The margins are the spacing; this was the accident. */
#ai-extras-tabs .nav-link {
    display: inline-flex;
    align-items: center;
    gap: 0;
}

.ai-tab-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;

    /* Off the word, and up off the baseline.

       It sat flush against the label with nothing between them, and an
       inline-flex box aligns on the baseline of its own first item -- so the
       pill hung a couple of pixels below the text it belongs to, which on a
       drawn circle reads as a mistake rather than as a choice. The lift is
       relative rather than a margin so it moves the ink without changing what
       the line reserves for it. */
    margin-left: 5px;
    position: relative;
    top: -2px;

    min-width: 18px;
    /* 19, not 18. Centring a glyph in an even-numbered box leaves it half a
       pixel low: the digit's ink is not centred on its own em box, and the
       browser has nowhere to put the remainder. An odd height gives the
       rounding somewhere to land and the number sits true. */
    height: 19px;
    padding: 0 5px;
    border-radius: 10px;
    background: var(--border, #e2e2e2);
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    color: var(--text-muted, #6b6b6b);
}

/* On the open tab it belongs to the label, so it takes the label's colour
   rather than sitting there as a grey lump on a highlighted word. */
.nav-link.active .ai-tab-count {
    background: var(--primary, #2e7d5b);
    color: #fff;
}

/* Present rather than counted: no pill, no padding, nothing for it to sit
   off-centre inside. The duotone check carries its own second tone, so the
   ring and the tick read apart where a solid one would be a blob.

   18px because that is the number badge's height. The icon IS its own circle,
   so it has to match the drawn one beside it rather than the 11px digit inside
   it -- sized to the text it replaces, it came out visibly the smaller of the
   two things claiming to be the same kind of mark. */
.ai-tab-done {
    min-width: 0;
    padding: 0;
    background: transparent;
    font-size: 18px;
    /* Its own lift: the pill above is a 19px box with an 11px digit centred
       in it, and this is an 18px glyph sitting on the baseline. The same
       offset would push it too high. */
    top: -1px;
    color: var(--logo-green, #2e7d5b);
}

/* On the open tab it stays green, and the white above it does not apply.

   .nav-link.active .ai-tab-count turns the COUNT pill into a filled primary
   lozenge with a white digit, which is right -- there is a background there
   for white to sit on. This shares that class and then takes the background
   away, so inheriting the white left a white tick on a white tab strip.

   That is why only Proofreading looked wrong: nothing was different about it
   except that it was the tab being looked at. Open Coverage instead and its
   tick vanished too.

   Green rather than the active label's --primary, because the tick is a
   status and not part of the highlight: the script HAS been proofread
   whether or not the tab is open. */
.nav-link.active .ai-tab-done {
    background: transparent;
    color: var(--logo-green, #2bb673);
}
/* The price list on the credits page -------------------------------------- */

.ai-price-intro,
.ai-price-note {
    margin: 0 0 12px;
    font-size: 0.92rem;
    line-height: 1.55;
    color: var(--text-soft, #6b6b6b);
}

.ai-price-note {
    margin: 12px 0 0;
}

.ai-price-table {
    width: 100%;
    border-collapse: collapse;
}

.ai-price-table th {
    padding: 6px 8px;
    border-bottom: 2px solid var(--border, #e2e2e2);
    text-align: left;
    font-size: 0.82rem;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--text-muted, #8a8a8a);
}

.ai-price-table td {
    padding: 10px 8px;
    border-bottom: 1px solid var(--border, #eee);
    vertical-align: top;
}

.ai-price-table tr:last-child td {
    border-bottom: 0;
}

/* The name, then what it is. Stacked rather than in two columns: the
   explanations are a sentence or two and a column of them would be a column of
   wrapped fragments. */
.ai-price-label strong {
    display: block;
    font-size: 0.95rem;
    color: var(--text-dark, #222);
}

.ai-price-what {
    display: block;
    margin-top: 3px;
    font-size: 0.88rem;
    line-height: 1.5;
    color: var(--text-soft, #6b6b6b);
}

th.ai-price-cost,
td.ai-price-cost {
    text-align: right;
    white-space: nowrap;
}

.ai-price-fixed {
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--logo-green, #2e7d5b);
}

/* A price that moves with the script's length, as a small ladder rather than a
   sentence: four lengths, four numbers, read down. */
.ai-price-scale {
    display: inline-flex;
    flex-direction: column;
    gap: 2px;
}

.ai-price-step {
    display: flex;
    align-items: baseline;
    justify-content: flex-end;
    gap: 8px;
    font-size: 0.85rem;
}

.ai-price-pages {
    color: var(--text-muted, #8a8a8a);
}

.ai-price-credits {
    min-width: 2.2em;
    font-weight: 700;
    color: var(--logo-green, #2e7d5b);
}

/* A choice belonging to an optional line ---------------------------------- */

/* Indented to the same 26px as the note above it, so the box, its explanation
   and its one setting read as one block rather than three list rows that
   happen to be adjacent. */
.ai-quote-opt {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 2px 0 6px 26px;
    font-size: 0.9rem;
}

.ai-quote-opt label {
    /* The row inherits space-between from .ai-quote-parts li, which is right
       for a name and a price at opposite ends and wrong here, where the label
       and the dropdown are one thing: it put the dialog's whole width between
       them. The auto margin absorbs that space on the left instead, so the
       pair travels to the right edge together and lines up with the column of
       prices above. */
    margin: 0 0 0 auto;
    color: var(--text-muted, #8a8a8a);
}

.ai-quote-opt select {
    /* Sized to its widest option rather than stretched: growing it would put
       the gap back, on the other side. */
    flex: none;
    max-width: 260px;
    padding: 4px 8px;
    border: 1px solid var(--border, #e6e6e6);
    border-radius: 4px;
    background: #fff;
    font-size: 0.9rem;
    cursor: pointer;
}

/* Off with the line it belongs to. A live dropdown under a dropped item
   invites a choice nothing is going to act on. */
.ai-quote-opt:has(select:disabled) {
    opacity: .55;
}

.ai-quote-opt select:disabled {
    cursor: default;
}


/* The line under the spinner while the AI works -----------------------------

   SweetAlert2 puts its loader above the html block, so this sits below it and
   needs the room. Centred and muted because it is a status, not a question --
   the dialog has no buttons and nothing is being asked. */
/* The spinner, which is ours rather than SweetAlert's -- a wait somebody is
   allowed to leave needs the confirm button, and Swal.showLoading() puts its
   spinner exactly there. See busyDialog() in js/ai-logline.js. */
.ai-busy-spin {
    margin: 4px 0 0;
    text-align: center;
    font-size: 1.6rem;
    color: var(--brand, #d4a017);
}

/* What happens if they close it. Smaller and quieter than the stage line:
   it is read once, at the start, and then never again. */
.ai-busy-note {
    margin: 18px auto 0;
    max-width: 30em;
    font-size: .82rem;
    line-height: 1.5;
    text-align: center;
    color: var(--text-muted, #8a8a8a);
    opacity: .85;
}

.ai-busy-line {
    margin: 14px 0 0;
    text-align: center;
    line-height: 1.45;
    color: var(--text-muted, #8a8a8a);
}

/* The Coverage tab with nothing in it yet ---------------------------------

   Not .ai-tab-empty, which is one grey centred line for a tab that simply has
   no content. This tab has no content because the writer has not bought any,
   which is a different situation and the only place on the card that has to
   argue for itself. Left-aligned and full width: it is read, not glanced at. */
.cv-pitch {
    padding: 6px 2px 4px;
    color: var(--text-soft, #6b6b6b);
    font-size: .93rem;
    line-height: 1.6;
}

.cv-pitch-lead {
    margin: 0 0 16px;
    color: var(--text-main, #2f2f2f);
}

.cv-pitch-sub {
    margin: 0 0 8px;
    font-weight: 600;
    color: var(--text-main, #2f2f2f);
}

.cv-pitch-list {
    margin: 0 0 16px;
    padding-left: 1.1rem;
    list-style: disc;
}

.cv-pitch-list li {
    margin-bottom: .55rem;
}

.cv-pitch-list b {
    color: var(--text-main, #2f2f2f);
    font-weight: 600;
}

/* The introductory price, which has to be legible as a temporary thing rather
   than read as the price. Tinted rather than shouted: it is good news, and a
   warning colour would make a cheap price look like a problem. */
.cv-pitch-promo {
    margin: 0 0 14px;
    padding: 10px 12px;
    border-left: 3px solid var(--brand, #d4a017);
    background: rgba(212, 160, 23, .07);
    border-radius: 3px;
    font-size: .88rem;
    color: var(--text-main, #2f2f2f);
}

.cv-pitch-promo i {
    margin-right: 6px;
    color: var(--brand, #d4a017);
}

/* The last word is about keeping them, so it sits apart from the list of what
   one contains. */
.cv-pitch-foot {
    margin: 0;
    padding-top: 12px;
    border-top: 1px solid var(--border-soft, #e6e6e6);
    font-size: .88rem;
}

/* Coverage -----------------------------------------------------------------

   A reader's report. Longer than anything else here and read differently: the
   verdict is glanced at, the prose once, and the quotations are what a writer
   comes back to -- so each one stays beside the paragraph that earned it. */

.cv-verdict {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding: 12px 16px;
    border-radius: 8px;
    margin-bottom: 14px;
}

.cv-verdict-word {
    font-size: 1.15rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
}

.cv-verdict-score {
    font-size: 1.5rem;
    font-weight: 700;
    white-space: nowrap;
}

/* The verdict and its score on the SHUT panel.

   The one thing anybody reads before deciding which report to open, so it is
   sized to be read at a glance down a stack of three rather than to sit
   politely inside the grey line it shares. Well above .ai-panel-meta's .82rem
   and above the title's .95rem too -- on this panel the judgement outranks the
   word 'Coverage', which is only there to say what kind of thing it is.

   The date that used to sit beside it is in the title now, and the draft is
   gone altogether, so this has the line largely to itself. */
.cv-meta-lead {
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.2;
}

/* Five, and they have to read as a ladder rather than five unrelated states:
   grey at the bottom, through amber, to green. */
.cv-meta-lead--recommend       { color: #17683a; }
.cv-meta-lead--consider-strong { color: #4a7a2c; }
.cv-meta-lead--consider        { color: #7a5c00; }
.cv-meta-lead--consider-weak   { color: #8a6a2f; }
.cv-meta-lead--pass            { color: #5b5b5b; }

/* The five answers mean different things and should not look alike. The two
   qualified Considers sit either side of the plain one rather than beside it:
   a Strong Consider is nearer a Recommend than it is to a Weak one. */
.cv-verdict--recommend       { background: #e6f4ea; color: #17683a; }
.cv-verdict--consider-strong { background: #eef4e4; color: #4a7a2c; }
.cv-verdict--consider        { background: #fdf3d8; color: #7a5c00; }
.cv-verdict--consider-weak   { background: #f8f1e2; color: #8a6a2f; }
.cv-verdict--pass            { background: #f2f2f2; color: #5b5b5b; }

.cv-cat-of {
    font-size: .7em;
    font-weight: 500;
    opacity: .65;
}

/* Form, genre and length. Sized with the paragraphs above them now that they
   live in the Overview box -- at .85rem they read as a caption under four
   sections of 1.1rem prose, which is the one thing they are not. */
.cv-facts {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 20px;
    margin-bottom: 10px;
    font-size: 1.05rem;
    line-height: 1.5;
    color: var(--text-soft, #555);
}

/* The label, quieter than the value it introduces -- the reverse of how it
   read when the whole line was grey. */
.cv-fact b {
    color: var(--text-muted, #8a8a8a);
    font-weight: 600;
    margin-right: 5px;
}

/* What the report says before it starts scoring: what this script IS, at four
   lengths. Everything below it is about how well it is written.

   Slate, not gold. The first version of this was warm cream with a gold left
   edge, which is exactly what .cv-standout wears -- so the box that says what
   the script IS and the box that says what the writer is BEST at read as the
   same kind of thing, sitting one above the other. Gold is spoken for; this is
   a cool grey-blue, distinct from the standout above it, from the blue
   .cv-format note, and from the near-white boxes further down. */
.cv-overview-box {
    margin: 0 0 18px;
    padding: 12px 16px 14px;
    border: 1px solid #d9dfe4;
    border-left: 4px solid #5b7c93;
    border-radius: 6px;
    background: #f6f8fa;
}

/* Ruled off, so the title reads as the box's own and not as a label on the
   logline directly under it. */
.cv-overview-title {
    margin-bottom: 12px;
    padding-bottom: 8px;
    border-bottom: 1px solid #e1e7eb;
}

.cv-overview-title .cv-cat-name i {
    margin-right: 7px;
    color: #5b7c93;
}

/* The headings inside it take the box's colour rather than the site gold, so
   the block reads as one thing. */
.cv-overview-box .cv-box-head i {
    color: #5b7c93;
}

/* The form, genre and length chips, now the last thing in the box and sitting
   on its tint. Whatever bottom margin they carried loose on the page is the
   box's padding now. */
.cv-overview-box .cv-facts {
    margin-bottom: 0;
}

/* The label on a box. Big enough to be read rather than squinted at, and no
   longer uppercase -- at this size the tracking that made small caps legible
   turns into a stretched-out banner competing with the category headings. */
.cv-box-head {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin: 0 0 7px;
    font-size: 1.1rem;
    font-weight: 700;
    letter-spacing: 0;
    color: var(--color-text-body);
}

/* Fixed width so the headings line up with each other down the report, and
   quieter than the words it introduces. */
.cv-box-head i {
    flex: 0 0 1.1em;
    color: var(--brand, #d4a017);
    font-size: .95em;
}

.cv-box-head + .cv-logline,
.cv-box-head + .cv-overview {
    margin-top: 0;
}

/* Every heading after the first wants space above it, away from the paragraph
   it follows. The first one is already clear of the title's rule. */
.cv-overview-title ~ .cv-box-head {
    margin-top: 14px;
}

.cv-overview-title + .cv-box-head {
    margin-top: 0;
}

.cv-logline {
    margin: 0 0 14px;
    font-size: 1.1rem;
    font-style: italic;
    line-height: 1.5;
    color: var(--text-dark, #333);
}

/* The same gap under it as under the logline, because it is no longer the last
   thing in the box -- the comparables and the audience follow it now, and their
   headings were sitting straight against the paragraph above.

   Whichever paragraph ends up last loses the margin below, so the box does not
   carry a gap its padding already provides. :last-child rather than a class,
   because which one is last depends on what the report returned. */
.cv-overview {
    margin: 0 0 14px;
    font-size: 1.1rem;
    line-height: 1.55;
}

.cv-overview-box > p:last-child {
    margin-bottom: 0;
}

/* All seven scores at a glance, above the seven that explain themselves.

   Boxed like the Overview, and neutral: this one is a table of contents for
   the section under it rather than a thing with an argument of its own, so it
   takes the plain near-white and lets the bars carry all the colour. */
.cv-summary {
    margin: 0 0 18px;
    padding: 12px 16px 14px;
    border: 1px solid var(--border, #e6e6e6);
    border-radius: 6px;
    background: #fcfcfc;
}

.cv-summary-title {
    margin-bottom: 10px;
    padding-bottom: 8px;
    border-bottom: 1px solid #ededed;
}

.cv-summary-title .cv-cat-name i {
    margin-right: 7px;
    color: var(--text-muted, #8a8a8a);
}

/* Three columns, so the names end together and every bar starts on the same
   line -- which is the whole point of putting them in a column. auto for the
   name rather than a fixed width: the longest is Marketability and it should
   set the measure rather than a number somebody guessed. */
.cv-sum-grid {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: 7px 12px;
}

/* Each row is three cells of the same grid rather than a box of its own, or
   the columns could not line up across rows. */
.cv-sum-row {
    display: contents;
}

.cv-sum-name {
    font-size: .95rem;
    font-weight: 600;
    letter-spacing: .02em;
    text-transform: uppercase;
    color: var(--text-soft, #555);
    white-space: nowrap;
}

.cv-sum-bar {
    display: block;
    height: 9px;
    border-radius: 5px;
    background: #ececec;
    overflow: hidden;
}

.cv-sum-bar > span {
    display: block;
    height: 100%;
    border-radius: 5px;
}

.cv-sum-score {
    font-size: 1.1rem;
    font-weight: 700;
    line-height: 1;
    white-space: nowrap;
    text-align: right;
}

/* The same bands as the cards below, from the same coverageBand(). */
.cv-sum-row--broken .cv-sum-bar > span { background: #c0392b; }
.cv-sum-row--weak   .cv-sum-bar > span { background: #e07b39; }
.cv-sum-row--fair   .cv-sum-bar > span { background: #c9a84c; }
.cv-sum-row--good   .cv-sum-bar > span { background: #4a9d5f; }
.cv-sum-row--strong .cv-sum-bar > span { background: #1f7a4d; }
.cv-sum-row--none   .cv-sum-bar > span { background: #ccc; }

.cv-sum-row--broken .cv-sum-score { color: #c0392b; }
.cv-sum-row--weak   .cv-sum-score { color: #e07b39; }
.cv-sum-row--fair   .cv-sum-score { color: #a8862c; }
.cv-sum-row--good   .cv-sum-score { color: #4a9d5f; }
.cv-sum-row--strong .cv-sum-score { color: #1f7a4d; }
.cv-sum-row--none   .cv-sum-score { color: #999; }

/* Two columns on anything roomy: seven rows is a lot of vertical space for a
   thing whose whole job is to save scrolling. */
@media (min-width: 620px) {
    .cv-sum-grid {
        grid-template-columns: auto 1fr auto auto 1fr auto;
        column-gap: 12px;
    }
}

/* The scoreboard, one category to a row.

   It was three across, which was chosen so the eye could compare scores rather
   than read them in order -- but there are seven categories, and seven does not
   divide by three. The last one sat alone on a line looking like an afterthought
   at whatever width the grid gave it, and the assessments underneath had grown
   to a paragraph each, which is not something to read in a 300px column.

   Full width gives the prose a sensible measure and puts the seven scores in a
   single vertical line down the left edge, which compares them better than three
   columns ever did. */
.cv-cats {
    display: grid;
    grid-template-columns: 1fr;
    gap: 14px;
    margin-bottom: 18px;
}

.cv-cat {
    padding: 12px 14px;
    border: 1px solid var(--border, #e6e6e6);
    border-left-width: 4px;
    border-radius: 6px;
    background: #fcfcfc;
}

.cv-cat-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
}

/* Full width made these the headings of the report rather than labels on a
   card in a grid, so they are sized as headings. The letter-spacing comes down
   with the size going up: tracking that opens up small uppercase type starts
   to look thin and stretched once the type is this big. */
.cv-cat-name {
    font-weight: 700;
    font-size: 1.2rem;
    letter-spacing: .03em;
    text-transform: uppercase;
    color: var(--text-soft, #555);
}

/* Kept clearly above the name beside it. The score is the thing being read
   down the column; the category is what it is about. */
.cv-cat-score {
    font-size: 1.6rem;
    font-weight: 700;
    line-height: 1;
    white-space: nowrap;
}

.cv-bar {
    height: 4px;
    margin: 8px 0 10px;
    border-radius: 2px;
    background: #ececec;
    overflow: hidden;
}

.cv-bar span {
    display: block;
    height: 100%;
}

/* The bands the prompt defines, so what a writer sees and what the model was
   told cannot drift apart. */
.cv-cat--broken { border-left-color: #c0392b; }
.cv-cat--weak   { border-left-color: #e07b39; }
.cv-cat--fair   { border-left-color: #c9a84c; }
.cv-cat--good   { border-left-color: #4a9d5f; }
.cv-cat--strong { border-left-color: #1f7a4d; }
.cv-cat--none   { border-left-color: #ccc; }

.cv-cat--broken .cv-bar span { background: #c0392b; }
.cv-cat--weak   .cv-bar span { background: #e07b39; }
.cv-cat--fair   .cv-bar span { background: #c9a84c; }
.cv-cat--good   .cv-bar span { background: #4a9d5f; }
.cv-cat--strong .cv-bar span { background: #1f7a4d; }

/* The argument for the score, which is the part a writer actually reads --
   five to eight sentences of it. Sized to be read rather than scanned. */
.cv-cat-text {
    margin: 0;
    font-size: 1.1rem;
    line-height: 1.55;
    color: var(--text-soft, #555);
}

/* The evidence, three across.

   The prompt asks for two or three quotations per category, so three is the
   real maximum rather than an arbitrary one. flex-grow lets two fill the row
   between them rather than leaving a third of it blank, and the min-width drops
   them to two-up and then one-up on a narrow card without a media query --
   these appear inside a dashboard panel whose width is not the window's. */
.cv-evidences {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 10px;
    align-items: stretch;
}

.cv-evidences .cv-evidence {
    flex: 1 1 calc(33.333% - 7px);
    min-width: 220px;
    margin: 0;
}

/* The line from the script. Monospaced, because it is a quotation from a
   document and not the report's own voice. */
.cv-evidence {
    margin: 10px 0 0;
    padding: 8px 10px;
    border-left: 3px solid var(--border, #ddd);
    background: #fff;
    font-family: ui-monospace, "Courier New", monospace;
    font-size: .82rem;
    line-height: 1.45;
    color: var(--text-dark, #444);
}

.cv-evidence cite {
    display: block;
    margin-top: 4px;
    font-family: inherit;
    font-style: normal;
    font-size: .95em;
    color: var(--text-muted, #999);
}

.cv-columns {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 14px;
    margin-bottom: 18px;
}

.cv-list h4 {
    margin: 0 0 8px;
    font-size: .82rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--text-soft, #555);
}

.cv-list ul {
    margin: 0;
    padding-left: 18px;
}

.cv-list li {
    margin-bottom: 7px;
    font-size: .93rem;
    line-height: 1.5;
}

.cv-list--good li::marker { color: #4a9d5f; }
.cv-list--bad li::marker  { color: #e07b39; }

/* The one thing a writer should leave with. Everything above it is the
   argument for this.

   It was --bg-light, which is a hair off the page behind it -- so the most
   actionable sentence in the report sat in a box you could barely see. Coral,
   which is --primary and already the colour of the step areas in the plan
   underneath: this is the imperative, and the plan is how to carry it out. */
.cv-note {
    padding: 12px 16px;
    border: 1px solid #f0d2cd;
    border-left: 4px solid var(--primary, #e85347);
    border-radius: 8px;
    background: #fdf2f0;
    margin-bottom: 16px;
}

.cv-note .cv-box-head i {
    color: var(--primary, #e85347);
}

/* Its heading is a .cv-box-head like every other box now. There is no
   '.cv-note h4' rule any more ON PURPOSE: an element selector inside a class
   beats a bare class, so it would have quietly won every argument with
   .cv-box-head and kept this one heading small and uppercase while the rest
   grew. Same reason .cv-plan h4 is gone. */
.cv-note-text {
    margin: 0;
    font-size: 1.02rem;
    line-height: 1.55;
}

/* The three closing notes as a group. It has never had a rule of its own --
   the paragraphs it used to hold carried their own spacing -- and the boxes now
   inside it want a gap above them, away from the What To Do Next list. */
.cv-tails {
    margin-top: 18px;
}

/* The closing note. Its own class rather than a second .cv-note rule -- there
   was one of those for a while, and two rules for one name is how a box ends
   up with whichever background happened to be written last. */
.cv-aside {
    margin: 0 0 10px;
    padding: 12px 14px;
    border: 1px solid var(--border, #e6e6e6);
    border-radius: 6px;
    background: #fcfcfc;
}

.cv-aside:last-child {
    margin-bottom: 0;
}

.cv-aside-text {
    margin: 0;
    font-size: 1.02rem;
    line-height: 1.5;
    color: var(--text-soft, #555);
}

/* The one that admits a limit. Tinted rather than greyed: it is the most
   honest paragraph in the report and should not look like the least. */
.cv-aside--caveat {
    border-color: #e6dcc0;
    background: #fdfaf2;
}

.cv-aside--caveat .cv-box-head i {
    color: #b08a2e;
}

/* The moments worth stopping on, in page order. Read with the script open
   beside it, which is why the page number is the thing that stands out. */
.cv-scenes {
    margin-bottom: 18px;
}

.cv-scenes h4,

.cv-scene {
    display: flex;
    gap: 12px;
    padding: 8px 0;
    border-bottom: 1px solid var(--border, #eee);
}

.cv-scene:last-child {
    border-bottom: 0;
}

.cv-scene-page {
    flex: none;
    width: 46px;
    font-family: ui-monospace, "Courier New", monospace;
    font-size: .82rem;
    color: var(--text-muted, #999);
    padding-top: 2px;
}

.cv-scene-body {
    font-size: .93rem;
    line-height: 1.5;
}

/* The plan. Numbered, and in the order the work should be done -- structural
   before line, because a line polished in a scene that gets cut is wasted. */
.cv-plan {
    padding: 14px 16px;
    border: 1px solid var(--border, #e6e6e6);
    border-radius: 8px;
    background: #fcfcfc;
    margin-bottom: 16px;
}

.cv-plan ol {
    margin: 0;
    padding-left: 20px;
}

.cv-plan li {
    margin-bottom: 14px;
}

.cv-plan li:last-child {
    margin-bottom: 0;
}

.cv-step-head {
    display: flex;
    gap: 8px;
    align-items: center;
    margin-bottom: 4px;
}

/* Which part of the script this job is about. */
.cv-step-area {
    font-size: .88rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--primary, #e85347);
}

/* What it costs to do, which is half of whether it gets done. Sized with the
   area beside it so the pair reads as one line rather than a label and a
   footnote. */
.cv-step-effort {
    font-size: .86rem;
    padding: 2px 9px;
    border-radius: 10px;
    background: var(--bg-light, #f0f0f0);
    color: var(--text-muted, #777);
}

.cv-step-change {
    margin: 0 0 4px;
    font-weight: 600;
    line-height: 1.5;
}

.cv-step-why,
.cv-step-where {
    margin: 0 0 3px;
    font-size: .89rem;
    line-height: 1.5;
    color: var(--text-soft, #666);
}

.cv-step-where {
    font-family: ui-monospace, "Courier New", monospace;
    font-size: .8rem;
    color: var(--text-muted, #999);
}

/* The best thing about the script -------------------------------------------

   Under the verdict, because a writer opening a report that says Consider is
   braced for what is wrong and will not go looking for what is right. Scores
   between four and seven all look alike at a glance; this is the sentence that
   says which instinct to trust through the rewrite. */
.cv-standout {
    padding: 12px 16px;
    margin-bottom: 14px;
    border: 1px solid #d8c88a;
    border-left: 4px solid var(--gold, #c9a84c);
    border-radius: 8px;
    background: #fdfaf0;
}

.cv-standout-head {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .74rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: #8a6d1f;
    margin-bottom: 6px;
}

.cv-standout-cat {
    padding: 1px 8px;
    border-radius: 10px;
    background: var(--gold, #c9a84c);
    color: #3a2f0b;
    letter-spacing: .04em;
}

.cv-standout-claim {
    margin: 0;
    font-size: 1rem;
    line-height: 1.55;
    color: var(--text-dark, #333);
}

/* And the card it belongs to, so the badge and the sentence agree. */
.cv-cat--best {
    border-color: #d8c88a;
    border-left-color: var(--gold, #c9a84c);
    background: #fffdf6;
}

.cv-cat--best .cv-cat-name i {
    color: var(--gold, #c9a84c);
}

/* What the report was read from, and when ----------------------------------

   Above the verdict. Coverage is an opinion about a particular set of pages on
   a particular day, and a report that does not say which pages is one nobody
   can argue with -- or trust six months later, having forgotten which draft
   they submitted. */
/* What was read, and when. It was .82rem, which is a footnote size for a line
   carrying the draft, the page count and the format the report judged it as --
   the three facts that decide whether the rest of it applies to the script the
   writer has now. */
.cv-read {
    margin: 0 0 12px;
    font-size: .98rem;
    line-height: 1.5;
    color: var(--text-muted, #8a8a8a);
}

.cv-read b {
    color: var(--text-soft, #666);
}

/* Still worth reading, and must not pretend the pages have not moved. */
.cv-read--stale {
    padding: 8px 10px;
    border-left: 3px solid var(--warning, #e0a800);
    background: #fffaf0;
    border-radius: 4px;
}

.cv-read-warn {
    display: block;
    margin-top: 5px;
    font-size: .95rem;
    color: #8a6d1f;
    font-weight: 600;
}

.cv-read-warn i {
    margin-right: 5px;
}

/* Who wrote it -------------------------------------------------------------

   The difference between a machine's opinion and one a reader has stood behind
   is the whole of what a human review is sold as, so a writer must never have
   to guess which they are looking at. */
.cv-by {
    display: inline-block;
    margin-right: 8px;
    padding: 1px 8px;
    border-radius: 10px;
    background: var(--bg-light, #f0f0f0);
    color: var(--text-muted, #777);
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
}

.cv-by--human {
    background: #e6f4ea;
    color: #17683a;
}

.cv-by--waiting {
    background: #fdf3d8;
    color: #7a5c00;
}

/* The author's way to be rid of a report -----------------------------------

   At the foot of the report rather than on its header line: a stack of three
   all carry one, and a trash can beside a collapsed title is a click away from
   deleting the wrong one. */
/* The author's controls, above the report ----------------------------------

   A header rather than a footer, so the border and the spacing are on the
   underside: this row introduces the report rather than closing it off.

   A flex row rather than text-align, because the share control stops being
   a button and becomes a row of its own once there is a link in it. */
/* The AI Extras panes, and the bottom padding they are allowed only while one
   of them is open.

   This was an inline padding:0 10px 10px on the container. With every tab shut
   -- which switchAiTab() now allows -- the panes contribute no height and that
   bottom 10px was the whole of what was left: a bare strip hanging under the
   tab bar with nothing in it. The Script Elements widget never had the problem
   because its container carries no bottom padding at all.

   :has() rather than a class the script toggles, because the question is about
   what is in the markup and the markup already answers it. That also covers
   the state the server renders, without the page having to be told twice. */
.ai-extras-panes {
    padding: 0 10px 10px;
}

/* No bottom padding while the widget is shut.

   That 10px is for the panes; with none of them open it is added to the 10px
   the hint line already carries below itself, and the line sits 10 above / 20
   below instead of centred. The Script Elements container has no bottom
   padding at all, which is why it looked right and this did not.

   This rule existed before the hint line did, to stop a bare strip hanging
   under the tab bar, and was then written as :not(:has(> .tabs-hint)) so it
   would stand down once there was something in that space. That was wrong on
   its own terms -- :has() asks whether the element is PRESENT, and the hint is
   always in the markup and merely hidden -- so the rule could never fire. It
   is the plain question again, which is the one that was wanted both times. */
.ai-extras-panes:not(:has(> .tab-pane.active)) {
    padding-bottom: 0;
}

/* ---- the closed state, and how anybody finds out about it --------------- */

/* The line that only exists while every tab is shut.

   Hidden by default and revealed by the absence of an open pane, so nothing
   has to tell it -- the same :has() question the padding above asks, and it
   covers the state the server renders as well as the one a click produces.

   It is here to make the closed widget legible: a head, a row of tabs and
   nothing else reads as something that failed to load. It cannot teach the
   CLOSING half, because nobody sees it until they have already closed
   something. The caret below is what does that. */
.tabs-hint {
    display: none;
    margin: 0;
    padding: 10px 2px;
    font-size: 13px;
    color: var(--text-muted, #8a8a8a);
}

.ai-extras-panes:not(:has(> .tab-pane.active)) > .tabs-hint,
.elements-panes:not(:has(> .tab-pane.active)) > .tabs-hint,
.media-panes:not(:has(> .tab-pane.active)) > .tabs-hint {
    display: block;
}

/* A caret on the open tab, pointing at the thing it will fold away.

   This is the half of the gesture nobody would guess at. A tab bar says
   'these are the choices'; it does not say 'and the one you are on will close
   if you press it again', and a title attribute only says so to somebody who
   already hovered and waited.

   A character rather than a Font Awesome glyph in ::after: the kit is loaded
   by name and weight and a pseudo-element that guesses either of those wrong
   renders a blank box. U+25B4 is in every font that will ever draw this page. */
/* The media widget is drawn three times on the site -- script, idea, project --
   so its strips are matched by a suffix rather than named one at a time. */
#ai-extras-tabs .nav-link.active::after,
#script-elements-tabs .nav-link.active::after,
ul[id$="-media-tabs"] .nav-link.active::after {
    content: "▲";
    margin-left: 6px;
    font-size: .75em;
    opacity: .8;
}

/* The bottom padding stays now, in every state.

   It was dropped when no tab was open, because what was left was a bare strip
   under the tab bar. The hint line lives in that space now, so the padding is
   the room it sits in rather than a gap. */

/* The line at the top of a panel that lets its contents be thrown away.

   One rule for all five -- coverage aside, which shares its row with Share
   this report -- so the bin is in the same place and the same shape whichever
   panel somebody is looking at.

   Right-aligned: it is the least likely thing anybody wants from the panel, so
   it sits away from the left margin where the eye lands, while staying on the
   first line where it can be found at all. The rule below it separates it from
   the content it governs. */
.ai-delete-row {
    display: flex;
    justify-content: flex-end;
    margin-bottom: 12px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--border, #eee);
}

.cv-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 18px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--border, #eee);
}

/* The offer ----------------------------------------------------------------

   Deliberately quieter than a primary button. Publishing coverage is a
   thing a writer should do on purpose, having decided to, and not because
   the brightest thing on the report invited them to. */
.cv-share {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 5px 12px;
    border: 1px solid var(--border, #e6e6e6);
    border-radius: 6px;
    background: #fff;
    color: var(--text-soft, #555);
    font-size: .82rem;
    cursor: pointer;
    transition: color .15s ease, border-color .15s ease;
}

.cv-share:hover {
    color: #17683a;
    border-color: #17683a;
}

/* The link, once it exists -------------------------------------------------

   Tinted, because a report with a public address is in a different state
   from one without and the writer should be able to see that from across
   the page rather than by reading a button. Green: the same colour the
   Recommend verdict uses, and the same thing it means here -- live. */
.cv-shared {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    flex: 1 1 320px;
    padding: 7px 10px;
    border: 1px solid #cfe4d6;
    border-radius: 6px;
    background: #f2f9f4;
}

.cv-shared-icon { color: #17683a; }

/* An input rather than text, so it can be selected on a phone where the
   copy button is not always how somebody chooses to do it. Styled to look
   like the line of text it is. */
.cv-share-url {
    flex: 1 1 200px;
    min-width: 0;
    padding: 3px 6px;
    border: 1px solid #dfece3;
    border-radius: 4px;
    background: #fff;
    color: var(--text-soft, #555);
    font-family: ui-monospace, "Courier New", monospace;
    font-size: .78rem;
}

.cv-share-copy,
.cv-share-revoke {
    padding: 4px 9px;
    border: 1px solid #cfe4d6;
    border-radius: 5px;
    background: #fff;
    color: var(--text-soft, #666);
    font-size: .82rem;
    cursor: pointer;
    transition: color .15s ease, border-color .15s ease;
}

.cv-share-copy:hover   { color: #17683a; border-color: #17683a; }
.cv-share-revoke:hover { color: var(--danger, #e85347); border-color: var(--danger, #e85347); }

/* The first question anybody who sends a link asks. */
.cv-share-views {
    font-size: .78rem;
    color: var(--text-muted, #8a8a8a);
    white-space: nowrap;
}

@media (max-width: 620px) {
    .cv-actions { justify-content: flex-start; }
    .cv-shared  { flex: 1 1 100%; }
}

.cv-delete {
    padding: 5px 12px;
    border: 1px solid var(--border, #e6e6e6);
    border-radius: 6px;
    background: #fff;
    color: var(--text-muted, #999);
    font-size: .82rem;
    cursor: pointer;
    transition: color .15s ease, border-color .15s ease;
}

.cv-delete:hover {
    color: var(--danger, #e85347);
    border-color: var(--danger, #e85347);
}

/* When the pages and the filing disagree -----------------------------------

   Above the verdict and the standout, because it changes how everything under
   it should be read. A report that judged a feature as a pilot is not wrong so
   much as answering a different question. */
.cv-format {
    display: flex;
    gap: 10px;
    padding: 12px 14px;
    margin-bottom: 14px;
    border: 1px solid #cfe0ee;
    border-left: 4px solid #3d7ea6;
    border-radius: 8px;
    background: #f4fafd;
    font-size: .93rem;
    line-height: 1.55;
}

.cv-format i {
    color: #3d7ea6;
    padding-top: 3px;
}

.cv-format b {
    display: block;
    margin-bottom: 3px;
    font-size: .74rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #2c6183;
}

/* Proofreading ---------------------------------------------------------------

   A report of errors rather than an argument, so it is drawn as a list and not
   as prose. The volume is the whole design problem: four hundred findings is a
   wall, and the tabs above these rules are what turn it into five short lists. */

.pr-total {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin: 0 0 14px;
}

.pr-total-n {
    font-size: 1.9rem;
    font-weight: 700;
    line-height: 1;
    color: var(--color-text-body);
}

.pr-total-w {
    font-size: 1rem;
    color: var(--text-muted, #8a8a8a);
}

/* Pages that were not read. Said near the top and coloured like a warning,
   because a writer who believes the whole script was checked has been misled by
   an omission. */
.pr-gap {
    display: flex;
    gap: 10px;
    margin: 0 0 14px;
    padding: 11px 13px;
    border: 1px solid #e6dcc0;
    border-left: 4px solid #d4a017;
    border-radius: 6px;
    background: #fdfaf2;
    font-size: 1rem;
    line-height: 1.5;
}

.pr-gap i { color: #b08a2e; }

.pr-tabs {
    margin-bottom: 10px;
}

.pr-tabs .nav-link i {
    margin-right: 6px;
    opacity: .7;
}

.pr-blurb {
    margin: 0 0 12px;
    font-size: .95rem;
    line-height: 1.5;
    color: var(--text-muted, #8a8a8a);
}

/* One finding. The page number runs down the left because that is what a writer
   scans to find their place; the quotation gets the weight because it is the
   thing being talked about. */
/* Padded on the sides as well, so a tinted row has an edge to sit inside
   rather than running into the panel wall. Every finding carries it, handled
   or not, or the tinted ones would sit 8px right of the rest. */
.pr-find {
    display: flex;
    gap: 12px;
    padding: 10px 8px;
    border-top: 1px solid #f0f0f0;
}

.pr-find:first-of-type { border-top: none; }

.pr-find-where {
    flex: 0 0 62px;
    text-align: right;
    padding-top: 2px;
}

.pr-find-page {
    display: block;
    font-size: 1rem;
    font-weight: 700;
    color: var(--color-text-body);
}

.pr-find-el {
    display: block;
    font-size: .72rem;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--text-muted, #aaa);
}

.pr-find-body { flex: 1 1 auto; min-width: 0; }

/* Monospaced for the same reason the coverage evidence is: it is a quotation
   from a document, not the report's own voice. */
.pr-find-quote {
    margin: 0 0 5px;
    padding: 6px 10px;
    border-left: 3px solid #e0e0e0;
    background: #fafafa;
    font-family: ui-monospace, "Courier New", monospace;
    font-size: .88rem;
    line-height: 1.45;
    color: var(--text-dark, #444);
    overflow-wrap: anywhere;
}

.pr-find-note {
    margin: 0;
    font-size: 1rem;
    line-height: 1.5;
    color: var(--text-soft, #555);
}

.pr-find-fix {
    display: flex;
    gap: 7px;
    margin: 5px 0 0;
    font-size: 1rem;
    line-height: 1.5;
    color: #1f7a4d;
}

.pr-find-fix i { padding-top: 4px; opacity: .8; }
.pr-find-fix span { font-weight: 600; }

/* Severity, on the quotation's edge only. A whole row tinted red for a missing
   comma reads as an emergency. */
.pr-find--high .pr-find-quote   { border-left-color: #c0392b; }
.pr-find--medium .pr-find-quote { border-left-color: #e0a800; }
.pr-find--low .pr-find-quote    { border-left-color: #d0d0d0; }

/* The icon on an AI Extras tab. Quieter than the label -- it is there to make
   the row scannable, not to compete with the word it sits beside. Comes up to
   full strength on the open tab, where it is part of the highlight. */
/* Close to the label. The icon and the word are one thing -- a gap wide enough
   to read as a separator makes the icon look like it belongs to the tab before
   it. */
.ai-tab-icon {
    margin-right: 5px;
    opacity: .55;
}

.nav-link.active .ai-tab-icon {
    opacity: 1;
}

/* The AI Extras tab row, and the tabs inside a proofreading report -----------

   Four tabs with an icon and a badge each, at the site's 18px nav-link with
   12px/16px padding, is a wide row -- and the AI Extras widget sits inside a
   card inside a column, so it runs out of width long before the window does.
   These are tighter than the site default on purpose, and tighter again as the
   window narrows, because the alternative is a tab row that wraps to two lines
   and stops reading as a row at all. */
#ai-extras-tabs {
    gap: 0;
    flex-wrap: wrap;
}

#ai-extras-tabs .nav-link,
.pr-tabs .nav-link {
    /* 17px rather than the 16 this was first cut to. The row had to lose width
       somewhere and the type was the wrong place to take it from -- these are
       the headings of the whole widget. The padding pays for it instead, which
       costs nothing legible: the tabs are separated by their own text, not by
       the air around it. */
    padding: 10px 9px;
    font-size: 17px;
}

.pr-tabs {
    gap: 0;
    flex-wrap: wrap;
}

@media (max-width: 900px) {

    #ai-extras-tabs .nav-link,
    .pr-tabs .nav-link {
        padding: 9px 7px;
        font-size: 15px;
    }

    .ai-tab-icon {
        margin-right: 4px;
    }

    .ai-tab-count {
        margin-left: 4px;
    }
}

/* Narrower still: the icon is doing the identifying by now, and the labels are
   what has to give. */
@media (max-width: 620px) {

    #ai-extras-tabs .nav-link,
    .pr-tabs .nav-link {
        padding: 8px 5px;
        font-size: 14px;
    }

    .ai-tab-icon {
        margin-right: 3px;
        opacity: .75;
    }
}

/* A finding somebody has dealt with ------------------------------------------

   Shown rather than removed. A list that quietly drops what has been done
   cannot answer "how much is left", and a writer who thumbed the wrong row
   has to be able to find what they did.

   The same three colours as the editor's sidebar, which is where these get
   set. The writer marks a finding in one place and reads it back in the
   other, and a tick that is green over there and grey over here is two
   different facts as far as anybody looking can tell.

   It was opacity .55 and a strikethrough, which is the treatment the sidebar
   started with and abandoned for the same reason: three quiet signals that
   all said the same thing, none of which announced itself, and a struck-out
   monospace quotation nobody could read -- on a page whose whole job is
   showing the writer what was found. */
.pr-find--fixed,
.pr-find--noted,
.pr-find--ignored {
    border-radius: 4px;
}

.pr-find--fixed {
    background: #eef7f0;
    box-shadow: inset 3px 0 0 #1f7a4d;
}

/* Amber: noted is not a finished thing. The writer took it on and has still
   to do it -- see classes/proofreadFinding.php. */
.pr-find--noted {
    background: #fdf7ea;
    box-shadow: inset 3px 0 0 #c08a2e;
}

.pr-find--ignored {
    background: #f5f5f5;
    box-shadow: inset 3px 0 0 #b8b8b8;
}

/* The quotation has a pale ground of its own, which over a tint reads as a
   white patch stuck on the row. Translucent instead, so it still lifts off
   the background but the state colour comes through it. */
.pr-find--fixed .pr-find-quote,
.pr-find--noted .pr-find-quote,
.pr-find--ignored .pr-find-quote {
    background: rgba(255, 255, 255, .55);
}

/* Quieter, not unreadable. The row is done, not gone. */
.pr-find--fixed .pr-find-note,
.pr-find--fixed .pr-find-fix,
.pr-find--noted .pr-find-note,
.pr-find--noted .pr-find-fix,
.pr-find--ignored .pr-find-note,
.pr-find--ignored .pr-find-fix {
    opacity: .7;
}

.pr-find-state {
    margin: 5px 0 0;
    font-size: .92rem;
    font-weight: 600;
}

.pr-find-state i { margin-right: 5px; }

.pr-find-state--fixed   { color: #1f7a4d; }
.pr-find-state--noted   { color: #96681c; }
.pr-find-state--ignored { color: var(--text-muted, #8a8a8a); }

/* Progress, beside the number that leads. */
.pr-total-done {
    display: block;
    font-size: .85rem;
    color: var(--text-muted, #8a8a8a);
}

/* ===========================================================================
   THE PUBLISHED COVERAGE PAGE  (pages/coverageshare.php)

   A coverage report at an address with no login behind it. The reader is a
   stranger who was sent a link -- a producer, a manager, a competition -- and
   very often on a phone.

   Everything below the hero is drawn by the same renderCoverage() the
   Coverage tab uses, and inherits .cv-* untouched. These rules are only the
   page around it: what a script is, above the opinion of it.
   =========================================================================== */

.cvs-page {
    max-width: 1040px;
    margin: 0 auto;
    padding: 28px 18px 60px;
}

/* What is being judged, before the judgement -------------------------------

   The poster earns its place here in a way it does not on a list. A reader
   who has been sent a link has no idea what they are looking at, and a score
   out of 100 attached to a title alone is a number about nothing. */
.cvs-hero {
    display: flex;
    align-items: flex-start;
    gap: 26px;
    margin-bottom: 26px;
}

.cvs-poster {
    flex: 0 0 190px;
}

.cvs-poster img {
    width: 100%;
    border-radius: 8px;
    border: 1px solid var(--border, #e0e0e0);
    display: block;
}

.cvs-herometa {
    flex: 1 1 auto;
    min-width: 0;
}

.cvs-title {
    margin: 0 0 6px;
    font-family: 'Playfair Display', Georgia, serif;
    font-size: 2.1rem;
    line-height: 1.15;
    color: var(--color-text-body, #2c3e50);
}

.cvs-episode {
    margin: 0 0 6px;
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--text-soft, #555);
}

.cvs-episode i { margin-right: 6px; opacity: .7; }

/* Type, length and author. Context for the score rather than a headline --
   a 45-page pilot and a 120-page feature are not judged by the same rules. */
.cvs-facts {
    margin: 0 0 12px;
    font-size: .95rem;
    color: var(--text-muted, #8a8a8a);
    text-transform: uppercase;
    letter-spacing: .04em;
}

.cvs-logline {
    margin: 0 0 10px;
    font-size: 1.12rem;
    line-height: 1.55;
    color: var(--color-text-body, #2c3e50);
}

.cvs-summary {
    margin: 0 0 12px;
    font-size: 1rem;
    line-height: 1.55;
    color: var(--text-soft, #555);
}

.cvs-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 12px;
}

/* Where the report comes from ---------------------------------------------

   Between the script and the judgement of it, because that is the order the
   reader needs: what is being judged, who is judging, then the judgement.

   The logo is here for the reason the whole page exists -- this is the one
   surface of the site a stranger sees, sent to them by somebody who liked
   what it produced. It is a rule and a mark, not a banner: whatever else
   this page is for, it is somebody's coverage first. */
.cvs-reporthead {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 18px;
    padding-bottom: 14px;
    border-bottom: 2px solid var(--border, #e0e0e0);
}

.cvs-reporthead img {
    flex: 0 0 auto;
    width: 116px;
    height: auto;
}

.cvs-reporthead h2 {
    margin: 0 0 3px;
    font-family: 'Playfair Display', Georgia, serif;
    font-size: 1.5rem;
    color: var(--color-text-body, #2c3e50);
}

.cvs-reporthead p {
    margin: 0;
    font-size: .95rem;
    line-height: 1.45;
    color: var(--text-muted, #8a8a8a);
}

/* The report itself. No panel around it here -- see renderCoverage()'s
   'bare' option -- so this is just the space it sits in. */
.cvs-report {
    margin-bottom: 34px;
}

/* The one thing asked of the reader --------------------------------------

   After the report, not before it. Somebody who has just read three thousand
   words about a screenplay is in a position to want one of their own; the
   same offer at the top is an advertisement in front of the thing they came
   for. */
.cvs-cta {
    padding: 26px;
    border: 1px solid var(--border, #e0e0e0);
    border-radius: 10px;
    background: #f7faf8;
    text-align: center;
}

.cvs-cta-lead {
    margin: 0 0 6px;
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--color-text-body, #2c3e50);
}

.cvs-cta-sub {
    margin: 0 0 18px;
    font-size: 1rem;
    line-height: 1.5;
    color: var(--text-soft, #555);
}

.cvs-cta-btn {
    display: inline-block;
    padding: 10px 22px;
    border-radius: 6px;
    background: #36a857;
    color: #fff;
    font-size: 1rem;
    font-weight: 600;
    text-decoration: none;
    transition: background .15s ease;
}

.cvs-cta-btn:hover { background: #2b8c48; color: #fff; }

/* A link that no longer opens anything ------------------------------------

   One message for every way it can fail -- revoked, deleted, never real.
   The reader can act on none of them, and naming which it was would be
   telling a stranger something about somebody else's script. */
.cvs-gone {
    max-width: 520px;
    margin: 60px auto;
    padding: 34px 26px;
    border: 1px solid var(--border, #e0e0e0);
    border-radius: 10px;
    text-align: center;
}

.cvs-gone i {
    font-size: 2.4rem;
    color: var(--text-muted, #b0b0b0);
    margin-bottom: 14px;
}

.cvs-gone h1 {
    margin: 0 0 10px;
    font-size: 1.5rem;
    color: var(--color-text-body, #2c3e50);
}

.cvs-gone p {
    margin: 0 0 20px;
    line-height: 1.55;
    color: var(--text-soft, #555);
}

/* The phone, which is where a forwarded link is most often opened. */
@media (max-width: 700px) {

    .cvs-hero {
        flex-direction: column;
        align-items: center;
        text-align: center;
        gap: 18px;
    }

    .cvs-poster { flex: 0 0 auto; width: 150px; }

    .cvs-chips { justify-content: center; }

    .cvs-title { font-size: 1.6rem; }

    /* Stacked, and the logo smaller -- at 116px beside two lines of text it
       takes a third of a phone's width for no gain. */
    .cvs-reporthead {
        flex-direction: column;
        align-items: flex-start;
        gap: 10px;
    }

    .cvs-reporthead img { width: 92px; }
}

/* Where the cast went ---------------------------------------------------------

   The Breakdown writes the major characters into the writer's own character
   records, so the Character section says so rather than listing them a second
   time. Tinted and iconed because it is a pointer to somewhere else on the
   page, not another finding to read. */
.ai-x-cast-note {
    margin: 10px 0 0;
    padding: 8px 11px;
    border-left: 3px solid var(--color-blue, #005e6a);
    border-radius: 0 4px 4px 0;
    background: #f2f7f8;
    font-size: 14px;
    line-height: 1.5;
    color: var(--text-soft, #555);
}

.ai-x-cast-note i {
    margin-right: 7px;
    color: var(--color-blue, #005e6a);
}

/* The breakdown's offer -------------------------------------------------------

   Two short lists rather than a paragraph, because the question a writer has
   in front of a tab called Breakdown next to a tab called Coverage is 'which
   one do I want and what do I get' -- and a list can be checked against what
   arrives, where a paragraph cannot. */
.ai-offer-lead {
    margin: 16px 0 6px;
    font-size: 13px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--color-blue, #005e6a);
}

.ai-offer-list {
    margin: 0;
    padding-left: 20px;
    line-height: 1.6;
}

.ai-offer-list li { margin-bottom: 5px; }

.ai-offer-foot {
    margin: 16px 0 18px;
    font-size: .95rem;
    color: var(--text-muted, #8a8a8a);
}

/* What the reading could not settle ------------------------------------------

   A box like the rest, because it is a section of the breakdown and not a
   footnote to it -- it is the honest half of the reading and often the most
   actionable. Amber rather than the neutral ground the others use: this one
   is asking the writer to go and decide something. */
.ai-x-confidence {
    margin-bottom: 12px;
    padding: 14px 16px;
    border: 1px solid #eadfc4;
    border-left: 4px solid #c08a2e;
    border-radius: 6px;
    background: #fdf9f0;
    font-size: 1.05rem;
    line-height: 1.55;
    color: var(--text-soft, #555);
}

.ai-x-confidence strong {
    display: block;
    margin-bottom: 6px;
    font-size: 1.2rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: #96681c;
}
