/* ai.css - the Khora AI page.

   This screen is the assistant, not the exhibition: the backdrop mark is pulled
   right back so it does not compete with the conversation. */
:root { --mark: .05; }

/*
   Loaded only by p06-ai.html, on top of base.css and skin-glass.css. It is kept
   out of those two because this is a different kind of screen - a full-height
   app shell rather than a page of cards - and mixing it in would put every other
   page at risk for no gain. It still consumes the same tokens, so it looks like
   the same site.

   Layout: sidebar + main on a wide screen; on a phone the sidebar becomes a
   drawer, because at 390px a 240px sidebar would leave 150px for the
   conversation. */

/* Scoped by id, not class, and it has to stay that way: a turn's class list is
   "turn ai", so a bare `.ai` rule also lands on every answer. That is not
   hypothetical - it is what `height: 100dvh` here used to do, stretching every
   reply to the full height of the window and leaving a screenful of empty glass
   between two questions. */
#ai {
  position: relative;
  z-index: 1;
  display: flex;
  height: 100%;
  height: 100dvh;
  overflow: hidden;
}

/* ---------------------------------------------------------------- sidebar */

.ai-side {
  flex: none;
  width: 248px;
  display: flex;
  flex-direction: column;
  border-right: 1px solid var(--line);
  background: var(--bar-bg);
  backdrop-filter: blur(20px) saturate(1.4);
  -webkit-backdrop-filter: blur(20px) saturate(1.4);
  padding: 12px 10px calc(12px + env(safe-area-inset-bottom));
  transition: width .28s var(--ease), transform .28s var(--ease);
}

.ai-side-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 4px 6px 12px;
}
.ai-brand {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
}
.ai-brand img { height: 22px; width: auto; flex: none; }
.ai-brand span {
  font-family: var(--font-display);
  font-size: 14px;
  letter-spacing: .04em;
  white-space: nowrap;
}

.ai-iconbtn {
  flex: none;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 9px;
  background: none;
  color: var(--fg-2);
  cursor: pointer;
  transition: background .2s var(--ease), color .2s var(--ease);
}
.ai-iconbtn:hover { background: var(--surface-hi); color: var(--fg-0); }
.ai-iconbtn svg { width: 17px; height: 17px; }

.ai-new {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 10px 11px;
  margin-bottom: 10px;
  border-radius: 11px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--fg-0);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  transition: background .2s var(--ease), border-color .2s var(--ease);
}
.ai-new:hover { background: var(--surface-hi); border-color: var(--line-hi); }
.ai-new svg { width: 15px; height: 15px; flex: none; }

.ai-nav { display: grid; gap: 1px; }

.ai-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 11px;
  border-radius: 9px;
  color: var(--fg-1);
  font-size: 13px;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border: 0;
  background: none;
  font-family: inherit;
  width: 100%;
  text-align: left;
  transition: background .18s var(--ease), color .18s var(--ease);
}
.ai-item:hover { background: var(--surface-hi); color: var(--fg-0); }
.ai-item.on { background: var(--surface-hi); color: var(--fg-0); }
.ai-item svg { width: 15px; height: 15px; flex: none; opacity: .8; }
.ai-item .ai-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent); flex: none;
}

.ai-group { margin-top: 14px; }
.ai-group-h {
  margin: 0 0 4px;
  padding: 0 11px;
  font-size: 10px;
  letter-spacing: .16em;
  color: var(--fg-3);
}

/* the chat list scrolls; everything above and below it stays put */
.ai-group.scroll { flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; }

.ai-user {
  flex: none;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  display: flex;
  align-items: center;
  gap: 9px;
  padding-left: 6px;
  padding-right: 6px;
}
.ai-avatar {
  width: 26px; height: 26px; flex: none;
  border-radius: 50%;
  background: linear-gradient(150deg, var(--accent), var(--accent-deep));
  color: #1a1410;
  display: grid; place-items: center;
  font-size: 11px; font-weight: 700;
}
/* Khora's own avatar. The visitor's keeps the disc and its initial - this one is
   the mark itself rather than a letter in a circle.

   It is the one place the mark is allowed below 40px: on this near-black ground
   the gold shape still reads at 20 (measured, not assumed), and the floor people
   quote is about it being comfortable rather than about it being recognisable at
   all. The disc version is what fails small - dark-on-gold loses contrast before
   the shape does - which is why there is no disc here. */
.ai-avatar.k { background: none; border-radius: 0; }
.ai-avatar.k::before {
  content: "";
  display: block;
  width: 100%;
  height: 100%;
  background: var(--accent);
  -webkit-mask: url(../assets/logo.svg) center / contain no-repeat;
  mask: url(../assets/logo.svg) center / contain no-repeat;
}

.ai-user-txt { min-width: 0; }
.ai-user-txt b { display: block; font-size: 11.5px; font-weight: 600; color: var(--fg-1); }
.ai-user-txt i { display: block; font-size: 10px; font-style: normal; color: var(--fg-3); }

/* ---------------------------------------------------------------- drawer (phone) */

.ai-backdrop {
  position: absolute;
  inset: 0;
  z-index: 3;
  background: rgba(0, 0, 0, .55);
  opacity: 0;
  pointer-events: none;
  transition: opacity .28s var(--ease);
}

/* Collapsed rail, wide screens only. On a phone the same button closes the
   drawer, which is why the rule is scoped here. */
@media (min-width: 720px) {
  .ai.rail .ai-side { width: 64px; padding-left: 9px; padding-right: 9px; }

  /* The brand goes entirely, mark and word: at 64px the wordmark would run out
     over the conversation. */
  .ai.rail .lbl,
  .ai.rail .ai-brand,
  .ai.rail .ai-group,
  .ai.rail .ai-user-txt { display: none; }

  .ai.rail .ai-side-top { justify-content: center; padding-left: 0; padding-right: 0; }

  /* The button that collapsed the rail is also the way out of it. Hiding it -
     which is what this rule used to do - left no way back. The icon flips so it
     points the way it will move the panel. */
  .ai.rail .ai-iconbtn svg { transform: rotate(180deg); }

  .ai.rail .ai-new,
  .ai.rail .ai-item { justify-content: center; padding-left: 0; padding-right: 0; }
}

@media (max-width: 719px) {
  .ai-side {
    position: absolute;
    z-index: 4;
    top: 0;
    bottom: 0;
    left: 0;
    transform: translateX(-100%);
    border-right-color: transparent;
    box-shadow: none;
  }
  .ai.open .ai-side {
    transform: none;
    border-right-color: var(--line);
    box-shadow: 0 0 60px rgba(0, 0, 0, .6);
  }
  .ai.open .ai-backdrop { opacity: 1; pointer-events: auto; }
}

/* ---------------------------------------------------------------- main column */

.ai-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.ai-bar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  padding-top: calc(10px + env(safe-area-inset-top));
  border-bottom: 1px solid var(--line);
}
.ai-bar h1 {
  margin: 0;
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: .03em;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
@media (min-width: 720px) { .ai-bar .ai-menu { display: none; } }

.ai-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 18px 16px 8px;
}

/* ---------------------------------------------------------------- empty state */

.ai-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100%;
  text-align: center;
  gap: 22px;
}
.ai-hero.gone { display: none; }
.ai-hero .ai-mark { height: 52px; width: auto; opacity: .9; }
.ai-hero h2 {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(30px, 9vw, 46px);
  font-weight: 600;
  letter-spacing: .04em;
  line-height: 1.05;
}
.ai-hero p {
  margin: -12px 0 0;
  max-width: 30em;
  font-size: 12.5px;
  line-height: 1.75;
  color: var(--fg-2);
}

/* ---------------------------------------------------------------- thread */

.ai-thread { display: grid; gap: 18px; max-width: 760px; margin: 0 auto; }
.ai-thread:empty { display: none; }

.turn { display: flex; gap: 11px; scroll-margin-top: 12px; }
.turn .ai-avatar { width: 24px; height: 24px; font-size: 10px; margin-top: 2px; }
/* a little wider than the lettered disc, so the mark has room to be itself */
.turn .ai-avatar.k { width: 28px; height: 25px; margin-top: 3px; }

.bub {
  min-width: 0;
  font-size: 13.5px;
  line-height: 1.75;
  color: var(--fg-0);
}
/* what the visitor typed: right-aligned, in a glass bubble */
.turn.me { flex-direction: row-reverse; }
.turn.me .bub {
  background: var(--glass-surface), rgba(34, 32, 30, .5);
  border: 1px solid var(--card-line);
  border-radius: 18px 18px 4px 18px;
  padding: 9px 13px;
  max-width: 78%;
}
.turn.ai .bub { padding-top: 2px; }
.turn.ai .bub p { margin: 0 0 9px; }
.turn.ai .bub p:last-child { margin-bottom: 0; }
.turn.ai .bub ul { margin: 0 0 9px; padding-left: 18px; }
.turn.ai .bub li { margin-bottom: 3px; }
.turn.ai .bub strong { color: var(--accent); font-weight: 600; }
.turn.ai .bub code {
  font-family: var(--font-mono);
  font-size: 12px;
  background: var(--surface-hi);
  padding: 1px 5px;
  border-radius: 5px;
}

/* an answer still arriving */
.dots { display: inline-flex; gap: 4px; padding: 6px 0; }
.dots i {
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--fg-3);
  animation: aiblink 1.1s infinite ease-in-out;
}
.dots i:nth-child(2) { animation-delay: .16s; }
.dots i:nth-child(3) { animation-delay: .32s; }
@keyframes aiblink { 0%, 80%, 100% { opacity: .25 } 40% { opacity: 1 } }

/* ---------------------------------------------------------------- composer */

.ai-composer { flex: none; padding: 10px 16px calc(14px + env(safe-area-inset-bottom)); }

.ai-box {
  max-width: 760px;
  margin: 0 auto;
  border-radius: 22px;
  border: 1px solid var(--card-line);
  background: var(--glass-surface), var(--card-bg);
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat)) brightness(var(--glass-bright));
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat)) brightness(var(--glass-bright));
  box-shadow: var(--card-shadow);
  padding: 10px 10px 8px;
}

.ai-box textarea {
  display: block;
  width: 100%;
  border: 0;
  background: none;
  color: var(--fg-0);
  font: inherit;
  font-size: 13.5px;
  line-height: 1.6;
  resize: none;
  outline: none;
  max-height: 140px;
  padding: 4px 6px;
}
.ai-box textarea::placeholder { color: var(--fg-3); }

.ai-box-foot {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-top: 6px;
}
.ai-box-foot .grow { flex: 1; }

.ai-mode {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 9px;
  border-radius: 999px;
  border: 1px solid var(--line);
  color: var(--fg-2);
  font-size: 10.5px;
  letter-spacing: .06em;
  cursor: pointer;
  background: none;
  font-family: inherit;
}
.ai-mode:hover { border-color: var(--line-hi); color: var(--fg-1); }

.ai-send {
  width: 30px; height: 30px;
  flex: none;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 0;
  background: var(--accent);
  color: #1a1410;
  cursor: pointer;
  transition: opacity .2s var(--ease), transform .2s var(--ease);
}
.ai-send:disabled { opacity: .35; cursor: default; }
.ai-send:not(:disabled):hover { transform: scale(1.06); }
.ai-send svg { width: 15px; height: 15px; }
/* ★Needed, and not obvious: `display` set by a class beats the browser's
   `[hidden] { display: none }`, so setting the property alone leaves the button
   on screen. The send and stop buttons swap places, and without this rule both
   of them showed at once - measured on a real run. */
.ai-send[hidden] { display: none; }

/* Stop. Takes the send button's place while the chain is running. Deliberately
   not the accent: sending is the accent action, stopping is the way out of one. */
.ai-stop {
  width: 30px; height: 30px;
  flex: none;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid var(--line-hi);
  background: none;
  color: var(--fg-1);
  cursor: pointer;
  transition: background .2s var(--ease), border-color .2s var(--ease),
              color .2s var(--ease);
}
.ai-stop:hover { background: var(--surface-hi); border-color: #e2705f; color: #e2705f; }
.ai-stop svg { width: 13px; height: 13px; }
.ai-stop[hidden] { display: none; }

.ai-below {
  max-width: 760px;
  margin: 7px auto 0;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 10.5px;
  color: var(--fg-3);
}
.ai-below .grow { flex: 1; }

/* ---------------------------------------------------------------- suggestion chips */

.ai-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  justify-content: center;
  max-width: 620px;
}
.ai-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 13px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--fg-1);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
  transition: background .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease);
}
.ai-chip:hover { background: var(--surface-hi); border-color: var(--line-hi); color: var(--fg-0); }
.ai-chip svg { width: 14px; height: 14px; opacity: .75; }

/* ---------------------------------------------------------------- inspiration */

/* A second screen inside the same shell rather than a page of its own: the
   sidebar and the top bar are unchanged, so switching between the conversation
   and the briefs does not reload anything. */
.ai-insp { display: none; }

.ai.insp .ai-insp { display: block; }
.ai.insp .ai-hero,
.ai.insp .ai-thread,
.ai.insp .ai-composer { display: none; }

/* ---- Khora Advantage：六张作品集跨页 ----
   和 Inspiration 一样是"同一个壳里的第二屏"：侧栏与顶栏不动，切换不重新加载。 */
.ai-adv { display: none; }

.ai.adv .ai-adv { display: block; }
.ai.adv .ai-hero,
.ai.adv .ai-thread,
.ai.adv .ai-composer { display: none; }

.adv-head { max-width: 1180px; margin: 0 auto 18px; }
.adv-head h2 {
  margin: 0 0 5px;
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 600;
  letter-spacing: .03em;
}
.adv-head p {
  margin: 0 0 8px;
  font-size: 12px;
  line-height: 1.7;
  color: var(--fg-2);
  max-width: 52em;
}
.adv-head em { font-style: normal; color: var(--accent); }

.adv-pages {
  display: flex;
  flex-direction: column;
  gap: 18px;
  max-width: 1180px;
  margin: 0 auto;
}
.adv-page { margin: 0; }
.adv-page img {
  display: block;
  width: 100%;
  height: auto;
  background: #000;
  /* 圆角**只在图片里做**（make_advantage.py 的 round_outer + _round_corners）——
     那里削圆同时盖掉了 PDF 阅读器给纸张渲染的圆角白缺口。
     这里再加一道 border-radius 会形成第二条弧（CSS 裁在 30px、图里削在 26px），
     看起来就是双重圆角。所以 CSS 这层不再裁、也不描边。 */
}

/* ---- 未登录时 hero 里的那一条 ----
   助手不登录就不答，所以必须在**打字之前**告诉他；角落那个账号入口太容易被走过。 */
.ai-gate {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin: 14px 0 0;
  padding: 10px 14px;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--fg-2);
  background: var(--surface-hi);
  border: 1px solid var(--accent-dim, var(--card-line));
  border-radius: var(--r);
  max-width: 620px;
}
.ai-gate[hidden] { display: none; }
.ai-gate-btn {
  padding: 6px 14px;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: #1a1207;
  background: var(--accent);
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  flex: none;
}
.ai-gate-btn:hover { background: #eab04a; }

.insp-head { max-width: 1000px; margin: 0 auto 16px; }
.insp-head h2 {
  margin: 0 0 5px;
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 600;
  letter-spacing: .03em;
}
.insp-head p {
  margin: 0;
  font-size: 12px;
  line-height: 1.7;
  color: var(--fg-2);
  max-width: 44em;
}

.insp-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 12px;
  max-width: 1000px;
  margin: 0 auto;
}

.insp-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 15px 12px;
  border-radius: var(--radius);
  border: 1px solid var(--card-line);
  background: var(--card-bg);
  box-shadow: var(--card-shadow);
  color: var(--fg-0);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: transform .24s var(--ease), border-color .24s var(--ease), box-shadow .24s var(--ease);
}
.insp-card:hover {
  transform: translateY(-2px);
  border-color: var(--card-line-c);
  box-shadow: var(--card-shadow-c);
}
.insp-card h3 {
  margin: 0;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .02em;
}
.insp-card p {
  margin: 0;
  font-size: 12px;
  line-height: 1.65;
  color: var(--fg-2);
  /* the briefs run long; four lines is enough to know whether you want it */
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.insp-meta {
  margin-top: auto;
  padding-top: 8px;
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 10px;
  letter-spacing: .12em;
  color: var(--fg-3);
}
.insp-meta .n { color: var(--accent); }

/* Phones. The count is set by **orientation**, because a phone is two very
   different shapes and one number does not suit both: upright there is room for
   three across, on its side five fit comfortably.

   Landscape needs a rule of its own rather than a wider version of the portrait
   one. A phone on its side is 780-930px wide, which is past the 720px line this
   stylesheet uses to mean "not a phone" - so it would otherwise pick up the
   desktop auto-fill rule. Height is what tells the two apart: a landscape phone
   is under 500px tall and a laptop is not, so tablets and desktops are left
   alone. */
@media (orientation: portrait) and (max-width: 719px) {
  .insp-grid { grid-template-columns: repeat(3, 1fr); gap: 8px; }
}
@media (orientation: landscape) and (max-height: 500px) {
  .insp-grid { grid-template-columns: repeat(5, 1fr); gap: 10px; }
  /* Five columns were right and almost entirely below the fold: a phone on its
     side has ~390px of height, and this pane's own introduction was taking most
     of it. The second paragraph is the one that goes - it says what the button
     at the foot of every replay says, and that button is on screen anyway. */
  .insp-head { margin-bottom: 10px; }
  .insp-head h2 { font-size: 20px; }
  .insp-head p { font-size: 11.5px; line-height: 1.5; }
  .insp-head p + p { display: none; }
}

/* ---------------------------------------------------------------- the account */

/* The bottom-left card. A button, not a div: it is the way in to the account. */
.ai-user {
  width: 100%;
  font: inherit;
  text-align: left;
  cursor: pointer;
  border-radius: 11px;
  border: 1px solid transparent;
  background: none;
  transition: background .2s var(--ease), border-color .2s var(--ease);
}
.ai-user:hover { background: var(--surface-hi); border-color: var(--line); }

/* ---------------------------------------------------------------- about

   A pane, not a page: the credits sit on the product rather than on the
   exhibition's front page. Nothing here is fetched and nothing here changes, so
   this is the one screen ai.js has nothing to paint. */
.ai-about { display: none; }
.ai.about .ai-about { display: block; }
.ai.about .ai-hero,
.ai.about .ai-thread,
.ai.about .ai-composer { display: none; }

.about-head { max-width: 1000px; margin: 0 auto 26px; }
.about-head h2 {
  margin: 0 0 5px;
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 600;
  letter-spacing: .03em;
}
.about-head p {
  margin: 0 0 8px;
  font-size: 12px;
  line-height: 1.7;
  color: var(--fg-2);
  max-width: 52em;
}
.about-head a { color: var(--accent); text-decoration: none; }
.about-head a:hover { text-decoration: underline; }

.about-block {
  max-width: 1000px;
  margin: 0 auto 22px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
}
.about-block h3 {
  margin: 0 0 7px;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--fg-3);
}
.about-block p {
  margin: 0;
  font-size: 12px;
  line-height: 1.7;
  color: var(--fg-2);
  max-width: 52em;
}
/* The line that says who made it, and the only line in the pane that is not
   grey. Declared after `.about-block p` and at the same weight, so it wins on
   order rather than on !important. */
.about-block p.about-by { margin: 0 0 10px; }
.about-by b { color: var(--fg-0); font-weight: 600; }

.about-list { margin: 0; padding: 0; list-style: none; }
.about-list li {
  position: relative;
  margin: 0 0 5px;
  padding-left: 15px;
  font-size: 12px;
  line-height: 1.7;
  color: var(--fg-2);
  max-width: 52em;
}
.about-list li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: .72em;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--accent);
  opacity: .8;
}

/* Name and address on one row. The name carries a fixed width so the addresses
   line up as a column underneath each other; on a narrow screen the row wraps
   and each pair stacks instead of the address being squeezed. */
.about-people { margin: 0; padding: 0; list-style: none; display: grid; gap: 3px; }
.about-people li {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 12px;
  font-size: 12px;
  line-height: 1.7;
}
.about-people b { color: var(--fg-0); font-weight: 600; min-width: 9.5em; }
.about-people a { color: var(--fg-2); text-decoration: none; }
.about-people a:hover { color: var(--accent); }

/* ---------------------------------------------------------------- my khora */

.ai-mine { display: none; }
.ai.mine .ai-mine { display: block; }
.ai.mine .ai-hero,
.ai.mine .ai-thread,
.ai.mine .ai-composer,
.ai.mine .ai-insp { display: none; }

.mine-head {
  display: flex;
  align-items: center;
  gap: 13px;
  max-width: 1000px;
  margin: 4px auto 18px;
}
.mine-avatar {
  width: 46px; height: 46px; flex: none;
  border-radius: 50%;
  display: grid; place-items: center;
  font-size: 17px; font-weight: 700;
  color: #1a1410;
  background: linear-gradient(150deg, var(--accent), var(--accent-deep));
}
.mine-id { min-width: 0; }
.mine-id h2 {
  margin: 0 0 4px;
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 600;
  letter-spacing: .02em;
}
.mine-id p { margin: 0; font-size: 12px; line-height: 1.6; color: var(--fg-2); }
.mine-id p b { color: var(--accent); font-weight: 600; }

/* the Closeness / Record switch */
.seg {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface);
  margin: 0 auto 8px;
}
.seg button {
  border: 0;
  border-radius: 999px;
  padding: 7px 16px;
  background: none;
  color: var(--fg-2);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
  transition: background .2s var(--ease), color .2s var(--ease);
}
.seg button.on { background: var(--surface-hi); color: var(--fg-0); }
.seg-note { margin: 0 auto 18px; font-size: 11.5px; color: var(--fg-3); }

.mine-pane { max-width: 1000px; margin: 0 auto; }
#mineSeg { display: flex; }
#segNote { display: block; }

/* ---------------------------------------------------------------- heat map */

/* 53 weeks across, whatever the width - the cells share what is left, which is
   how a contribution graph stays readable on a phone without scrolling the page. */
.heat {
  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(7, 1fr);
  grid-auto-columns: 1fr;
  gap: 3px;
  margin-bottom: 6px;
}
.heat i {
  display: block;
  aspect-ratio: 1;
  border-radius: 2.5px;
  background: var(--surface);
}
.heat i.l1 { background: color-mix(in srgb, var(--accent) 32%, var(--surface)); }
.heat i.l2 { background: color-mix(in srgb, var(--accent) 56%, var(--surface)); }
.heat i.l3 { background: color-mix(in srgb, var(--accent) 78%, var(--surface)); }
.heat i.l4 { background: var(--accent); }

.heat-months {
  display: flex;
  justify-content: space-between;
  font-size: 9.5px;
  letter-spacing: .1em;
  color: var(--fg-3);
  margin-bottom: 26px;
}

/* ---------------------------------------------------------------- self growth */

.grow-block {
  display: flex;
  align-items: center;
  gap: 22px;
  padding: 16px 18px;
  border-radius: var(--radius);
  border: 1px solid var(--card-line);
  background: var(--card-bg);
  box-shadow: var(--card-shadow);
}
.grow-text { flex: 1; min-width: 0; }
.grow-text h3 {
  margin: 0 0 7px;
  font-family: var(--font-display);
  font-size: 14.5px;
  font-weight: 600;
}
.grow-text p {
  margin: 0 0 13px;
  font-size: 12px;
  line-height: 1.7;
  color: var(--fg-2);
  max-width: 40em;
}
.grow-btn {
  padding: 9px 16px;
  border-radius: 999px;
  border: 1px solid var(--line-hi);
  background: var(--surface-hi);
  color: var(--fg-0);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}
.grow-btn.on { border-color: var(--accent); color: var(--accent); background: none; }

/* the dot orb lights up as the record fills, so it reads as a read-out rather
   than an ornament */
.orb {
  flex: none;
  width: 132px;
  height: 132px;
  display: grid;
  grid-template-columns: repeat(11, 1fr);
  grid-template-rows: repeat(11, 1fr);
  gap: 3px;
}
.orb i { border-radius: 50%; background: var(--track); transition: background .5s var(--ease); }
.orb i.on { background: var(--accent); }
.orb i.lit { background: var(--fg-0); }

@media (max-width: 719px) {
  .grow-block { flex-direction: column; align-items: flex-start; gap: 16px; }
  .orb { width: 108px; height: 108px; align-self: center; }
  .heat { gap: 2px; }
  .mine-head { gap: 11px; }
  .mine-avatar { width: 40px; height: 40px; font-size: 15px; }
}

/* ---------------------------------------------------------------- record */

.rec-h { margin: 4px 0 4px; font-family: var(--font-display); font-size: 14.5px; font-weight: 600; }
.rec-sub { margin: 0 0 12px; font-size: 11.5px; line-height: 1.7; color: var(--fg-2); }
.rec-sub b { color: var(--accent); font-weight: 600; }

.rec-chart { margin-bottom: 28px; }
.rec-chart svg { display: block; width: 100%; height: auto; overflow: visible; }
.rec-chart .axis { stroke: var(--line); stroke-width: 1; }
.rec-chart .line { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linejoin: round; }
.rec-chart .dot { fill: var(--accent); }
.rec-chart text { fill: var(--fg-3); font-size: 10px; font-family: var(--font-body); }

.rec-bars { display: grid; gap: 7px; }
.rec-row {
  display: grid;
  grid-template-columns: 66px 1fr 44px;
  align-items: center;
  gap: 10px;
  font-size: 11px;
  color: var(--fg-2);
}
.rec-row .bar { height: 9px; border-radius: 999px; background: var(--track); overflow: hidden; }
.rec-row .bar i { display: block; height: 100%; background: var(--accent); }
.rec-row .n { text-align: right; color: var(--fg-1); font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------- sign in */

.ai-auth {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  padding: 20px;
  background: rgba(4, 4, 6, .82);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.ai-auth[hidden] { display: none; }

.auth-card {
  width: 100%;
  max-width: 340px;
  padding: 24px 22px 20px;
  border-radius: var(--radius);
  border: 1px solid var(--card-line);
  background: var(--card-bg);
  box-shadow: var(--card-shadow-c);
  text-align: center;
}
.auth-mark { height: 34px; width: auto; opacity: .9; }
.auth-card h2 { margin: 12px 0 6px; font-family: var(--font-display); font-size: 19px; font-weight: 600; }
.auth-lede { margin: 0 0 18px; font-size: 11.5px; line-height: 1.7; color: var(--fg-2); }
.auth-label { display: block; text-align: left; font-size: 10px; letter-spacing: .16em; color: var(--fg-3); margin-bottom: 6px; }
.auth-input {
  width: 100%;
  padding: 11px 13px;
  border-radius: 11px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--fg-0);
  font: inherit;
  font-size: 14px;
  outline: none;
}
.auth-input:focus { border-color: var(--accent); }
.auth-go {
  width: 100%;
  margin-top: 12px;
  padding: 12px;
  border-radius: 11px;
  border: 0;
  background: var(--accent);
  color: #1a1410;
  font: inherit;
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
}
.auth-alt {
  width: 100%;
  margin-top: 9px;
  padding: 10px;
  border-radius: 11px;
  border: 1px solid var(--line);
  background: none;
  color: var(--fg-2);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}
.auth-alt:hover { color: var(--fg-0); border-color: var(--line-hi); }

/* ---------------------------------------------------------------- flip cards */

/* Front is the piece the brief produced, back is the brief. On a pointer device
   hovering turns it over; on a touch screen there is no hover, so the two faces
   simply stack instead - hiding the brief behind a hover would put it out of
   reach on the phone this exhibition is meant to be read on. */
.insp-card {
  position: relative;
  height: 258px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  perspective: 1100px;
  -webkit-tap-highlight-color: transparent;
}
.insp-flip {
  position: absolute;
  inset: 0;
  display: block;
  transform-style: preserve-3d;
  transition: transform .55s var(--ease);
}
.insp-face {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  border-radius: var(--radius);
  border: 1px solid var(--card-line);
  background: var(--card-bg);
  box-shadow: var(--card-shadow);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  overflow: hidden;
}

.insp-front { align-items: center; justify-content: center; padding: 12px 12px 32px; }
.insp-front img { max-width: 100%; max-height: 100%; object-fit: contain; }
.insp-name {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 7px 12px 9px;
  font-size: 11px;
  letter-spacing: .04em;
  color: var(--fg-2);
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.insp-back {
  transform: rotateY(180deg);
  padding: 14px 15px 12px;
  gap: 8px;
  text-align: left;
  border-color: var(--card-line-c);
}

@media (hover: hover) {
  .insp-card:hover .insp-flip,
  .insp-card:focus-visible .insp-flip { transform: rotateY(180deg); }
}

@media (hover: none) {
  .insp-card { height: auto; perspective: none; }
  .insp-flip { position: static; transform: none !important; }
  .insp-face { position: static; backface-visibility: visible; }
  .insp-back { transform: none; height: auto; margin-top: 10px; }
  /* relative, or the name - which is absolutely placed - anchors to the whole
     card and lands on top of the brief text below it */
  /* relative, or the name - see above - anchors to the whole card */
  .insp-front { position: relative; min-height: 150px; }
  /* half the width of a desktop card, so the back has to tighten up */
  .insp-back { padding: 11px 12px 10px; gap: 6px; }
  .insp-back h3 { font-size: 12.5px; }
  .insp-back p { font-size: 11px; line-height: 1.6; -webkit-line-clamp: 4; }
  .insp-meta { font-size: 9.5px; padding-top: 5px; }
}

/* ==========================================================================
   Khora Designer —— 「必经关卡」表单 / 规划书 / 生成进度
   与既有 .bub / .ai-box 同一套令牌（--card-line / --glass-surface / --accent）
   ========================================================================== */

/* ---- 问题表单卡片 ---- */
.kf { display: flex; flex-direction: column; gap: 14px; max-width: 620px; }
.kf-lead { margin: 0; font-size: 13.5px; line-height: 1.75; color: var(--fg-0); }
.kf-lead em { font-style: normal; opacity: .62; }
.kf-q { display: flex; flex-direction: column; gap: 7px; }
.kf-label {
  display: block;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--fg-0);
  font-weight: 600;
}
.kf-tag {
  font-style: normal; font-weight: 400; font-size: 11px;
  opacity: .5; margin-left: 5px;
}
.kf-why { font-size: 11.5px; line-height: 1.55; opacity: .55; margin: 0; }
.kf-input {
  width: 100%;
  box-sizing: border-box;
  resize: vertical;
  min-height: 40px;
  padding: 9px 12px;
  font: inherit;
  font-size: 13px;
  line-height: 1.5;
  color: var(--fg-0);
  background: var(--surface-hi);
  border: 1px solid var(--card-line);
  border-radius: 12px;
  outline: none;
  transition: border-color .2s var(--ease);
}
.kf-input:focus { border-color: var(--accent); }
.kf-opts { display: flex; flex-wrap: wrap; gap: 7px; }
.kf-opt {
  padding: 7px 13px;
  font: inherit;
  font-size: 12.5px;
  color: var(--fg-0);
  background: var(--surface-hi);
  border: 1px solid var(--card-line);
  border-radius: 999px;
  cursor: pointer;
  transition: border-color .18s var(--ease), background .18s var(--ease), color .18s var(--ease);
}
.kf-opt:hover { border-color: var(--accent); }
.kf-opt.on {
  border-color: var(--accent);
  color: #1a1410;
  background: var(--accent);
  font-weight: 600;
}
.kf-foot {
  display: flex; align-items: center; gap: 10px;
  padding-top: 3px; flex-wrap: wrap;
}
.kf-submit {
  padding: 9px 20px;
  font: inherit; font-size: 13px; font-weight: 600;
  color: #1a1410;
  background: var(--accent);
  border: 0; border-radius: 999px;
  cursor: pointer;
  transition: transform .18s var(--ease), opacity .18s var(--ease);
}
.kf-submit:not(:disabled):hover { transform: scale(1.03); }
.kf-submit:disabled { opacity: .4; cursor: default; }
.kf-skip {
  padding: 9px 15px;
  font: inherit; font-size: 12.5px;
  color: var(--fg-0); opacity: .72;
  background: transparent;
  border: 1px solid var(--card-line);
  border-radius: 999px;
  cursor: pointer;
}
.kf-skip:hover { opacity: 1; border-color: var(--accent); }
.kf-note { font-size: 11.5px; opacity: .5; margin-left: auto; }

/* 「这其实是设计需求」—— 判据漏网时的补救入口。
   不抢眼，但要在回答正下方，用户一脸问号时能一眼看到。 */
.kf-asks {
  margin-top: 10px;
  font-size: 11.5px;
  padding: 6px 12px;
  opacity: .6;
}
.kf-asks:not(:disabled):hover { opacity: 1; }

/* 登录失败的原因 —— 必须显示出来。以前只有一个静默的 localStorage 写入，
   现在要走网络，失败时不说原因就等于"点了没反应"。 */
.auth-err {
  margin: 9px 0 0;
  font-size: 12px;
  line-height: 1.55;
  color: #e08a7a;
}

/* ---- ★2026-09-29 点选式作答：5 选项 / Other / 长宽高 ----
   用户不再打字答题，所以这一组是整张表单的主要交互面。 */

.kf-group { display: flex; flex-direction: column; gap: 7px; }

/* 有序刻度：5 档连成一条谱，一眼看出"从左到右程度递增"。
   并列备选不加这个类 —— 它保持散开的胶囊按钮，那是对的，因为那 5 个之间没有顺序。 */
.kf-group.graded .kf-opts {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 0;
}
.kf-group.graded .kf-opt {
  border-radius: 0;
  margin-left: -1px;              /* 相邻边框叠成一条，读起来才是连续刻度 */
  padding: 9px 5px;
  font-size: 11.5px;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.kf-group.graded .kf-opt:first-child { border-radius: 10px 0 0 10px; margin-left: 0; }
.kf-group.graded .kf-opt:last-child { border-radius: 0 10px 10px 0; }
.kf-group.graded .kf-opt.on { position: relative; z-index: 1; }

/* Other：虚线边框，看得出是"出口"而不是第 6 个选项 */
.kf-otherbtn { border-style: dashed; opacity: .78; }
.kf-otherbtn:hover { opacity: 1; }
.kf-other-in {
  width: 100%;
  box-sizing: border-box;
  padding: 8px 12px;
  font: inherit;
  font-size: 12.5px;
  color: var(--fg-0);
  background: var(--surface-hi);
  border: 1px solid var(--accent);
  border-radius: 10px;
  outline: none;
}
.kf-multi { font-size: 11px; opacity: .5; margin: 0; }

/* 等待中的进度提示。文字会随等待时间改口（见 ai.js 的 WAIT_NOTES）——
   光转圈的话，访客分不清"模型慢"和"服务器死了"，而这个区别很要紧。 */
.kf-wait {
  margin: 8px 0 0;
  font-size: 12px;
  line-height: 1.6;
  opacity: .6;
  transition: opacity .3s var(--ease);
}

/* 生成完成后的结果卡 —— 与 Training 归档用的是同一套 .mcard / .mview，
   所以刚跑出来的设计和展陈里那些看起来是一件事。 */
.kp-result { margin-top: 12px; max-width: 620px; }
.kp-result .mcard { width: 100%; }

/* 3D 视图脚注里的「白色缺失层」开关 */
.mview-gap {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  opacity: .75;
  cursor: pointer;
  user-select: none;
}
.mview-gap input { accent-color: var(--accent); margin: 0; }

/* 尺寸题：三个数字框（全流程唯一保留"填"的题，因为它是硬约束） */
.kf-dims { display: flex; gap: 9px; flex-wrap: wrap; }
.kf-dim {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 11px;
  font-size: 12.5px;
  background: var(--surface-hi);
  border: 1px solid var(--card-line);
  border-radius: 12px;
  transition: border-color .18s var(--ease);
}
.kf-dim:focus-within { border-color: var(--accent); }
.kf-dim-n { opacity: .6; }
.kf-dim-in {
  width: 60px;
  padding: 0;
  font: inherit;
  font-size: 13px;
  color: var(--fg-0);
  background: transparent;
  border: 0;
  outline: none;
  text-align: right;
}
/* 数字框右侧那两个小箭头在深色玻璃上很难看，去掉 */
.kf-dim-in::-webkit-outer-spin-button,
.kf-dim-in::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.kf-dim-in { -moz-appearance: textfield; appearance: textfield; }
.kf-dim-u { opacity: .45; font-size: 11.5px; }

/* ---- 规划设计书卡片 ---- */
.kb { display: flex; flex-direction: column; gap: 11px; max-width: 620px; }
.kb-head { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
.kb-title { margin: 0; font-size: 15.5px; font-weight: 600; color: var(--accent); }
.kb-sub { font-size: 11.5px; opacity: .55; }
.kb-list { margin: 0; padding-left: 17px; font-size: 13px; line-height: 1.7; }
.kb-list li { margin-bottom: 5px; }
.kb-list b { color: var(--accent); font-weight: 600; }
.kb-narr {
  border: 1px solid var(--card-line);
  border-radius: 12px;
  background: var(--surface-hi);
  padding: 0;
  overflow: hidden;
}
.kb-narr summary {
  padding: 9px 13px;
  font-size: 12.5px;
  cursor: pointer;
  list-style: none;
  opacity: .82;
}
.kb-narr summary::-webkit-details-marker { display: none; }
.kb-narr summary::before { content: "▸ "; opacity: .6; }
.kb-narr[open] summary::before { content: "▾ "; }
.kb-narr p {
  margin: 0;
  padding: 0 13px 12px;
  font-size: 12.5px;
  line-height: 1.8;
  opacity: .86;
}
.kb-open { font-size: 12px; line-height: 1.6; opacity: .6; }
.kb-open ul { margin: 5px 0 0; padding-left: 17px; }
.kb-go {
  align-self: flex-start;
  padding: 10px 22px;
  font: inherit; font-size: 13px; font-weight: 600;
  color: #1a1410;
  background: var(--accent);
  border: 0; border-radius: 999px;
  cursor: pointer;
  transition: transform .18s var(--ease), opacity .18s var(--ease);
}
.kb-go:not(:disabled):hover { transform: scale(1.03); }
.kb-go:disabled { opacity: .4; cursor: default; }

/* ---- 生成进度卡片 ---- */
.kp { display: flex; flex-direction: column; gap: 10px; max-width: 560px; }
.kp-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.kp-title { font-size: 13px; font-weight: 600; }
.kp-pct { font-size: 12px; opacity: .6; font-variant-numeric: tabular-nums; }
.kp-bar {
  height: 3px; border-radius: 999px;
  background: var(--surface-hi);
  overflow: hidden;
}
.kp-bar i {
  display: block; height: 100%; width: 0;
  background: var(--accent);
  border-radius: 999px;
  transition: width .5s var(--ease);
}
.kp-steps {
  list-style: none; margin: 0; padding: 0;
  font-size: 12.5px; line-height: 1.7;
  max-height: 240px; overflow-y: auto;
}
.kp-steps li {
  display: flex; align-items: baseline; gap: 8px;
  opacity: .42;
  transition: opacity .3s var(--ease);
}
.kp-steps li.on { opacity: 1; }
.kp-steps li.now { opacity: 1; font-weight: 600; }
.kp-steps li.now::after {
  content: "";
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--accent);
  margin-left: 2px;
  animation: kp-pulse 1.1s ease-in-out infinite;
}
@keyframes kp-pulse { 0%,100% { opacity: .25 } 50% { opacity: 1 } }
.kp-steps .t { font-variant-numeric: tabular-nums; opacity: .5; flex: none; }
.kp-steps .d { opacity: .6; }
.kp-done { font-size: 12.5px; line-height: 1.6; }
.kp-done .err { color: #e2705f; }
.kp-link {
  align-self: flex-start;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 9px 18px;
  font-size: 13px; font-weight: 600;
  color: #1a1410;
  background: var(--accent);
  border-radius: 999px;
  text-decoration: none;
}
.kp-scores {
  display: flex; gap: 16px; flex-wrap: wrap;
  font-size: 12.5px; font-variant-numeric: tabular-nums;
}
.kp-scores span b { color: var(--accent); font-weight: 600; }

/* ---------------------------------------------------------------- a project */

.ai-proj { display: none; }
.ai.proj .ai-proj { display: block; }
.ai.proj .ai-hero,
.ai.proj .ai-thread,
.ai.proj .ai-insp,
.ai.proj .ai-mine { display: none; }

/* The composer does **not** stay. A folder is a place conversations are kept,
   not a place to type into, and a composer sitting there is bound to whichever
   conversation was last open - which is how a second chat in a folder ended up
   written inside the first one. Starting one is a button now, in the
   composer's own place. The footer hint row goes with it: "Select project"
   under a folder you have already selected reads as a contradiction. */
.ai.proj .ai-box,
.ai.proj .ai-below { display: none; }
.ai-pnew { display: none; }
.ai.proj .ai-pnew {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  width: 100%;
  max-width: 760px;
  margin: 0 auto;
  padding: 13px 16px;
  border-radius: 22px;
  border: 1px dashed var(--line-hi);
  background: none;
  color: var(--fg-1);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  transition: background .2s var(--ease), border-color .2s var(--ease),
              color .2s var(--ease);
}
.ai.proj .ai-pnew:hover {
  background: var(--surface-hi);
  border-color: var(--accent);
  color: var(--fg-0);
}
.ai-pnew svg { width: 15px; height: 15px; flex: none; }

.proj-head {
  display: flex;
  align-items: center;
  gap: 13px;
  max-width: 1000px;
  margin: 4px auto 18px;
}
/* A project's mark is drawn the way the picker drew it, so a project looks like
   the thing that was chosen rather than a plain square of its colour. */
.proj-mark {
  position: relative;
  flex: none;
  display: grid;
  place-items: center;
  color: #1a1410;
}
.proj-mark.is-folder { width: 72px; height: 56px; }
.proj-mark.is-folder > svg { width: 100%; height: 100%; display: block; }
/* 64% of the folder here, against the picker's 46%: this pair is two thirds the
   size, and the mark wants about 40px or it reads as dirt. That is the same
   floor the top bar's logo is pinned at. */
.proj-mark.is-folder .mark-logo.on-folder { width: 64%; }
/* the mark on its own, for a project that chose no folder */
.proj-mark.is-logo { width: 58px; height: 46px; }
.proj-id { min-width: 0; flex: 1; }
.proj-id h2 {
  margin: 0 0 4px;
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 600;
  letter-spacing: .02em;
  /* a name is typed by hand and can be long; without this its glyphs run out of
     their box and straight over the Edit button beside it */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.proj-id p { margin: 0; font-size: 12px; line-height: 1.6; color: var(--fg-2); }
.proj-id p b { color: var(--accent); font-weight: 600; }


.proj-list-h {
  margin: 0 0 2px;
  font-size: 10px;
  letter-spacing: .16em;
  color: var(--fg-3);
}


@media (max-width: 719px) {
  .proj-head { gap: 11px; }
  .proj-mark.is-folder { width: 62px; height: 48px; }
  .proj-mark.is-folder .mark-logo.on-folder { width: 72%; }
  .proj-mark.is-logo { width: 52px; height: 43px; }
}

/* ---------------------------------------------------------------- new project */

.ai-newp {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  padding: 20px;
  background: rgba(4, 4, 6, .82);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.ai-newp[hidden] { display: none; }

.newp-card {
  width: 100%;
  max-width: 400px;
  padding: 26px 24px 18px;
  border-radius: var(--radius);
  border: 1px solid var(--card-line);
  background: var(--card-bg);
  box-shadow: var(--card-shadow-c);
  text-align: center;
}
.newp-card h2 {
  margin: 0 0 5px;
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 600;
}
.newp-lede { margin: 0 0 6px; font-size: 12px; color: var(--fg-2); }

/* Three to a row so each mark has the room to be read. The mark is the constant
   and the colour is the choice, which is why selection is size and brightness
   rather than a tick - there is nothing to tick. */
.newp-folders {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  width: 100%;
  max-width: 330px;
  margin: 20px auto 18px;
}
.newp-folder {
  position: relative;
  width: 100%;
  aspect-ratio: 72 / 56;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  color: var(--fg-3);
  opacity: .5;
  transform: scale(.86);
  transition: transform .28s var(--ease), opacity .28s var(--ease),
              filter .28s var(--ease);
}
.newp-folder svg { width: 100%; height: 100%; display: block; }
.newp-folder .mark-logo.on-folder { width: 46%; }
.newp-folder.on {
  opacity: 1;
  transform: scale(1);
  filter: drop-shadow(0 6px 16px rgba(201, 160, 106, .3));
}
/* The mark on its own has no solid shape to carry a dim state: at half opacity a
   dot matrix on a near-black card is dirt, not a choice. It keeps more of its
   brightness and gives up size instead. */
.newp-folder.is-logo:not(.on) { opacity: .85; }
.newp-folder:hover { opacity: .85; }

/* ---------------------------------------------------------------- conversations */

/* A list of conversations can appear in two places - the sidebar's Chats and a
   project's own screen - so the row styling is shared and only the frame
   differs. */
.chat-empty {
  margin: 0;
  padding: 8px 11px;
  font-size: 11.5px;
  line-height: 1.65;
  color: var(--fg-3);
}

.proj-chats { margin-bottom: 22px; }
.proj-chats-list { display: grid; gap: 2px; }

/* On a project screen the rows sit in the wider column, not the sidebar, so they
   get the project's own spacing rather than the sidebar's tight padding. */
.proj-chats-list .ai-item {
  padding: 10px 12px;
  border: 1px solid transparent;
  font-size: 13px;
}
.proj-chats-list .ai-item:hover {
  border-color: var(--line);
  background: var(--surface-hi);
}

/* ---------------------------------------------------------------- editing

   Two things a visitor can now name: their own projects, and their own
   conversations. Both names live in this browser, and both are drawn from the
   same few pieces as the rest of the page. */

/* Khora's mark goes in through a mask rather than as an <img>, so it can take
   the project's colour instead of staying white. */
.mark-logo {
  display: block;
  width: 100%;
  height: 100%;
  background: currentColor;
  -webkit-mask: url(../assets/logo.svg) center / contain no-repeat;
  mask: url(../assets/logo.svg) center / contain no-repeat;
}

/* Stamped on a folder: dark against the colour, centred on the folder's body
   just below its tab. */
.mark-logo.on-folder {
  position: absolute;
  left: 50%;
  top: 55%;
  width: 46%;
  height: auto;
  aspect-ratio: 1136 / 943;
  transform: translate(-50%, -50%);
  background: #1a1410;
}
/* With no folder under it the mark keeps the base rule's currentColor, so it is
   the project's own colour rather than a dark shape on a dark card. */
.mark-logo.alone {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 100%;
  transform: translate(-50%, -50%);
}

/* In the sidebar there is no room for the mark to read, so a logo project shows
   as a plain chip of its colour - the same square, just smaller. */
.ai-mark-chip {
  width: 15px;
  height: 15px;
  flex: none;
  border-radius: 4.5px;
}

.proj-edit {
  margin-left: auto;
  flex: none;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: none;
  color: var(--fg-2);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
  transition: color .18s var(--ease), border-color .18s var(--ease);
}
.proj-edit:hover { color: var(--fg-0); border-color: var(--line-hi); }
.proj-edit svg { width: 13px; height: 13px; }
/* display:flex above would otherwise beat the default [hidden] rule */
.proj-edit[hidden] { display: none; }

.newp-sub { margin-top: 9px; }

/* Deleting is the one thing in this page that cannot be undone, so it does not
   look like the Cancel button that sits under it. */
.auth-alt.danger { color: #c98f7a; border-color: rgba(201, 143, 122, .3); }
.auth-alt.danger:hover { color: #e0a894; border-color: rgba(201, 143, 122, .55); }
.auth-alt.danger.armed {
  color: #1a1410;
  background: #c98f7a;
  border-color: #c98f7a;
}

/* --- a conversation row -----------------------------------------------------

   The row is the list item; opening and renaming are two buttons inside it, so a
   tap meant for one can never land on the other. On a touch screen there is no
   hover to reveal the pencil with, so it is simply there. */
.chat-row { padding: 0; gap: 0; }

.chat-row .chat-open {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 2px 8px 11px;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}
.chat-row .lbl {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chat-row .chat-edit {
  flex: none;
  width: 26px;
  height: 26px;
  margin-right: 5px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--fg-3);
  cursor: pointer;
  opacity: 0;
  transition: opacity .18s var(--ease), color .18s var(--ease),
              background .18s var(--ease);
}
.chat-row .chat-edit svg { width: 14px; height: 14px; }
.chat-row:hover .chat-edit { opacity: 1; }
.chat-row .chat-edit:hover { color: var(--fg-0); background: var(--surface-hi); }
@media (hover: none) { .chat-row .chat-edit { opacity: .5; } }

/* Same row, in the wider column: the project screen's own spacing. */
.proj-chats-list .chat-row { padding: 0; }
.proj-chats-list .chat-open { padding: 10px 2px 10px 12px; }

/* ---------------------------------------------------------------- the archive

   The Training project is the run's own screen, not a place to type. Each entry
   is a brief the chain was really given and what its own nodes wrote back about
   the design that came out. The steps replay that chain's order of work; they
   are a replay of something that already happened, and the reply says so. */

.chain { display: grid; gap: 11px; margin: 0 0 16px; }

.chain-step {
  display: grid;
  grid-template-columns: 14px 1fr;
  gap: 10px;
  opacity: 0;
  transform: translateY(5px);
  transition: opacity .38s var(--ease), transform .38s var(--ease);
}
.chain-step.in { opacity: 1; transform: none; }
.chain-step .tick {
  width: 13px; height: 13px;
  margin-top: 3px;
  border-radius: 50%;
  border: 1px solid var(--line-hi);
  transition: background .3s var(--ease), border-color .3s var(--ease);
}
.chain-step.in .tick { background: var(--accent); border-color: var(--accent); }
.chain-step .k {
  display: block;
  margin-bottom: 3px;
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--fg-3);
}
.chain-step .v { font-size: 12.5px; line-height: 1.68; color: var(--fg-2); }
.chain-step .v b { color: var(--accent); font-weight: 600; }

/* The interview, as it was actually conducted: the questions this run was asked
   and the answers it was given. Indented the way the other step bodies are, so
   it reads as part of the step rather than as a second column of chat. */
.qa-h {
  margin: 10px 0 5px;
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--fg-3);
}
.qa-h:first-child { margin-top: 0; }
.qa, .qa-plain {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 7px;
}
.qa li, .qa-plain li {
  padding-left: 11px;
  border-left: 2px solid var(--line);
}
.qa .q { display: block; color: var(--fg-2); }
.qa .a { display: block; color: var(--accent); }
.qa .a::before { content: "\2192\00a0"; opacity: .65; }
.qa-plain li { color: var(--fg-2); }

/* The foot of a replay, and the only thing there that leads anywhere: the
   design's own expanded brief goes into the message box, unsent. */
.chain-add {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 15px;
  padding: 11px 15px;
  border-radius: 13px;
  border: 1px solid var(--line-hi);
  background: none;
  color: var(--fg-1);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
  transition: background .2s var(--ease), border-color .2s var(--ease),
              color .2s var(--ease);
}
.chain-add:hover {
  background: var(--surface-hi);
  border-color: var(--accent);
  color: var(--fg-0);
}
.chain-add svg { width: 14px; height: 14px; flex: none; }
.chain-add i {
  font-style: normal;
  font-size: 10.5px;
  letter-spacing: .02em;
  color: var(--fg-3);
}
/* a card whose round kept no model file: nothing to open */
.mcard.nomodel { cursor: default; }
.mcard.nomodel .go { display: none; }

/* what the chain wrote about its own design, kept visually apart from the
   interface's own words so the two are never confused */
.done { margin: 0 0 13px; font-size: 13.5px; color: var(--fg-0); }

.note {
  margin: 0 0 4px;
  padding-left: 13px;
  border-left: 2px solid rgba(201, 160, 106, .38);
}
.note-h {
  margin: 0 0 6px;
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--fg-3);
}
.note p { margin: 0 0 8px; font-size: 12.5px; line-height: 1.72; color: var(--fg-2); }
.note p:last-child { margin-bottom: 0; }

/* the interface saying why an entry is thinner than its neighbours, as opposed to
   the chain's own words which get the coloured rule */
.norec { margin: 0 0 10px; font-size: 12.5px; line-height: 1.72; color: var(--fg-3); }

/* ---- the design a reply produced, and the model behind it */

.mcard {
  display: grid;
  grid-template-columns: 104px 1fr;
  gap: 14px;
  align-items: center;
  width: 100%;
  margin-top: 14px;
  padding: 12px;
  border-radius: 16px;
  border: 1px solid var(--card-line);
  background: var(--card-bg);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color .2s var(--ease), background .2s var(--ease);
}
.mcard:hover { border-color: var(--line-hi); background: var(--surface-hi); }
.mcard img {
  width: 104px; height: 124px;
  display: block;
  object-fit: contain;
  border-radius: 10px;
  background: rgba(0, 0, 0, .28);
}
/* the title only - a bare `.mcard b` would also catch the numbers in the line
   under it and stack them one per row */
.mcard .t {
  display: block;
  margin-bottom: 5px;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .02em;
}
.mcard .fig {
  font-size: 11.5px;
  line-height: 1.7;
  color: var(--fg-2);
  font-variant-numeric: tabular-nums;
}
.mcard .fig b { color: var(--accent); font-weight: 600; }
.mcard .fig i { font-style: normal; color: var(--fg-3); }
.mcard .go {
  display: block;
  margin-top: 7px;
  font-size: 11px;
  letter-spacing: .04em;
  color: var(--accent);
}

.mview { margin-top: 10px; }
.mview canvas {
  display: block;
  width: 100%;
  height: 330px;
  border-radius: 14px;
  background: rgba(0, 0, 0, .3);
}
.mview-foot {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 8px;
  font-size: 11px;
  color: var(--fg-3);
}
.mview-foot button {
  padding: 6px 12px;
  border-radius: 9px;
  border: 1px solid var(--line);
  background: none;
  color: var(--fg-2);
  font: inherit;
  font-size: 11.5px;
  cursor: pointer;
}
.mview-foot button:hover { color: var(--fg-0); border-color: var(--line-hi); }
.mview-foot .grow { flex: 1; }

@media (max-width: 719px) {
  .mcard { grid-template-columns: 78px 1fr; gap: 11px; padding: 10px; }
  .mcard img { width: 78px; height: 96px; }
  .mview canvas { height: 250px; }
}
