/* css/character.css
 *
 * The Characters sidebar panel and the add/edit dialog.
 *
 * Namespaced .sc- throughout, so this is safe to load anywhere -- the same
 * arrangement css/storyboard.css uses with .sb-.
 *
 * The palette is the board's: the gold accent for anything the writer has
 * claimed, neutrals for everything the script merely reports. A character that
 * has been written up is the writer's own work, so the tracked list wears the
 * accent and the untracked names underneath stay grey.
 */

/* ---------------------------------------------------------------- the panel */

.sc-panel {
    padding: 0 4px 12px;
    /* A flex item in #sidebarcontent, which is a fixed-height column. min-height
       is the line that lets it shrink far enough to scroll rather than run off
       the bottom -- the same pair .scene-list needs. */
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
}

/* The editor styles every paragraph in the sidebar as prose -- floated left at
   full width, with one fixed margin -- in `#sidebarcontent p`
   (editor/css/pr-editor.css). That suits the panels that are prose. It does not
   suit this one, in two ways:

   The float: anything after a heading that establishes its own formatting
   context -- a flex row, a scroller -- is placed beside those floats rather than
   below them, and a full-width float leaves nowhere to go but off the right
   edge.

   The margin: at (1,0,1) it outranks any class, so every margin this file sets
   on a paragraph was quietly discarded and the headings sat on what came before
   them.

   Scoped by #sidebarcontent so it only answers that rule where that rule
   applies, and so it outranks it. The paragraph rules below each carry a second
   selector for the same reason -- the values stay written once, and apply both
   in the sidebar and wherever this panel is used next. */
#sidebarcontent .sc-panel p {
    float: none;
    width: auto;
}

.sc-panel .sc-empty,
#sidebarcontent .sc-panel .sc-empty {
    color: #6b6b7a;
    font-size: 13px;
    line-height: 1.5;
    margin: 10px 2px;
}

/* The role a group of characters share.
 *
 * Quieter than .sc-heading below, which separates the written-up characters from
 * the names the script merely knows -- that is a division between two kinds of
 * thing, while this is a division within one kind. Same family, less weight.
 *
 * Two selectors for the same reason every paragraph in this panel needs them:
 * #sidebarcontent p floats and re-margins anything in the editor's sidebar, and
 * an id beats a class. */
.sc-panel .sc-role,
#sidebarcontent .sc-panel .sc-role {
    margin: 12px 2px 3px;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: #8d8781;
}

/* The first group sits directly under the button above it and needs no gap of
   its own; only the ones after it are separating themselves from a list. */
.sc-panel .sc-role:first-child,
#sidebarcontent .sc-panel .sc-role:first-child {
    margin-top: 2px;
}

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

.sc-item {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 6px 6px;
    border-radius: 6px;
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease, box-shadow .15s ease;
}

.sc-item:hover {
    background: #f3f2f2;
}

/* Square rather than round: these are reference pictures a writer has pinned up,
   not profile avatars, and a square keeps more of what was in the frame. */
.sc-thumb {
    flex: 0 0 34px;
    width: 34px;
    height: 34px;
    border-radius: 5px;
    background: #e2dedb;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    color: #8d8781;
    font-size: 14px;
}

.sc-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* min-width:0 so a long name ellipses instead of pushing the row wider than the
   sidebar -- a flex item will not shrink below its content without it. */
.sc-item-text {
    min-width: 0;
    display: flex;
    flex-direction: column;
    line-height: 1.3;
}

/* Upper case, as a cue is written. The name is stored however it was typed --
   the record keeps what the writer wrote -- and shown the way the script says
   it, which is also how it appears on a scene card. */
.sc-item-name {
    font-size: 13.5px;
    font-weight: 600;
    color: #201e1d;
    text-transform: uppercase;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sc-item-sub {
    font-size: 11.5px;
    color: #6b6b7a;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* The space above is the point of this element: it is what separates the names
   the script knows from the characters already written up. */
.sc-panel .sc-heading,
#sidebarcontent .sc-panel .sc-heading {
    margin: 16px 2px 2px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--text-dark);
}

.sc-panel .sc-note,
#sidebarcontent .sc-panel .sc-note {
    margin: 0 2px 8px;
    font-size: 11.5px;
    line-height: 1.45;
    color: #6b6b7a;
}

/* Names the script knows and nobody has written up. Dashed like the empty
   dropzone in the dialog: both are somewhere with nothing in it yet. */
.sc-untracked-select {
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
    /* Stated, not inherited. editor/css/pr-editor.css resets margin to 0 on
       every input, select, textarea and button, so a select in this panel has
       nothing of its own to fall back on. The 2px sides line the box up with the
       heading and the note above it, which carry the same. */
    margin: 0 2px 10px;
    padding: 6px 8px;
    border: 1px solid #bb9378;
    border-radius: 6px;
    background: transparent;
    color: #4a4644;
    font-size: 12.5px;
    font-family: inherit;
    cursor: pointer;
    transition: border-color .15s ease, background .15s ease;
}

.sc-untracked-select:hover,
.sc-untracked-select:focus {
    border-style: solid;
    border-color: var(--gold, #c9a84c);
    background: #f7f0dc;
    outline: none;
}

/* Not the whole page, where there is a whole page.

   100% is right in the sidebar, which is 260px of column. On the script
   summary page the same rule stretched the dropdown across the widget, where a
   control that wide reads as a field to fill in rather than as a way in --
   and it dwarfed the cards it feeds.

   Capped rather than fixed, so it still shrinks on a narrow window. 340px is
   the width a character card stops at, so the two line up. */
.sc-panel--wide .sc-untracked-select {
    max-width: 340px;
}

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

.sc-dialog {
    width: min(620px, 92vw);
}

.sc-top {
    display: flex;
    gap: 16px;
    align-items: flex-start;
}

.sc-fields {
    flex: 1 1 auto;
    min-width: 0;
}

/* Two per line where the values are short. Collapses to one on a narrow modal,
   which is where the dialog ends up on a phone. */
.sc-row {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
}

.sc-row>.form-group {
    flex: 1 1 150px;
    min-width: 0;
}

/* Three to a line rather than two and a stray.

   At a 150px basis a third field cannot fit beside the other two, so it wraps
   -- and alone on its line, flex-grow stretches it the full width of the form,
   which is how a Race dropdown came to be as wide as the Biography box. A
   smaller basis for the rows that hold three lets them sit together, and the
   flex-wrap above still drops them onto their own lines when the dialog is
   narrow. */
.sc-row--three>.form-group {
    flex: 1 1 105px;
}

/* Not this dialog's to change. The same grey, the same cursor and the same
   reasoning as .sb-slug-row.is-locked on a card the screenplay owns. */
.sc-dialog .dialog-field[readonly] {
    background: #f3f2f2;
    color: #6b6664;
    cursor: not-allowed;
}

.sc-field-note {
    display: flex;
    align-items: baseline;
    gap: 6px;
    margin: 4px 0 0;
    font-size: 11.5px;
    line-height: 1.35;
    color: #8d8781;
}

.sc-field-note i {
    font-size: 10px;
}

/* 156 rather than 140.

   The portrait and everything under it share one width, and what is under it
   now includes the sketch button -- "Sketch Character" does not fit on one line
   at 140. Widened here rather than letting the button break out of the column,
   so the picture, Remove image and the button all still line up. The fields
   beside it lose the 16px, which they have to spare. */
.sc-portrait {
    flex: 0 0 156px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.sc-dropzone {
    position: relative;
    width: 156px;
    height: 156px;
    border: 2px dashed #cfc9c5;
    border-radius: 8px;
    background: #faf8f3;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    overflow: hidden;
    transition: border-color .2s, background .2s;
}

.sc-dropzone:hover,
.sc-dropzone.is-over {
    border-color: var(--gold, #c9a84c);
    background: #f7f0dc;
}

/* Solid once there is something in it: the dashes say "put something here", and
   they have stopped being true.

   The cursor changes with them. A pointer on a filled frame promises the file
   dialog it used to open; zoom-in promises what it does now, which is to show
   the picture full size. */
.sc-dropzone.has-image {
    border-style: solid;
    border-color: #e4e0d6;
    background: #fff;
    cursor: zoom-in;
}

.sc-dropzone img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.sc-dropzone-prompt {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 7px;
    padding: 8px;
    text-align: center;
    color: #8d8781;
    font-size: 11.5px;
    line-height: 1.35;
    pointer-events: none;
}

.sc-dropzone-prompt i {
    font-size: 26px;
    color: #cfc9c5;
}

/* The X on the picture.

   Hidden by default and shown by .has-image on the dropzone, rather than by an
   inline style: the class is already maintained everywhere the picture changes
   -- the upload preview, the remove, and the AI sketch picker -- so there is
   one thing to keep right instead of two that can disagree.

   Dark on a translucent ground rather than a red link, because it sits on top
   of somebody's portrait and has to be legible over hair, sky or a white
   collar without shouting at any of them. */
.sc-image-remove,
.sc-image-replace,
.sc-image-download {
    display: none;
    position: absolute;
    top: 6px;
    width: 24px;
    height: 24px;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(20, 16, 12, .55);
    color: #fff;
    font-size: 13px;
    line-height: 1;
    cursor: pointer;
    transition: background .15s;
}

.sc-image-remove {
    right: 6px;
}

/* Beside the X, and the same size: these are a pair, and one of them being
   quieter than the other would be a claim about which is more likely. */
.sc-image-replace {
    right: 34px;
    font-size: 12px;
}

/* Third along. Text-decoration because it is an anchor and the dialog
   underlines those; nothing about this one should look like a link. */
.sc-image-download {
    right: 62px;
    font-size: 12px;
    text-decoration: none;
}

.sc-dropzone.has-image .sc-image-remove,
.sc-dropzone.has-image .sc-image-replace,
.sc-dropzone.has-image .sc-image-download {
    display: flex;
}

.sc-image-remove:hover {
    background: #b91c1c;
}

.sc-image-replace:hover,
.sc-image-download:hover {
    background: var(--primary, #6576ff);
    color: #fff;
}

/* ---- profession: one value, offered like a tag ---- */

/* The border, the corners and the padding come from .dialog-field in
   css/modal.css, which this element carries -- so it is outlined and sized like
   the inputs beside it, and stays that way if that rule changes. What is left
   here is the only part that is actually its own: a row that a chip and a caret
   share. */
.sc-prof-field {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    align-items: center;
    cursor: text;
}

/* With a chip in place there is nothing left to type -- one profession, so the
   entry goes rather than sitting there inviting a second. */
.sc-prof-field.full #sc-prof-entry {
    display: none;
}

/* Invisible: the wrapper is the box, and this is only the caret inside it. Its
   own padding would make the field taller than the inputs it sits beside, which
   is what the wrapper's .dialog-field padding is already for. */
#sc-prof-entry {
    flex: 1 1 90px;
    min-width: 70px;
    border: 0;
    outline: none;
    padding: 0;
    font: inherit;
    background: transparent;
}

/* Sized to stay just inside the height of the caret beside it, so a field with a
   chip in it is no taller than the empty one -- and no taller than the select it
   sits next to in the same row. */
.sc-prof-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: #f7f0dc;
    border: 1px solid var(--gold, #c9a84c);
    color: #8a6f21;
    border-radius: 13px;
    padding: 0 6px 0 10px;
    font-size: .82rem;
    line-height: 1.55;
}

.sc-prof-chip button {
    border: 0;
    background: none;
    padding: 0;
    cursor: pointer;
    color: inherit;
    opacity: .6;
    font-size: .8rem;
    line-height: 1;
    display: flex;
    align-items: center;
}

.sc-prof-chip button:hover {
    opacity: 1;
    color: #b91c1c;
}

/* position:relative rather than absolute: the modal scrolls, and an absolutely
   positioned list detaches from the field the moment it does. */
/* What the list is positioned against. Only this field's group, so nothing else
   in the dialog gains a containing block it did not ask for. */
.sc-prof-group {
    position: relative;
}

.sc-prof-dropdown {
    display: none;
    /* Out of the flow, hanging from the bottom of the field.
     *
     * It was position:relative, on the reasoning that the dialog scrolls and an
     * absolutely positioned list would come adrift from its field. That was
     * wrong: absolute is measured against .sc-prof-group, which scrolls with
     * everything else, so the list stays where it belongs -- only `fixed` would
     * have detached. What relative actually did was leave the list in the flow,
     * so opening it grew the dialog and pushed Physical Appearance and Biography
     * down the screen.
     *
     * Out of flow it overlays them instead. The dialog's own box has
     * overflow:auto and a max-height, so a long list extends what can be
     * scrolled to rather than what the dialog measures. */
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    /* Above the fields it covers. Nothing else in the dialog sets a z-index, so
       this only has to beat the default. */
    z-index: 20;
    /* Hangs off the bottom of the field, so it wears the field's border and the
       field's corners -- the same token, and the same radius, as .dialog-field. */
    border: 1px solid var(--border);
    border-top: 0;
    border-radius: 0 0 4px 4px;
    background: #fff;
    max-height: 215px;
    overflow-y: auto;
    box-shadow: 0 3px 8px rgba(0, 0, 0, .07);
}

.sc-prof-dropdown.show {
    display: block;
}

.sc-prof-option {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 11px;
    cursor: pointer;
    font-size: .88rem;
}

.sc-prof-option.active {
    background: #f4f6f9;
}

.sc-prof-option>i {
    color: #9aa5b1;
    font-size: .78rem;
}

.sc-prof-count {
    margin-left: auto;
    color: #9aa5b1;
    font-size: .78rem;
}

.sc-prof-create {
    border-top: 1px solid #eef0f3;
    color: #166534;
}

@media (max-width: 560px) {

    /* The portrait goes above the fields rather than beside them: at this width
       a 156px column leaves the name field too narrow to read what is in it. */
    .sc-top {
        flex-direction: column;
    }

    .sc-portrait {
        flex-basis: auto;
        align-self: center;
    }
}

/* ------------------------------------------------ the panel on an idea page

   The same markup as the sidebar, laid out across a page instead of down a
   260px column. One render path and one difference in the stylesheet, so a
   character that gains a field gains it in both places at once.

   The cards wrap rather than sit in fixed columns, because the number of them
   is what varies: a story with one protagonist and six supporting characters
   should not leave five empty slots in a grid, and a narrow window should not
   scroll sideways to reach the seventh. */

.sc-list--wide {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

/* Grow to share whatever the row has left, but never past a width where the
   line of prose underneath stops being readable, and never below one where the
   name has to ellipsis. Between those two the number per row is the window's
   business. */
.sc-list--wide .sc-item {
    flex: 1 1 240px;
    max-width: 340px;
    align-items: flex-start;
    padding: 10px;
    border: 1px solid var(--sb-line, #c9c5c3);
    border-radius: 6px;
    background: #fff;
}

/* The card and .idea-board answer a hover the same way, because they answer a
   click the same way: both open the thing they name. A tint as well as the gold
   edge -- a border alone is a small change to notice on a card this size, and it
   reads as decoration rather than as "this one".

   Its own rule rather than leaning on .sc-item:hover above. That one sets a
   background, but so does the card, with the same weight and further down the
   file, so the card's white won every time and the wide list has never shown a
   hover at all.

   --gold-tint is the gold lightened most of the way to white. It lives in
   global.css because the idea tiles and the dashboard tables wear it too, and
   a hover meaning the same thing in three places should not be three hex
   codes that happen to agree today.

   Not --sb-accent-tint, which is spoken for: that is what a selected or
   just-saved card wears on a board, and hovering is not selecting. */
@media (hover: hover) {

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

/* A face worth looking at rather than a marker beside a name.

   TALLER THAN IT IS WIDE, AND FOR A REASON

   2:3, which is the shape the sketches are generated in -- see
   aiImageSpec('image.character'). A square crops a portrait to its middle:
   .sc-thumb img is object-fit: cover, so 56x56 took a band across the face and
   threw away the top of the head and the shoulders, which on a charcoal study
   is most of what there was to look at.

   84 rather than something smaller because the card is already about that tall:
   a name, a line of facts and two clamped lines of prose inside 10px of
   padding. The picture now runs the height of the text beside it instead of
   floating at the top of a card with space under it.

   An uploaded photograph is cropped to 2:3 by the same cover rule, which is the
   right way round: the shape is the site's, and every card matches whether the
   picture was drawn or taken. */
.sc-list--wide .sc-thumb {
    flex: 0 0 56px;
    width: 56px;
    height: 84px;
    border-radius: 6px;
    font-size: 20px;
}

.sc-list--wide .sc-item-text {
    gap: 2px;
    padding-top: 1px;
}

.sc-list--wide .sc-item-name {
    font-size: 15px;
}

.sc-list--wide .sc-item-sub {
    font-size: 13.5px;
}

/* Two lines of what they look like, and the card stays the height it was.
   Clamped here rather than cut in the JS so the whole sentence is still in the
   page -- it is the dialog's to show in full, not this list's to throw away. */
.sc-list--wide .sc-item-blurb {
    margin-top: 3px;
    font-size: 13px;
    line-height: 1.3;
    color: #6b6b7a;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
}

/* Making one up, where there is no script to have named them. */
.sc-new-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 10px;
    padding: 6px 12px;
    border: 1px solid var(--sb-line, #c9c5c3);
    border-radius: 5px;
    background: #fff;
    color: #201e1d;
    font-family: 'Cabin Condensed', sans-serif;
    font-size: 13px;
    cursor: pointer;
}

.sc-new-btn:hover {
    border-color: var(--sb-accent, #c9a84c);
    background: var(--sb-accent-tint, #f7f0dc);
}

/* On a page the panel is a section of it, not a column that scrolls on its own.
   The sidebar rule above makes it a scrolling flex item, which inside a page
   section would give the section its own scrollbar. */
.idea-section .sc-panel {
    padding: 0;
    flex: none;
    overflow: visible;
}
/* ------------------------------------------------ a character, read only

   What somebody invited to look over an idea gets when they click a name.

   Not the form with its controls disabled. A greyed-out field says "you may
   not touch this" about each line separately instead of simply showing the
   person, and it leaves a submit button on a dialog that has nothing to
   submit. This is a different thing, so it is drawn as one -- see the
   !$canEdit branch in popup/storyCharacter.php.

   It borrows .sc-top and .sc-portrait from the form above, because a face
   beside a handful of facts is the same arrangement whether or not the facts
   can be typed into. */

.sc-dialog--view .sc-view-portrait {
    width: 156px;
    border-radius: 6px;
    display: block;
}

/* The short facts. A definition list rather than a two-column grid of divs:
   these genuinely are terms and their values, and a reader with a screen
   reader gets that for free. */
.sc-facts {
    flex: 1 1 auto;
    min-width: 0;
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 4px 14px;
    margin: 0;
    align-content: start;
}

.sc-facts dt {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--sb-muted, #6b6664);
    /* Baselines, so a label sits on the same line as the value beside it
       rather than a pixel above it. */
    align-self: baseline;
}

.sc-facts dd {
    margin: 0;
    font-size: 15px;
    color: var(--sb-ink, #201e1d);
    align-self: baseline;
}

/* The prose below, one block per piece of writing that has any. */
.sc-view-block {
    margin-top: 16px;
}

.sc-view-head {
    margin: 0 0 4px;
    font-size: 13px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--gold, #c9a84c);
}

/* 1.45 rather than the dialog's own leading: this is the only place in a
   character dialog where a paragraph is read rather than scanned. */
.sc-view-text {
    margin: 0;
    font-size: 15px;
    line-height: 1.45;
    color: var(--sb-ink, #201e1d);
}

/* A face you can look at properly ---------------------------------------------

   Only the ones that ARE pictures. The blank placeholder opens the character
   dialog like the rest of the row, so it must not advertise a zoom it does
   not do. Same cursor the script poster uses for the same promise. */
.sc-thumb-zoom {
    cursor: zoom-in;
    transition: filter .15s ease;
}

.sc-thumb-zoom:hover {
    filter: brightness(1.08);
}
