/* ==========================================================================
   Higgsfield Studio — design system + every component
   --------------------------------------------------------------------------
   Dark only. No framework, no @import (index.html loads Inter + Noto Sans JP).
   Sections:
     01  Tokens
     02  Reset & base
     03  Scrollbars, focus, selection
     04  Buttons
     05  Chips & status badges
     06  Topbar / brand / tabs / account menu
     07  Auth gate
     08  App shell & view layout
     09  Composer — kind row, fields, prompt
     10  Media slots (dropzones, thumbs, upload progress)
     11  Params (segmented / input / range / toggle / json / chooser)
     12  Rules, composer foot, cost
     13  Stage cards & library cards
     14  Library head, filters, search
     15  Empty states, spinners
     16  Modals (base / wide / detail / confirm)
     17  Model picker + uploads picker
     18  Workspace picker
     19  Toasts & boot splash
     20  Share
     21  Utilities
     22  Japanese mode
     23  Responsive
     24  Reduced motion & print

   --------------------------------------------------------------------------
   DYNAMIC-MARKUP VOCABULARY — this list is the real one.
   Every name below is emitted by js/{main,generate,library}.js and styled here,
   so the fallback stylesheets those modules inject are redundant. Verified by
   scanning `class=` / `className` / `classList.*` / `el(tag, class)` in all
   four modules; if you add a class in JS, add its rule here too.

   main.js
     .hfs-boot > .hfs-boot-dot + .hfs-boot-text
     .toast[.toast-ok|.toast-error|.toast-warn|.toast-info][.is-in]
        > .toast-dot + .toast-msg
     .modal.modal-confirm-wrap > .modal-backdrop
        + .modal-panel.modal-confirm > .modal-head > .modal-title + .icon-btn
                                     + .confirm-message + .confirm-actions
     .ws-item[.is-active][.is-busy] > .ws-item-main > .ws-name + .ws-meta
                                    + .ws-badge ;  .ws-note ;  .hfs-inline-msg
     body.is-modal-open ; .modal.is-open (state marker, no paint)

   generate.js
     .param[data-param] > .param-head > .row > .param-label + .param-req
                        > (.seg > .seg-btn[.is-active]
                          | select | input | textarea
                          | .toggle > input + .toggle-track + .toggle-text
                          | .row > input[type=range] + input.num-narrow
                          | .row > input.row-grow + .icon-btn-sm
                          | .chooser > .row > input.row-grow + .icon-btn-sm
                                     > .chooser-pop > .chooser-item)
                        + .param-hint + .param-err
     .slot[data-param] > .slot-head > .slot-title(> .param-req) + .slot-count
                       > .slot-drop[.is-drag] > .slot-items > .thumb
                                                  > (img|video|.thumb-audio
                                                     |.thumb-file|.thumb-bar>i)
                                                  + .thumb-x
                                              > .slot-cta
                       > .slot-tools > input.slot-id + .btn.btn-soft.btn-sm
     .stage-card[data-id] > .stage-media > (img|video|pre|.thumb-audio
                                            |.thumb-file|.stage-progress>i)
                          > .stage-bar > .badge.is-{queued|progress|completed
                                                   |failed|nsfw|canceled}
                                       + .stage-name + .stage-actions>.icon-btn-sm
     .model-card[.is-active] > .model-card-top > .model-card-badge
                             + .model-card-name + .model-card-jt + .model-card-hint
     .uploads-grid > .upload-tile ;  .spinner-inline ;  .btn.is-undo

   library.js
     .lib-card[.is-playing] > .lib-card-media[data-kind]
            > (img.lib-thumb | video.lib-video[.is-bare] | .lib-play
               | .lib-audio > .lib-audio-ico + .lib-audio-el
               | pre.lib-textout | .lib-ph[.lib-ph-lg] > .lib-ph-ico + .lib-ph-text)
            + .lib-badge[data-status]
        > .lib-card-body > .lib-card-row > .lib-card-model + .lib-card-time
                         + .lib-card-prompt[.is-pending][.is-muted]
                         + .lib-card-prompt-en
     .lib-grid[.is-empty]
     detail modal: .detail-video | .detail-image | .detail-text
                   | .detail-audio > .detail-audio-ico + .detail-audio-el
     .param-list > .param-row > .param-key + .param-val
     .meta-foot > .foot-row > .foot-key + .foot-val ;  .mono-id
     .ref-list > .ref-item > .ref-thumb > .ref-media[.ref-audio|.ref-blank]
                           + .ref-meta > .ref-role
     .meta-prompt[.is-muted] ; .meta-prompt-ja[.is-pending]
   ========================================================================== */


/* ==========================================================================
   01  Tokens
   ========================================================================== */

:root {
  color-scheme: dark;

  /* Surfaces & ink — measured from higgsfield.ai */
  --bg:          #0B0B0C;
  --surface:     #131517;
  --surface-2:   #191B1E;
  --surface-3:   #212429;
  --line:        #26292E;
  --line-soft:   #1D2024;
  --text:        #F7F7F8;
  --text-dim:    #9CA3AB;
  --text-mute:   #6B7178;
  --accent:      #D1FE17;
  --accent-ink:  #1A1A1A;
  --danger:      #FF5A5A;
  --warn:        #F1C40F;
  --ok:          #4ADE80;

  /* Derived tints (kept as rgba so they layer over any surface) */
  --accent-08:   rgba(209, 254, 23, 0.08);
  --accent-14:   rgba(209, 254, 23, 0.14);
  --accent-24:   rgba(209, 254, 23, 0.24);
  --accent-40:   rgba(209, 254, 23, 0.40);
  --danger-12:   rgba(255, 90, 90, 0.12);
  --danger-30:   rgba(255, 90, 90, 0.30);
  --warn-12:     rgba(241, 196, 15, 0.12);
  --warn-18:     rgba(241, 196, 15, 0.18);
  --warn-30:     rgba(241, 196, 15, 0.30);
  --ok-12:       rgba(74, 222, 128, 0.12);
  --ok-30:       rgba(74, 222, 128, 0.30);
  --white-04:    rgba(255, 255, 255, 0.04);
  --white-07:    rgba(255, 255, 255, 0.07);
  --black-40:    rgba(0, 0, 0, 0.40);

  /* Radii */
  --radius:      10px;
  --radius-sm:   8px;
  --radius-lg:   16px;
  --radius-pill: 999px;

  /* Elevation */
  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-2: 0 6px 20px rgba(0, 0, 0, 0.42);
  --shadow-3: 0 24px 70px rgba(0, 0, 0, 0.62);
  --ring:     0 0 0 3px var(--accent-24);

  /* Motion */
  --dur:      140ms;
  --dur-modal: 200ms;
  --ease:     cubic-bezier(0.22, 0.61, 0.36, 1);

  /* Metrics */
  --topbar-h:   64px;
  --composer-w: clamp(360px, 30vw, 460px);
  --pad:        20px;
  --gap:        12px;

  /* Type */
  --font: "Inter", "Noto Sans JP", system-ui, -apple-system, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               "Liberation Mono", monospace;
  --lh: 1.5;
}


/* ==========================================================================
   02  Reset & base
   ========================================================================== */

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

html,
body {
  height: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 14px;
  line-height: var(--lh);
  font-feature-settings: "cv02", "cv03", "cv04", "ss01";
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow: hidden;               /* the app owns its own scroll regions */
}

/* A modal owns the scroll while it is up (main.js toggles this on <body>). */
body.is-modal-open { overflow: hidden; }

h1, h2, h3, h4, p, figure, pre { margin: 0; }

a {
  color: inherit;
  text-decoration: none;
}

a:hover { color: var(--accent); }

img,
video,
canvas { display: block; max-width: 100%; }

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
  margin: 0;
}

button { cursor: pointer; background: none; border: 0; }

[hidden] { display: none !important; }

[disabled],
.is-disabled,
[aria-disabled="true"],
button:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}

hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 14px 0;
}

code, pre, .mono { font-family: var(--font-mono); }

/* The one role rule: a guest never sees the controls that would destroy the
   shared session for everyone else. main.js sets <body data-role="guest">. */
body[data-role="guest"] .owner-only { display: none !important; }


/* ==========================================================================
   03  Scrollbars, focus, selection
   ========================================================================== */

* {
  scrollbar-width: thin;
  scrollbar-color: var(--surface-3) transparent;
}

*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }

*::-webkit-scrollbar-thumb {
  background: var(--surface-3);
  border: 3px solid transparent;
  background-clip: content-box;
  border-radius: var(--radius-pill);
}

*::-webkit-scrollbar-thumb:hover { background: #33373E; background-clip: content-box; }
*::-webkit-scrollbar-corner { background: transparent; }

:focus { outline: none; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Inputs get the ring as a shadow so nothing jumps by 2px on focus. */
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: none;
  border-color: var(--accent-40);
  box-shadow: var(--ring);
}

::selection {
  background: var(--accent);
  color: var(--accent-ink);
}

::placeholder {
  color: var(--text-mute);
  opacity: 1;
}


/* ==========================================================================
   04  Buttons
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-width: max-content;          /* JA labels grow the button, never clip it */
  min-height: 36px;
  padding: 0 16px;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--text);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.005em;
  white-space: nowrap;
  transition: background var(--dur) var(--ease),
              color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              transform var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
}

.btn:hover { background: var(--surface-3); }
.btn:active { transform: translateY(1px); }

.btn svg { width: 16px; height: 16px; flex: none; fill: currentColor; }

/* Primary — the lime pill */
.btn-accent {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
  font-weight: 700;
}

.btn-accent:hover {
  background: #DDFF4C;
  border-color: #DDFF4C;
  box-shadow: 0 6px 22px rgba(209, 254, 23, 0.18);
}

.btn-accent:disabled,
.btn-accent[disabled] {
  background: var(--surface-3);
  border-color: var(--line);
  color: var(--text-mute);
  box-shadow: none;
}

/* Secondary — quiet raised pill */
.btn-soft {
  background: var(--surface-2);
  border-color: var(--line);
  color: var(--text-dim);
}

.btn-soft:hover {
  background: var(--surface-3);
  border-color: #313640;
  color: var(--text);
}

.btn-soft.is-active,
.btn-soft[aria-pressed="true"] {
  background: var(--accent-14);
  border-color: var(--accent-40);
  color: var(--accent);
}

/* Tertiary — text only */
.btn-ghost {
  background: transparent;
  color: var(--text-dim);
}

.btn-ghost:hover {
  background: var(--white-04);
  color: var(--text);
}

.btn-danger {
  background: var(--danger-12);
  border-color: var(--danger-30);
  color: var(--danger);
}

.btn-danger:hover { background: rgba(255, 90, 90, 0.2); }

/* Sizes */
.btn-xs { min-height: 26px; padding: 0 10px; font-size: 11px; gap: 5px; }
.btn-xs svg { width: 13px; height: 13px; }

.btn-sm { min-height: 30px; padding: 0 12px; font-size: 12px; gap: 6px; }
.btn-sm svg { width: 14px; height: 14px; }

.btn-lg {
  min-height: 48px;
  padding: 0 26px;
  font-size: 15px;
  border-radius: var(--radius-pill);
}

.btn-block { width: 100%; }

.btn-lg svg { width: 18px; height: 18px; }

/* Busy state: label dims, a spinner rides in front — unless the button has
   already been handed its own .spinner + .btn-label (main.js does that for
   #share-toggle, so it can keep saying "Starting…" while it spins). */
.btn.is-busy { pointer-events: none; position: relative; }
.btn.is-busy:not(:has(.spinner)) { color: transparent; }

.btn.is-busy:not(:has(.spinner))::after {
  content: "";
  position: absolute;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-top-color: transparent;
  animation: hfs-spin 700ms linear infinite;
}

.btn-accent.is-busy::after { border-color: var(--accent-ink); border-top-color: transparent; }
.btn-soft.is-busy::after,
.btn-ghost.is-busy::after { border-color: var(--text-dim); border-top-color: transparent; }

/* A spinner living inside a button borrows the button's ink. */
.btn .spinner {
  width: 15px;
  height: 15px;
  flex: none;
  border-width: 2px;
  border-color: currentColor;
  border-top-color: transparent;
}

/* The text half of a button that also carries an icon or a spinner. */
.btn-label { min-width: 0; }

/* The EN button turns into an "undo" once a draft has been translated. */
.btn.is-undo {
  background: var(--accent-14);
  border-color: var(--accent-40);
  color: var(--accent);
}

/* Language pill — outlined, solid lime once JA is on */
.btn-lang {
  background: transparent;
  border-color: var(--line);
  color: var(--text-dim);
  padding: 0 14px;
  font-weight: 600;
}

.btn-lang .chip-ico {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.btn-lang:hover {
  border-color: var(--accent-40);
  color: var(--text);
  background: var(--accent-08);
}

.btn-lang[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}

.btn-lang[aria-pressed="true"]:hover {
  background: #DDFF4C;
  border-color: #DDFF4C;
}

/* Share pill — same outlined family as .btn-lang. Goes lime and grows a
   soft pulsing dot while the studio is actually reachable from outside. */
.btn-share {
  position: relative;
  background: transparent;
  border-color: var(--line);
  color: var(--text-dim);
  padding: 0 14px;
  font-weight: 600;
}

.share-ico {
  width: 16px;
  height: 16px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.btn-share:hover {
  border-color: var(--accent-40);
  color: var(--text);
  background: var(--accent-08);
}

.btn-share.is-live {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
  padding-right: 26px;
}

.btn-share.is-live:hover { background: #DDFF4C; border-color: #DDFF4C; }

.btn-share.is-live::after {
  content: "";
  position: absolute;
  right: 12px;
  top: 50%;
  width: 7px;
  height: 7px;
  margin-top: -3.5px;
  border-radius: 50%;
  background: var(--accent-ink);
  animation: hfs-live 1.6s var(--ease) infinite;
}

/* Icon-only button (modal close, card actions) */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  flex: none;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-dim);
  font-size: 20px;
  line-height: 1;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

.icon-btn:hover {
  background: var(--surface-3);
  color: var(--text);
}

.icon-btn svg { width: 16px; height: 16px; fill: currentColor; }

/* Small icon button — dice, chooser caret, stage download/reuse. */
.icon-btn-sm {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  flex: none;
  padding: 0;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text-dim);
  font-size: 14px;
  line-height: 1;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}

.icon-btn-sm:hover {
  background: var(--surface-3);
  border-color: #343941;
  color: var(--text);
}

.icon-btn-sm svg { width: 14px; height: 14px; fill: currentColor; }


/* ==========================================================================
   05  Chips & status badges
   ========================================================================== */

.chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: max-content;
  height: 36px;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--text-dim);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              color var(--dur) var(--ease);
}

.chip:hover {
  background: var(--surface-3);
  border-color: #313640;
  color: var(--text);
}

.chip-ico { width: 15px; height: 15px; flex: none; fill: currentColor; }

.chip-credits { color: var(--accent); border-color: rgba(209, 254, 23, 0.22); background: var(--accent-08); }
.chip-credits:hover { background: var(--accent-14); border-color: var(--accent-40); color: var(--accent); }
.chip-credits #credits-value { font-variant-numeric: tabular-nums; letter-spacing: 0.01em; }

.chip-account { padding-left: 5px; max-width: 230px; }

.account-email {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 160px;
  font-weight: 500;
}

.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  flex: none;
  border-radius: 50%;
  background: linear-gradient(140deg, var(--accent) 0%, #7FD41C 55%, #3FA9A0 100%);
  color: var(--accent-ink);
  font-size: 11px;
  font-weight: 800;
  text-transform: uppercase;
}

/* Filter pills (library + model picker) */
.chip-filter {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: max-content;
  height: 32px;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-dim);
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}

.chip-filter:hover { background: var(--surface-2); color: var(--text); }

.chip-filter.is-active {
  background: var(--surface-3);
  border-color: #343941;
  color: var(--text);
}

/* --------------------------------------------------------------------------
   Status badge — generate.js emits `badge is-<status>`, nothing else. Five
   distinguishable states; a neutral base would make every stage look alike.
   -------------------------------------------------------------------------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex: none;
  height: 22px;
  padding: 0 9px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  background: var(--surface-3);
  color: var(--text-dim);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

.badge::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

/* amber = accepted, waiting for a worker */
.badge.is-queued {
  color: var(--warn);
  border-color: var(--warn-30);
  background: var(--warn-12);
}

/* lime = the model is running right now (the dot breathes) */
.badge.is-progress {
  color: var(--accent);
  border-color: var(--accent-40);
  background: var(--accent-14);
}

.badge.is-progress::before { animation: hfs-pulse 1.2s ease-in-out infinite; }

/* green = landed */
.badge.is-completed {
  color: var(--ok);
  border-color: var(--ok-30);
  background: var(--ok-12);
}

/* red = failed / blocked */
.badge.is-failed,
.badge.is-nsfw {
  color: var(--danger);
  border-color: var(--danger-30);
  background: var(--danger-12);
}

/* grey = deliberately stopped */
.badge.is-canceled {
  color: var(--text-mute);
  border-color: var(--line);
  background: var(--surface-2);
}


/* ==========================================================================
   06  Topbar / brand / tabs / account menu
   ========================================================================== */

.topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  height: var(--topbar-h);
  flex: none;
  padding: 0 18px;
  background: rgba(11, 11, 12, 0.86);
  backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
  border-bottom: 1px solid var(--line);
}

.topbar-left,
.topbar-right {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;               /* the bar is one row at every width */
  gap: 10px;
  min-width: 0;
}

.topbar-right { position: relative; flex: none; }
.topbar-left { min-width: 0; }

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-right: 14px;
  margin-right: 4px;
  border-right: 1px solid var(--line);
  min-width: max-content;
}

.brand-mark {
  display: inline-flex;
  filter: drop-shadow(0 3px 10px rgba(209, 254, 23, 0.22));
}

.brand-mark svg { display: block; }

.brand-name {
  font-size: 15px;
  font-weight: 800;
  letter-spacing: -0.015em;
  white-space: nowrap;
}

.brand-thin {
  font-weight: 500;
  color: var(--text-dim);
  letter-spacing: 0;
}

/* Tab pills */
.tabs {
  display: flex;
  align-items: center;
  gap: 4px;
  flex: none;
  padding: 4px;
  border-radius: var(--radius-pill);
  background: var(--surface);
  border: 1px solid var(--line-soft);
}

.tab {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-width: max-content;
  height: 32px;
  padding: 0 14px;
  border-radius: var(--radius-pill);
  color: var(--text-dim);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

.tab:hover { color: var(--text); background: var(--white-04); }

.tab.is-active,
.tab[aria-selected="true"] {
  background: var(--surface-3);
  color: var(--text);
  box-shadow: var(--shadow-1);
}

.tab-ico { width: 15px; height: 15px; flex: none; fill: currentColor; opacity: 0.85; }
.tab.is-active .tab-ico { fill: var(--accent); opacity: 1; }

/* Account dropdown */
.menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 60;
  min-width: 220px;
  padding: 6px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--surface);
  box-shadow: var(--shadow-3);
}

.menu.is-open { animation: hfs-rise var(--dur-modal) var(--ease); }

.menu-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 36px;
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  color: var(--text-dim);
  font-size: 13px;
  font-weight: 500;
  text-align: left;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

.menu-item:hover { background: var(--surface-2); color: var(--text); }

.menu-danger { color: var(--danger); }
.menu-danger:hover { background: var(--danger-12); color: var(--danger); }


/* ==========================================================================
   07  Auth gate
   ========================================================================== */

.auth-gate {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  overflow-y: auto;
  background:
    radial-gradient(900px 520px at 50% -10%, rgba(209, 254, 23, 0.09), transparent 62%),
    radial-gradient(700px 460px at 90% 110%, rgba(64, 140, 255, 0.07), transparent 60%),
    var(--bg);
}

.auth-card {
  width: 100%;
  max-width: 460px;
  padding: 34px 32px 28px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  background: linear-gradient(180deg, var(--surface) 0%, #101215 100%);
  box-shadow: var(--shadow-3);
  text-align: center;
  animation: hfs-rise 260ms var(--ease);
}

.auth-logo {
  width: 56px;
  height: 56px;
  margin: 0 auto 18px;
  border-radius: 16px;
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath d='M9 22c0-6 3.2-9.4 6.6-9.4 2.3 0 3.6 1.5 3.6 3.4 0 2.6-2.4 4-4.6 4.6M23 10c0 6-3.2 9.4-6.6 9.4' stroke='%230B0B0C' stroke-width='2.4' stroke-linecap='round' fill='none'/%3E%3C/svg%3E")
    center / 100% 100% no-repeat,
    linear-gradient(150deg, var(--accent), #A9E00C);
  box-shadow: 0 12px 34px rgba(209, 254, 23, 0.22);
}

.auth-title {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.02em;
  margin-bottom: 8px;
}

.auth-sub {
  color: var(--text-dim);
  font-size: 13.5px;
  line-height: 1.6;
  margin-bottom: 18px;
  text-wrap: balance;
}

.auth-cmd {
  display: block;
  padding: 12px 14px;
  margin-bottom: 18px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: 12.5px;
  text-align: left;
  overflow-x: auto;
  white-space: pre;
}

.auth-cmd code { color: inherit; }
.auth-cmd::before { content: "$ "; color: var(--text-mute); }

.auth-card .btn-lg { width: 100%; }

.auth-status {
  min-height: 20px;
  margin: 14px 0 4px;
  color: var(--text-dim);
  font-size: 12.5px;
  line-height: 1.55;
}

.auth-url-wrap {
  margin: 10px 0 6px;
  padding: 12px;
  border-radius: var(--radius);
  border: 1px dashed var(--line);
  background: var(--surface-2);
  text-align: left;
}

.auth-hint {
  color: var(--text-mute);
  font-size: 12px;
  margin-bottom: 6px;
}

.auth-url {
  display: block;
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.auth-card .btn-ghost { margin-top: 6px; }


/* ==========================================================================
   08  App shell & view layout
   ========================================================================== */

.app {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

.view {
  flex: 1;
  min-height: 0;
}

/* --- Generate: composer + stage ----------------------------------------- */
.view-generate {
  display: grid;
  grid-template-columns: var(--composer-w) minmax(0, 1fr);
  height: calc(100dvh - var(--topbar-h));
  overflow: hidden;
}

.composer {
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
  background: var(--surface);
  border-right: 1px solid var(--line);
}

.composer-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 18px var(--pad) 22px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.composer-foot {
  position: sticky;
  bottom: 0;
  z-index: 5;
  flex: none;
  padding: 14px var(--pad) calc(14px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--line);
  background: linear-gradient(180deg, rgba(19, 21, 23, 0.86), var(--surface) 40%);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

/* --- Stage --------------------------------------------------------------- */
.stage {
  min-width: 0;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 0 var(--pad) 28px;
  background:
    radial-gradient(760px 400px at 78% -8%, rgba(209, 254, 23, 0.045), transparent 60%),
    var(--bg);
}

.stage-head {
  position: sticky;
  top: 0;
  z-index: 6;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding: 16px 0 12px;
  background: linear-gradient(180deg, var(--bg) 72%, rgba(11, 11, 12, 0));
}

.stage-title {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.stage-tools {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* --- Library ------------------------------------------------------------- */
.view-library {
  height: calc(100dvh - var(--topbar-h));
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 0 var(--pad) 32px;
  background: var(--bg);
}


/* ==========================================================================
   09  Composer — kind row, fields, prompt
   ========================================================================== */

/* Six pills in a 360–460px composer always overflow, and "Workflows" /
   「ワークフロー」 must never be cut in half. So: scroll horizontally with no
   visible scrollbar, never shrink a pill, keep a trailing spacer so the last
   label can clear the fade, and fade the right edge so it reads as scrollable. */
.kind-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  border: 1px solid var(--line-soft);
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -ms-overflow-style: none;
  scroll-snap-type: x proximity;
  scroll-padding-inline: 4px 26px;
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 26px), rgba(0, 0, 0, 0) 100%);
  mask-image: linear-gradient(to right, #000 calc(100% - 26px), rgba(0, 0, 0, 0) 100%);
}

.kind-row::-webkit-scrollbar { display: none; }

/* Trailing spacer: at maximum scroll the last pill sits clear of the fade,
   so its label is always fully opaque. (padding-inline-end is unreliable at
   the scroll end in a flex scroller; a flex item is not.) */
.kind-row::after {
  content: "";
  flex: 0 0 20px;
  height: 1px;
}

.kind {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;                  /* never squeeze a label */
  min-width: max-content;
  height: 30px;
  padding: 0 13px;
  border-radius: var(--radius-pill);
  color: var(--text-dim);
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
  scroll-snap-align: start;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

.kind:hover { color: var(--text); background: var(--white-04); }

.kind.is-active,
.kind[aria-selected="true"] {
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 700;
}

/* --- field scaffold ------------------------------------------------------ */
.field {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}

.field-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: 30px;
}

.field-label {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-mute);
}

.field-tools {
  display: flex;
  align-items: center;
  gap: 8px;
}

.counter {
  color: var(--text-mute);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
}

/* --- current model card -------------------------------------------------- */
.model-current {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 5px;
  width: 100%;
  padding: 14px 15px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--surface-2);
  text-align: left;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}

.model-current:hover {
  background: var(--surface-3);
  border-color: #343941;
}

.model-current:active { transform: translateY(1px); }

.model-current-name {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.3;
  overflow-wrap: anywhere;
}

.model-current-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  color: var(--text-mute);
  font-size: 12px;
  font-family: var(--font-mono);
  line-height: 1.5;
  overflow-wrap: anywhere;
}

/* --- prompt -------------------------------------------------------------- */
.prompt {
  width: 100%;
  min-height: 132px;
  padding: 14px 15px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--text);
  font-size: 15px;
  line-height: 1.6;
  resize: vertical;
  transition: background var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}

.prompt:hover { background: #1C1F22; }

.prompt:focus {
  outline: none;
  background: var(--surface-2);
  border-color: var(--accent-40);
  box-shadow: var(--ring);
}

.prompt-sm { min-height: 64px; font-size: 13.5px; padding: 11px 13px; }

.prompt-translation {
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  border-left: 2px solid var(--accent-40);
  background: var(--accent-08);
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1.7;
  overflow-wrap: anywhere;
}


/* ==========================================================================
   10  Media slots (dropzones, thumbs, upload progress)
   ========================================================================== */

.media-slots {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.media-slots:empty { display: none; }

.slot {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}

.slot-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.slot-title {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-dim);
  overflow-wrap: anywhere;
}

.slot-title .param-req { color: var(--accent); }

.slot-count {
  color: var(--text-mute);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  flex: none;
}

/* the drop target itself */
.slot-drop {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px;
  border-radius: var(--radius);
  border: 1px dashed var(--line);
  background: var(--surface-2);
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
}

.slot-drop:hover { border-color: #343941; background: #1C1F22; }

.slot-drop.is-drag {
  border-color: var(--accent);
  background: var(--accent-08);
  box-shadow: var(--ring);
}

.slot-drop:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.slot-items {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.slot-items:empty { display: none; }

.slot-cta {
  padding: 10px 4px;
  color: var(--text-mute);
  font-size: 12px;
  line-height: 1.5;
  text-align: center;
  overflow-wrap: anywhere;
}

.slot-cta b { color: var(--text-dim); font-weight: 600; }

.slot-tools {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

/* paste-a-UUID input */
.slot-id {
  flex: 1 1 auto;
  min-width: 0;
  height: 30px;
  padding: 0 11px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 11.5px;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.slot-id:hover { border-color: #343941; }

/* --- thumbnails of attached references ---------------------------------- */
.thumb {
  position: relative;
  width: 78px;
  height: 78px;
  flex: none;
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--bg);
}

.thumb img,
.thumb video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.thumb-audio {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: var(--accent);
  font-size: 20px;
  line-height: 1;
  background: var(--surface-2);
}

.thumb-file {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 6px;
  color: var(--text-mute);
  font-family: var(--font-mono);
  font-size: 9.5px;
  line-height: 1.4;
  text-align: center;
  overflow: hidden;
  overflow-wrap: anywhere;
}

.thumb-x {
  position: absolute;
  top: 4px;
  right: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  padding: 0;
  border-radius: 50%;
  background: rgba(11, 11, 12, 0.78);
  border: 1px solid var(--line);
  color: var(--text);
  font-size: 13px;
  line-height: 1;
  opacity: 0;
  transform: scale(0.9);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease),
              background var(--dur) var(--ease);
}

.thumb:hover .thumb-x,
.thumb-x:focus-visible { opacity: 1; transform: scale(1); }

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

/* per-file upload progress: .thumb-bar > i */
.thumb-bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3px;
  background: rgba(11, 11, 12, 0.72);
  overflow: hidden;
}

.thumb-bar i {
  display: block;
  width: 0%;
  height: 100%;
  background: var(--accent);
  transition: width 180ms linear;
}


/* ==========================================================================
   11  Params (segmented / input / range / toggle / json / chooser)
   ========================================================================== */

.params {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.params:empty { display: none; }

.param {
  display: flex;
  flex-direction: column;
  gap: 7px;
  min-width: 0;
  padding: 10px 12px;
  border-radius: var(--radius);
  background: var(--surface-2);
  border: 1px solid var(--line-soft);
  transition: border-color var(--dur) var(--ease);
}

.param:hover { border-color: var(--line); }

/* Textareas, JSON blobs and sliders want the full composer width. */
.param:has(textarea),
.param:has(.seg),
.param:has(input[type="range"]),
.param:has(.chooser) { grid-column: 1 / -1; }

.param-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  min-width: 0;
}

.param-head .row { min-width: 0; flex: 1 1 auto; }

.param-label {
  display: inline;
  color: var(--text-dim);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.03em;
  line-height: 1.45;
  /* JA labels wrap; they never truncate mid-word */
  overflow-wrap: anywhere;
  word-break: normal;
  line-break: strict;
}

.param-req { color: var(--accent); font-weight: 700; }

.param-hint {
  color: var(--text-mute);
  font-size: 11px;
  line-height: 1.5;
  text-align: right;
  overflow-wrap: anywhere;
}

/* A hint used as a block (empty-state text in the model list / chooser). */
.params > .param-hint,
.model-list > .param-hint,
.uploads-grid > .param-hint,
.chooser-pop > .param-hint { text-align: left; }

.model-list > .param-hint,
.uploads-grid > .param-hint { grid-column: 1 / -1; padding: 28px 4px; }

.param-err {
  color: var(--danger);
  font-size: 11px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.param-err:empty { display: none; }

/* A cost estimate that came back complaining is a warning, not a failure —
   the form is still submittable, the price is just unknown. */
.param-err.is-cost-hint { color: var(--warn); }

/* --- native controls inside a param (the JS emits them unclassed) -------- */
.param input[type="text"],
.param input[type="number"],
.param input[type="search"],
.param textarea,
.param select {
  width: 100%;
  min-width: 0;
  min-height: 34px;
  padding: 7px 11px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text);
  font-size: 13px;
  line-height: 1.4;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
}

.param input:hover,
.param textarea:hover,
.param select:hover { border-color: #343941; }

.param input[type="number"] { font-variant-numeric: tabular-nums; }

.param input::-webkit-outer-spin-button,
.param input::-webkit-inner-spin-button { opacity: 0.4; }

.param textarea {
  min-height: 76px;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.55;
  resize: vertical;
}

.param select,
.select-sm {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 30px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239CA3AB' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 9px center;
  background-size: 14px 14px;
  cursor: pointer;
  text-overflow: ellipsis;
}

.param select option,
.select-sm option {
  background: var(--surface-2);
  color: var(--text);
}

.select-sm {
  width: auto;
  min-width: 70px;
  height: 30px;
  min-height: 30px;
  padding: 0 28px 0 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background-color: var(--bg);
  color: var(--text);
  font-size: 12px;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.select-sm:hover { border-color: #343941; }

/* --- segmented enum (≤5 short values) ----------------------------------- */
.seg {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  min-width: 0;
}

.seg-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: max-content;
  height: 30px;
  padding: 0 13px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--bg);
  color: var(--text-dim);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}

.seg-btn:hover { background: var(--surface-3); color: var(--text); border-color: #343941; }

.seg-btn.is-active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
  font-weight: 700;
}

/* --- range (the JS emits a bare input[type=range] in a .row) ------------- */
.param input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  flex: 1 1 auto;
  min-width: 0;
  width: auto;
  height: 20px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}

.param input[type="range"]::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: var(--radius-pill);
  background: var(--surface-3);
}

.param input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 15px;
  height: 15px;
  margin-top: -5.5px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid #0F1113;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.5);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.param input[type="range"]:hover::-webkit-slider-thumb { transform: scale(1.12); }
.param input[type="range"]:active::-webkit-slider-thumb { box-shadow: 0 0 0 6px var(--accent-24); }

.param input[type="range"]::-moz-range-track {
  height: 4px;
  border-radius: var(--radius-pill);
  background: var(--surface-3);
}

.param input[type="range"]::-moz-range-progress {
  height: 4px;
  border-radius: var(--radius-pill);
  background: var(--accent);
}

.param input[type="range"]::-moz-range-thumb {
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid #0F1113;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.5);
}

.param input[type="range"]:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 4px var(--accent-24); }
.param input[type="range"]:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 4px var(--accent-24); }

/* the numeric twin beside a slider, and the id/seed inputs that must grow */
.num-narrow { max-width: 96px; flex: 0 0 auto; }
.row-grow { flex: 1 1 auto; min-width: 0; }

/* --- boolean toggle (never a default checkbox) --------------------------- */
.toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  cursor: pointer;
  user-select: none;
  min-width: 0;
}

.toggle input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
  pointer-events: none;
}

.toggle-track {
  position: relative;
  display: inline-block;
  width: 38px;
  height: 22px;
  flex: none;
  border-radius: var(--radius-pill);
  background: var(--surface-3);
  border: 1px solid var(--line);
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.toggle-track::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 2px;
  width: 15px;
  height: 15px;
  margin-top: -7.5px;
  border-radius: 50%;
  background: var(--text-dim);
  box-shadow: var(--shadow-1);
  transition: transform var(--dur) var(--ease), background var(--dur) var(--ease);
}

.toggle input:checked + .toggle-track {
  background: var(--accent);
  border-color: var(--accent);
}

.toggle input:checked + .toggle-track::after {
  transform: translateX(16px);
  background: var(--accent-ink);
}

.toggle input:focus-visible + .toggle-track { box-shadow: var(--ring); }
.toggle input:disabled + .toggle-track { opacity: 0.45; cursor: not-allowed; }

.toggle-text {
  font-size: 12.5px;
  color: var(--text-dim);
  overflow-wrap: anywhere;
}

/* Any stray native checkbox in generated markup still reads as Higgsfield. */
input[type="checkbox"]:not(.toggle input),
input[type="radio"] { accent-color: var(--accent); }

/* --- chooser popover (voices, souls, presets) ---------------------------- */
.chooser {
  position: relative;
  min-width: 0;
}

.chooser-pop {
  position: absolute;
  z-index: 40;
  left: 0;
  right: 0;
  top: calc(100% + 5px);
  max-height: 244px;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 5px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--surface-3);
  box-shadow: var(--shadow-3);
  animation: hfs-rise var(--dur) var(--ease);
}

.chooser-item {
  display: block;
  width: 100%;
  padding: 7px 9px;
  border-radius: 7px;
  color: var(--text);
  font-size: 12px;
  line-height: 1.45;
  text-align: left;
  overflow-wrap: anywhere;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

.chooser-item:hover { background: var(--surface-2); color: var(--accent); }


/* ==========================================================================
   12  Rules, composer foot, cost
   ========================================================================== */

.rules {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 12px;
  border-radius: var(--radius);
  border-left: 3px solid var(--warn);
  background: var(--warn-12);
}

.rules-title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--warn);
}

.rule {
  position: relative;
  padding-left: 14px;
  color: var(--text-dim);
  font-size: 12px;
  line-height: 1.55;
  overflow-wrap: anywhere;
}

.rule::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 8px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--warn);
}

/* --- cost row + generate ------------------------------------------------- */
.cost {
  display: flex;
  align-items: baseline;
  gap: 7px;
  flex-wrap: wrap;
  margin-bottom: 10px;
  padding: 0 2px;
}

.cost-label {
  color: var(--text-mute);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.cost-value {
  color: var(--accent);
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
  transition: color var(--dur) var(--ease);
}

/* generate.js dims the figure while a fresh estimate is in flight, and mutes
   it outright when there is no price to show. */
.cost-value.is-loading { color: var(--text-dim); opacity: 0.6; }
.cost-value.is-muted { color: var(--text-mute); }

.cost-unit {
  color: var(--text-dim);
  font-size: 12px;
  font-weight: 500;
}

/* The explanation under the estimate ("free while the model is in preview"). */
.cost-note {
  margin: -4px 0 10px;
  padding: 0 2px;
  color: var(--text-mute);
  font-size: 11.5px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.composer-error {
  margin-top: 10px;
  padding: 9px 11px;
  border-radius: var(--radius-sm);
  border-left: 3px solid var(--danger);
  background: var(--danger-12);
  color: var(--danger);
  font-size: 12.5px;
  line-height: 1.55;
  overflow-wrap: anywhere;
}


/* ==========================================================================
   13  Stage cards & library cards
   ========================================================================== */

.stage-grid,
.lib-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 12px;
  padding: 0;                      /* the view owns the page padding */
  align-content: start;
}

.stage-grid:empty,
.lib-grid:empty,
.lib-grid.is-empty { display: none; }

/* --- shared tile chrome --------------------------------------------------- */
.stage-card,
.lib-card {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  border-radius: var(--radius);
  border: 1px solid var(--line-soft);
  background: var(--surface);
  overflow: hidden;
  cursor: pointer;
  outline: none;
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease), background var(--dur) var(--ease);
}

.stage-card:hover,
.lib-card:hover {
  transform: translateY(-3px);
  border-color: #333941;
  background: var(--surface-2);
  box-shadow: var(--shadow-2);
}

.stage-card:focus-visible,
.lib-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* --- stage card (generate.js) -------------------------------------------- */
.stage-media {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: linear-gradient(135deg, #16181B 0%, #0F1113 100%);
}

.stage-media img,
.stage-media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.stage-media audio { width: 90%; }

.stage-media pre {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 12px;
  color: var(--text-dim);
  font-size: 11px;
  line-height: 1.55;
  white-space: pre-wrap;
  overflow: auto;
}

.stage-media .thumb-audio,
.stage-media .thumb-file {
  position: absolute;
  inset: 0;
  background: transparent;
  font-size: 26px;
}

.stage-media .thumb-file { font-size: 11px; }

/* indeterminate sweep while the job is in flight */
.stage-progress {
  position: absolute;
  inset: auto 0 0 0;
  height: 2px;
  overflow: hidden;
  background: rgba(11, 11, 12, 0.5);
}

.stage-progress i {
  display: block;
  width: 34%;
  height: 100%;
  background: var(--accent);
  animation: hfs-slide 1.4s ease-in-out infinite;
}

.stage-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  padding: 9px 10px 10px;
}

.stage-name {
  flex: 1 1 auto;
  min-width: 0;
  color: var(--text-dim);
  font-size: 12px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.stage-actions {
  display: flex;
  align-items: center;
  gap: 5px;
  flex: none;
}

/* --- library card (library.js) ------------------------------------------- */
.lib-card-media {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: linear-gradient(135deg, #16181B 0%, #0F1113 100%);
}

.lib-card-media[data-kind="image"] { aspect-ratio: 1 / 1; }

.lib-thumb,
.lib-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 240ms var(--ease), opacity var(--dur) var(--ease);
}

.lib-video { opacity: 0; }
.lib-video.is-bare,
.lib-card.is-playing .lib-video { opacity: 1; }

.lib-card:hover .lib-thumb { transform: scale(1.035); }

.lib-play {
  position: absolute;
  left: 9px;
  bottom: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: rgba(11, 11, 12, 0.66);
  border: 1px solid rgba(255, 255, 255, 0.08);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: opacity var(--dur) var(--ease);
}

.lib-play svg { width: 13px; height: 13px; fill: var(--text); }
.lib-card.is-playing .lib-play { opacity: 0; }

/* status pill, top-right of the tile — same five colours as .badge */
.lib-badge {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 2;
  padding: 4px 8px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  background: rgba(11, 11, 12, 0.72);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: var(--text-dim);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1;
  white-space: nowrap;
}

.lib-badge[data-status="queued"] { color: var(--warn); border-color: var(--warn-30); }
.lib-badge[data-status="in_progress"] { color: var(--accent); border-color: var(--accent-40); }
.lib-badge[data-status="completed"] { color: var(--ok); border-color: var(--ok-30); }
.lib-badge[data-status="failed"],
.lib-badge[data-status="nsfw"] { color: var(--danger); border-color: var(--danger-30); }
.lib-badge[data-status="canceled"] { color: var(--text-mute); }

/* placeholder when there is no media to show yet */
.lib-ph {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px;
  color: var(--text-mute);
  text-align: center;
  background:
    repeating-linear-gradient(135deg, #131517 0 10px, #191B1E 10px 20px);
}

.lib-ph-lg {
  position: relative;
  min-height: 320px;
  width: 100%;
  border-radius: var(--radius);
}

.lib-ph-ico svg { width: 22px; height: 22px; fill: currentColor; opacity: 0.7; }

.lib-ph-text {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.lib-ph[data-status="failed"],
.lib-ph[data-status="nsfw"] { color: var(--danger); }
.lib-ph[data-status="in_progress"],
.lib-ph[data-status="queued"] { color: var(--warn); }

/* audio tiles */
.lib-audio {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 16px;
}

.lib-audio-ico svg,
.detail-audio-ico svg { width: 26px; height: 26px; fill: var(--text-mute); }

.lib-audio-el { width: 100%; max-width: 200px; height: 32px; }

/* text results have no media — show the text */
.lib-textout {
  position: absolute;
  inset: 0;
  display: -webkit-box;
  -webkit-line-clamp: 8;
  line-clamp: 8;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: 0;
  padding: 14px;
  color: var(--text-dim);
  font-size: 12px;
  line-height: 1.5;
  white-space: pre-wrap;
}

.lib-text-ico { display: none; }

.lib-card-body {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 10px 11px 11px;
  min-width: 0;
}

.lib-card-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  min-width: 0;
}

.lib-card-model {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
  font-size: 12px;
  font-weight: 600;
}

.lib-card-time {
  flex: none;
  color: var(--text-mute);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.lib-card-prompt {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: 0;
  color: var(--text);
  font-size: 12.5px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

/* the JA rendering is still being fetched */
.lib-card-prompt.is-pending { opacity: 0.55; }
.lib-card-prompt.is-muted { color: var(--text-mute); font-style: italic; }

.lib-card-prompt-en {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: 0;
  color: var(--text-mute);
  font-size: 11px;
  line-height: 1.45;
  overflow-wrap: anywhere;
}

.lib-card-prompt:empty,
.lib-card-prompt-en:empty { display: none; }


/* ==========================================================================
   14  Library head, filters, search
   ========================================================================== */

.lib-head {
  position: sticky;
  top: 0;
  z-index: 6;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding: 16px 0 12px;
  background: linear-gradient(180deg, var(--bg) 74%, rgba(11, 11, 12, 0));
}

.lib-filters {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  min-width: 0;
}

.lib-tools {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.search {
  width: 220px;
  height: 32px;
  min-height: 32px;
  padding: 0 12px 0 32px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  color: var(--text);
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236B7178' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-3.6-3.6'/%3E%3C/svg%3E")
    no-repeat left 10px center / 14px 14px,
    var(--surface-2);
  font-size: 12.5px;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.search:hover { border-color: #343941; }

.search::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }

.search:focus {
  border-color: var(--accent-40);
  box-shadow: var(--ring);
}

.search-lg {
  width: 100%;
  height: 40px;
  min-height: 40px;
  padding-left: 38px;
  font-size: 14px;
  background-position: left 14px center;
  background-size: 16px 16px;
}

.loading {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 0;
}


/* ==========================================================================
   15  Empty states, spinners
   ========================================================================== */

.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 64px 24px;
  text-align: center;
}

.empty-art {
  width: 92px;
  height: 92px;
  margin-bottom: 8px;
  border-radius: var(--radius-lg);
  border: 1px dashed var(--line);
  background:
    radial-gradient(48px 48px at 50% 42%, var(--accent-14), transparent 70%),
    repeating-linear-gradient(45deg, rgba(255, 255, 255, 0.022) 0 8px, transparent 8px 16px),
    var(--surface);
  box-shadow: inset 0 0 40px rgba(0, 0, 0, 0.35);
}

.empty-title {
  color: var(--text);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.empty-sub {
  color: var(--text-mute);
  font-size: 13px;
  line-height: 1.6;
  max-width: 42ch;
  text-wrap: balance;
}

.spinner {
  display: inline-block;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid var(--surface-3);
  border-top-color: var(--accent);
  animation: hfs-spin 750ms linear infinite;
}

/* rides inside a button label while a cost estimate resolves */
.spinner-inline {
  display: inline-block;
  width: 13px;
  height: 13px;
  margin-left: 8px;
  vertical-align: -2px;
  border-radius: 50%;
  border: 2px solid rgba(0, 0, 0, 0.25);
  border-top-color: var(--accent-ink);
  animation: hfs-spin 700ms linear infinite;
}

@keyframes hfs-spin { to { transform: rotate(360deg); } }

@keyframes hfs-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.28; }
}

@keyframes hfs-live {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.35; transform: scale(0.78); }
}

@keyframes hfs-slide {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(320%); }
}

@keyframes hfs-fade { from { opacity: 0; } to { opacity: 1; } }

@keyframes hfs-rise {
  from { opacity: 0; transform: translateY(10px) scale(0.985); }
  to   { opacity: 1; transform: none; }
}


/* ==========================================================================
   16  Modals
   ========================================================================== */

.modal {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(6, 6, 7, 0.66);
  backdrop-filter: blur(6px) saturate(120%);
  -webkit-backdrop-filter: blur(6px) saturate(120%);
  animation: hfs-fade var(--dur-modal) var(--ease);
}

.modal-panel {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 520px;
  max-height: 88vh;
  max-height: 88dvh;
  overflow: hidden;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  background: var(--surface);
  box-shadow: var(--shadow-3);
  animation: hfs-rise var(--dur-modal) var(--ease);
}

.modal-wide { max-width: 1040px; }
.modal-detail { max-width: 1180px; }
.modal-share { max-width: 480px; }
.modal-confirm { max-width: 460px; }

/* A confirm can be raised over another modal, so it outranks one. */
.modal-confirm-wrap { z-index: 140; }

.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex: none;
  padding: 16px 18px;
  border-bottom: 1px solid var(--line);
}

.modal-title {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.015em;
  min-width: 0;
  overflow-wrap: anywhere;
}

.modal-head-tools {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.modal-tools {
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: none;
  padding: 14px 18px;
  border-bottom: 1px solid var(--line-soft);
}

/* --- confirm dialog (built by HFS.confirmDialog) ------------------------- */
.confirm-message {
  margin: 0;
  padding: 18px 20px 6px;
  color: var(--text-dim);
  font-size: 13.5px;
  line-height: 1.6;
  overflow-wrap: anywhere;
}

.confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  flex-wrap: wrap;
  padding: 16px 20px 20px;
}

/* --- detail modal body --------------------------------------------------- */
.detail-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  min-height: 0;
  flex: 1;
  overflow: hidden;
}

.detail-media {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  min-height: 260px;
  padding: 16px;
  overflow: auto;
  background:
    radial-gradient(600px 320px at 50% 0%, rgba(255, 255, 255, 0.03), transparent 65%),
    #0D0E10;
}

.detail-video,
.detail-image {
  max-width: 100%;
  max-height: min(72vh, 720px);
  width: auto;
  height: auto;
  display: block;
  border-radius: var(--radius);
  background: #0B0B0C;
  box-shadow: var(--shadow-2);
}

.detail-audio {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  width: 100%;
  padding: 48px 24px;
}

.detail-audio-el { width: min(420px, 100%); }

.detail-text {
  align-self: flex-start;
  width: 100%;
  max-height: min(72vh, 720px);
  margin: 0;
  padding: 16px 18px;
  overflow: auto;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text-dim);
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.65;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.detail-meta {
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: 0;
  padding: 16px 18px 22px;
  overflow-y: auto;
  border-left: 1px solid var(--line);
  background: var(--surface);
}

.meta-block {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}

.meta-block:empty { display: none; }

.meta-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.meta-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-mute);
}

.meta-prompt {
  padding: 11px 12px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text);
  font-size: 13px;
  line-height: 1.65;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.meta-prompt.is-muted { color: var(--text-mute); font-style: italic; }

.meta-prompt-ja {
  border-left: 2px solid var(--accent-40);
  background: var(--accent-08);
  color: var(--text-dim);
}

.meta-prompt-ja.is-pending { opacity: 0.55; }

/* --- submitted params, as key/value rows --------------------------------- */
.param-list {
  display: flex;
  flex-direction: column;
  margin: 0;
  min-width: 0;
}

.param-row {
  display: grid;
  grid-template-columns: minmax(96px, 40%) minmax(0, 1fr);
  gap: 10px;
  padding: 7px 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: 12px;
  line-height: 1.5;
}

.param-row:last-child { border-bottom: 0; }

.param-key {
  margin: 0;
  color: var(--text-mute);
  overflow-wrap: anywhere;
}

.param-val {
  margin: 0;
  color: var(--text);
  overflow-wrap: anywhere;
  font-variant-numeric: tabular-nums;
}

/* --- ids / timestamps under the params ----------------------------------- */
.meta-foot {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}

.foot-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.4;
  color: var(--text-mute);
}

.foot-key { flex: none; }

.foot-val {
  color: var(--text-dim);
  text-align: right;
  overflow-wrap: anywhere;
}

.mono-id {
  padding: 3px 7px;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text-dim);
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.4;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.mono-id:hover { color: var(--accent); border-color: var(--accent-40); }

/* --- reference media in the detail modal --------------------------------- */
.ref-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.ref-item {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 92px;
  min-width: 0;
}

.ref-thumb {
  display: block;
  width: 92px;
  height: 92px;
  flex: none;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--surface-2);
  overflow: hidden;
}

.ref-media {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.ref-audio { height: 32px; margin-top: 30px; object-fit: none; }

.ref-blank {
  display: flex;
  align-items: center;
  justify-content: center;
  background: repeating-linear-gradient(135deg, #131517 0 8px, #191B1E 8px 16px);
}

.ref-meta {
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: flex-start;
  min-width: 0;
}

.ref-role {
  color: var(--text-dim);
  font-size: 11px;
  letter-spacing: 0.03em;
  overflow-wrap: anywhere;
}


/* ==========================================================================
   17  Model picker + uploads picker
   ========================================================================== */

.model-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(248px, 1fr));
  gap: 10px;
  align-content: start;
  padding: 14px 18px 20px;
}

.model-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  min-width: 0;
  padding: 13px 14px;
  border-radius: var(--radius);
  border: 1px solid var(--line-soft);
  background: var(--surface-2);
  color: var(--text);
  text-align: left;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.model-card:hover {
  background: var(--surface-3);
  border-color: #343941;
  transform: translateY(-2px);
}

.model-card.is-active {
  border-color: var(--accent);
  background: var(--accent-08);
  box-shadow: 0 0 0 1px var(--accent) inset, 0 0 0 3px var(--accent-14);
}

.model-card-top {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  min-width: 0;
}

/* the media-type / workflow tag — quiet by default, lime on the chosen card */
.model-card-badge {
  display: inline-flex;
  align-items: center;
  height: 19px;
  padding: 0 8px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  background: var(--surface-3);
  color: var(--text-dim);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
}

.model-card-badge:empty { display: none; }

.model-card.is-active .model-card-badge {
  border-color: var(--accent-40);
  background: var(--accent-14);
  color: var(--accent);
}

.model-card-name {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.35;
  color: var(--text);
  overflow-wrap: anywhere;
}

.model-card.is-active .model-card-name { color: var(--accent); }

.model-card-jt {
  color: var(--text-mute);
  font-family: var(--font-mono);
  font-size: 11px;
  overflow-wrap: anywhere;
}

.model-card-hint {
  color: var(--text-mute);
  font-size: 11.5px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.model-card-hint:empty { display: none; }
.model-card-hint b { color: var(--text-dim); font-weight: 600; }

/* --- previously uploaded assets ------------------------------------------ */
.uploads-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  gap: 10px;
  max-height: 60vh;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 14px 18px 20px;
  align-content: start;
}

.upload-tile {
  padding: 0;
  aspect-ratio: 1 / 1;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--surface-2);
  overflow: hidden;
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.upload-tile:hover { border-color: var(--accent-40); transform: translateY(-2px); }

.upload-tile img,
.upload-tile video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}


/* ==========================================================================
   18  Workspace picker
   ========================================================================== */

.ws-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 0;
  overflow-y: auto;
  padding: 14px 18px 20px;
}

.ws-item {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  padding: 12px 14px;
  border-radius: var(--radius);
  border: 1px solid var(--line-soft);
  background: var(--surface-2);
  color: var(--text);
  text-align: left;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.ws-item:hover { background: var(--surface-3); border-color: #343941; }

.ws-item.is-active {
  border-color: var(--accent-40);
  background: var(--accent-08);
}

.ws-item.is-busy { pointer-events: none; color: transparent; }

.ws-item.is-busy::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 18px;
  height: 18px;
  margin: -9px 0 0 -9px;
  border-radius: 50%;
  border: 2px solid var(--text-dim);
  border-top-color: transparent;
  animation: hfs-spin 700ms linear infinite;
}

.ws-item-main { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }

.ws-name {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -0.01em;
  overflow-wrap: anywhere;
}

.ws-meta {
  color: var(--text-mute);
  font-size: 11.5px;
  overflow-wrap: anywhere;
}

.ws-badge {
  flex: none;
  height: 22px;
  padding: 0 9px;
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
}

.ws-note {
  margin: 14px 0 0;
  padding: 0 20px;
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1.6;
}

/* a plain sentence dropped into a modal body (errors, "nothing here yet") */
.hfs-inline-msg {
  padding: 18px 20px;
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1.6;
  overflow-wrap: anywhere;
}


/* ==========================================================================
   19  Toasts & boot splash
   ========================================================================== */

.toasts {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 300;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  pointer-events: none;
  max-width: min(400px, calc(100vw - 36px));
}

/* main.js reveals a toast by adding .is-in and hides it by removing it. */
.toast {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  width: 100%;
  padding: 11px 13px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--surface-3);
  color: var(--text);
  font-size: 13px;
  line-height: 1.5;
  box-shadow: var(--shadow-3);
  pointer-events: auto;
  cursor: pointer;
  opacity: 0;
  transform: translateY(8px) scale(0.98);
  transition: opacity 180ms var(--ease), transform 180ms var(--ease);
}

.toast.is-in { opacity: 1; transform: none; }

.toast-dot {
  width: 8px;
  height: 8px;
  margin-top: 6px;
  flex: none;
  border-radius: 50%;
  background: var(--text-dim);
}

.toast-msg { min-width: 0; overflow-wrap: anywhere; }

.toast-ok {
  border-color: var(--ok-30);
  background: linear-gradient(180deg, var(--ok-12), var(--surface-3));
}

.toast-ok .toast-dot { background: var(--ok); }

.toast-error {
  border-color: var(--danger-30);
  background: linear-gradient(180deg, var(--danger-12), var(--surface-3));
}

.toast-error .toast-dot { background: var(--danger); }

.toast-warn {
  border-color: var(--warn-30);
  background: linear-gradient(180deg, var(--warn-12), var(--surface-3));
}

.toast-warn .toast-dot { background: var(--warn); }

.toast-info .toast-dot { background: #8FB6FF; }

/* --- boot splash --------------------------------------------------------- */
.hfs-boot {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  grid-auto-flow: row;
  place-items: center;
  align-content: center;
  gap: 14px;
  background: var(--bg);
}

.hfs-boot-dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 26px rgba(209, 254, 23, 0.35);
  animation: hfs-live 1.1s ease-in-out infinite;
}

.hfs-boot-text {
  color: var(--text-mute);
  font-size: 13px;
  letter-spacing: 0.01em;
}


/* ==========================================================================
   20  Share
   --------------------------------------------------------------------------
   The link is deliberately public: anyone who opens it can generate on this
   account. The panel says so in words that cannot be dismissed, and the
   controls that would tear the shared session down are owner-only.
   ========================================================================== */

.share-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-height: 0;
  padding: 16px 18px 20px;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* --- status line ---------------------------------------------------------- */
.share-state {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
  color: var(--text-dim);
  font-size: 13px;
  font-weight: 600;
  overflow-wrap: anywhere;
}

.share-state .dot {
  width: 9px;
  height: 9px;
  flex: none;
  border-radius: 50%;
  background: var(--text-mute);
  box-shadow: none;
}

.share-state.is-live,
body[data-sharing="on"] .share-state { color: var(--accent); }

.share-state.is-live .dot,
body[data-sharing="on"] .share-state .dot {
  background: var(--accent);
  box-shadow: 0 0 12px rgba(209, 254, 23, 0.5);
  animation: hfs-live 1.6s var(--ease) infinite;
}

.share-state-text { min-width: 0; }

/* --- the warning that never goes away ------------------------------------ */
.share-warning {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 13px;
  border-left: 3px solid var(--warn);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--warn-12);
}

.share-warning-ico {
  width: 17px;
  height: 17px;
  flex: none;
  margin-top: 1px;
  fill: var(--warn);
}

.share-warning-text {
  min-width: 0;
  color: #F3DFA0;
  font-size: 12.5px;
  line-height: 1.6;
  overflow-wrap: anywhere;
}

/* --- the link ------------------------------------------------------------- */
.share-url-row {
  display: flex;
  align-items: stretch;
  gap: 0;                          /* the copy button sits flush against it */
  min-width: 0;
}

.share-url {
  flex: 1 1 auto;
  min-width: 0;
  height: 38px;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-right: 0;
  border-radius: var(--radius-sm) 0 0 var(--radius-sm);
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.4;
  text-overflow: ellipsis;
  user-select: all;
  -webkit-user-select: all;
  cursor: text;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.share-url:hover { border-color: #343941; }

.share-url:focus,
.share-url:focus-visible {
  outline: none;
  border-color: var(--accent-40);
  box-shadow: none;
}

#share-copy {
  flex: none;
  min-height: 38px;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

/* --- QR: a phone camera needs real white, not a dark plate ---------------
   main.js renders an inline <svg class="share-qr-svg"> and parks a caption
   under it, so the white plate goes on the SVG — a white container would put
   the caption on white too. */
.share-qr {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
}

.share-qr:empty { display: none; }

.share-qr svg,
.share-qr-svg,
.share-qr img,
.share-qr canvas {
  display: block;
  width: 168px;
  height: 168px;
  max-width: 100%;
  padding: 10px;
  border-radius: 14px;
  background: #FFFFFF;
  box-shadow: var(--shadow-2);
}

.share-qr img,
.share-qr canvas { image-rendering: pixelated; }

.share-qr-hint {
  margin: 0;
  color: var(--text-mute);
  font-size: 11.5px;
  line-height: 1.5;
  text-align: center;
  overflow-wrap: anywhere;
}

/* dimmed while the link is not live yet */
.share-qr.is-pending { opacity: 0.5; }
.share-url-row.is-pending .share-url { opacity: 0.55; }

/* --- who can reach it: the same segmented family as .kind-row ------------ */
.share-scope {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  border: 1px solid var(--line-soft);
}

/* The labels are i18n copy and can run long, so a pill grows to two lines
   rather than clipping — the container's pill radius follows the height. */
.share-scope-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 1 1 0;
  min-width: 0;
  min-height: 34px;
  height: auto;
  padding: 6px 12px;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-dim);
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.35;
  text-align: center;
  text-wrap: balance;
  white-space: normal;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

.share-scope-btn:hover { color: var(--text); background: var(--white-04); }

.share-scope-btn.is-active,
.share-scope-btn[aria-pressed="true"],
.share-scope-btn[aria-selected="true"] {
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 700;
}

/* one line saying what the chosen scope actually means */
.share-scope-hint {
  margin: -6px 0 0;
  color: var(--text-mute);
  font-size: 11.5px;
  line-height: 1.55;
  overflow-wrap: anywhere;
}

/* Tailscale cannot share this machine at all — the controls are gone and
   this is what stands in their place. */
.share-unavailable {
  margin: 0;
  padding: 12px 13px;
  border-left: 3px solid var(--line);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--surface-2);
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1.6;
  overflow-wrap: anywhere;
}

.share-unavailable-detail {
  display: block;
  margin-top: 6px;
  color: var(--text-mute);
  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.55;
  overflow-wrap: anywhere;
}

/* --- primary action ------------------------------------------------------- */
#share-toggle.is-live {
  background: var(--danger-12);
  border-color: var(--danger-30);
  color: var(--danger);
}

#share-toggle.is-live:hover {
  background: rgba(255, 90, 90, 0.2);
  border-color: var(--danger);
  box-shadow: none;
}

/* --- the exact command, for when the UI is not enough --------------------- */
.share-hint {
  margin: 0;
  color: var(--text-mute);
  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.6;
  white-space: pre-wrap;
  word-break: normal;
  overflow-wrap: anywhere;
}

.share-hint:empty { display: none; }

/* when the sentence and the command are separate nodes */
.share-hint-label {
  font-family: var(--font);
  color: var(--text-mute);
}

.share-hint-cmd {
  color: var(--text-dim);
  font-family: var(--font-mono);
  overflow-wrap: anywhere;
}


/* ==========================================================================
   21  Utilities
   ========================================================================== */

.row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }


/* ==========================================================================
   22  Japanese mode
   ========================================================================== */

body[data-lang="ja"] {
  --font: "Noto Sans JP", "Inter", system-ui, -apple-system, "Hiragino Kaku Gothic ProN",
          "Yu Gothic", Meiryo, sans-serif;
  --lh: 1.72;
  letter-spacing: 0.01em;
}

/* JA needs air: headings and dense labels loosen slightly. */
body[data-lang="ja"] .auth-title,
body[data-lang="ja"] .modal-title,
body[data-lang="ja"] .empty-title { line-height: 1.5; }

body[data-lang="ja"] .btn,
body[data-lang="ja"] .chip,
body[data-lang="ja"] .tab,
body[data-lang="ja"] .kind,
body[data-lang="ja"] .seg-btn,
body[data-lang="ja"] .share-scope-btn,
body[data-lang="ja"] .chip-filter {
  /* size to content, never a fixed width — JA strings are longer */
  padding-left: 15px;
  padding-right: 15px;
  letter-spacing: 0.02em;
}

body[data-lang="ja"] .btn-sm,
body[data-lang="ja"] .chip-filter { padding-left: 13px; padding-right: 13px; }
body[data-lang="ja"] .btn-xs { padding-left: 11px; padding-right: 11px; }
body[data-lang="ja"] .share-scope-btn { padding-left: 10px; padding-right: 10px; }

body[data-lang="ja"] .field-label,
body[data-lang="ja"] .meta-label,
body[data-lang="ja"] .cost-label,
body[data-lang="ja"] .slot-title,
body[data-lang="ja"] .lib-ph-text {
  letter-spacing: 0.04em;
  text-transform: none;          /* uppercase is meaningless for kana/kanji */
  font-size: 12px;
}

/* Wrap Japanese labels on real breaks; never truncate mid-word. */
body[data-lang="ja"] .param-label,
body[data-lang="ja"] .param-hint,
body[data-lang="ja"] .slot-cta,
body[data-lang="ja"] .empty-sub,
body[data-lang="ja"] .auth-sub,
body[data-lang="ja"] .rule,
body[data-lang="ja"] .model-card-hint,
body[data-lang="ja"] .share-warning-text {
  word-break: normal;
  overflow-wrap: anywhere;
  line-break: strict;
}

body[data-lang="ja"] .param-label { font-size: 12px; line-height: 1.55; }
body[data-lang="ja"] .prompt { line-height: 1.8; }
body[data-lang="ja"] .prompt-translation,
body[data-lang="ja"] .meta-prompt-ja { line-height: 1.85; }

/* Latin runs inside a JA UI (job types, emails, URLs) stay on Inter. */
body[data-lang="ja"] .model-current-meta,
body[data-lang="ja"] .model-card-jt,
body[data-lang="ja"] .account-email,
body[data-lang="ja"] .auth-cmd,
body[data-lang="ja"] .auth-url,
body[data-lang="ja"] .mono-id,
body[data-lang="ja"] .foot-row,
body[data-lang="ja"] .slot-id,
body[data-lang="ja"] .share-url,
body[data-lang="ja"] .share-hint,
body[data-lang="ja"] .brand-name {
  font-family: "Inter", var(--font-mono), var(--font);
  letter-spacing: 0;
}

body[data-lang="ja"] .share-url,
body[data-lang="ja"] .share-hint,
body[data-lang="ja"] .mono-id,
body[data-lang="ja"] .foot-row,
body[data-lang="ja"] .slot-id { font-family: var(--font-mono); }

body[data-lang="ja"] .brand-name { font-family: "Inter", "Noto Sans JP", sans-serif; }

/* The toggle reads 「EN」 when JA is active — keep both states equal width-ish. */
#lang-toggle span { min-width: 2.5em; text-align: center; }


/* ==========================================================================
   23  Responsive
   ========================================================================== */

/* Wide desktops: a roomier stage grid */
@media (min-width: 1600px) {
  .stage-grid,
  .lib-grid { grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); }
}

/* Narrow desktop / large tablet — one-column params */
@media (max-width: 1280px) {
  .params { grid-template-columns: minmax(0, 1fr); }
  .param:has(textarea),
  .param:has(.seg),
  .param:has(input[type="range"]),
  .param:has(.chooser) { grid-column: auto; }
  .detail-body { grid-template-columns: minmax(0, 1fr) 300px; }
}

/* The share pill is one more thing in a full topbar. Below 1100 the two
   longest strings go: the account email (the avatar still identifies it) and
   the credits figure (the chip keeps its icon, tooltip and click target). */
@media (max-width: 1100px) {
  .topbar { gap: 12px; }
  .topbar-left, .topbar-right { gap: 8px; }

  .account-email { display: none; }
  .chip-account { padding: 0 5px; max-width: none; }

  #credits-value { display: none; }
  .chip-credits { padding: 0 11px; }
}

/* Stack the Generate view */
@media (max-width: 1023px) {
  /* One scroller for the whole view; rows size to their content (min-height:0
     would let the auto rows shrink below it and the panels would overlap). */
  .view-generate {
    grid-template-columns: minmax(0, 1fr);
    grid-auto-rows: min-content;
    align-content: start;
    height: auto;
    min-height: calc(100dvh - var(--topbar-h));
    overflow-y: auto;
  }

  .composer {
    min-height: auto;
    border-right: 0;
    border-bottom: 1px solid var(--line);
  }

  .composer-scroll {
    flex: none;
    min-height: auto;
    overflow: visible;
  }

  /* Static, not sticky: a floating foot would sit on top of the settings. */
  .composer-foot {
    position: static;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background: var(--surface);
  }

  .stage {
    min-height: auto;
    overflow: visible;
    padding-top: 4px;
  }

  .stage-head { position: static; background: none; }
}

/* Tablet chrome — the tabs become icons; their names stay for screen readers. */
@media (max-width: 900px) {
  :root { --pad: 14px; }

  .topbar { padding: 0 12px; gap: 8px; }
  .topbar-left, .topbar-right { gap: 7px; }
  .brand { padding-right: 10px; }
  .brand-name { display: none; }

  .tab { gap: 0; padding: 0 11px; }
  .btn-lang, .btn-share { padding: 0 12px; }

  .tab span {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .tab-ico { width: 16px; height: 16px; }

  .detail-body {
    grid-template-columns: minmax(0, 1fr);
    overflow-y: auto;
  }

  .detail-media { min-height: 200px; }
  .detail-video,
  .detail-image { max-height: 52vh; }

  .detail-meta { border-left: 0; border-top: 1px solid var(--line); }

  .modal { padding: 12px; }
  .modal-panel { max-height: 92dvh; }

  .model-list { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
}

/* Phone */
@media (max-width: 640px) {
  .topbar { height: 56px; padding: 0 8px; gap: 6px; }
  .app { --topbar-h: 56px; }

  .topbar-left { flex: 1; min-width: 0; gap: 6px; overflow: hidden; }
  .topbar-right { flex: none; gap: 6px; }

  .brand { padding-right: 8px; margin-right: 0; }
  .brand-mark svg { width: 24px; height: 24px; }

  .tabs { padding: 3px; }
  .tab { height: 28px; padding: 0 9px; }

  .chip { height: 32px; }
  .chip-credits { padding: 0 10px; font-size: 12px; }
  .chip-account { display: none; }

  .btn-lang,
  .btn-share { height: 32px; min-height: 32px; padding: 0 10px; }
  .btn-lang .chip-ico { display: none; }
  #lang-toggle span { min-width: 0; font-size: 12px; }

  /* the globe alone still reads as "share" */
  #share-btn-label { display: none; }
  .btn-share.is-live { padding-right: 10px; }
  .btn-share.is-live::after { display: none; }

  .stage-grid,
  .lib-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }

  .search { width: 100%; }
  .lib-tools { width: 100%; }
  .lib-tools .search { flex: 1; }

  .share-scope { flex-direction: column; align-items: stretch; border-radius: var(--radius); }
  .share-scope-btn { width: 100%; }

  .toasts { left: 12px; right: 12px; bottom: 12px; max-width: none; }
}


/* ==========================================================================
   24  Reduced motion & print
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  .stage-card:hover,
  .lib-card:hover,
  .model-card:hover,
  .upload-tile:hover { transform: none; }

  .lib-card:hover .lib-thumb { transform: none; }
  .spinner { border-top-color: var(--accent); }
  .toast { opacity: 1; transform: none; }
}

@media print {
  body { background: #fff; color: #000; overflow: visible; }
  .topbar, .composer, .toasts, .modal, .auth-gate, .hfs-boot { display: none !important; }
  .app, .view, .stage, .view-library { height: auto; overflow: visible; }
  .stage-card, .lib-card { break-inside: avoid; border-color: #ccc; }
}
