/* css/idea.css
 *
 * The Ideas page: the wall of them, and one at a time.
 *
 * Namespaced .idea- throughout, so this is safe to load anywhere -- the same
 * arrangement css/storyboard.css uses with .sb- and css/character.css with .sc-.
 *
 * The palette is the board's, deliberately. An idea and the board it grows is
 * the same piece of work at two stages, and giving them different colours would
 * make them look like different parts of the site.
 */

.idea-host {
    display: flex;
    flex-direction: column;
    width: 100%;
    min-height: 0;
    font-family: var(--font-sans);
    color: var(--sb-ink, #201e1d);
}

/* ------------------------------------------------- the panel on the dashboard

   The same widget as the page, inside a .card between the other two dashboard
   widgets. The page version fills the viewport and scrolls its own grid; here
   the card is as tall as its contents and the page does the scrolling, which
   is what the tables above and below it do.

   Two classes rather than one: .idea-host sets the height rules this undoes,
   weighs the same, and is written first -- so on one class it would win. */

.idea-host.idea-host--panel {
    min-height: 0;
}

/* Only the padding, to sit at the same inset as the .dash-grid walls above
   and below it. The tile width is the page grid's and stays there: a row of
   ideas and a row of screenplays should break at the same place. */
.idea-host--panel .idea-grid {
    padding: 10px;
    overflow-y: visible;
}

.idea-host--panel .idea-empty-state {
    padding: 20px;
}

/* Nothing here for .empty-label -- the placeholder the markup carries before
   the first fetch lands, and the "No Ideas Yet" that replaces it. Both are
   dressed by `.card .empty-label` in dashboard.css, with the tables above and
   below, which is the whole point of them looking alike.

   It would have won if it were still here: two classes, same as that rule, and
   idea.css is loaded after dashboard.css. */

/* The arrow at the head's left edge, before the bulb.

   The colour, the hover and the text treatment are .solid-btn's, in global.css
   -- the same purple button the script, folder and profile pages go back with,
   so the way off a page looks like one decision across all four.

   align-self:center against the head's own align-items:flex-end, which is what
   holds the title and the kicker down when the title wraps to two lines. The
   bulb wants the opposite: .idea-brand is the tallest thing on the line, so it
   fills the head's content box, and the bulb is centred inside it -- centring
   this button in the head puts the two on the same axis. Bottom-justified it
   sat below the bulb it is supposed to sit beside. */
.idea-back-btn {
    flex: none;
    align-self: center;
    justify-content: center;
    border: none;
    cursor: pointer;
}

/* The square, re-asserted over .solid-btn.

   Needed rather than tidy: global.css loads AFTER this file, so at equal
   specificity solid-btn wins -- and its padding (7px 15px, sized for a button
   with words in it) would stretch this one into a lozenge, while its .85rem
   would shrink the arrow inside it. Two classes here beats its one whatever
   the load order does next.

   30px square, the bulb's own size -- the two sit side by side on one axis, so
   matching the glyph beside it is what makes the pair read as a pair. */
.idea-head .idea-back-btn {
    width: 30px;
    height: 30px;
    padding: 0;
    font-size: 17px;
}

/* ---------------------------------------------------------------- the head */

/* PINNED, like the back bars on the script, folder and profile pages.
 *
 * An idea grows: attributes, titles, loglines, characters, scenes, notes,
 * attachments. Once it is taller than the window, the way back and everything
 * else on this line were only reachable by scrolling up for them.
 *
 * It needs nothing else to make it work, which is why this is three lines
 * where the dashboard's bars took seven:
 *
 *   - its parent is .idea-detail, which wraps the head AND the body, so the
 *     box it may travel inside is already the whole idea;
 *   - it is opaque and always was -- white, with a 2px rule along the bottom,
 *     so nothing shows through it and it reads as a docked toolbar rather than
 *     as text that stopped moving;
 *   - it is full width inside its column, so nothing scrolls past its sides
 *     and it needs no negative margins to reach the gutters.
 *
 * Sticky on a flex item is fine, and flex:none stays: the head must not be
 * squeezed by a long body.
 *
 * Docked flush against the header rather than 6px below it like the other
 * three. Those are loose buttons on the page's own background and need the
 * gap to look deliberate; this is a bar with an edge, and a gap under the
 * header would show the page sliding through it. */
.idea-head {
    position: sticky;
    top: var(--header-height);
    z-index: 20;
    display: flex;
    flex-wrap: nowrap;
    align-items: flex-end;
    gap: 8px;
    padding: 10px 20px;
    border-bottom: 2px solid var(--sb-rule, #201e1d);
    background: #fff;
    flex: none;
}

/* Takes the slack and gives it back first. min-width:0 is what lets a long
   title ellipsis rather than push the button off the end.

   A row now: the bulb, then everything else stacked beside it. */
.idea-brand {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 10px;
}

/* The bulb. Sized to the two lines beside it rather than to either one of them
   -- the title and the kicker together are about 30px tall, and an icon matched
   to the title alone sat short against the pair. The page's own gold, so it
   reads as part of the heading rather than as a button somebody forgot to
   finish. */
.idea-brand-icon {
    flex: none;
    font-size: 30px;
    color: var(--gold, #c9a84c);
}

/* min-width:0 again, and for the same reason: without it the stack refuses to
   shrink below its longest line and the title stops ellipsising. */
.idea-brand-stack {
    flex: 1 1 auto;
    min-width: 0;
}

/* The heading of a single idea, which is the same name the card above wore --
   so it carries the serif through from the wall into the idea itself. */
.idea-title-text {
    font-family: 'Playfair Display', Georgia, serif;
    display: block;
    min-width: 0;
    font-size: 22px;
    font-weight: 700;
    line-height: 1.15;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* The title and the plus that adds an alternate to it, on one line.
   The title keeps all the slack -- and its min-width:0 above -- so a long one
   still ellipsises rather than pushing the button off the end of the row. */
.idea-title-row {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
}

/* Out of the way until it is wanted.
   The other pluses sit beside headings in small caps and read as part of the
   furniture; this one sits beside a 22px serif heading, where a full-strength
   icon competes with the title for the eye. It comes up to the same weight on
   hover and on focus, which is when somebody is looking for it. */
.idea-title-add {
    flex: none;
    opacity: .45;
    transition: opacity .15s;
}

.idea-title-row:hover .idea-title-add,
.idea-title-add:focus-visible {
    opacity: 1;
}

.idea-brand-sub {
    display: flex;
    align-items: baseline;
    gap: 10px;
}

.idea-kicker {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--sb-muted, #6b6664);
}

.idea-readonly {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--sb-danger, #e85347);
}

.idea-nav-btn {
    flex: none;
    align-self: flex-end;
    border: 0;
    cursor: pointer;
    font-family: var(--font-sans);
}

/* The words on the header button go when the title needs the room -- the same
   trade, and the same breakpoint, as the board's header. The icon stays and the
   button keeps its aria-label, so nothing is lost but the drawing. */
@media (max-width: 1200px) {

    .idea-head .idea-nav-btn-label {
        display: none;
    }

    .idea-head .idea-nav-btn {
        padding: 7px 10px;
    }
}

/* ---------------------------------------------------------------- the wall */

.idea-list,
.idea-detail {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

/* auto-fill rather than auto-fit: with one idea, auto-fit would stretch its
   tile the width of the screen, which reads as a banner rather than as the
   first of a set. */
.idea-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 16px;
    padding: 20px;
    overflow-y: auto;
}

/* A tile with a gear over it. The wrapper is what the gear is positioned
   against, and the card is the whole of it -- see renderTile(), which only
   wraps the tiles that have one. */
.idea-card-cell {
    position: relative;
    display: flex;
}

.idea-card-cell .idea-card {
    flex: 1;
    min-width: 0;
}

/* In the corner, out of the flow, like the one on a screenplay card. */
/* Cornered, like .dash-card-actions on every other card. */
.idea-card-actions {
    position: absolute;
    top: 0px;
    right: 0px;
    z-index: 1;
}

/* Room for it, so a long title runs out of line before it runs under the cog. */
.idea-card-cell .idea-card-title {
    padding-right: 24px;
}

.idea-card {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 10px;
    border: 2px solid var(--sb-line, #c9c5c3);
    border-radius: 6px;
    background: var(--sb-surface, #fff);
    color: inherit;
    text-decoration: none;
    transition: border-color .15s ease, background .15s ease, box-shadow .15s ease;
}

@media (hover: hover) {

    /* The cell as well as the card. The gear sits over the tile rather than
       inside it -- a button inside a link is neither one thing nor the other --
       so a pointer on the gear is not on the card, and the tile went cold under
       the very control being reached for. On a screenplay card the gear is
       inside, and the card stays lit; these two should not differ.

       The cell is the card plus that gear and nothing else, so this lights
       exactly what a reader would say they were pointing at. */
    .idea-card:hover,
    .idea-card-cell:hover .idea-card {
        border-color: var(--sb-accent, #c9a84c);
        background: var(--gold-tint, #faf7ef);
        box-shadow: 0 1px 0 rgba(32, 30, 29, .18);
    }
}

/* An idea somebody else shared, at rest: the same wash a shared screenplay
   wears in the lists below this panel -- see --shared-tint in css/global.css,
   and .dash-card.is-shared in css/dashboard.css, which this is the ideas' half
   of. One mark for both walls, because they sit one above the other.

   The hover stays exactly what it was for every other tile, which is why the
   second rule puts the gold back: these two selectors are the ones above, and
   without them .idea-card.is-shared would win on source order and a shared tile
   would be the only one on the wall that did not answer the pointer. */
.idea-card.is-shared {
    background: var(--shared-tint);
}

@media (hover: hover) {

    .idea-card.is-shared:hover,
    .idea-card-cell:hover .idea-card.is-shared {
        background: var(--gold-tint, #faf7ef);
    }
}

/* The same serif the script and folder cards wear -- see .dash-card-title in
   css/dashboard.css. An idea is named like any other work on the site, and the
   ideas wall sits on the dashboard beside those cards, so it would be the one
   list in a different typeface. 700 is a weight template.php requests. */
.idea-card-title {
    font-family: 'Playfair Display', Georgia, serif;
    margin: 0;
    font-size: 16px;
    font-weight: 700;
    line-height: 1.2;

    /* The star is a child of the heading now. baseline rather than center:
       it sits against the first line of a title that wraps, which is where a
       capital letter starts and so where the eye already is. */
    display: flex;
    align-items: baseline;
    gap: 6px;
}

.idea-card-star {
    flex: none;
    font-size: 13px;
    color: var(--gold, #c9a84c);
}

/* Takes the wrapping, so the star stays on the first line rather than being
   dragged down by a long title. */
.idea-card-title-text {
    min-width: 0;
    color: var(--text-dark);
}

/* ------------------------------------------------ the foot of a tile

   The chips sit on the bottom edge whatever else the tile holds, so they line
   up across a row however long the loglines are. The cards are already the
   height of the tallest in their row -- they are grid items and grid stretches
   them -- so this only has to say where in that height the chips go.

   margin-top: auto in a flex column takes the free space, which is the whole
   trick. What is not obvious is that TWO auto margins share it: putting one on
   the counts as well would sit them a third of the way down with the chips two
   thirds, and neither on the edge. So the counts take it and the chips give it
   back when they follow the counts -- the pair travels down together and stays
   together, and a tile with no counts still has its chips on the floor.

   The counts come along on purpose. Pinning the chips alone would leave the
   line above them stranded halfway up a tall tile, and those two lines are
   read as one thing: what is on this idea, and where it has got to.

   The counts get their auto from their own rule further down rather than from
   here -- it weighs more than this would and is written after it, so a
   margin-top set here would be cancelled by a shorthand eighty lines away. */

.idea-card-attrs {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;

    /* For a tile with no counts on it: nothing above has taken the space, so
       the chips take it themselves and land on the floor all the same. */
    margin-top: auto;
}

/* And when there are counts, they took it -- so the chips give theirs back and
   follow them down. Two auto margins would have split it between them and put
   neither on the edge. Two classes, so it wins wherever it is written. */
.dash-card-icons+.idea-card-attrs {
    margin-top: 2px;
}

/* The idea page chip, shrunk. It keeps .idea-attr and its .is- class, so
   every colour rule above applies here untouched -- what Abandoned looks
   like is decided in one place and not two.

   The Stage and Status labels are dropped on a tile: "On Hold" says which
   field it is, and a wall is scanned rather than read.

   Two classes rather than one, and deliberately: .idea-attr sets the padding
   this overrides, weighs exactly as much, and is written further down the
   file -- so on one class the base would win and the small chip would come
   out full size. Doubling the class settles it wherever either rule sits. */
.idea-attr.idea-attr--sm {
    padding: 1px 8px;
    border-radius: 10px;
}

.idea-attr--sm .idea-attr-value {
    font-size: 12px;
    font-weight: 600;
}

/* Three lines. A logline that runs longer than that is a synopsis, and the tile
   is not where it should be read. */
.idea-card-logline {
    margin: 0;
    font-size: 15px;
    line-height: 1.4;
    color: var(--color-blue);
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    overflow: hidden;
}

.idea-card-genres {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin-top: 2px;
}

/* The line under the title on an idea somebody else shared: who lent it, and
   when the loan runs out. Everything about how it looks is in css/dashboard.css
   under .shared-by, which the Screenplays list draws the same line with -- this
   only gives it the tile's own spacing. */
.idea-card-sub {
    margin: -2px 0 2px;
}

.idea-genre {
    padding: 2px 8px;
    border-radius: 11px;
    background: var(--sb-accent-tint, #f7f0dc);
    color: #8a6f21;
    font-size: 14px;
    font-weight: 600;
}

/* ── THE FULL-WIDTH CARD ───────────────────────────────────────────────────

   The third shape the dashboard's Ideas panel can take: the same tiles, one to
   a row, in the .dash-rows wall the Projects and Screenplays lists stack their
   full-width cards in -- so the three panels on that page break the same way
   and sit at the same inset.

   No picture down the left, unlike those two. An idea has no poster, and an
   icon invented to fill that column would be the same icon on every row.

   What the extra width buys is read rather than left: the title and the
   logline go up a size or two, the logline gives back its third line because
   two at this width hold more than three did at 300px, and the counts and the
   stage/status chips -- two short rows at the foot of a tile -- become one. */

/* Nothing to say about the cell itself. .idea-card-cell is already a flex box
   the card fills, and .dash-rows makes it full width; the gear it carries is
   cornered against it exactly as on a tile. */

.idea-card-wide {
    gap: 4px;
}

.idea-card-wide .idea-card-title {
    font-size: 22px;
    line-height: 1.25;
}

.idea-card-wide .idea-card-star {
    font-size: 17px;
}

/* Two lines, not three -- see above. */
.idea-card-wide .idea-card-logline {
    margin-top: 2px;
    font-size: 18px;
    line-height: 1.35;
    -webkit-line-clamp: 2;
    line-clamp: 2;
}

/* What is on the idea, and where it has got to, along one line at the foot.

   Both children arrive holding the auto top margin that pins them to the
   floor of a tile -- see the note on the foot of a tile above. In a row that
   margin means something else entirely, so it is taken back here and the
   parent does the pinning for both of them at once. */
.idea-card-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 16px;
    margin-top: auto;
    padding-top: 6px;
}

.idea-card-foot .dash-card-icons,
.idea-card-foot .idea-card-attrs {
    margin: 0;
    padding-top: 0;
}

@media (max-width: 700px) {

    .idea-card-wide .idea-card-title {
        font-size: 19px;
    }

    .idea-card-wide .idea-card-logline {
        font-size: 16px;
    }
}

/* auto on the top edge: it takes the tile's free space, which puts the counts
   and the chips that follow them on the floor of the card. See the foot of a
   tile, above -- this is the half of that rule which has to live here, because
   the shorthand it replaces would have cancelled it from up there.

   The space above the line is padding rather than margin for that same reason:
   the top margin is spoken for, and on a short tile it is worth nothing --
   auto is whatever is left over, which on a tile that fills its row is none.
   Padding is 3px whatever the tile is doing. */
.idea-card .dash-card-icons {
    margin: auto 0 3px;
    padding-top: 3px;
}

.idea-empty-state {
    padding: 30px 20px;
    max-width: 560px;
}

.idea-empty-state p {
    margin: 0 0 8px;
    font-size: 14px;
    line-height: 1.5;
    color: var(--sb-muted, #6b6664);
}

/* -------------------------------------------------------------- one idea */

/* NOT A SCROLL PANE, WHATEVER THIS USED TO INTEND.
 *
 * overflow-y:auto sat here for a page that was meant to scroll inside a fixed
 * frame -- and nothing in the chain above ever capped the height, so it never
 * scrolled once: .main-wrap, .content and .page are all auto-height, the body
 * simply grew, and the window scrolled. Measured on an idea with 22 notes: the
 * page was 8796px tall and .idea-body.scrollTop was 0.
 *
 * Removed rather than left as a comment, because it was not harmless. An
 * overflow container is a scrollport, and a sticky child positions against the
 * nearest one -- so the notes column below could never stick to anything,
 * having been pinned to a box that does not move. See .idea-col-side. */
.idea-body {
    flex: 1 1 auto;
    min-height: 0;
    padding: 18px 20px;
    /* The page's own floor, carried here because #page-ideas has given it up --
       see the note above @container below for why it had to. The last thing in
       .idea-detail is this element now, so this is where the 10px goes. Kept as
       a margin rather than folded into the padding above so the two numbers stay
       the two different things they are: 18 is the idea's own bottom inset and
       10 is the page's. The wide layout takes both away. */
    margin-bottom: 10px;
    display: flex;
    flex-direction: column;
    /* The space between an idea's sections -- Loglines, Genres, Summary, the
       cast, the boards, Notes. Every one of them also carries its own inner
       spacing, so 18 here read as more than it was. */
    gap: 15px;
}

.idea-section {
    max-width: 720px;
}

/* ------------------------------------------------ the second column

   THE NOTES MOVE TO THE RIGHT, WHERE THERE IS ROOM FOR THEM.

   The idea is capped at 720px because it is a column of short sections to be
   read, not a page that fills whatever window it is given -- which on a wide
   screen left a column's worth of nothing down the right hand side while the
   notes sat a long scroll below the end of the idea.

   ASKED OF THE PAGE, NOT OF THE WINDOW. A container query, because the dashboard
   has a left nav that opens and closes: the same 1200px window gives this page
   two rather different widths, and a media query would answer for the window and
   be wrong for one of them. 1050 is the width at which 720 of idea, a gutter and
   a readable notes column fit side by side -- at the very bottom of that range
   the idea gives up a few pixels, and it is back to its full width by about
   1110.

   Where it does not fit, nothing here applies: .idea-body is a column, the two
   wrappers are columns inside it, and the notes are the next thing after the
   idea -- exactly where they were before there were two columns at all. That is
   also what a browser without container queries gets, which is why the markup
   is in the narrow order rather than the wide one. */

.idea-detail {
    container-type: inline-size;
    container-name: idea;
}

.idea-col-main,
.idea-col-side {
    display: flex;
    flex-direction: column;
    /* The same gap .idea-body had between sections when it held them itself. */
    gap: 15px;
    min-width: 0;
    margin-bottom: 20px;
}

/* No notes drawn at all -- not a thing that happens today, since the heading is
   always there, but an empty 320px column would be a hole rather than a space. */
.idea-col-side:empty {
    display: none;
}

/* THE PAGE'S OWN FLOOR, AND WHY IT IS TAKEN AWAY FROM UP HERE.
 *
 * .page in css/dashboard.css gives every dashboard page 10px on all four
 * sides. At two columns that bottom 10px is dead weight: the notes column is a
 * fixed height measured off the window, so anything standing under it is only
 * a reason for the page to scroll with nothing at the end of the scroll.
 *
 * It cannot be switched off by the container query below. The container is
 * .idea-detail, two levels down from the page element, and a container query
 * only ever dresses things inside its container -- an element cannot be styled
 * by a query it is the ancestor of. A media query would reach it, and would be
 * wrong for exactly the reason the note at the head of this section gives: the
 * left nav opens and closes, so one window width is two page widths.
 *
 * So the padding comes off unconditionally, and the one-column layout puts it
 * back from inside the container, where the query can see it -- as a bottom
 * margin on .idea-body, which is the last thing in .idea-detail. (It was on a
 * .idea-status line under the body until that element was removed; see
 * setStatus() in js/idea.js.) The rule that undoes it is in the query below,
 * weighs the same, and wins on source order alone.
 *
 * The wall of ideas does not need it either way: .idea-grid carries 20px of
 * its own. */
#page-ideas {
    padding-bottom: 0;
}

@container idea (min-width: 1050px) {

    .idea-body {
        flex-direction: row;
        /* Both columns start at the top. Without this they stretch to the
           height of the taller one, which on a short idea with one note means a
           NOTES heading floating in the middle of its own column. */
        align-items: flex-start;
        gap: 28px;
        /* NOTHING UNDER THE COLUMNS AT ALL.
           The notes column below is a fixed height measured from the window, so
           it -- not the idea -- decides how tall the page is, and every pixel
           beneath it is a pixel the page scrolls for nothing. Both of the
           numbers this element carries at narrow widths go: its own 18px inset
           and the 10px it is holding on the page's behalf. See #page-ideas
           above. */
        padding-bottom: 0;
        margin-bottom: 0;
    }

    .idea-col-main {
        flex: 1 1 auto;
        max-width: 720px;
    }

    /* Fixed, and narrower than the idea: a note is a line or two and reads
       better narrow, and a second column that grew with the window would end up
       wider than the idea it is a note about.

       Against the right edge, with the free space between the two columns
       rather than beyond them. The idea is capped at 720 and the notes at 320,
       so on a wide window there is always something left over -- parked on the
       right it read as a stray third column of nothing, and the notes looked
       like part of the idea rather than a margin to it. An auto left margin
       takes whatever is going, which is also why the 28px gap above is a floor
       and not the usual distance. */
    .idea-col-side {
        flex: 0 0 320px;
        margin-left: auto;

        /* IT STAYS ON SCREEN, AND IT SCROLLS ITSELF WHEN IT HAS TO.
         *
         * A busy idea is a long page and a busy set of notes is a long column,
         * and the two lengths have nothing to do with each other. Left alone,
         * twenty notes made the page 8800px tall: the idea ended at 900 and the
         * rest was notes beside an empty column, with the notes you were reading
         * carrying the idea they are about off the top of the screen.
         *
         * Sticky rather than a second scrolling pane. The page scrolls the way
         * every other dashboard page scrolls, and this column comes along --
         * only scrolling inside itself when the notes are taller than the screen
         * is, which is the one case that needs it.
         *
         * THE TWO NUMBERS ARE NOT THE SAME NUMBER, AND 120 IS NOT A GUESS.
         *
         * 74 is the idea's sticky head -- 62px at every width, since a long
         * title ellipsises rather than wrapping -- plus 12px, so the notes stop
         * clear of that bar rather than sliding up until they touch it. Ben's
         * number, and the right one.
         *
         * 110 is 90 of page and 20 of air, and only the 90 is arithmetic.
         *
         * A fixed height means the column, not the idea, decides how tall the
         * page is, so the most it can be given is the window less everything
         * else standing in the same stack:
         *
         *     50  the site header -- var(--header-height), subtracted above
         *     10  #page-ideas padding-top (.page in css/dashboard.css)
         *     62  .idea-head
         *     18  .idea-body padding-top
         *      0  below the column, because there is nothing below it
         *
         * Nothing else contributes: .main-wrap, .content, .idea-host and
         * .idea-detail carry no vertical padding, and the page's floor and the
         * body's bottom padding and margin are all zeroed at this width.
         *
         * At exactly 90 the page fits the window and the box sits on the
         * window's bottom edge, which reads as a box that has been cut off
         * rather than one that ends. The extra 20 is that gap -- Ben's number,
         * and the only judgement in the calc. It comes out of the column's
         * height rather than out of anything below it, because there is nothing
         * below it: a margin here would grow the page again and put the scroll
         * back that the 90 was worked out to remove.
         *
         * IT WAS 120, AND THE 30 THAT WENT WAS AN EMPTY LINE. A .idea-status
         * element used to close the page off under the body -- the idea's error
         * line, which held 30px open to say nothing on every idea anyone has
         * ever opened. It is gone: setStatus() in js/idea.js raises a toast, so
         * errors are read wherever the reader is rather than written below the
         * fold. Put anything back under .idea-body and its height comes off
         * this number.
         *
         * An earlier 110 here was the same number for a different reason -- the
         * status line was still under the body then, and it left the page 10px
         * longer than the window. The two have nothing to do with each other.
         *
         * THIRTY-SIX PIXELS OF SLACK, AND THEY ARE LOAD-BEARING. The column
         * starts at header+90 in the flow and pins at header+74, so on a page
         * long enough to scroll its foot stops 36px clear of the window -- the
         * 20 of air plus the 16 it moved up by. That is also what keeps the
         * sticky clamp off it: a sticky item cannot stand outside its parent's
         * content box, and .idea-body's now ends at the window's own bottom
         * edge.
         *
         * Move any line of that list and this number moves with it.
         *
         * HEIGHT, NOT max-height, AND THAT IS THE POINT OF THE BORDER.
         *
         * The box is drawn now, so it has to be a box whatever is in it: on a
         * max-height a single note would have left a 40px rectangle floating
         * beside a full page of idea. A fixed height makes the outline read as
         * a column the notes live in rather than a ring drawn round however
         * many there happen to be -- the height is the cap, it is just always
         * taken.
         *
         * The border and padding are inside the height: global.css puts
         * box-sizing:border-box on everything, so the 2px and the 5px come out
         * of the calc rather than being added to it.
         *
         * align-self overrides the flex-start the row sets: a sticky item has to
         * be shorter than the box it travels inside, and a stretched item is
         * exactly as tall as it, which pins it in place and looks like sticky
         * being broken.
         *
         * NOT THE SCROLLER ANY MORE. overflow is hidden rather than auto: the
         * heading has to stay put and only the notes under it move, so the
         * scrollport is .idea-text-list further down. Hidden and not visible,
         * because the list is clipped to this box and a rounded border with
         * notes running out past the corner of it is worse than no border. */
        position: sticky;
        top: calc(var(--header-height) + 74px);
        align-self: flex-start;
        height: calc(100vh - var(--header-height) - 110px);
        border: 2px solid var(--color-blue);
        border-radius: 6px;
        padding: 5px 8px;
        overflow: hidden;
    }

    /* ------------------------------ the heading stays, the notes move

       THE PLUS IS ALWAYS THERE TO BE CLICKED.

       The whole column scrolled until now, heading and all, so on a long set of
       notes the NOTES bar -- and the plus that is the only way to add one --
       went off the top of the box and had to be scrolled back to. Adding a note
       is the thing this column is for; the way in should not be something you
       have to go and find.

       So the section becomes a column of its own inside the box: the bar fixed
       at its top, the list taking the rest and scrolling inside it.

       min-height:0 on both, and it is not optional. A flex item's floor is the
       size of its content, not zero -- so without it the list refuses to be
       shorter than all of its notes, grows the section, and the box clips it
       instead of anyone scrolling anything.

       Only the note column, not .idea-section everywhere: the sections down the
       main column are read one after another on a page that scrolls as a whole,
       and giving any of them its own scrollport would be the thing the note at
       the head of .idea-body warns about. */
    .idea-col-side .idea-section {
        flex: 1 1 auto;
        min-height: 0;
        display: flex;
        flex-direction: column;
    }

    /* The 6px is not decoration either. The bar carries margin-bottom:0
       everywhere else because the list under it is part of the same block and
       scrolls with it; here it does not, so a note arriving from below would
       slide up until it touched the word NOTES and vanish against it. A band of
       space is what makes the heading read as the lid of the box rather than
       as the first thing in the list. */
    .idea-col-side .idea-section-bar {
        flex: none;
        margin-bottom: 6px;
    }

    .idea-col-side .idea-text-list {
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        /* Reaching the last note should not then start scrolling the page
           underneath it. */
        overscroll-behavior: contain;
        /* Room for the scrollbar before there is one, so the notes do not shift
           sideways the moment one more of them arrives. */
        scrollbar-gutter: stable;
    }
}

/* The house gold, from css/global.css, which every page loads. Named rather
   than the board's --sb-accent so the section headings track the site's colour
   if it ever moves -- they are furniture of this page, not of the board. */
.idea-section-head {
    margin: 0 0 5px;
    font-size: 16px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--gold, #c9a84c);
}

/* A heading and the one button that acts on the whole section: a plus to add
   another of whatever it holds, or the pencil that opens the genre picker.
   Drawn rather than revealed on hover, unlike the buttons on a single piece of
   writing -- those act on something already visible, and this is the way to
   something that is not there yet. */
/* No gap under a heading: the page is a column of short sections and 5px on
   each of seven of them was 35px of air doing nothing. The space between one
   section and the next is what separates them -- see .idea-section -- and that
   is still there. */
.idea-section-bar {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 0;
}

.idea-section-bar .idea-section-head {
    margin: 0;
}

/* A button that is there to say where a button will be. */
.idea-tool[disabled] {
    opacity: .35;
    cursor: not-allowed;
}

.idea-section-empty {
    margin: 0;
    font-size: 13px;
    line-height: 1.45;
    color: var(--sb-muted, #6b6664);
}

/* The part of the page that is not built yet, saying so. An empty panel reads
   as something that failed to load. */
.idea-section--soon .idea-section-empty {
    padding: 10px 12px;
    border: 1px dashed var(--sb-line, #c9c5c3);
    border-radius: 6px;
}

/* ------------------------------------------------- the writing on an idea */

.idea-text-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* A piece of writing and the buttons that act on it. The buttons sit at the
   right rather than in a row underneath, so a one-line logline and a
   six-paragraph summary put them in the same place.

   A rule down the left edge and nothing else. A box around every paragraph
   turns a page of writing into a page of cards, and these are not cards -- they
   are what somebody wrote. The bar is enough to say where one ends and the next
   begins, and it costs no background.

   It wraps so that the author line below can take a row of its own. Nothing
   else in here wraps: the writing is flex:1 with min-width:0 so it shrinks
   rather than pushing anything down, and the buttons are a fixed 26px each.

   The 10px is between columns only. It was written for the space between the
   writing and the buttons beside it, and is far too much between the author's
   name and the words underneath it -- which is the only row gap there is. */
.idea-text {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 0 10px;
    padding: 1px 0 1px 10px;
    border-left: 2px solid var(--sb-line, #c9c5c3);
    background: none;
}

/* An arrow, not an I-beam.
   The browser draws an I-beam over any text, which is a promise that clicking
   will put a cursor in it. On a heading or a date that promise is false, and a
   reader who believes it clicks and nothing happens. The writing itself is the
   exception below -- there, clicking really does open it, so the I-beam stays.
   Text remains selectable throughout; only the drawing of the pointer changes. */
.idea-section-empty,
.idea-lead-title,
.idea-section-head,
.idea-subsection-head,
.idea-text-meta {
    cursor: default;
}

/* Basis 0, not auto, and it is the author line above that makes it matter.
   A flex row breaks on the items' content widths, not on what they would shrink
   to -- so with the row now wrapping, a long note measured wider than the line
   and sent the date and the buttons beside it down to a row of their own. At a
   basis of nought the writing measures nothing and takes the leftover space
   instead, which is what it was already doing when the row could not wrap. */
.idea-text-body {
    flex: 1 1 0;
    min-width: 0;
    cursor: default;
}

/* Writing that opens when it is clicked says so: the caret, and an underline
   when the pointer is over it. One rule for the heading and for the prose under
   it, because they are opened the same way and should look equally openable --
   the title being a column rather than a row in idea_texts is a fact about the
   database, not about renaming an idea.

   No pencil beside any of them: a small button doing the same thing as the
   large obvious target next to it is a second way to do one thing. */
/* A pencil, which CSS has no name for -- so it is drawn here and carried in the
   rule. An SVG rather than a file so that nothing on this page waits on a
   request for a 300-byte image, and white-filled with a dark outline so it is
   visible over both the page and a selection.

   "3 21" is the hotspot: the pencil's tip, so the point that acts is the point
   that looks like it acts. The keyword after the comma is what a browser uses
   if it will not take the image -- a hand, which at least still says "this
   does something". */
.idea-text-body.is-editable,
.idea-lead-title.is-editable {
    cursor: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='24'%20height='24'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M3.2%2020.8l1.2-4.1L15.5%205.6l2.9%202.9L7.3%2019.6z'%20fill='%23ffffff'%20stroke='%23201e1d'%20stroke-width='1.6'%20stroke-linejoin='round'/%3E%3Cpath%20d='M14.4%206.7l2.9%202.9M4.4%2016.7l2.9%202.9'%20stroke='%23201e1d'%20stroke-width='1.6'/%3E%3C/svg%3E") 3 21, pointer;
}

@media (hover: hover) {

    .idea-text-body.is-editable:hover,
    .idea-lead-title.is-editable:hover {
        text-decoration: underline;
        text-decoration-color: var(--sb-line, #c9c5c3);
        text-underline-offset: 3px;
    }
}

/* Keyboard users never hover, and a paragraph is not a button. */
.idea-text-body.is-editable:focus-visible,
.idea-lead-title.is-editable:focus-visible {
    outline: 2px solid var(--sb-accent, #c9a84c);
    outline-offset: 3px;
    border-radius: 3px;
}

.idea-text-body p {
    margin: 0 0 8px;
    font-size: 16px;
    line-height: 1.5;
    /* A pasted paragraph can carry a word longer than the column. */
    overflow-wrap: break-word;
}

.idea-text-body p:last-child {
    margin-bottom: 0;
}

/* The leading logline or summary is the thing itself, not an entry in a list of
   them. No bar and no indent: it sits flush under its heading and reads at the
   size somebody would read it at. */
.idea-text.is-lead {
    border-left: 0;
    padding-left: 0;
}

.idea-text.is-lead .idea-text-body p {
    font-size: 16px;
    color: var(--color-text-body);
    font-weight: bold;
}

/* An alternate is subordinate to the one above it, and is set in from it to say
   so. Notes carry neither this nor .is-lead -- they keep the bar the base rule
   gives them, at the left margin, because a note is not an alternative to
   another note and has nothing to be indented under. */
.idea-text.is-alt {
    margin-left: 20px;
}

/* And set smaller, which is the one place the reduction belongs: an alternate is
   being kept in mind rather than read. Everything else on the page -- the lead,
   and every note -- is main text at the base size. */
.idea-text.is-alt .idea-text-body p {
    font-size: 14px;
}

/* The last thing on the row, past the buttons -- see renderText(), which is
   where the order is decided. The writing takes all the slack in the line, so
   last is what puts the date against the right edge of every row whether or not
   that row has a trash can on it. */
.idea-text-meta {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-top: 5px;
    font-size: 11px;
    color: var(--sb-muted, #6b6664);
}

/* ------------------------------------------------- a note is laid out flat

   WHO, WHEN AND THE TRASH CAN GO ABOVE THE WRITING, NOT BESIDE IT.

   Everywhere else in this page the date and the buttons share the line with the
   words, and the words take the slack -- which is right for a logline or a
   summary sitting in a 720px column. A note in the second column has 320px to
   work with, and a date and a trash can beside it left a ribbon of text about
   thirty characters wide: a paragraph set in a gutter.

   So the note's row breaks in two. The line above carries the name, the date
   and the tools; the writing below gets the whole width of .idea-text-list,
   whatever that width happens to be. It is the same in one column as in two --
   one layout for a note, not a layout per screen -- and in the wide column it
   reads as a small heading over a paragraph, which is what a note with somebody
   else's name on it is anyway.

   Done with order and a full-width basis rather than by building the markup
   differently: .idea-text already wraps for the author line, and renderText()
   appends in the order the other sections want. */

/* ONE BOX, so the three things in it cannot come apart.
   They were three items on .idea-text's own line, which is free to wrap -- and
   a date with a trash can on the line under it is two rows of furniture over a
   note that may be one line long. In a box of their own they are a byline: the
   name, the date, and the can at the end of it.
   Full width of the row, so the writing starts underneath rather than beside.
   The 2px is the only space between the two -- .idea-text has no row gap, for
   exactly this reason. */
.idea-text-head {
    flex: 0 0 100%;
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 2px;
    min-width: 0;
}

/* Sized to its name rather than to the line: the base rule gives it the whole
   row, which is what it wants when it stands alone above a logline. */
.idea-text-head .idea-text-author {
    flex: 0 1 auto;
    min-width: 0;
    margin: 0;
    /* A long display name should not push the date off the end. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.idea-text-head .idea-text-meta {
    flex: none;
    margin-top: 0;
}

/* Beside the date, not out at the right margin: the whole point of this line is
   that it is one block rather than two things at opposite ends of a column. */
.idea-text-head .idea-text-tools {
    flex: none;
    align-self: center;
}

/* The heading over the alternates, set in to the depth they are set in to and
   a size below the section's own -- it is a division of that section rather
   than a section beside it. */
.idea-subsection-head {
    margin: 0px 0 4px 20px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--sb-muted, #6b6664);
}

/* Four lines of an alternate summary, and no more. A summary runs to a page,
   and three of them under a leading one would be a screen of writing that
   nobody asked to read -- the alternates are there to be remembered and chosen
   between, and the whole of one can be seen by opening it to edit.

   Only summaries. A logline is a sentence and clamping one would cut a sentence
   in half to save nothing. */
.idea-section--summary .idea-text.is-alt .idea-text-body {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 4;
    line-clamp: 4;
    overflow: hidden;
    /* The clamp draws the ellipsis; this is the guarantee underneath it, for
       anywhere the clamp is not honoured over block children. Four lines at the
       14px/1.5 the paragraphs are set in. */
    max-height: 84px;
}

/* ---------------------------------------------------------------- the tools */

.idea-text-tools {
    flex: none;
    display: flex;
    gap: 2px;
    align-self: flex-start;
}

.idea-tool {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: 5px;
    background: none;
    color: var(--sb-muted, #6b6664);
    font-size: 12px;
    cursor: pointer;
}

.idea-tool--danger:hover {
    color: var(--sb-danger, #e85347);
}

@media (hover: hover) {

    /* Out of the way until the writing is being looked at. On touch there is no
       hovering, so they are simply always there -- the alternative is a row of
       buttons that can only be reached by a gesture the device does not have. */
    .idea-text-tools {
        opacity: 0;
        transition: opacity .12s ease;
    }

    .idea-text:hover .idea-text-tools,
    .idea-text:focus-within .idea-text-tools {
        opacity: 1;
    }

    .idea-tool:hover {
        border-color: var(--sb-line, #c9c5c3);
        background: #fff;
        color: var(--sb-ink, #201e1d);
    }
}

/* Keyboard users never hover. Without this the tools would be focusable and
   invisible at the same time. */
.idea-tool:focus-visible {
    opacity: 1;
    outline: 2px solid var(--sb-accent, #c9a84c);
    outline-offset: 1px;
}

/* -------------------------------------------------------------- the editor */

.idea-editor {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 8px 10px;
    border: 1px solid var(--sb-accent, #c9a84c);
    border-radius: 6px;
    background: #fff;

    /* The ceiling, because the field inside grows with what is typed into it
       and would otherwise carry the Save and Cancel buttons off the bottom of
       the screen -- a box whose only way out is somewhere you cannot see.

       Put on the box rather than on the field, which is the point. The buttons
       are a flex item that does not shrink, the field is one that does, so
       what is left over after the buttons and this box's own padding and
       border is exactly what the field may take. Nobody has to guess at the
       height of the buttons, and nobody has to correct the guess when they
       change.

       The 120px is the page above it -- the header and the section heading --
       and a little air below. It is the one measurement here that is a
       judgement rather than a consequence. */
    max-height: calc(100vh - 120px);
}

/* An editor standing in for an alternate keeps its indent, so that opening one
   does not make it jump left and then back again on save. */
.idea-editor.is-alt {
    margin-left: 20px;
}

/* .idea-grow::after is in here with the fields, not in a rule of its own.
   It is the copy of the text that the growing box measures itself against, and
   it can only measure right while it is laid out exactly as the field is: same
   font, same size, same line-height, same padding, same border, same wrapping.
   Sharing the declaration is what stops the two drifting -- css/modal.css has
   the note on what happens when they do, which is a box that shivers as you
   type. Change a value here and the mirror changes with it, because it is not
   a copy of the rule, it is the rule. */
.idea-textarea,
.idea-input,
.idea-grow::after {
    width: 100%;
    padding: 6px 8px;
    border: 1px solid var(--sb-line, #c9c5c3);
    border-radius: 4px;
    background: #fff;
    color: var(--sb-ink, #201e1d);
    font-family: var(--font-sans);
    font-size: 15px;
    line-height: 1.45;
    /* Said rather than left to the browser, because it has to be the same on
       both. A textarea breaks a long unbroken run of characters at its edge;
       a div left to itself does not, and would report a box a line short. */
    overflow-wrap: break-word;
}

/* A textarea that grows with what is typed into it.
 *
 * Two copies of the same text in one grid cell -- the field, and an ::after
 * the browser can measure -- so the cell takes the height of the taller of
 * them. renderTextEditor() keeps the copy up to date on every keystroke, and
 * the box follows the writing down.
 *
 * This is the page's own wrapper and not the .grow-wrap in css/dashboard.css,
 * which sets its own font and padding for the fields on that page. Borrowing
 * it here would have meant a mirror laid out to dashboard measurements around
 * a field laid out to these. */
.idea-grow {
    display: grid;

    /* A flex item will not shrink below its content unless it is told it may,
       and the ceiling on .idea-editor above is worth nothing unless this can.
       Without it the field keeps its full height and the box grows past the
       cap regardless. */
    min-height: 0;

    /* The mirror is only hidden, not absent, so it still draws past the cap
       once the field has stopped growing. */
    overflow: hidden;
}

.idea-grow>.idea-textarea,
.idea-grow::after {
    grid-area: 1 / 1 / 2 / 2;
}

.idea-grow::after {
    content: attr(data-replicated-value) " ";
    /* The trailing space in the content is not a typo: a value ending in a
       newline would otherwise measure as though it did not, and the box would
       fail to grow on the one keystroke that most obviously needs it. */
    white-space: pre-wrap;
    visibility: hidden;
}

.idea-grow>.idea-textarea {
    /* No drag handle. The box sizes itself, and a handle beside it is a second
       answer to a question already answered. This is the only thing the page
       says about resizing: every textarea on it is inside one of these, so the
       `resize: vertical` that used to sit with the field applied to nothing. */
    resize: none;
    /* And it scrolls once the cap stops it growing. The wrapper hides what
       overflows it, so without this the writing past the cap would be there
       and unreachable. */
    overflow: auto;
}

.idea-textarea:focus,
.idea-input:focus {
    outline: 2px solid var(--sb-accent, #c9a84c);
    outline-offset: -1px;
    border-color: var(--sb-accent, #c9a84c);
}

/* Never shrunk. This is the half of the cap on .idea-editor that says what
   the field has to leave room for -- if these could be squeezed the field
   would squeeze them rather than scroll. */
.idea-editor-tools {
    flex: none;
    display: flex;
    align-items: center;
    gap: 8px;
}

.idea-save-btn {
    border: 0;
    border-radius: 5px;
    padding: 5px 14px;
    font-family: var(--font-sans);
    font-size: 13px;
    cursor: pointer;
}

.idea-cancel-btn {
    border: 0;
    background: none;
    padding: 5px 4px;
    color: var(--sb-muted, #6b6664);
    font-family: var(--font-sans);
    font-size: 13px;
    cursor: pointer;
}

.idea-cancel-btn:hover {
    color: var(--sb-ink, #201e1d);
    text-decoration: underline;
}

/* The title, edited where it is drawn -- so the box has to be the size of the
   heading it replaces rather than the size of a field in a form. */
.idea-title-editor {
    padding: 0;
    border: 0;
    background: none;
}

.idea-title-editor .idea-input {
    font-size: 20px;
    font-weight: 700;
}

/* ------------------------------------------------------------- the Add menu */

.idea-head-tools {
    flex: none;
    display: flex;
    align-items: flex-end;
    gap: 8px;
}

/* .idea-add, .idea-add-menu and .idea-add-item were here: the Add button in
   the header and the list it dropped. Both went when every section grew its own
   plus -- see the note in js/idea.js where renderAddMenu() used to be.

   .idea-attr-menu further down was written as "the same furniture" as that
   menu and now carries the whole description of it, which is the right place
   for it: it is the one menu on this page that still exists. */

/* .idea-status and .idea-status.is-error were here: a 12px line under the body
   that setStatus() in js/idea.js wrote a failed save into, and a min-height of
   30px that held it open whether it had anything to say or not.

   Gone with the element. Every caller but one was a .catch(), and the line was
   the last thing on the page with nothing scrolling it into view -- so a save
   that failed while you were reading the top of a long idea wrote its message
   several hundred pixels below the fold. setStatus() raises alertToastTR now,
   which is on screen wherever the reader is. The 30px it was holding went to
   .idea-col-side, which is measured off the window and wants every pixel
   nothing else is standing in. */

/* ------------------------------------------------------------- the dialog */

.idea-dialog {
    width: min(520px, 92vw);
}

.idea-dialog .idea-field-note {
    margin: 4px 0 0;
    font-size: 11.5px;
    line-height: 1.35;
    color: var(--sb-muted, #6b6664);
}

/* The genre picker was vanillaSelectBox, and two rules lived here to cope with
   it: one to overrule the inline styles the library writes on its own button,
   and one to stop the menu it dropped being clipped by the modal. Both went
   with it -- the genres are a grid of checkboxes now, styled by .sm-checks in
   css/dashboard.css, and a grid neither writes inline styles nor drops out of
   anything. See popup/ideaGenres.php.

   The clipping rule is worth a word because removing it is a change in its own
   right: .modal360-content clips so that a dialog taller than the window can be
   scrolled, and that dialog is now the taller of the two -- eighteen genres in
   a grid rather than one closed menu -- so it wants the clipping back. */

/* --------------------------------------------- stage, status and the star

   The row under the title. Three controls that answer "where is this one and
   do I care about it" without reading a word of the idea itself, which is why
   they come before everything that has to be read.

   Wraps, because on a narrow window two chips and a star will not sit on one
   line and the alternative is a chip cut in half. */

.idea-attrs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    max-width: 720px;
}

/* ------------------------------------------------------------------ chips */

.idea-attr {
    /* The menu hangs off this. */
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 4px 4px 4px 10px;
    border: 1px solid var(--sb-line, #c9c5c3);
    border-radius: 14px;
    background: var(--sb-surface, #fff);
}

/* Small caps, the size every other kicker on the page settled at. */
.idea-attr-label {
    flex: none;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--sb-muted, #6b6664);
}

/* A button that does not look like one until it is reached for: the chip is
   the thing being clicked, and a second border inside the first would say
   there were two controls here. */
.idea-attr-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 8px;
    border: 0;
    border-radius: 11px;
    background: none;
    color: inherit;
    font-family: inherit;
    cursor: pointer;
    transition: background .15s ease;
}

@media (hover: hover) {

    .idea-attr-btn:hover {
        background: var(--gold-tint, #faf7ef);
    }
}

.idea-attr-btn:focus-visible {
    outline: 2px solid var(--gold, #c9a84c);
    outline-offset: 1px;
}

.idea-attr-value {
    font-size: 14px;
    font-weight: 600;
    white-space: nowrap;
}

.idea-attr-caret {
    font-size: 10px;
    color: var(--sb-muted, #6b6664);
}

/* A chip with nothing to click: what a reader sees, and what the writer sees on
   a value that cannot be changed.

   .idea-attr is padded 4px on the right against 10px on the left, which looks
   even only because .idea-attr-btn adds 8px of its own after the caret -- 10
   against 12, near enough. Take the button away and the same rule reads 10
   against 4, and the text sits visibly hard against the right edge.

   Symmetric here rather than 12px: with no caret there is no optical weight on
   that side to balance, so even is even.

   It cannot reach the small chips on the wall tiles. Those are built as their
   own span in renderTileCard() and never go through renderAttrChip(), so they
   never carry this class -- which is why this needs no :not() to stay off
   .idea-attr--sm and its 1px 8px. */
.idea-attr--static {
    padding-right: 10px;
}

/* To Be Determined, which is an answer rather than a gap.

   An idea starts here and a writer can choose it back deliberately, so it
   reads as a value: upright, not italic, and in the ordinary ink. The muted
   italic below is for a stage nobody has ever set, which is a different
   thing and should not look the same. */
.idea-attr.is-undecided .idea-attr-value {
    font-weight: 600;
    color: var(--sb-muted, #6b6664);
}

/* An idea from before these fields existed. Nothing guesses on its behalf, so
   the chip says what it is missing and reads as an invitation rather than as
   a value -- lighter, and in the muted colour the rest of the page uses for
   things that are not there yet. */
.idea-attr.is-unset .idea-attr-value {
    font-weight: 400;
    font-style: italic;
    color: var(--sb-muted, #6b6664);
}

/* ---------------------------------------------------------- what it says

   Colour on the Status chip only. Stage is a progression and every step of it
   is a perfectly good place to be, so colouring it would be inventing a value
   judgement the writer did not ask for -- the last one gets the house gold
   because finishing is worth marking, and the rest stay plain.

   Status is different: it is the difference between an idea being worked on
   and one that was given up, and that is worth seeing before reading.

   Classes come from the slug, so a status added to story_values later gets
   the plain chip rather than no rule at all. */

.idea-attr--stage.is-complete {
    border-color: var(--gold, #c9a84c);
    background: var(--gold-tint, #faf7ef);
}

.idea-attr--status.is-active {
    border-color: #7ba86b;
    background: #f2f7f0;
}

.idea-attr--status.is-active .idea-attr-value {
    color: #46663a;
}

.idea-attr--status.is-complete {
    border-color: var(--gold, #c9a84c);
    background: var(--gold-tint, #faf7ef);
}

.idea-attr--status.is-complete .idea-attr-value {
    color: #8a6f21;
}

.idea-attr--status.is-on-hold {
    border-color: #c9a84c;
    background: #fbf6ea;
}

.idea-attr--status.is-on-hold .idea-attr-value {
    color: #8a6f21;
}

/* Abandoned recedes rather than alarms. It is not an error -- putting an idea
   down is a legitimate end for one -- so it greys out instead of going red. */
.idea-attr--status.is-abandoned {
    border-color: #c9c5c3;
    background: #f3f2f2;
}

.idea-attr--status.is-abandoned .idea-attr-value {
    color: #6b6664;
    text-decoration: line-through;
    text-decoration-thickness: 1px;
}

/* ------------------------------------------------------------- the menu

   A white card on a light border with a soft shadow, and left-aligned: this
   hangs under a chip in the middle of the page, and a menu pinned to the chip's
   right edge would open away from the word it belongs to. It used to be
   described as "the same furniture as .idea-add-menu", which was the header's
   Add menu -- gone now, so the description lives here. */

.idea-attr-menu {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    z-index: 30;
    min-width: 180px;
    display: flex;
    flex-direction: column;
    padding: 4px;
    border: 1px solid var(--sb-line, #c9c5c3);
    border-radius: 6px;
    background: #fff;
    box-shadow: 0 6px 18px rgba(32, 30, 29, .18);
}

.idea-attr-menu[hidden] {
    display: none;
}

.idea-attr-item {
    padding: 7px 10px;
    border: 0;
    border-radius: 4px;
    background: none;
    color: var(--sb-ink, #201e1d);
    font-family: var(--font-sans);
    font-size: 14px;
    text-align: left;
    white-space: nowrap;
    cursor: pointer;
}

.idea-attr-item:hover,
.idea-attr-item:focus-visible {
    background: var(--sb-accent-tint, #f7f0dc);
}

/* The one it already is. Bold rather than ticked: a tick would need a column
   of space kept clear on every other row to line up in. */
.idea-attr-item.is-chosen {
    font-weight: 700;
    color: #8a6f21;
    cursor: default;
}

/* ------------------------------------------------------------- the star

   Hollow when off and solid when on -- the cue that survives being glanced at,
   and the one that still works when the gold does not read. */

.idea-star {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: none;
    color: var(--sb-muted, #6b6664);
    font-size: 17px;
    line-height: 1;
    cursor: pointer;
    transition: color .15s ease, background .15s ease, transform .12s ease;
}

span.idea-star {
    cursor: default;
}

.idea-star.is-on {
    color: var(--gold, #c9a84c);
}

@media (hover: hover) {

    button.idea-star:hover {
        background: var(--gold-tint, #faf7ef);
        color: var(--gold, #c9a84c);
        transform: scale(1.1);
    }
}

@media (prefers-reduced-motion: reduce) {

    button.idea-star:hover {
        transform: none;
    }
}

.idea-star:focus-visible {
    outline: 2px solid var(--gold, #c9a84c);
    outline-offset: 1px;
}

/* ------------------------------------------------------- deleting an idea

   The one control on this page that cannot be undone from this page, so it is
   the one that does not look like the others. Red only on a hover: a red
   button sitting in the header of every idea would read as a warning about
   the idea rather than as something to press.

   Two classes, since .solid-btn and .idea-nav-btn both set a background and
   are written in other files. */

.idea-nav-btn.idea-nav-btn--danger {
    background: none;
    border: 1px solid var(--sb-line, #c9c5c3);
    color: var(--sb-muted, #6b6664);
    transition: color .15s ease, border-color .15s ease, background .15s ease;
}

@media (hover: hover) {

    .idea-nav-btn.idea-nav-btn--danger:hover {
        border-color: var(--sb-danger, #e85347);
        background: #fdf2f1;
        color: var(--sb-danger, #e85347);
    }
}

.idea-nav-btn.idea-nav-btn--danger:focus-visible {
    outline: 2px solid var(--sb-danger, #e85347);
    outline-offset: 1px;
}

/* Inside the confirmation, which is a SweetAlert rather than part of the page.
   The reassurance is quieter than the warning above it: it is there to be
   found by somebody looking for it, not to compete with the question. */
.idea-delete-ask p {
    margin: 0 0 8px;
}

.idea-delete-ask .idea-delete-keep {
    margin: 12px 0 0;
    font-size: 14px;
    color: var(--sb-muted, #6b6664);
}

/* ------------------------------------------------------------ scene boards

   Cards that wrap, the way .sb-cards lays the board picker out and the way the
   Characters panel lays out beside it. A row each was a great deal of width for
   a title and five words of meta, and an idea holding three arrangements showed
   three near-empty bands down the page.

   auto-fill rather than auto-fit, for the same reason .idea-grid uses it: with
   one board, auto-fit would stretch its card the width of the column, which
   reads as a banner rather than as the first of a set.

   220px rather than the picker's 240: this column is capped at 720px, and 220
   is what lets three sit on a line there instead of two. Below that the grid
   drops to two and then to one on its own -- the point at which a card can no
   longer show its title and its meta is the point at which it should have the
   line to itself. */

.idea-board-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 10px;
}

.idea-board {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 10px 12px;
    border: 1px solid var(--sb-line, #c9c5c3);
    border-radius: 6px;
    background: var(--sb-surface, #fff);
    color: inherit;
    text-decoration: none;
    transition: border-color .15s ease, background .15s ease, box-shadow .15s ease;
}

/* The same three declarations as .sc-list--wide .sc-item:hover, and deliberately
   so: the cast card and the board card sit on the same page, one above the
   other, and both open what they name when clicked. */
@media (hover: hover) {

    .idea-board:hover {
        border-color: var(--gold, #c9a84c);
        background: var(--gold-tint, #faf7ef);
        box-shadow: 0 1px 0 rgba(32, 30, 29, .18);
    }
}

.idea-board-text {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.idea-board-title {
    font-size: 15px;
    font-weight: 700;
    line-height: 1.25;
    /* "Three acts, told backwards" in a 220px card shortens rather than pushing
       the card taller than the ones beside it. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.idea-board-meta {
    font-size: 12px;
    color: var(--sb-muted, #6b6664);
}



/* -------------------------------------------------- attachments and media

   The widget itself is the one the script and project panels draw -- see
   renderAttachmentsMedia() in pages/dashboard.php. It is moved into this host
   rather than rebuilt, so what follows is the only thing that differs about it
   here, and it is all presentation.

   Scoped to the host on purpose: the script and project panels keep the heading
   they have always had. */

.idea-attachments-host {
    /* NO NEGATIVE MARGIN.
     *
     * This was -4px, to take back spacing the widget's own block-head brings
     * with it -- built for a panel that starts at the top of a page rather than
     * a section in a column. The block-head's spacing has since come down (see
     * the .block-title rule below, which sets its margin outright), so the -4
     * was no longer cancelling anything: it was pulling ATTACHMENTS/MEDIA four
     * pixels closer to the scene board above it than any other heading on the
     * page sits to what precedes it.
     *
     * The column's own 15px gap is the spacing between sections. Nothing here
     * should be adding to it or taking from it. */
    margin-top: 0;
}

/* The heading and the tab labels take this page's section styling, because on
   this page that is what they are -- Attachments/Media sits in the same column
   as Logline and Notes and should not be the one shouting.
   
   The weight, the tracking, the case and the colour are shared. The SIZE is
   not, and that is the fix rather than the omission: this block used to set
   both to 14px under a comment claiming they matched .idea-section-head, which
   has been 16px since the day the file was written. They never matched, and
   ATTACHMENTS/MEDIA has been drawing a size smaller than LOGLINE beside it.

   The heading is 16px below, with its siblings. The tabs stay at 14px on
   purpose: Files and Images are controls you click, not titles, and a tab strip
   set in heading-sized capitals reads as four more section headings.

   This sets the RESTING state only. It does not lose to .nav-tabs
   .nav-link.active on its own: both are three classes, and css/idea.css loads
   after css/dashboard.css, so a tie goes to this one -- which left the selected
   tab gold along with the rest. The rule below is what gives it back. */
/* .04em, down from .06, to match .nav-tabs .nav-link now that the whole site
   is uppercase. The colour and the weight are this page's own -- a gold strip
   is the idea page's theme -- but the letterform spacing is not a theme, and
   two tab rows a scroll apart set differently is the drift this was fixing. */
.idea-attachments-host .block-title,
.idea-attachments-host .nav-tabs .nav-link {
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--gold, #c9a84c);
}

/* The heading's own size and spacing, which a tab has no use for. 16px is
   .idea-section-head's, and the two want to stay that way -- see the note
   above about them having drifted once already. */
.idea-attachments-host .block-title {
    font-size: 16px;
    margin: 0 0 5px;
}

/* And the 5px indent, which is not this page's.
   
   .block-head carries padding-left: 5px in css/dashboard.css, built for a
   widget that starts at the top of a panel page. Here the widget is one section
   in a column of them, and that 5px was enough to make ATTACHMENTS/MEDIA sit
   visibly right of LOGLINE and SCENE BOARDS above it. */
.idea-attachments-host .block-head {
    padding-left: 0;

    /* And 4px on top, which is not arbitrary.
     *
     * Every other heading on this page sits in .idea-section-bar -- a flex row
     * 26px tall, because of the plus or pencil beside it, with the 16px heading
     * centred in it. That leaves 5px above the letters. This widget's heading
     * has no such row and sat 1px below its section's top, so ATTACHMENTS/MEDIA
     * rode 4px higher than every heading above and below it and looked crowded
     * against the scene board.
     *
     * Measured, not guessed: section-top to heading-top is 5px there and was
     * 1px here. */
    padding-top: 4px;
}

/* And the tab's own padding, which the heading has no use for. 12px was built
   for the 18px labels the widget used to carry on a panel page and left the
   row taller than the type needed.

   NO font-size ANY MORE. This set 14px back when the site default was 18 and
   sentence case, and this page had already gone uppercase on its own -- see
   the rule above, which has been doing that since it was written. The default
   is now 16px uppercase everywhere, which is what this page wanted in the
   first place, so the override has nothing left to say. */
.idea-attachments-host .nav-tabs .nav-link {
    /* 5px under against 9 over, the site's uneven tab padding at this row's
       own scale. See .nav-tabs .nav-link in css/dashboard.css. */
    padding: 9px 16px 5px 16px;
}

/* The selected tab, said here because the gold above would otherwise take it.
   Four classes, so this outweighs both that rule and dashboard.css's own --
   which is what it is for: the resting tabs carry the page's heading colour and
   the chosen one carries the site's, the way it does on every other panel. */
.idea-attachments-host .nav-tabs .nav-link.active {
    color: var(--primary);
    border-bottom-color: var(--primary);
}

/* No icon. None of the other section titles has one, and a photo-video glyph
   beside a gold uppercase heading is the widget's own furniture showing through
   a page that does not use it. Hidden rather than cut from the markup: the same
   markup draws the script and project panels, where the icon belongs. */
.idea-attachments-host .block-title i {
    display: none;
}

/* The one button the widget has, sitting at the right edge of its heading row.
   .block-between is flex-start, so auto on the left is what pushes it over --
   the row has no other item to space it against. Only the left margin is
   touched; the button's own vertical margin is right as it is.

   The height comes from the padding. The button is built for a panel heading
   with room to spare, and at that size it sets the height of this row and makes
   the Attachments bar taller than every other section heading on the page. 3px
   brings it back in line. Horizontal padding is left alone -- the label still
   needs its room.

   Deliberately unlike the plus icons on the other sections, which sit next to
   their heading. Attachments has a wide labelled button rather than a glyph, and
   a labelled button beside a short gold heading reads as part of the title. */
.idea-attachments-host #idea-media-upload-btn {
    margin-left: auto;
    font-size: 14px;
    gap: 0px;
    padding: 4px 10px 3px 10px;
    border: 1px solid #aca8a8;
}

/* The widget's card carries margin-bottom: 24px, which is right on a panel page
   where it separates one widget from the next. Here the sections are a flex
   column with its own 18px gap, so the two stack and Notes appears to be pushed
   away from Attachments while every other section sits evenly.

   The gap is the page's to decide, so the card gives its margin up. */
.idea-attachments-host .card {
    margin-bottom: 0;
}

/* Thumbnails and file names, sized for a 720px column rather than a full panel.

   The widget is built for a page where it has the width to itself. Here it sits
   in the same column as the loglines, so a 200px thumbnail is most of the
   column and an 18px file name is larger than the prose above it. */

.idea-attachments-host .media-thumb {
    max-width: 150px;
    max-height: 150px;
}

/* The file name. .caption-text sets 18px for a panel; on this page it is the
   only thing in the column louder than the writing it sits under. */
.idea-attachments-host .scriptTitle {
    font-size: 14px;
}

/* And its icon, which is 30px and would tower over the name once the name comes
   down. Not asked for, but leaving it would trade one mismatch for another. */
.idea-attachments-host .caption-text i {
    font-size: 20px;
}

/* The attachments table's column headings, sized for this column.
 *
 * .content thead tr th was 16px with 10px of padding, built for a table with a
 * panel to itself, and here it was the loudest thing in a 720px column and
 * taller than the rows beneath it. That rule has since come down to 14px with
 * the change of face, so only the padding below is still doing work -- the
 * size is kept because it says what this column wants rather than what the
 * base rule currently happens to be, and the two have already drifted once.
 *
 * Anchored on .card rather than written as .idea-attachments-host thead tr th,
 * which would carry exactly the weight of the rule it is overriding and win only
 * because css/idea.css happens to load second. .card is inside the widget and
 * always will be, so this wins on its own terms.
 */
.idea-attachments-host .card thead tr th {
    padding: 5px 10px;
    font-size: 14px;
}

/* The space under the tab strip.

   14px is built for a panel that owns its page, where the tabs are the top of
   the thing and the pane below them is most of it. Here the widget is one
   section in a column of sections, and the sections space themselves: the
   column's own 18px gap is already doing this job, so the pane's padding was
   being added to it and Attachments sat looser than everything above it.

   Vertical only. The pane has never been indented and should not start. */
.idea-attachments-host .tab-pane {
    padding: 8px 0;
}

/* "No Images", "No Videos", "No Audio Files" -- and the same for a tab with
   nothing in it yet.

   20px is the size on the dashboard, where it is a line of its own in a wide
   panel with nothing to compare against. This column runs 16px headings over
   15px prose, and a 20px line in the middle of it was the largest text on the
   page by a clear step -- an empty tab saying more, loudly, than the writing
   around it.

   18px, and still above the heading. That is deliberate rather than a
   half-measure: it is a placeholder in the middle of an empty box and should
   read as one instead of as something somebody wrote. The muted colour and the
   centring say the same thing and are unchanged. What it stops being is the
   thing the eye goes to first. */
.idea-attachments-host .noneparagraph {
    font-size: 18px;
}

/* ------------------------------------------------------ sharing an idea

   popup/ideaShare.php: who has been asked to read this, and a form for asking
   one more. Wider than the other idea dialogs because it holds a table, and it
   is deliberately NOT in the :has() overflow:visible rule above -- that rule
   exists so the genre picker's menu can escape a short dialog, and this one has
   no picker and every reason to scroll when the list gets long. */

.idea-share-dialog {
    width: min(680px, 94vw);
}

.idea-share-title {
    margin: 0 0 2px;
    font-size: 20px;
    font-weight: 600;
    color: var(--sb-ink, #2c2724);
}

/* Said once, at the top, instead of a privilege dropdown holding one option --
   a control that asks a question it will not accept an answer to. */
.idea-share-note {
    margin: 0 0 16px;
    padding: 8px 12px;
    border-left: 3px solid var(--warning);
    background: var(--sb-tint, rgba(225, 148, 7, .07));
    font-size: 13.5px;
    line-height: 1.45;
    color: var(--sb-muted, #6b6664);
}

.idea-share-note i {
    margin-right: 5px;
    color: var(--warning);
}

/* --------------------------------------------------- who it is shared with

   The table moved out of the dialog and onto the page, under "Shared With".
   It carries no .popupTable class here, so the specificity fight that made the
   old rules lose is simply not on -- but they stay anchored on the section
   anyway, because .idea-invite-table td is one class and one element and this
   file is full of things that beat that by accident.

   Everything centred, headings and cells alike, so a column reads as a column. */

/* Anchored, so it beats .card's own 24px bottom margin on specificity rather
   than on css/idea.css happening to load after css/dashboard.css. The section
   below it provides the gap. */
.idea-section--invites .idea-invite-table {
    width: 100%;
    margin: 0;
    font-size: 14px;

    /* NOT border-collapse: collapse, which is what this had. A collapsed table
       draws its edges per-cell, so .card's 10px radius has nothing to round --
       the box would come out square at the corners and the border would double
       up along the top. Separate with no spacing looks identical and lets the
       table's own border and radius be the ones that draw. */
    border-collapse: separate;
    border-spacing: 0;
}

/* The rounded edge needs air, or the first and last columns sit against it.
   :first-child / :last-child rather than a padding on every cell, which would
   push the middle three apart for no reason. */
.idea-section--invites .idea-invite-table th:first-child,
.idea-section--invites .idea-invite-table td:first-child {
    padding-left: 14px;
}

.idea-section--invites .idea-invite-table th:last-child,
.idea-section--invites .idea-invite-table td:last-child {
    padding-right: 14px;
}

.idea-section--invites .idea-invite-table th,
.idea-section--invites .idea-invite-table td {
    text-align: center;
    padding: 6px 8px;
}

.idea-section--invites .idea-invite-table th {
    font-size: 13px;
    font-weight: 600;
    color: var(--sb-muted, #6b6664);
    border-bottom: 1px solid var(--border);
    /* Only the bottom edge. A top border here would sit a hair inside the
       card's own and read as a double line. */
    padding-top: 10px;
}

.idea-section--invites .idea-invite-table td {
    vertical-align: middle;
    border-bottom: 1px solid var(--sb-rule, rgba(0, 0, 0, .06));
}

.idea-section--invites .idea-invite-table tr:last-child td {
    border-bottom: 0;
    padding-bottom: 10px;
}

/* An address is the longest thing in the row and the least worth reading in
   full, so it is the one that gives way first. */
.idea-section--invites .idea-invite-email {
    max-width: 260px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.idea-invite-status {
    font-size: 13px;
    font-weight: 600;
}

/* Named for the condition of the invitation rather than for the word on
   screen or the value in the column.

   'reading' is "accepted and still good", which is why it is not called
   'accepted': an invitation that has lapsed carries that column value too, and
   a class named after it would quietly claim both. The word the writer reads
   IS Accepted -- see ideaInviteForClient(), where the label and the state are
   worked out side by side and deliberately do not have to match. */
.idea-invite-status.is-reading {
    color: var(--primary-green);
}

.idea-invite-status.is-waiting {
    color: var(--warning);
}

.idea-invite-status.is-declined {
    color: var(--danger);
}

.idea-invite-status.is-expired {
    color: var(--sb-muted, #6b6664);
}

/* The X that ends somebody's access. .idea-tool gives it its size and hit area;
   this is only the colour it warns in. */
.idea-tool.idea-tool--danger {
    color: var(--sb-muted, #6b6664);
}

.idea-tool.idea-tool--danger:hover {
    color: var(--danger);
    border-color: var(--danger);
}

/* The form is a second thing the panel does, and this line is what says so.
   It used to hang off an "Invite someone" heading; the heading went and the
   rule moved onto the form itself, because what was doing the work was the
   line rather than the words above it. */
#form-idea-share {
    padding-top: 16px;
    border-top: 1px solid var(--border);
}

/* Two fields that belong together and are each half a name. Collapses rather
   than shrinking below the width where a name stops being readable. */
.idea-share-names {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
}

.idea-share-names .form-group {
    flex: 1 1 200px;
    min-width: 0;
}

/* The date input draws itself full-width like every other field here, which
   makes a six-character value look like a missing one. */
.idea-share-date {
    max-width: 200px;
}

/* Whose note this is.
 *
 * Only drawn on a note, and only on somebody else's -- ideaTextForClient()
 * sends an empty author otherwise -- so an idea nobody else has written on
 * looks exactly as it did before notes were shared. That is the point of
 * putting the test on the server: the page has no rule saying "unless it is
 * mine", because it is never told about those.
 *
 * Above the words rather than beside the date below them, because it is who is
 * speaking and that is read first. Which it was not: .idea-text is a row, so a
 * paragraph dropped into it became a column beside the writing and pushed the
 * writing right. flex-basis:100% is what makes it a line of its own -- it
 * fills the row, and everything after it wraps underneath. */
.idea-text-author {
    flex: 0 0 100%;
    margin: 0 0 3px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .04em;
    color: var(--gold, #c9a84c);
}

/* The name is a link to whoever wrote the note.
 *
 * It takes the line's own colour rather than the browser's blue: it is a name
 * first and a link second, and a blue name over a gold one down a column of
 * notes would read as two different kinds of thing. The underline on hover is
 * what says it can be followed -- which is the whole of what a link has to
 * say once the pointer is on it. */
.idea-author-link {
    color: inherit;
    text-decoration: none;
    cursor: pointer;
}

.idea-author-link:hover,
.idea-author-link:focus-visible {
    text-decoration: underline;
}

/* The AI read of the leading logline ---------------------------------------

   A row of the logline list, directly under the lead and above the Alternate
   loglines heading -- so what it is a read OF is never in question. The panel
   it holds is drawn by includes/loglinerender.php and carries its own styling
   from css/ai-logline.css, which the dashboard loads alongside this.

   Indented to the depth the lead sits at, so it reads as belonging to that
   logline rather than to the list. */
.idea-ai-review {
    /* Nothing at the bottom, and the panel's own margin is taken off below so
       the two cannot stack. 16 here plus .ai-panel's 14 put a 30px hole
       between the lead logline and the alternates -- the panel is sized for
       the script card, where several sit in a column and need telling apart.
       Here the list's own spacing already separates the rows. */
    margin: 2px 0 0 10px;
}

.idea-ai-review .ai-panel {
    margin-bottom: 0;
}

/* The Analyse button, sized for a heading rather than for a form.
 *
 * It sits in .idea-section-bar now, beside the LOGLINE heading and its plus,
 * so it has to be the height of that line -- a full .btn is 42px tall against
 * a 26px plus and a heading in small caps, which makes the row look like a
 * toolbar that has landed on the page rather than a heading with two controls
 * on it.
 *
 * TWO CLASSES, AND THAT IS THE POINT
 *
 * .btn carries its own padding and font-size, and css/global.css is loaded
 * AFTER this file -- see template.php, which puts it last on purpose. A rule
 * of one class here loses to a rule of one class there whatever it says, which
 * is exactly what happened the first time this was written as
 * .idea-ai-review-go alone: 42px, unchanged. The section bar is what it lives
 * in, so naming it is honest rather than a specificity trick.
 *
 * The words stay. This is the one AI action on the page and it spends credits;
 * an icon alone would be a thing to guess at. */
.idea-section-bar .idea-ai-review-go {
    padding: 2px 10px;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.5;
    border-radius: 4px;
    white-space: nowrap;
    flex: none;
    gap: 4px;
}

/* No lift and no shadow on a button this size: .btn:hover raises it 2px, which
   on a 24px control beside a heading reads as the row twitching. */
.idea-section-bar .idea-ai-review-go:hover {
    transform: none;
    box-shadow: none;
    border-color: var(--sb-accent, #c9a84c);
}

.idea-section-bar .idea-ai-review-go i {
    font-size: 11px;
}

/* QUICK SKETCH, ON THE CHARACTERS HEADING
 *
 * The same move the Analyse button above made, for the same reason: an action
 * on a section belongs on that section's line. It was a lone button sitting
 * over the cast, which on a page of headings-with-controls was the one control
 * that had wandered off.
 *
 * The span is a hole, not a box. js/character.js writes the button into it when
 * the cast lands -- it owns whether Quick sketch can run at all -- and
 * display:contents means an empty slot costs nothing, not even the row's 6px
 * gap, on every idea where the answer is no.
 *
 * The sizing below is .idea-section-bar .idea-ai-review-go's, declared again
 * rather than shared: the two buttons come from different stylesheets (this one
 * and css/ai-images.css) and neither is the other's base. If a third joins them
 * they should become one list. */
.idea-sketch-slot {
    display: contents;
}

.idea-section-bar .sc-quick-sketch {
    padding: 2px 10px;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.5;
    border-radius: 4px;
    white-space: nowrap;
    flex: none;
    gap: 4px;
}

.idea-section-bar .sc-quick-sketch i {
    font-size: 11px;
    /* .sc-quick-sketch i carries a 5px right margin for the button in the
       panel, where there is no flex gap to do it. Here there is one. */
    margin-right: 0;
}

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

/* And the wrapper with it, before there is a report to put in it.
 *
 * The out div hid itself, which was not enough: the wrapper stayed, and it is
 * an item in .idea-text-list -- a flex column with an 8px gap. So an idea that
 * had never been analysed carried an invisible row under its logline, the gap
 * that separates it from the row above, and this rule's own top margin: about
 * ten pixels of nothing between the logline and GENRE(S), on the one section
 * where the page looked loose.
 *
 * display:none takes it out of the flex flow entirely, gap included. :has()
 * re-evaluates as soon as the report is written in, so the space appears with
 * the thing that needs it. */
.idea-ai-review:has(.idea-ai-review-out:empty) {
    display: none;
}