/* =============================================================================
   Dectrick's LLM Studio — the theme engine.

   TWO mechanisms, and the split is the important part:

   1. Colours, typeface, corners and density are CSS CUSTOM PROPERTIES. They
      inherit, so a nested scope (a preview tile) that redeclares them wins for
      everything inside it, automatically.

   2. Element variants — header, bubble, composer, background, avatar, button —
      are MODIFIER CLASSES on the element itself, never `[data-x] .child`
      descendant rules. A descendant rule cannot be overridden by a nested
      scope: both selectors match with equal specificity and source order
      decides, so a "rounded bubble" tile sitting inside a "terminal" page would
      draw terminal. Putting the variant on the element removes the conflict
      entirely, which is what lets the studio show real working miniatures
      instead of screenshots that drift.

   Adding a variant = one entry in themes.py + one class here.
   ============================================================================= */

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

:root, .scope {
  --bg: #0a0d14;
  --surface: #121724;
  --line: #232a3d;
  --text: #e8ecf5;
  --muted: #8891a8;
  --accent: #5b8cff;
  --accent-text: #ffffff;

  --radius: 10px;
  --gap: 1rem;
  --pad: 1.1rem;

  --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, sans-serif;
  --font-head: var(--font-body);
  --head-weight: 650;
  --head-spacing: -0.02em;
}

/* --- Typeface / corners / density: variables only, so they nest correctly --- */
[data-font="sans"]    { --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, sans-serif; --font-head: var(--font-body); --head-weight: 650; --head-spacing: -0.02em; }
[data-font="serif"]   { --font-body: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif; --font-head: var(--font-body); --head-weight: 600; --head-spacing: -0.01em; }
[data-font="mono"]    { --font-body: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; --font-head: var(--font-body); --head-weight: 600; --head-spacing: 0; }
[data-font="display"] { --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, sans-serif; --font-head: "Impact", "Haettenschweiler", "Arial Narrow Bold", sans-serif; --head-weight: 400; --head-spacing: .01em; }

[data-radius="sharp"] { --radius: 0px; }
[data-radius="soft"]  { --radius: 10px; }
[data-radius="round"] { --radius: 20px; }

[data-density="compact"]     { --gap: .6rem;  --pad: .7rem; }
[data-density="comfortable"] { --gap: 1rem;   --pad: 1.1rem; }
[data-density="spacious"]    { --gap: 1.6rem; --pad: 1.6rem; }

/* --- Base ------------------------------------------------------------------ */
html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--font-body);
  background: var(--bg);
  color: var(--text);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
.scope { font-family: var(--font-body); color: var(--text); }
h1, h2, h3 { font-family: var(--font-head); font-weight: var(--head-weight); letter-spacing: var(--head-spacing); line-height: 1.15; margin: 0 0 .5em; }
a { color: var(--accent); }
::selection { background: var(--accent); color: var(--accent-text); }

/* =============================================================================
   BACKGROUND — .bgfx plus one modifier. Drawn in CSS: nothing to download,
   so it cannot half-load and leave a page with no ground under it.
   ============================================================================= */
.bgfx { position: fixed; inset: 0; z-index: -1; pointer-events: none; background: var(--bg); }

/* Inside a preview scope it must be ABSOLUTE, bounded by that scope.
   Left fixed, it escapes its container and covers the whole viewport — and
   since the preview column is a later sibling with its own stacking context,
   its background then paints straight over the settings panel and the panel
   reads as blank. Cost a screenshot to find; every element was present, laid
   out and the right colour, and none of it was on screen. */
.scope .bgfx { position: absolute; }
.bgfx.-g-flat { background: var(--bg); }
.bgfx.-g-gradient {
  background:
    radial-gradient(120% 90% at 8% -10%, color-mix(in srgb, var(--accent) 34%, transparent), transparent 60%),
    var(--bg);
}
.bgfx.-g-grid {
  background-color: var(--bg);
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--line) 65%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--line) 65%, transparent) 1px, transparent 1px);
  background-size: 34px 34px;
}
.bgfx.-g-dots {
  background-color: var(--bg);
  background-image: radial-gradient(color-mix(in srgb, var(--line) 90%, transparent) 1.2px, transparent 1.2px);
  background-size: 20px 20px;
}
.bgfx.-g-mesh {
  background:
    radial-gradient(45% 40% at 12% 8%,  color-mix(in srgb, var(--accent) 26%, transparent), transparent 70%),
    radial-gradient(50% 45% at 88% 92%, color-mix(in srgb, var(--accent) 18%, transparent), transparent 70%),
    var(--bg);
}
.bgfx.-g-noise {
  background-color: var(--bg);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.05'/%3E%3C/svg%3E");
}

/* =============================================================================
   LAYOUT
   ============================================================================= */
.wrap { width: min(1080px, 100% - 2.5rem); margin-inline: auto; }
.wrap--wide { width: min(1440px, 100% - 2rem); }
.chat-wrap { width: min(820px, 100% - 2rem); margin-inline: auto; }

/* =============================================================================
   HEADER
   ============================================================================= */
.hd { display: flex; align-items: center; gap: var(--gap); }
.hd__brand { display: flex; align-items: center; gap: .6rem; min-width: 0; }
.hd__name { font-family: var(--font-head); font-weight: var(--head-weight); letter-spacing: var(--head-spacing); font-size: 1.02rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hd__tag { color: var(--muted); font-size: .8rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hd__spacer { flex: 1; }
.hd__actions { display: flex; align-items: center; gap: .5rem; }

.hd.-h-minimal { padding: calc(var(--pad) * 1.1) 0; }
.hd.-h-bar { padding: var(--pad) 1.2rem; background: var(--surface); border-bottom: 1px solid var(--line); }
.hd.-h-centered { flex-direction: column; text-align: center; gap: .25rem; padding: calc(var(--pad) * 1.5) 0; }
.hd.-h-centered .hd__spacer { display: none; }
.hd.-h-centered .hd__brand { flex-direction: column; }
.hd.-h-floating {
  margin: var(--gap) 0; padding: .6rem .9rem;
  background: color-mix(in srgb, var(--surface) 85%, transparent);
  border: 1px solid var(--line); border-radius: calc(var(--radius) + 12px);
  box-shadow: 0 10px 30px rgba(0,0,0,.22);
}
.hd.-h-split { padding: var(--pad) 0; border-bottom: 1px solid var(--line); }
.hd.-h-split .hd__tag { display: none; }

/* =============================================================================
   BUTTONS
   ============================================================================= */
.btn {
  font: inherit; font-size: .86rem; font-weight: 600; cursor: pointer;
  padding: .55rem .95rem; border-radius: var(--radius);
  border: 1px solid transparent; background: var(--accent); color: var(--accent-text);
  transition: filter .15s ease, background .15s ease, border-color .15s ease;
  white-space: nowrap; text-decoration: none; display: inline-block;
}
.btn:hover { filter: brightness(1.1); }
.btn:disabled { opacity: .45; cursor: not-allowed; }

.btn.-btn-solid    { background: var(--accent); color: var(--accent-text); border-color: transparent; }
.btn.-btn-outline  { background: transparent; color: var(--text); border-color: var(--line); border-width: 2px; }
.btn.-btn-outline:hover { border-color: var(--accent); }
.btn.-btn-ghost    { background: transparent; color: var(--accent); border-color: transparent; }
.btn.-btn-ghost:hover { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.btn.-btn-gradient { background: linear-gradient(120deg, var(--accent), color-mix(in srgb, var(--accent) 45%, #ffffff)); color: var(--accent-text); border-color: transparent; }
.btn.-btn-pill     { border-radius: 999px; background: var(--accent); color: var(--accent-text); }

/* Quiet is a role, not a variant — it stays legible under every variant. */
.btn--quiet { background: transparent !important; color: var(--muted) !important; border: 1px solid var(--line) !important; }
.btn--quiet:hover { color: var(--text) !important; border-color: var(--accent) !important; }

/* =============================================================================
   AVATAR
   ============================================================================= */
.av { flex: 0 0 auto; width: 30px; height: 30px; display: grid; place-items: center; font-size: .68rem; font-weight: 700; overflow: hidden; }
.av.-a-none { display: none; }
.av.-a-initials { border-radius: 999px; background: color-mix(in srgb, var(--accent) 22%, transparent); color: var(--text); }
.av.-a-dot { width: 9px; height: 9px; border-radius: 999px; background: var(--accent); font-size: 0; margin-top: .5rem; }
.av.-a-mark { border-radius: calc(var(--radius) * .8); background: var(--accent); color: var(--accent-text); }
.av.-a-square { border-radius: 0; background: var(--accent); color: var(--accent-text); }
.msg--user .av.-a-mark { background: color-mix(in srgb, var(--accent) 20%, transparent); color: var(--text); }

/* =============================================================================
   MESSAGES
   ============================================================================= */
.msg { display: flex; gap: .65rem; margin-bottom: var(--gap); align-items: flex-start; }
.msg--user { flex-direction: row-reverse; }
.msg__body { min-width: 0; max-width: 84%; }
.msg__role { display: none; font-size: .68rem; letter-spacing: .09em; text-transform: uppercase; color: var(--muted); margin-bottom: .3rem; }
.msg--user .msg__role { text-align: right; }
.msg__img { display: block; max-width: 220px; border-radius: var(--radius); margin-bottom: .5rem; border: 1px solid var(--line); }
.msg__text { padding: var(--pad); border-radius: var(--radius); background: var(--surface); border: 1px solid transparent; white-space: pre-wrap; word-wrap: break-word; overflow-wrap: anywhere; }
.msg--user .msg__text { background: color-mix(in srgb, var(--accent) 20%, transparent); }

.msg__text.-b-rounded { border-radius: calc(var(--radius) + 8px); }
.msg__text.-b-square  { border-radius: 0; }
.msg__text.-b-bordered { background: transparent; border: 1px solid var(--line); }
.msg--user .msg__text.-b-bordered { background: transparent; border-color: var(--accent); }
.msg__text.-b-flat { background: transparent; padding: 0 0 .2rem; }
.msg--user .msg__text.-b-flat { background: transparent; }
.msg__text.-b-terminal {
  background: transparent; padding: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .9rem;
}
.msg--user .msg__text.-b-terminal { background: transparent; }
.msg__text.-b-terminal::before { content: "› "; color: var(--accent); }
.msg--user .msg__text.-b-terminal::before { content: "$ "; }
.msg__text.-b-card {
  border-radius: calc(var(--radius) + 4px); border: 1px solid var(--line);
  box-shadow: 0 8px 26px rgba(0,0,0,.28), inset 0 1px 0 color-mix(in srgb, var(--text) 6%, transparent);
}
/* The flat and terminal variants drop the container, so the role label is the
   only thing left saying who is speaking. Without this they are ambiguous. */
.msg__text.-b-flat + .msg__role, .msg__body:has(.-b-flat) .msg__role,
.msg__body:has(.-b-terminal) .msg__role { display: block; }

/* =============================================================================
   COMPOSER
   ============================================================================= */
.cmp { display: flex; align-items: flex-end; gap: .5rem; padding: .45rem; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); }
.cmp__field { flex: 1; min-width: 0; }
.cmp textarea, .cmp__fake {
  width: 100%; resize: none; border: 0; outline: 0; background: transparent; color: var(--text);
  font: inherit; font-size: .95rem; line-height: 1.5; padding: .45rem .5rem; max-height: 180px; display: block;
}
.cmp__fake { color: var(--muted); }
.cmp textarea::placeholder { color: var(--muted); }
.cmp__tools { display: flex; align-items: center; gap: .35rem; }
.icon-btn { width: 34px; height: 34px; display: grid; place-items: center; cursor: pointer; background: transparent; border: 1px solid var(--line); border-radius: var(--radius); color: var(--muted); font-size: 1rem; }
.icon-btn:hover { color: var(--text); border-color: var(--accent); }

.cmp.-c-pill { border-radius: 999px; padding: .3rem .3rem .3rem .85rem; }
.cmp.-c-pill .icon-btn, .cmp.-c-pill .btn { border-radius: 999px; }
.cmp.-c-boxed { flex-direction: column; align-items: stretch; }
.cmp.-c-boxed .cmp__tools { justify-content: flex-end; }
.cmp.-c-inline { background: transparent; border: 0; border-top: 1px solid var(--line); border-radius: 0; padding: .5rem 0; }
.cmp.-c-inline .cmp__field { position: relative; padding-left: 1rem; }
.cmp.-c-inline .cmp__field::before { content: "›"; position: absolute; left: 0; top: .45rem; color: var(--accent); }
.cmp.-c-floating { border-radius: calc(var(--radius) + 14px); box-shadow: 0 16px 40px rgba(0,0,0,.35); margin-bottom: .5rem; }
.cmp.-c-split { padding: 0; overflow: hidden; align-items: stretch; }
.cmp.-c-split textarea, .cmp.-c-split .cmp__fake { padding: .8rem .9rem; }
.cmp.-c-split .cmp__tools { align-self: stretch; gap: 0; }
.cmp.-c-split .btn { height: 100%; border-radius: 0; padding-inline: 1.2rem; }
.cmp.-c-split .icon-btn { height: 100%; border-radius: 0; border-top: 0; border-bottom: 0; }

/* =============================================================================
   Shared pieces
   ============================================================================= */
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: calc(var(--pad) * 1.15); }
.muted { color: var(--muted); }
.pill { display: inline-block; font-size: .72rem; padding: .18rem .55rem; border: 1px solid var(--line); border-radius: 999px; color: var(--muted); }
.select { font: inherit; font-size: .82rem; color: var(--text); background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: .4rem .55rem; cursor: pointer; }
.quota { font-size: .76rem; color: var(--muted); white-space: nowrap; }
.quota b { color: var(--accent); }

.gate { border: 1px solid var(--accent); border-radius: var(--radius); padding: calc(var(--pad) * 1.15); background: color-mix(in srgb, var(--accent) 8%, var(--surface)); }
.gate h3 { margin-bottom: .3rem; }
.gate__row { display: flex; gap: .5rem; margin-top: .8rem; flex-wrap: wrap; }
.gate input, .field-input {
  flex: 1; min-width: 200px; font: inherit; font-size: .9rem; padding: .55rem .7rem; color: var(--text);
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius); outline: 0;
}
.gate input:focus, .field-input:focus { border-color: var(--accent); }
.err { color: #ff6b6b; font-size: .82rem; margin-top: .5rem; }

.typing span { display: inline-block; width: 6px; height: 6px; margin-right: 3px; border-radius: 50%; background: var(--muted); animation: blink 1.2s infinite; }
.typing span:nth-child(2) { animation-delay: .2s; }
.typing span:nth-child(3) { animation-delay: .4s; }
@keyframes blink { 0%, 60%, 100% { opacity: .25; } 30% { opacity: 1; } }

/* =============================================================================
   PORTFOLIO
   ============================================================================= */
.hero { padding: clamp(2.5rem, 8vw, 6rem) 0 clamp(2rem, 5vw, 3.5rem); }
.hero h1 { font-size: clamp(2rem, 5.4vw, 3.6rem); max-width: 18ch; }
.hero p { font-size: clamp(1rem, 1.6vw, 1.12rem); color: var(--muted); max-width: 62ch; }
.hero__cta { display: flex; gap: .7rem; margin-top: 1.8rem; flex-wrap: wrap; }
.status { display: inline-flex; align-items: center; gap: .5rem; font-size: .8rem; color: var(--muted); margin-bottom: 1.2rem; }
.status i { width: 8px; height: 8px; border-radius: 50%; background: #35d07f; box-shadow: 0 0 0 4px color-mix(in srgb, #35d07f 20%, transparent); }

section { padding: clamp(2rem, 5vw, 3.5rem) 0; }
section > h2 { font-size: clamp(1.3rem, 2.6vw, 1.9rem); }
.section-note { color: var(--muted); margin: -.2rem 0 1.6rem; max-width: 60ch; }
.grid { display: grid; gap: var(--gap); grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.proj h3 { margin-bottom: .15rem; }
.proj .role { font-size: .78rem; color: var(--accent); margin-bottom: .6rem; }
.stack { display: flex; flex-wrap: wrap; gap: .35rem; margin-top: .9rem; }
.skills { display: grid; gap: var(--gap); grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.skills h4 { margin: 0 0 .5rem; font-size: .78rem; letter-spacing: .09em; text-transform: uppercase; color: var(--muted); }
footer { border-top: 1px solid var(--line); padding: 2rem 0 3rem; color: var(--muted); font-size: .85rem; }

/* =============================================================================
   THE STUDIO
   ============================================================================= */
.st-layout { display: grid; grid-template-columns: 400px 1fr; gap: 1.2rem; align-items: start; }
@media (max-width: 980px) { .st-layout { grid-template-columns: 1fr; } }
.st-panel { max-height: calc(100vh - 6rem); overflow-y: auto; padding-right: .5rem; }
.st-group { margin-bottom: 1.5rem; }
.st-group > h3 { font-size: .74rem; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); margin-bottom: .3rem; }
.st-group > .hint { font-size: .75rem; color: var(--muted); margin: 0 0 .7rem; }
.st-field { margin-bottom: .8rem; }
.st-field label { display: block; font-size: .78rem; color: var(--muted); margin-bottom: .3rem; }
.st-field input[type="text"], .st-field textarea, .st-field select {
  width: 100%; font: inherit; font-size: .88rem; padding: .5rem .6rem; color: var(--text);
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius); outline: 0;
}
.st-field textarea { resize: vertical; min-height: 68px; }
.st-field input:focus, .st-field textarea:focus { border-color: var(--accent); }
.st-colors { display: grid; grid-template-columns: repeat(2, 1fr); gap: .5rem; }
.st-color { display: flex; align-items: center; gap: .5rem; font-size: .74rem; color: var(--muted); }
.st-color input[type="color"] { width: 36px; height: 26px; padding: 0; border: 1px solid var(--line); border-radius: 6px; background: none; cursor: pointer; flex: 0 0 auto; }

.st-variants { display: grid; grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); gap: .5rem; }
.st-variant { cursor: pointer; border: 1px solid var(--line); border-radius: var(--radius); padding: .4rem; background: var(--bg); text-align: left; font: inherit; color: inherit; transition: border-color .15s ease; }
.st-variant:hover { border-color: color-mix(in srgb, var(--accent) 60%, var(--line)); }
.st-variant[aria-pressed="true"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.st-variant__name { font-size: .72rem; margin-top: .35rem; color: var(--text); font-weight: 600; }
.st-variant__blurb { font-size: .63rem; color: var(--muted); line-height: 1.35; }

/* A miniature. Spacing shrinks with the type so it reads as a small version of
   the page rather than a squashed one. */
.mini {
  --pad: .3rem; --gap: .28rem; --radius: 5px;
  /* Tall enough for two turns AND the composer. At 64px the composer fell off
     the bottom, so half the composer variants previewed as an empty box. */
  position: relative; height: 100px; overflow: hidden; border-radius: 5px;
  background: var(--bg); padding: .32rem; font-size: 8.5px; line-height: 1.35; pointer-events: none;
}
.mini .bgfx { position: absolute; z-index: 0; }
.mini > *:not(.bgfx) { position: relative; z-index: 1; }
.mini .av { width: 14px; height: 14px; font-size: 6px; }
.mini .av.-a-dot { width: 5px; height: 5px; margin-top: .2rem; }
.mini .msg { margin-bottom: .25rem; gap: .25rem; }
.mini .msg__body { max-width: 88%; }
.mini .msg__role { font-size: 6px; margin-bottom: .1rem; }
.mini .msg__text { font-size: 8px; }
.mini .msg__text.-b-terminal { font-size: 8px; }
.mini .btn { font-size: 7px; padding: .18rem .34rem; border-radius: calc(var(--radius) * .8); }
.mini .cmp { padding: .14rem; }
.mini .cmp__fake { font-size: 7px; padding: .14rem .24rem; }
.mini .icon-btn { width: 11px; height: 11px; font-size: 6px; }
.mini .hd { padding: .25rem .3rem; margin: 0; }
.mini .hd__name { font-size: 8.5px; }
.mini .hd__tag { font-size: 6px; }
.mini .hd__actions .btn { font-size: 5px; }

.st-preview { position: sticky; top: 1rem; border: 1px solid var(--line); border-radius: calc(var(--radius) + 6px); overflow: hidden; }
.st-preview__bar { display: flex; align-items: center; gap: .5rem; padding: .5rem .8rem; border-bottom: 1px solid var(--line); font-size: .74rem; color: var(--muted); background: var(--surface); }
.st-preview__bar .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--line); }
.st-tabs { display: flex; gap: .3rem; margin-left: auto; }
.st-stage { position: relative; height: min(74vh, 760px); overflow: auto; padding: 1rem; }
.st-actions { display: flex; gap: .5rem; align-items: center; position: sticky; bottom: 0; padding: .8rem 0; background: linear-gradient(to top, var(--bg) 72%, transparent); }
.saved { font-size: .78rem; color: #35d07f; }
.st-lock { max-width: 420px; margin: 12vh auto; }
