/* ==========================================================================
   SOFTBOOK AI — VIDEO COMPOSER
   Extracted from the inline <style> in create-video.html so the standalone
   page and the studio workspace can share one copy. Requires bento.css.
   ========================================================================== */

    /* ----------------------------------------------------------------
       Dropdowns. create-image.css leaves <select> flush against its
       own text, and the native arrow disappears once the chip sets a
       transparent background — so pad it and draw the chevron here.
       ---------------------------------------------------------------- */
    .composer-rail .chip select {
      appearance: none;
      -webkit-appearance: none;
      padding: 6px 26px 6px 10px;
      border: 0;
      border-radius: 8px;
      background-color: transparent;
      color: inherit;
      font: inherit;
      line-height: 1.4;
      cursor: pointer;
      background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23a0a6b2'><path d='M4.6 6.2 8 9.6l3.4-3.4 1.1 1.1L8 11.8 3.5 7.3z'/></svg>");
      background-repeat: no-repeat;
      background-position: right 8px center;
      background-size: 12px;
    }
    .composer-rail .chip select:hover { background-color: rgba(127, 127, 127, .12); }
    .composer-rail .chip select:focus-visible {
      outline: 2px solid rgba(110, 168, 254, .55);
      outline-offset: 2px;
    }
    /* The popup list inherits the transparent background otherwise and
       becomes unreadable on some platforms. Padding matches the rest of
       the create flows. */
    .composer-rail .chip select option {
      color: initial;
      background-color: initial;
      padding: 9px 12px;
      line-height: 1.6;
    }

    /* Fine-tuning selects need room for their arrow too. */
    #safety_checker,
    #safety_tolerance { padding: 10px 34px 10px 14px; }

    /* ----------------------------------------------------------------
       Title field. The composer's floating-group now uses a label above
       a bordered box (see create-image.css), so the title only needs the
       standard control padding.
       ---------------------------------------------------------------- */
    .composer-body .floating-group #title {
      padding: 11px 14px;
      border-radius: var(--sb-r-md);
      font-size: .9375rem;
    }
    .composer-body .floating-group + .floating-group { margin-top: 16px; }

    /* ----------------------------------------------------------------
       Engine picker. Reuses .ingredient-option from create-image.css
       (the same card the image studio uses for its source picker) but
       lays them out inline instead of inside a dropdown panel.
       ---------------------------------------------------------------- */
    .engine-grid {
      display: grid;
      gap: 10px;
      grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    }
    .engine-grid .ingredient-option {
      position: relative;
      align-items: flex-start;
      padding: 12px 12px 12px 11px;
      border: 1px solid var(--sb-line);
      background: var(--sb-fill-1, rgba(127,127,127,.06));
      transition: border-color var(--sb-t), background var(--sb-t), box-shadow var(--sb-t);
    }
    .engine-grid .ingredient-option:hover {
      border-color: var(--sb-line-strong);
      background: var(--sb-fill-2);
    }
    .engine-grid .ingredient-option small { white-space: normal; }
    .engine-grid .src-copy { padding-right: 26px; }
    .engine-grid .ingredient-option:focus-visible {
      outline: 2px solid var(--sb-violet-soft);
      outline-offset: 2px;
    }

    /* Selected state. This has to out-rank the two rules above, which is
       why it repeats the .engine-grid prefix — without it the plain
       .ingredient-option.selected rule in create-image.css loses on source
       order and the chosen card looked identical to the others. */
    .engine-grid .ingredient-option.selected {
      border-color: var(--sb-violet);
      background: rgba(109, 93, 252, .16);
      box-shadow: 0 0 0 2px rgba(109, 93, 252, .45),
                  0 16px 32px -20px rgba(109, 93, 252, .95);
    }
    .engine-grid .ingredient-option.selected strong { color: var(--sb-text); }
    .engine-grid .ingredient-option.selected::after {
      content: "✓";
      position: absolute;
      top: 10px;
      right: 10px;
      width: 20px;
      height: 20px;
      display: grid;
      place-items: center;
      border-radius: 50%;
      background: var(--sb-violet);
      color: #fff;
      font-size: .7rem;
      font-weight: 700;
      line-height: 1;
    }

    .src-thumb-wan      { background-image: linear-gradient(140deg, #6d5dfc, #46c2ff); }
    .src-thumb-veottv   { background-image: linear-gradient(140deg, #ff8a3d, #ffc75f); }
    .src-thumb-veoitv   { background-image: linear-gradient(140deg, #af46ff, #ff7eb3); }
    .src-thumb-klingitv { background-image: linear-gradient(140deg, #0fb9a4, #5ee7c8); }
    .src-thumb-klingttv { background-image: linear-gradient(140deg, #1f9d55, #86e08a); }
    .src-thumb-klingedit { background-image: linear-gradient(140deg, #c2410c, #f59e0b); }

    /* Character counter. The engines cap the prompt at 2500 and reject
       anything longer outright, so the limit is stated rather than
       discovered — a rejection after a long write is a bad way to learn a
       rule. Amber from 90%, red at the ceiling. */
    .prompt-count {
      margin-top: 4px;
      text-align: right;
      font-size: .7rem;
      font-variant-numeric: tabular-nums;
      color: var(--sb-text-dim);
      transition: color var(--sb-t);
    }
    .prompt-count.is-near { color: #ffb74d; }
    .prompt-count.is-full { color: #ff6b6b; font-weight: 600; }

    /* Boot state. The form carries .form-booting until the engine list has
       loaded, because before an engine is selected the resolution list, the
       duration list, the prompt label and the visible panels all belong to
       no engine in particular — and watching them rearrange themselves a
       few hundred milliseconds after load reads as a bug rather than as
       loading. display:none rather than visibility:hidden so the hidden
       form contributes no height under the skeleton. */
    .form-booting { display: none; }

    .boot-skeleton {
      display: flex;
      flex-direction: column;
      gap: var(--sb-gap);
      margin-top: 8px;
    }
    .boot-row { display: flex; gap: var(--sb-gap); }
    .boot-row .boot-tile-md { flex: 2; }
    .boot-row .boot-tile-sm { flex: 1; }

    .boot-tile {
      border-radius: var(--sb-r-lg);
      background: var(--sb-fill-2);
      border: 1px solid var(--sb-line);
      position: relative;
      overflow: hidden;
    }
    .boot-tile-lg { height: 168px; }
    .boot-tile-md,
    .boot-tile-sm { height: 300px; }

    .boot-tile::after {
      content: "";
      position: absolute;
      inset: 0;
      transform: translateX(-100%);
      background: linear-gradient(90deg, transparent,
                  rgba(255, 255, 255, .05), transparent);
      animation: bootShimmer 1.4s infinite;
    }
    @keyframes bootShimmer { to { transform: translateX(100%); } }

    @media (max-width: 991.98px) {
      .boot-row { flex-direction: column; }
      .boot-tile-md, .boot-tile-sm { height: 200px; }
    }
    @media (prefers-reduced-motion: reduce) {
      .boot-tile::after { animation: none; }
    }

    /* The source-clip preview is a <video>, but shares the still preview's
       box so both panels sit the same in the aside. */
    #videoPreview1 { width: 100%; border-radius: var(--sb-r-md); background: #000; }

    /* Reference list. Each row shows the thumbnail beside the @tag it will
       be cited by, because the number is positional — it changes when a row
       is removed or switched between kinds, and the user has to be able to
       see that happen rather than discover it in the output. */
    /* The two reference kinds do different jobs and the difference is not
       guessable from a dropdown, so it is spelled out once above the list
       rather than left to be discovered from a 422. */
    .edit-ref-legend {
      list-style: none;
      margin: 10px 0 12px;
      padding: 0;
      display: flex;
      flex-direction: column;
      gap: 8px;
    }
    .edit-ref-legend li {
      padding: 8px 10px;
      border-radius: var(--sb-r-md);
      background: var(--sb-fill-2);
      border: 1px solid var(--sb-line);
    }
    .edit-ref-legend strong {
      display: block;
      font-size: .78rem;
      font-weight: 650;
      margin-bottom: 2px;
    }
    .edit-ref-legend span {
      display: block;
      font-size: .72rem;
      line-height: 1.45;
      color: var(--sb-text-dim);
    }

    .edit-ref-list { display: flex; flex-direction: column; gap: 8px; }

    .edit-ref {
      display: flex;
      align-items: center;
      gap: 10px;
      padding: 7px;
      border-radius: var(--sb-r-md);
      background: var(--sb-fill-2);
      border: 1px solid var(--sb-line);
    }
    /* An element can carry a frontal shot plus angles of the same subject,
       so the row holds a strip rather than a single thumbnail. Each is
       captioned, because which one is the frontal is positional and fal
       treats it differently from the rest. */
    .edit-ref-shots { display: flex; align-items: flex-start; gap: 5px; flex: 0 0 auto; }

    .edit-ref-shot { display: block; width: 44px; text-align: center; }
    .edit-ref-shot img {
      width: 44px; height: 44px;
      object-fit: cover;
      border-radius: 8px;
      background: #000;
      display: block;
    }
    .edit-ref-shot em {
      display: block;
      font-style: normal;
      font-size: .55rem;
      line-height: 1.4;
      margin-top: 2px;
      color: var(--sb-text-dim);
    }

    .edit-ref-add-angle {
      width: 44px; height: 44px;
      display: flex; align-items: center; justify-content: center;
      padding: 0;
      border: 1px dashed var(--sb-line-strong);
      border-radius: 8px;
      background: transparent;
      color: var(--sb-text-dim);
      cursor: pointer;
      line-height: 1;
      -webkit-tap-highlight-color: transparent;
    }
    .edit-ref-add-angle i { display: block; font-size: 13px; line-height: 1; vertical-align: 0; }
    .edit-ref-add-angle:hover { color: var(--sb-text); border-color: var(--sb-violet); }
    .edit-ref-body { flex: 1; min-width: 0; }
    .edit-ref-tag {
      display: block;
      font-size: .7rem;
      color: var(--sb-violet);
      margin-bottom: 3px;
    }
    .edit-ref-body .form-select { font-size: .78rem; padding: 3px 26px 3px 8px; }

    .edit-ref-remove {
      flex: 0 0 30px;
      width: 30px; height: 30px;
      display: flex; align-items: center; justify-content: center;
      padding: 0;
      border: 1px solid var(--sb-line);
      border-radius: 50%;
      background: transparent;
      color: var(--sb-text-dim);
      cursor: pointer;
      line-height: 1;
      -webkit-tap-highlight-color: transparent;
    }
    .edit-ref-remove i { display: block; font-size: 12px; line-height: 1; vertical-align: 0; }
    .edit-ref-remove:hover { color: #fff; background: rgba(255, 60, 80, .8); }

    @media (hover: none) {
      .edit-ref-remove { width: 34px; height: 34px; flex-basis: 34px; }
    }

    /* ----------------------------------------------------------------
       Cost pill beside the submit button. The cost bar at the top of the
       page is a long scroll away by the time you reach Generate, so the
       number is repeated here where the decision is actually made.
       ---------------------------------------------------------------- */
    .cost-pill {
      display: inline-flex;
      align-items: center;
      gap: 7px;
      height: 42px;
      padding: 0 15px;
      border-radius: 999px;
      background: var(--sb-fill-2);
      border: 1px solid var(--sb-line-strong);
      font-size: .8125rem;
      font-weight: 600;
      color: var(--sb-text-dim);
      white-space: nowrap;
      transition: border-color var(--sb-t), color var(--sb-t);
    }
    .cost-pill i { color: var(--sb-violet-soft); font-size: .95rem; }
    .cost-pill b { color: var(--sb-text); font-weight: 700; }
    .cost-pill.is-unknown { opacity: .68; }

    /* ----------------------------------------------------------------
       AI script assistant

       Lives inside the composer, above the prompt, as a collapsed
       disclosure. It is deliberately quiet when shut: one line that
       answers a question the user is already asking themselves.
       ---------------------------------------------------------------- */
    .sa-disclosure {
      margin: 16px 0;
      border: 1px solid var(--sb-line-strong);
      border-radius: var(--sb-r-md);
      background: var(--sb-fill-1, rgba(127,127,127,.06));
      overflow: hidden;
    }
    .sa-disclosure[open] { background: var(--sb-fill-2); }

    .sa-summary {
      display: flex;
      align-items: center;
      gap: 11px;
      padding: 12px 14px;
      cursor: pointer;
      list-style: none;
      user-select: none;
    }
    .sa-summary::-webkit-details-marker { display: none; }
    .sa-summary:hover { background: var(--sb-fill-2); }
    .sa-summary:focus-visible {
      outline: 2px solid var(--sb-violet-soft);
      outline-offset: -2px;
    }

    .sa-head-icon { font-size: 1.05rem; color: var(--sb-violet-soft); }
    .sa-summary-copy { flex: 1; min-width: 0; }
    .sa-summary-copy strong {
      display: block;
      font-size: .9375rem;
      font-weight: 600;
      line-height: 1.3;
    }
    .sa-summary-copy small {
      display: block;
      margin-top: 2px;
      font-size: .8125rem;
      line-height: 1.5;
      color: var(--sb-text-dim);
    }

    .sa-chevron {
      font-size: .85rem;
      color: var(--sb-text-faint);
      transition: transform var(--sb-t);
    }
    .sa-disclosure[open] .sa-chevron { transform: rotate(180deg); }

    .sa-panel {
      padding: 4px 14px 14px;
      border-top: 1px solid var(--sb-line);
    }

    .sa-controls { display: grid; gap: 14px; padding-top: 14px; }
    .sa-field .form-label { margin-bottom: 7px; }
    .sa-opt { color: var(--sb-text-faint); font-weight: 400; }

    /* Motion is a segmented control rather than a select: four short
       options are faster to compare side by side than inside a menu,
       and it keeps the jargon-free labels visible at all times. */
    .sa-seg {
      display: grid;
      grid-template-columns: repeat(4, 1fr);
      gap: 6px;
    }
    .sa-seg-btn {
      padding: 9px 6px;
      font-size: .8125rem;
      font-weight: 550;
      color: var(--sb-text-dim);
      background: var(--sb-fill-1, rgba(127,127,127,.06));
      border: 1px solid var(--sb-line);
      border-radius: var(--sb-r-md);
      cursor: pointer;
      transition: border-color var(--sb-t), background var(--sb-t), color var(--sb-t);
    }
    .sa-seg-btn:hover { border-color: var(--sb-line-strong); background: var(--sb-fill-3, rgba(127,127,127,.1)); }
    .sa-seg-btn.is-on {
      border-color: var(--sb-violet);
      background: rgba(109, 93, 252, .16);
      color: var(--sb-text);
      box-shadow: 0 0 0 1px rgba(109, 93, 252, .4);
    }
    .sa-seg-btn:focus-visible {
      outline: 2px solid var(--sb-violet-soft);
      outline-offset: 2px;
    }

    .sa-check {
      display: flex;
      align-items: center;
      gap: 9px;
      font-size: .875rem;
      cursor: pointer;
      margin: 0;
    }
    .sa-check input { width: 16px; height: 16px; accent-color: var(--sb-violet); cursor: pointer; }
    .sa-lock .custom-note { margin-top: 6px; }

    .sa-foot {
      margin-top: 16px;
      display: flex;
      align-items: center;
      gap: 12px;
      flex-wrap: wrap;
    }
    .sa-go[disabled] { opacity: .5; cursor: not-allowed; transform: none; filter: none; }
    .sa-cost-note { color: var(--sb-text-faint); font-weight: 400; }

    .sa-undo {
      margin-top: 12px;
      display: flex;
      align-items: center;
      gap: 10px;
      font-size: .8125rem;
      color: var(--sb-text-dim);
    }
    .sa-undo-btn {
      background: none;
      border: 0;
      padding: 0;
      font: inherit;
      font-weight: 600;
      color: var(--sb-violet-soft);
      text-decoration: underline;
      cursor: pointer;
    }

    /* ----------------------------------------------------------------
       CONTROL HEIGHTS

       Every clickable thing on this page was taking its height from
       whatever padding it happened to inherit: Generate landed at 46px,
       the cost pill sitting right beside it at 42, the gallery button at
       31 (Bootstrap btn-sm), the motion segments at 37. Sat next to each
       other that reads as broken rather than as hierarchy.

       Two tiers, and only two. Anything you press to make something
       happen matches everything else you press. The chip rail is a
       settings strip rather than an action row, so it sits one step down
       and matches itself.

       Heights are set with min-height plus flex centring rather than by
       tuning padding, so a button that wraps to two lines grows instead
       of spilling out of its own box.
       ---------------------------------------------------------------- */
    .sb {
      --vs-action-h: 44px;   /* also the 44px minimum touch target */
      --vs-chip-h: 36px;
    }

    .wizard-actions .wizard-btn,
    .sa-foot .wizard-btn,
    .upload-box .btn,
    .sa-seg-btn,
    .cost-pill {
      min-height: var(--vs-action-h);
    }

    .wizard-actions .wizard-btn,
    .sa-foot .wizard-btn,
    .upload-box .btn {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding-top: 0;
      padding-bottom: 0;
      line-height: 1.25;
    }

    .cost-pill { height: auto; }
    .composer-rail .chip { height: var(--vs-chip-h); }

    /* ----------------------------------------------------------------
       RESPONSIVE

       The bento collapses to a single column at 991.98px, and from that
       point DOM order is reading order. #composerCol holds the prompt
       *and* the Generate button, and it precedes the frame picker in the
       markup — so on a phone the required opening image sat underneath
       the button that consumes it. Reordering here rather than moving
       the markup leaves the desktop two-column layout untouched.
       ---------------------------------------------------------------- */
    @media (max-width: 991.98px) {
      #enginePicker    { order: 1; }
      #firstFramePanel { order: 2; }
      #composerCol     { order: 3; }

      /* Kling can stack two upload tiles here, which builds a tall wall
         in front of the prompt, so the previews give some height back. */
      #firstFramePanel .preview-image { max-height: 150px; }
    }

    @media (max-width: 575.98px) {
      /* Chips stretch to fill each row rather than wrapping to a ragged
         edge, which is what made the rail look shuffled. */
      .composer-rail { gap: 6px; }
      .composer-rail .chip { flex: 1 1 150px; height: 40px; }
      .composer-rail .chip select { flex: 1; max-width: none; }

      /* The price goes above the button rather than beside it: it is the
         last thing worth reading before you commit, and a full-width
         target is easier to hit than one sharing a row. */
      .wizard-actions,
      .sa-foot { flex-wrap: wrap; gap: 10px; }
      .wizard-actions .wizard-btn,
      .sa-foot .wizard-btn { width: 100%; order: 2; }
      .wizard-actions .cost-pill,
      .sa-foot .cost-pill { order: 1; width: 100%; justify-content: center; }

      .sa-seg { grid-template-columns: repeat(2, 1fr); }

      /* Five engine cards is a long scroll before anything else happens. */
      .engine-grid { gap: 8px; }
      .engine-grid .src-thumb { width: 38px; height: 38px; }
      .engine-grid .ingredient-option small { font-size: .72rem; }
    }
