/* Sathi — chat client for a VRM agent instance. */

/* ----------------------------------------------------------------- *
 * Palette
 *
 * Two layers of colour, on purpose.
 *
 * The pack picks one brand colour, and it has to work in both themes: a hex
 * chosen to sit on white — `#0B1F8F`, say — is barely visible on a dark
 * ground. So `applyAccent` publishes two of them, `--accent-light` and
 * `--accent-dark`, and each theme block picks the one it needs.
 *
 * Underneath that sits a fixed pastel set the pack does not own. It paints
 * the ambient wash behind the product — the drifting aurora, the tints on
 * chips and tiles — and it stays the same dream whichever brand colour is
 * mounted in front of it. The accent still leads: it brands the mark, the
 * send button, the focus rings and every primary action. The pastels are the
 * room the brand is standing in.
 * ----------------------------------------------------------------- */
:root{
  /* The six. Fixed, brand-independent, always in this order around the wheel
     so anything that cycles them (chips, starters, tiles) reads as a set. */
  --p-lilac:#C9B9FF;
  --p-blush:#FFB3D9;
  --p-peach:#FFC5A3;
  --p-butter:#FFE7A0;
  --p-mint:#A6EBD2;
  --p-sky:#A5D8FF;
  --p-lav:#E7E0FF;

  --ground:#FBF9FF;
  --side:color-mix(in srgb,#FFFFFF 52%,transparent);
  --sunken:color-mix(in srgb,var(--p-lav) 46%,#FFFFFF);
  --raised:color-mix(in srgb,#FFFFFF 78%,transparent);
  /* Where a real, opaque surface is needed — anything drawn over a scrim, or
     a tile whose own blur would stack on the one underneath it. */
  --solid:#FFFFFF;
  --ink:#241B3D;
  --ink-2:#4B4269;
  --muted:#766D92;
  --faint:#9A91B5;
  --line:color-mix(in srgb,var(--p-lilac) 46%,transparent);
  --line-2:color-mix(in srgb,var(--p-lilac) 78%,transparent);
  --accent:var(--accent-light,#8B7BF7);
  --accent-ink:var(--accent-ink-light,#FFFFFF);
  --ok:#0FA083;
  --ok-soft:color-mix(in srgb,var(--p-mint) 40%,#FFFFFF);
  --warn:#C2760B;
  --warn-soft:color-mix(in srgb,var(--p-butter) 46%,#FFFFFF);
  --stop:#D6455C;
  --stop-soft:color-mix(in srgb,var(--p-blush) 34%,#FFFFFF);

  /* Shadows carry the accent's hue rather than grey. A neutral drop shadow
     under a pastel card is the one thing that makes it look like a screenshot
     of a different app pasted in. */
  --sh-1:0 1px 2px color-mix(in srgb,var(--accent) 12%,transparent);
  --sh-2:0 18px 40px -26px color-mix(in srgb,var(--accent) 55%,transparent);
  --sh-pop:0 28px 64px -22px color-mix(in srgb,var(--accent) 60%,transparent);
  --scrim:color-mix(in srgb,#2A1F4D 40%,transparent);
  --r:16px;
  --blur:saturate(170%) blur(20px);

  /* Derived from whichever accent the current theme chose. */
  --accent-soft:color-mix(in srgb,var(--accent) 12%,transparent);
  --accent-lift:color-mix(in srgb,var(--accent) 55%,#FFFFFF);
  --accent-pastel:color-mix(in srgb,var(--accent) 42%,var(--p-lilac));
  --shadow:var(--sh-1),var(--sh-2);
  --glow:0 10px 30px -12px color-mix(in srgb,var(--accent) 62%,transparent);

  /* The three gradients everything else is cut from. */
  --grad-brand:linear-gradient(135deg,var(--accent-lift),var(--accent) 58%,color-mix(in srgb,var(--accent) 55%,var(--p-blush)));
  --grad-cool:linear-gradient(120deg,var(--p-sky),var(--p-lilac) 55%,var(--p-blush));
  --grad-warm:linear-gradient(120deg,var(--p-blush),var(--p-peach) 52%,var(--p-butter));
}

/* One dark palette, written twice because it is applied from two places: the
   media query for "system", the attribute for an explicit choice. */
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --p-lilac:#A48BFF; --p-blush:#FF8FC6; --p-peach:#FFA97C;
    --p-butter:#FFD470; --p-mint:#6FE0BC; --p-sky:#78C4FF; --p-lav:#2A2350;
    --ground:#12101F;
    --side:color-mix(in srgb,#0D0B1A 58%,transparent);
    --sunken:#221C3E;
    --raised:color-mix(in srgb,#2A2350 74%,transparent);
    --solid:#251E47;
    /* One step brighter than a flat-ground palette would need. The wash behind
     these is not a constant any more, and the faintest tier is the first thing
     a moving gradient swallows. */
  --ink:#F1ECFF; --ink-2:#CFC7EA; --muted:#A69DC6; --faint:#867DA6;
    --line:color-mix(in srgb,var(--p-lilac) 20%,transparent);
    --line-2:color-mix(in srgb,var(--p-lilac) 34%,transparent);
    --accent:var(--accent-dark,#B9A8FF);
    --accent-ink:var(--accent-ink-dark,#15122A);
    --accent-soft:color-mix(in srgb,var(--accent) 20%,transparent);
    --accent-lift:color-mix(in srgb,var(--accent) 68%,#FFFFFF);
    --accent-pastel:color-mix(in srgb,var(--accent) 55%,var(--p-lilac));
    --ok:#4FE0BB; --ok-soft:color-mix(in srgb,var(--p-mint) 16%,#1A1636);
    --warn:#FFC24D; --warn-soft:color-mix(in srgb,var(--p-butter) 15%,#1F1834);
    --stop:#FF8095; --stop-soft:color-mix(in srgb,var(--p-blush) 16%,#211632);
    --sh-1:0 1px 2px rgba(0,0,0,.5);
    --sh-2:0 20px 44px -26px rgba(0,0,0,.9);
    --sh-pop:0 30px 70px -20px rgba(0,0,0,.9);
    --scrim:rgba(8,6,18,.62);
    --glow:0 12px 34px -12px color-mix(in srgb,var(--accent) 55%,transparent);
  }
}
:root[data-theme="dark"]{
  --p-lilac:#A48BFF; --p-blush:#FF8FC6; --p-peach:#FFA97C;
  --p-butter:#FFD470; --p-mint:#6FE0BC; --p-sky:#78C4FF; --p-lav:#2A2350;
  --ground:#12101F;
  --side:color-mix(in srgb,#0D0B1A 58%,transparent);
  --sunken:#221C3E;
  --raised:color-mix(in srgb,#2A2350 74%,transparent);
  --solid:#251E47;
  /* One step brighter than a flat-ground palette would need. The wash behind
     these is not a constant any more, and the faintest tier is the first thing
     a moving gradient swallows. */
  --ink:#F1ECFF; --ink-2:#CFC7EA; --muted:#A69DC6; --faint:#867DA6;
  --line:color-mix(in srgb,var(--p-lilac) 20%,transparent);
  --line-2:color-mix(in srgb,var(--p-lilac) 34%,transparent);
  --accent:var(--accent-dark,#B9A8FF);
  --accent-ink:var(--accent-ink-dark,#15122A);
  --accent-soft:color-mix(in srgb,var(--accent) 20%,transparent);
  --accent-lift:color-mix(in srgb,var(--accent) 68%,#FFFFFF);
  --accent-pastel:color-mix(in srgb,var(--accent) 55%,var(--p-lilac));
  --ok:#4FE0BB; --ok-soft:color-mix(in srgb,var(--p-mint) 16%,#1A1636);
  --warn:#FFC24D; --warn-soft:color-mix(in srgb,var(--p-butter) 15%,#1F1834);
  --stop:#FF8095; --stop-soft:color-mix(in srgb,var(--p-blush) 16%,#211632);
  --sh-1:0 1px 2px rgba(0,0,0,.5);
  --sh-2:0 20px 44px -26px rgba(0,0,0,.9);
  --sh-pop:0 30px 70px -20px rgba(0,0,0,.9);
  --scrim:rgba(8,6,18,.62);
  --glow:0 12px 34px -12px color-mix(in srgb,var(--accent) 55%,transparent);
}

*{box-sizing:border-box}
.sprite{position:absolute;width:0;height:0;overflow:hidden}
html,body{height:100%}
/* The ground goes on the root, not the body: the aurora sits at `z-index:-1`,
   and an element behind the body only shows through if the body itself has no
   background of its own to hide it with. */
html{background:var(--ground)}
body{overscroll-behavior-y:none}
body{
  margin:0; background:none; color:var(--ink);
  font-family:Figtree,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
  font-size:15px; line-height:1.6; -webkit-font-smoothing:antialiased;
}
/* A display face for the things that are a name rather than a sentence. */
.brand-name,.hero-name,.signin-title,.set-head h1,.fail-inner h1,.metric .mv,.b-hero .bh-v{
  font-family:"Space Grotesk",Figtree,ui-sans-serif,system-ui,sans-serif}
.mono,code{font-family:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,monospace}
button,textarea{font:inherit;color:inherit}
button{cursor:pointer;background:none;border:none}
::selection{background:color-mix(in srgb,var(--accent) 26%,transparent);color:var(--ink)}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:8px}
svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}

/* Scrollbars in the same palette as everything else. A default grey gutter
   down the side of a pastel column is the loudest thing on the screen. */
.scroll,.ins-body,.set-scroll,.sheet-b,.strip{scrollbar-width:thin;
  scrollbar-color:color-mix(in srgb,var(--accent) 34%,transparent) transparent}
.scroll::-webkit-scrollbar,.ins-body::-webkit-scrollbar,.set-scroll::-webkit-scrollbar,
.sheet-b::-webkit-scrollbar,.strip::-webkit-scrollbar{width:10px;height:8px}
.scroll::-webkit-scrollbar-thumb,.ins-body::-webkit-scrollbar-thumb,.set-scroll::-webkit-scrollbar-thumb,
.sheet-b::-webkit-scrollbar-thumb,.strip::-webkit-scrollbar-thumb{
  background:color-mix(in srgb,var(--accent) 30%,transparent);border-radius:999px;
  border:3px solid transparent;background-clip:content-box}
.scroll::-webkit-scrollbar-thumb:hover,.ins-body::-webkit-scrollbar-thumb:hover,
.set-scroll::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb,var(--accent) 52%,transparent);
  background-clip:content-box}

/* ---------- the ambient layer ----------
 *
 * Six blurred pastel fields behind the whole app, drifting on their own clock
 * and shifted by the pointer and the transcript's scroll at six different
 * depths — the parallax is what keeps it from reading as a static wallpaper.
 *
 * Two transform channels, deliberately: the keyframes animate `translate`,
 * `scale` and `rotate`, which are properties of their own, while `ambient.js`
 * writes `transform`. Neither overwrites the other, so the drift keeps running
 * underneath the parallax instead of fighting it for one declaration.
 * --------------------------------------- */
.aurora{position:fixed;inset:0;z-index:-1;overflow:hidden;pointer-events:none;contain:strict}
.blob{position:absolute;border-radius:50%;opacity:.6;
  filter:blur(72px) saturate(150%);
  will-change:transform,translate;
  transform:translate3d(var(--dx,0px),var(--dy,0px),0);
  animation:drift var(--dur,30s) var(--del,0s) ease-in-out infinite alternate}
@keyframes drift{
  from{translate:0 0;scale:1;rotate:0deg}
  to{translate:7% -9%;scale:1.22;rotate:16deg}
}
/* Placed for the layout rather than at random: one behind the sidebar, one
   over the composer, one high right where the inspector opens, and the
   accent-tinted pair near the middle where the conversation actually is. */
.b1{width:46vw;height:46vw;left:-12vw;top:-14vh;background:var(--p-lilac);--dur:34s}
.b2{width:38vw;height:38vw;right:-8vw;top:-6vh;background:var(--p-blush);--dur:29s;--del:-6s}
.b3{width:42vw;height:42vw;left:22vw;bottom:-22vh;background:var(--p-sky);--dur:38s;--del:-12s}
.b4{width:30vw;height:30vw;right:4vw;bottom:-14vh;background:var(--p-peach);--dur:26s;--del:-3s}
.b5{width:26vw;height:26vw;left:46vw;top:16vh;background:var(--accent-pastel);--dur:32s;--del:-16s;opacity:.42}
.b6{width:22vw;height:22vw;left:8vw;top:44vh;background:var(--p-mint);--dur:24s;--del:-9s;opacity:.34}

/* On a dark ground the same opacity reads as fog rather than light. */
:root[data-theme="dark"] .blob{opacity:.4}
:root[data-theme="dark"] .b5,:root[data-theme="dark"] .b6{opacity:.3}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]) .blob{opacity:.4}
  :root:not([data-theme="light"]) .b5,:root:not([data-theme="light"]) .b6{opacity:.3}
}

/* Grain. Half a percent of noise over a wash of flat gradients is the whole
   difference between "soft" and "washed out" — it gives the blur an edge to
   sit against without adding a single legible pixel. */
.grain{position:absolute;inset:0;opacity:.5;mix-blend-mode:soft-light;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.4'/%3E%3C/svg%3E");
  background-size:160px 160px}
:root[data-theme="dark"] .grain{opacity:.3;mix-blend-mode:overlay}

/* Motion is decoration, and the ambient layer is decoration on top of that.
   Someone who has asked for less of it gets a still gradient. */
@media (prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important}
  .blob{transform:none!important}
}

.app{display:grid;grid-template-columns:274px minmax(0,1fr);height:100dvh}
.app.ins{grid-template-columns:274px minmax(0,1fr) 380px}

/* ---------- sidebar ----------
 *
 * Three things, in the order they matter: the way to start again, the chat
 * that is open, and — kept quiet at the bottom — what is mounted behind it
 * and who it thinks you are. Glass rather than a panel, so the aurora keeps
 * moving underneath and the column reads as part of the same surface.
 * ------------------------------ */
.side{background:var(--side);border-right:1px solid var(--line);display:flex;flex-direction:column;min-height:0;
  backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur)}
.side-top{padding:16px 12px 8px}
.newchat{position:relative;overflow:hidden;display:flex;align-items:center;gap:9px;width:100%;height:44px;padding:0 14px;
  border:1px solid var(--line-2);border-radius:14px;background:var(--raised);color:var(--ink);
  font-size:14px;font-weight:600;letter-spacing:-.006em;
  box-shadow:var(--sh-1);
  transition:border-color .18s ease,color .18s ease,transform .18s cubic-bezier(.32,.72,0,1),box-shadow .18s ease}
/* The gradient is painted underneath and faded in. A background that swaps on
   hover snaps; an opacity that changes does not. */
.newchat::before{content:"";position:absolute;inset:0;background:var(--grad-cool);opacity:0;
  transition:opacity .22s ease}
.newchat>*{position:relative}
.newchat:hover{border-color:color-mix(in srgb,var(--accent) 50%,var(--line-2));color:var(--accent);
  transform:translateY(-1px);box-shadow:var(--sh-1),var(--glow)}
.newchat:hover::before{opacity:.24}
.newchat:active{transform:translateY(0) scale(.99)}
.newchat svg{width:16px;height:16px;stroke-width:2.3}
.side-label{padding:14px 16px 6px;margin:0;font-size:10.5px;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--faint)}
.threads{flex:none;padding:0 8px;display:flex;flex-direction:column;gap:3px}
.thread-item{position:relative;display:flex;flex-direction:column;gap:3px;padding:11px 13px 11px 17px;
  border-radius:14px;text-align:left;width:100%;transition:background .16s ease,transform .16s ease}
.thread-item .t{font-size:13.5px;font-weight:550;line-height:1.35;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.thread-item .s{font-size:11px;color:var(--faint)}
.thread-item:hover{background:color-mix(in srgb,var(--p-lilac) 16%,transparent);transform:translateX(2px)}
.thread-item.on{background:var(--raised);box-shadow:inset 0 0 0 1px var(--line),var(--sh-1)}
/* The marker is the brand gradient rather than a flat rule: it is the only
   thing in the column saying which chat is live, so it gets to be the bright
   thing in it. */
.thread-item.on::before{content:"";position:absolute;left:6px;top:11px;bottom:11px;width:3px;
  border-radius:2px;background:var(--grad-brand)}
.side-note{margin:0;padding:10px 16px 0;font-size:11px;line-height:1.5;color:var(--faint)}

.side-foot{margin-top:auto;padding:10px;border-top:1px solid var(--line);display:flex;flex-direction:column;gap:8px}
.packcard{background:var(--raised);border:1px solid var(--line);border-radius:14px;padding:11px 13px;font-size:12px;
  box-shadow:var(--sh-1)}
.pc-load{color:var(--muted)}
.pc-row{display:flex;align-items:center;gap:7px}
.pc-dot{width:7px;height:7px;border-radius:50%;background:var(--ok);flex:none;
  animation:pulse 2.8s ease-in-out infinite}
.pc-dot.down{background:var(--stop);animation:none;
  box-shadow:0 0 0 3px color-mix(in srgb,var(--stop) 20%,transparent)}
@keyframes pulse{
  0%,100%{box-shadow:0 0 0 3px color-mix(in srgb,var(--ok) 22%,transparent)}
  50%{box-shadow:0 0 0 7px color-mix(in srgb,var(--ok) 4%,transparent)}
}
.pc-name{font-weight:600;font-size:12.5px;letter-spacing:-.004em;min-width:0;overflow:hidden;text-overflow:ellipsis}
.pc-v{font-size:10.5px;color:var(--faint);margin-left:auto;flex:none}
.pc-meta{color:var(--muted);margin-top:4px;line-height:1.5;font-size:11.5px}
.pc-caps{display:flex;flex-wrap:wrap;gap:4px;margin-top:8px}
.cap{font-size:9.5px;letter-spacing:.03em;padding:3px 8px;border-radius:999px;background:var(--sunken);
  color:var(--ink-2);border:1px solid var(--line)}
/* The capabilities cycle the six so the row reads as a set rather than as one
   grey chip repeated eleven times. */
.pc-caps .cap:nth-child(6n+1){background:color-mix(in srgb,var(--p-lilac) 30%,transparent)}
.pc-caps .cap:nth-child(6n+2){background:color-mix(in srgb,var(--p-mint) 30%,transparent)}
.pc-caps .cap:nth-child(6n+3){background:color-mix(in srgb,var(--p-peach) 30%,transparent)}
.pc-caps .cap:nth-child(6n+4){background:color-mix(in srgb,var(--p-sky) 30%,transparent)}
.pc-caps .cap:nth-child(6n+5){background:color-mix(in srgb,var(--p-blush) 30%,transparent)}
.pc-caps .cap:nth-child(6n+6){background:color-mix(in srgb,var(--p-butter) 34%,transparent)}
.cap.off{color:var(--faint);border-style:dashed;background:transparent!important}

.account{display:flex;align-items:center;gap:9px;padding:8px 9px;border-radius:14px;cursor:pointer;
  border:1px solid transparent;transition:border-color .16s ease,background .16s ease}
.account[hidden]{display:none}
.account:hover{background:var(--raised);border-color:var(--line)}
.account.arming{background:var(--stop-soft);border-color:color-mix(in srgb,var(--stop) 30%,var(--line))}
.acc-av{width:30px;height:30px;border-radius:50%;flex:none;display:grid;place-items:center;
  background:var(--grad-cool);color:var(--ink-2);border:1px solid var(--line)}
.acc-av svg{width:15px;height:15px}
.account.arming .acc-av{background:var(--solid);color:var(--stop);border-color:transparent}
.acc-t{display:flex;flex-direction:column;min-width:0;line-height:1.3}
.acc-id{font-size:12.5px;font-weight:600;letter-spacing:-.004em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.acc-sub{font-size:9.5px;color:var(--faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.account.arming .acc-id{color:var(--stop)}
.acc-out{width:32px;height:32px;border-radius:11px;margin-left:auto;flex:none;display:grid;place-items:center;
  color:var(--faint);transition:background .14s ease,color .14s ease}
.acc-out:hover{background:var(--stop-soft);color:var(--stop)}
.acc-out svg{width:16px;height:16px}
.account.arming .acc-out{background:var(--stop);color:#FFFFFF}

/* ---------- main ---------- */
.main{display:flex;flex-direction:column;min-width:0;min-height:0}
.bar{height:62px;flex:none;display:flex;align-items:center;gap:11px;padding:0 18px;
  border-bottom:1px solid var(--line);position:sticky;top:0;z-index:5;
  background:color-mix(in srgb,var(--ground) 58%,transparent);
  backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur)}
.bar-title{display:flex;align-items:center;gap:10px;min-width:0}
.bar-mark{display:block;flex:none;line-height:0;border-radius:11px;
  box-shadow:0 4px 14px -4px color-mix(in srgb,var(--accent) 60%,transparent)}
.bar-mark svg,.brand-mark svg,.avatar svg,.hero-mark svg{fill:none;stroke:none;width:100%;height:100%}
.bar-mark svg{width:30px;height:30px}
.bar-title strong{font-size:16px;font-weight:600;letter-spacing:-.016em;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.skillpill{font-size:10.5px;color:var(--ink-2);background:color-mix(in srgb,var(--p-lilac) 24%,transparent);
  border:1px solid var(--line);padding:3px 9px;border-radius:999px;white-space:nowrap;flex:none}
.bar-right{margin-left:auto;display:flex;align-items:center;gap:8px}
.icon{width:36px;height:36px;border-radius:12px;display:grid;place-items:center;color:var(--muted);
  transition:background .16s ease,color .16s ease,transform .16s cubic-bezier(.32,.72,0,1)}
.icon:hover{background:color-mix(in srgb,var(--p-lilac) 24%,transparent);color:var(--ink);transform:translateY(-1px)}
.icon:active{transform:translateY(0) scale(.94)}
.icon[aria-pressed="true"]{background:var(--accent-soft);color:var(--accent)}

/* One control, three states: the icon is the label. */
.themebtn svg{display:none}
.themebtn[data-mode="light"] .i-light,
.themebtn[data-mode="dark"] .i-dark,
.themebtn[data-mode="system"] .i-system{display:block}
.signin-theme{position:absolute;top:18px;right:18px;z-index:2;color:var(--muted)}
.signin-theme:hover{background:color-mix(in srgb,#FFFFFF 44%,transparent);color:var(--ink)}

.scroll{flex:1;overflow-y:auto;scroll-behavior:smooth;overscroll-behavior:contain}
.thread{max-width:768px;min-height:100%;margin:0 auto;padding:34px 24px 48px;
  display:flex;flex-direction:column;gap:26px}

/* ---------- opening state ----------
 *
 * The greeting is the pack's chrome, not a turn: no message was sent, so
 * nothing was logged and no model ran. Given a whole screen it can say so by
 * being composed rather than pretending to be the first reply — and the moment
 * a real turn starts it steps back into the transcript as an ordinary message. */
/* `safe` again: on a short viewport — a phone with the keyboard up — a plain
   centre would push the mark off the top with no way to scroll back to it. */
.thread.opening{justify-content:safe center;padding-bottom:30px}
.hero{display:flex;flex-direction:column;align-items:center;text-align:center;gap:15px}
/* The mark breathes, and `ambient.js` gives it its own parallax depth. Same
   two-channel trick as the blobs: `translate` here, `transform` from script. */
.hero-mark{width:64px;height:64px;line-height:0;border-radius:19px;
  box-shadow:0 14px 34px -12px color-mix(in srgb,var(--accent) 70%,transparent);
  transform:translate3d(var(--dx,0px),var(--dy,0px),0);
  animation:float 6s ease-in-out infinite alternate}
@keyframes float{from{translate:0 -5px}to{translate:0 5px}}
/* Type set in the brand gradient. It is the agent's name — the one word on
   this screen allowed to be the loudest thing on it. */
.hero-name{margin:2px 0 0;font-size:27px;font-weight:700;letter-spacing:-.028em;line-height:1.15;
  background:var(--grad-brand);-webkit-background-clip:text;background-clip:text;color:transparent}
.hero-greet{margin:0;max-width:520px;font-size:15.5px;line-height:1.65;color:var(--muted)}
.starters{display:grid;grid-template-columns:1fr 1fr;gap:10px;width:100%;max-width:560px;margin-top:12px}
.starter{position:relative;overflow:hidden;display:flex;align-items:center;gap:11px;text-align:left;padding:14px 15px;
  border:1px solid var(--line-2);border-radius:18px;background:var(--raised);color:var(--ink);
  font-size:13.5px;font-weight:550;line-height:1.4;
  backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
  box-shadow:var(--sh-1);
  transition:border-color .2s ease,transform .2s cubic-bezier(.32,.72,0,1),box-shadow .2s ease}
/* Each ice breaker gets its own pastel, cycled in the fixed order. Four
   suggestions that are four different colours read as four choices; four in
   the same grey read as a list. */
.starter::before{content:"";position:absolute;inset:0;opacity:0;transition:opacity .22s ease;
  background:linear-gradient(120deg,var(--tint,var(--p-lilac)),transparent 78%)}
.starter>*{position:relative}
.starter:nth-child(6n+1){--tint:var(--p-lilac)}
.starter:nth-child(6n+2){--tint:var(--p-mint)}
.starter:nth-child(6n+3){--tint:var(--p-peach)}
.starter:nth-child(6n+4){--tint:var(--p-sky)}
.starter:nth-child(6n+5){--tint:var(--p-blush)}
.starter:nth-child(6n+6){--tint:var(--p-butter)}
.starter span{flex:1;min-width:0}
.starter svg{width:15px;height:15px;flex:none;color:var(--faint);transition:transform .2s ease,color .2s ease}
.starter:hover:not(:disabled){border-color:color-mix(in srgb,var(--accent) 50%,var(--line-2));
  transform:translateY(-3px);box-shadow:var(--sh-1),var(--sh-2)}
.starter:hover:not(:disabled)::before{opacity:.5}
.starter:hover:not(:disabled) svg{color:var(--accent);transform:translateX(3px)}
.starter:active:not(:disabled){transform:translateY(-1px) scale(.99)}
.starter:disabled{opacity:.45;cursor:default}

/* ---------- messages ---------- */
/* Each message arrives rather than appears. It is a chat: a line that pops in
   fully formed reads as a page reflow, and one that rises reads as a reply. */
.msg{display:flex;gap:12px;align-items:flex-start;animation:rise .45s cubic-bezier(.22,.8,.28,1) both}
@keyframes rise{from{opacity:0;transform:translateY(12px) scale(.985)}to{opacity:1;transform:none}}
.msg.user{justify-content:flex-end}
.avatar{width:30px;height:30px;border-radius:11px;flex:none;display:grid;place-items:center;line-height:0;
  font-size:12px;font-weight:700;background:var(--grad-brand);color:var(--accent-ink);margin-top:2px;
  box-shadow:0 4px 12px -4px color-mix(in srgb,var(--accent) 55%,transparent)}
.body{min-width:0;display:flex;flex-direction:column;gap:11px;flex:1}
.msg.user .body{flex:0 1 auto;align-items:flex-end;max-width:min(560px,84%)}
.prose{font-size:15.5px;line-height:1.72;color:var(--ink);white-space:pre-wrap;overflow-wrap:anywhere;
  letter-spacing:-.004em}
.prose strong{font-weight:650}
.prose code{background:color-mix(in srgb,var(--p-lilac) 26%,transparent);border-radius:6px;padding:1.5px 6px;font-size:13px}
.prose sup.src{font-family:"IBM Plex Mono",monospace;font-size:9.5px;color:var(--accent);
  background:var(--accent-soft);border-radius:5px;padding:1px 4px;margin:0 1px;vertical-align:super;line-height:1}
/* The customer's own words, in a gradient bubble with the tail on their side.
   The pack's accent leads it, so whose app this is stays legible. */
.msg.user .prose{
  background:linear-gradient(135deg,color-mix(in srgb,var(--accent) 16%,transparent),
    color-mix(in srgb,var(--p-blush) 26%,transparent));
  border:1px solid color-mix(in srgb,var(--accent) 20%,transparent);
  border-radius:22px 22px 8px 22px;padding:12px 16px;max-width:100%;font-size:15px;line-height:1.6;
  box-shadow:var(--sh-1)}
.typing{display:inline-flex;gap:5px;align-items:center;height:24px}
.typing i{width:7px;height:7px;border-radius:50%;background:var(--accent);opacity:.35;animation:bob 1.2s infinite}
.typing i:nth-child(2){animation-delay:.16s;background:var(--p-blush)}
.typing i:nth-child(3){animation-delay:.32s;background:var(--p-sky)}
@keyframes bob{0%,60%,100%{opacity:.32;transform:translateY(0) scale(.9)}30%{opacity:1;transform:translateY(-4px) scale(1)}}

/* tool + system lines */
.toolline{display:flex;align-items:center;gap:9px;font-size:12.5px;color:var(--muted);
  background:var(--sunken);border:1px solid var(--line);border-radius:999px;padding:7px 14px;
  width:fit-content;max-width:100%}
.toolline .mono{font-size:11.5px;color:var(--ink-2)}
.toolline .tick{font-size:11px;font-weight:700;color:var(--warn)}
.toolline.ok{background:var(--ok-soft);border-color:color-mix(in srgb,var(--ok) 30%,var(--line))}
.toolline.ok .tick{color:var(--ok)}
.toolline.denied{background:var(--stop-soft);border-color:color-mix(in srgb,var(--stop) 35%,var(--line));color:var(--stop)}
.spin{width:12px;height:12px;border-radius:50%;border:1.8px solid var(--line-2);border-top-color:var(--accent);
  animation:spin .7s linear infinite;flex:none}
@keyframes spin{to{transform:rotate(360deg)}}
.batch{font-size:12.5px;color:var(--muted);display:flex;align-items:center;gap:8px}

.cites{display:flex;flex-wrap:wrap;gap:6px}
.cite{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;padding:6px 12px;border-radius:999px;
  border:1px solid var(--line);background:var(--raised);color:var(--ink-2);text-decoration:none;
  transition:border-color .16s ease,color .16s ease,transform .16s ease}
.cite:hover{border-color:var(--accent);color:var(--accent);transform:translateY(-1px)}
.cite .n{font-family:"IBM Plex Mono",monospace;font-size:10px;color:var(--faint)}

.notice{font-size:12.5px;border-radius:14px;padding:11px 14px;border:1px solid;line-height:1.55;max-width:560px}
.notice.block{background:var(--stop-soft);border-color:color-mix(in srgb,var(--stop) 26%,var(--line));color:var(--ink-2)}
.notice.ground{background:var(--ok-soft);border-color:color-mix(in srgb,var(--ok) 26%,var(--line));color:var(--ink-2)}
.notice b{font-family:"IBM Plex Mono",monospace;font-size:9.5px;letter-spacing:.06em;text-transform:uppercase;
  display:block;margin-bottom:3px}
.notice.block b{color:var(--stop)} .notice.ground b{color:var(--ok)}

/* ---------- A2UI ----------
 *
 * The pack's own surfaces. Nothing here decides what is drawn — the catalog
 * does that, and the runtime sends the blocks — so these rules only have to
 * make whatever arrives look like it belongs to the same product as the
 * sentence above it.
 * --------------------------- */
.chips{display:flex;flex-wrap:wrap;gap:8px}
.chip{border:1px solid var(--line-2);background:var(--raised);border-radius:999px;padding:9px 16px;
  font-size:13.5px;font-weight:550;color:var(--ink);
  transition:border-color .16s ease,color .16s ease,background .16s ease,transform .16s cubic-bezier(.32,.72,0,1)}
.chip:nth-child(6n+1){--tint:var(--p-lilac)}
.chip:nth-child(6n+2){--tint:var(--p-mint)}
.chip:nth-child(6n+3){--tint:var(--p-peach)}
.chip:nth-child(6n+4){--tint:var(--p-sky)}
.chip:nth-child(6n+5){--tint:var(--p-blush)}
.chip:nth-child(6n+6){--tint:var(--p-butter)}
.chip:hover:not(:disabled){border-color:color-mix(in srgb,var(--accent) 55%,transparent);color:var(--ink);
  background:color-mix(in srgb,var(--tint,var(--p-lilac)) 40%,var(--solid));transform:translateY(-2px)}
.chip:active:not(:disabled){transform:translateY(0) scale(.97)}
.chip:disabled{opacity:.42;cursor:default}

.card{border:1px solid var(--line);border-radius:22px;background:var(--raised);
  backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
  box-shadow:var(--shadow);overflow:hidden;max-width:470px}
.card-h{display:flex;gap:12px;align-items:flex-start;padding:15px 17px;border-bottom:1px solid var(--line)}
/* The glyph tile is the pack's, and it sits two inches from the agent's mark:
   tinted rather than filled, so the identity out-ranks the decoration. */
.card-h .ic{width:34px;height:34px;border-radius:12px;background:var(--grad-cool);color:var(--ink);
  display:grid;place-items:center;font-size:15px;line-height:1;flex:none;font-weight:600}
.card-h h3{margin:0;font-size:14.5px;font-weight:650;line-height:1.35;letter-spacing:-.01em}
.card-h .sub{font-size:12px;color:var(--muted);margin-top:2px;line-height:1.4}
.card-h .wid{margin-left:auto;font-family:"IBM Plex Mono",ui-monospace,monospace;font-size:9px;color:var(--faint);
  flex:none;padding-top:4px;letter-spacing:-.01em}
.card-b{padding:16px 17px;display:flex;flex-direction:column;gap:13px}
.card-f{padding:13px 17px;border-top:1px solid var(--line);display:flex;gap:8px;flex-wrap:wrap;
  background:color-mix(in srgb,var(--p-lav) 30%,transparent)}

.btn{border:1px solid var(--line-2);background:var(--raised);border-radius:12px;padding:9px 15px;
  font-size:13px;font-weight:600;color:var(--ink);
  transition:border-color .16s ease,color .16s ease,transform .14s ease,box-shadow .16s ease,filter .16s ease}
.btn:hover:not(:disabled){border-color:var(--accent);color:var(--accent);transform:translateY(-1px)}
.btn.primary{background:var(--grad-brand);color:var(--accent-ink);border-color:transparent;
  box-shadow:var(--glow)}
.btn.primary:hover:not(:disabled){filter:brightness(1.06) saturate(1.08);color:var(--accent-ink);
  box-shadow:var(--glow),var(--sh-2)}
.btn:active:not(:disabled){transform:translateY(0) scale(.97)}
.btn:disabled{opacity:.42;cursor:default}
/* The pack asks for these two by name. `link` is the quiet disclosure that
   opens a sheet; `ghost` is the decline beside a primary — "Maybe later"
   should not carry the same weight as "Enable AutoPay". */
.btn.link{border-color:transparent;background:none;color:var(--accent);padding-left:0;padding-right:0;box-shadow:none}
.btn.link:hover:not(:disabled){text-decoration:underline;transform:none}
.btn.ghost{border-color:transparent;background:none;color:var(--muted);box-shadow:none}
.btn.ghost:hover:not(:disabled){color:var(--ink);border-color:var(--line-2)}

/* A surface is the card plus what the pack put around it. */
.surface{display:flex;flex-direction:column;gap:11px;max-width:470px}
.outer-actions{display:flex;gap:8px;flex-wrap:wrap}

/* ---- sheets (WIDGET-CONTRACT 5.11) ----
   Self-contained panels the pack already filled. They open over the
   conversation and close again without a round trip, which is why they are
   drawn here rather than sent as a message. */
.sheet-scrim{position:fixed;inset:0;z-index:40;background:var(--scrim);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  display:flex;align-items:flex-end;justify-content:center;padding:0;
  animation:sheet-in .2s ease-out}
/* Opaque, not glass: a sheet is the front-most thing on the screen, and a
   blurred conversation showing through it is where legibility goes. */
.sheet{background:var(--solid);color:var(--ink);width:min(520px,100%);max-height:88vh;
  border:1px solid var(--line);border-bottom:0;border-radius:26px 26px 0 0;
  box-shadow:0 -12px 60px rgba(40,25,80,.3);display:flex;flex-direction:column;overflow:hidden;
  animation:sheet-up .3s cubic-bezier(.32,.72,0,1)}
.sheet.full{max-height:96vh;height:96vh}
@media (min-width:700px){
  .sheet-scrim{align-items:center;padding:24px}
  .sheet{border-bottom:1px solid var(--line);border-radius:26px}
  .sheet.full{height:auto}
}
.sheet-h{display:flex;align-items:flex-start;gap:10px;padding:17px 19px;border-bottom:1px solid var(--line)}
.sheet-h h3{margin:0;font-size:15px;font-weight:650;letter-spacing:-.012em}
.sheet-h .sub{font-size:12px;color:var(--muted);margin-top:3px}
.sheet-x{margin-left:auto;flex:none;width:32px;height:32px;border-radius:11px;border:0;background:none;
  color:var(--muted);font-size:20px;line-height:1;cursor:pointer;transition:background .14s ease,color .14s ease}
.sheet-x:hover{background:var(--sunken);color:var(--ink)}
.sheet-b{padding:17px 19px;display:flex;flex-direction:column;gap:14px;overflow-y:auto;flex:1 1 auto}
.sheet-f{padding:13px 19px;border-top:1px solid var(--line);
  background:color-mix(in srgb,var(--p-lav) 34%,transparent);
  display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}
@keyframes sheet-in{from{opacity:0} to{opacity:1}}
@keyframes sheet-up{from{transform:translateY(18px) scale(.985)} to{transform:none}}
@media (prefers-reduced-motion:reduce){.sheet-scrim,.sheet{animation:none}}

.b-title{font-size:14.5px;font-weight:650;letter-spacing:-.01em;line-height:1.4;color:var(--ink)}
.b-text{font-size:13.5px;color:var(--ink-2);line-height:1.6}
.b-text.caption{font-size:12px;color:var(--muted)}
.b-hero{display:flex;flex-direction:column;gap:3px}
.b-hero .bh-t{font-size:11px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--muted)}
/* The one number the card exists for, in the brand gradient. */
.b-hero .bh-v{font-size:23px;font-weight:700;letter-spacing:-.026em;line-height:1.25;
  background:var(--grad-brand);-webkit-background-clip:text;background-clip:text;color:transparent}
.b-hero .bh-s{font-size:12.5px;color:var(--muted);line-height:1.5}

.kvs{display:flex;flex-direction:column}
.kv{display:flex;justify-content:space-between;gap:14px;font-size:13px;padding:8px 0;border-bottom:1px solid var(--line)}
.kv:first-child{padding-top:0} .kv:last-child{border-bottom:0;padding-bottom:0}
.kv .k{color:var(--muted)} .kv .v{font-weight:600;text-align:right;font-variant-numeric:tabular-nums}
.kv.strong{font-size:14px} .kv.strong .k{color:var(--ink-2)} .kv.strong .v{font-weight:700}
.kv .note{font-style:normal;color:var(--faint);font-size:11.5px;margin-left:5px}
.hr{height:1px;background:var(--line);margin:1px 0}

/* A titled group inside a contract — the sheets lean on these, and a run of
   rows with no heading over it is three tables pretending to be one. */
.group{display:flex;flex-direction:column;gap:9px}
.group-h{display:flex;align-items:center;justify-content:space-between;gap:10px}
.group-t{font-size:12px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--muted)}

.metric{display:flex;align-items:baseline;gap:9px}
.metric .mv{font-size:32px;font-weight:700;letter-spacing:-.034em;font-variant-numeric:tabular-nums;line-height:1.1;
  background:var(--grad-brand);-webkit-background-clip:text;background-clip:text;color:transparent}
.metric .mk{font-size:12px;color:var(--muted)}

.prog{display:flex;flex-direction:column;gap:7px}
.prog-h{display:flex;justify-content:space-between;gap:12px;font-size:12.5px}
.prog-h .pk{color:var(--muted)}
.prog-h .pv{font-weight:600;font-variant-numeric:tabular-nums}
.bar-w{height:9px;border-radius:999px;background:var(--sunken);overflow:hidden;
  box-shadow:inset 0 0 0 1px var(--line)}
.bar-w i{display:block;height:100%;border-radius:999px;transition:width .6s cubic-bezier(.32,.72,0,1);
  background:linear-gradient(90deg,var(--p-mint),var(--ok))}
.bar-w.warn i{background:linear-gradient(90deg,var(--p-butter),var(--warn))}

.pill{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:650;padding:4px 11px;
  border-radius:999px;border:1px solid var(--line);background:var(--sunken);color:var(--ink-2);width:fit-content}
.pill.ok{background:var(--ok-soft);color:var(--ok);border-color:color-mix(in srgb,var(--ok) 30%,var(--line))}
.pill.warn{background:var(--warn-soft);color:var(--warn);border-color:color-mix(in srgb,var(--warn) 30%,var(--line))}
/* A banner is an announcement about the whole card; a pill is a label on one
   thing in it. Same words, different weight, so they are drawn differently. */
.banner{display:flex;align-items:flex-start;gap:9px;font-size:12.5px;line-height:1.5;color:var(--ink-2);
  background:var(--sunken);border:1px solid var(--line);border-radius:14px;padding:11px 13px}
.banner i{width:7px;height:7px;border-radius:50%;background:var(--muted);flex:none;margin-top:5px}
.banner.ok{background:var(--ok-soft);border-color:color-mix(in srgb,var(--ok) 26%,var(--line))}
.banner.ok i{background:var(--ok)}
.banner.warn{background:var(--warn-soft);border-color:color-mix(in srgb,var(--warn) 26%,var(--line))}
.banner.warn i{background:var(--warn)}

.callout{border-left:3px solid transparent;border-image:var(--grad-brand) 1;
  background:linear-gradient(120deg,var(--accent-soft),color-mix(in srgb,var(--p-blush) 16%,transparent));
  border-radius:0 14px 14px 0;
  padding:11px 14px;font-size:12.5px;color:var(--ink-2);line-height:1.55}

.rows{display:flex;flex-direction:column;gap:8px}
.row{display:flex;align-items:center;gap:12px;padding:11px 13px;border:1px solid var(--line);
  border-radius:16px;background:var(--sunken);width:100%;text-align:left}
.row.tap{cursor:pointer;transition:border-color .16s ease,background .16s ease,transform .16s cubic-bezier(.32,.72,0,1),box-shadow .16s ease}
.row.tap:hover:not(:disabled){border-color:color-mix(in srgb,var(--accent) 50%,var(--line));background:var(--solid);
  transform:translateY(-2px);box-shadow:var(--sh-1),var(--sh-2)}
.row.tap:active:not(:disabled){transform:translateY(0) scale(.995)}
.row.tap:disabled{opacity:.5;cursor:default}
.row .lg{width:34px;height:34px;border-radius:12px;display:grid;place-items:center;flex:none;
  font-size:11.5px;font-weight:700;font-family:"IBM Plex Mono",ui-monospace,monospace;
  background:var(--grad-cool);color:var(--ink)}
.row .rm{min-width:0;flex:1}
.row .rt{font-size:13px;font-weight:650;line-height:1.35;color:var(--ink)}
.row .rs{font-size:11.5px;color:var(--muted);line-height:1.45;margin-top:1px}
.row .ra{margin-left:auto;flex:none;display:flex;align-items:center;gap:7px}
.row .rl{font-size:11.5px;font-weight:650;color:var(--accent)}
.row .rc{width:15px;height:15px;color:var(--faint);stroke-width:2.2;flex:none;transition:transform .16s ease,color .16s ease}
.row.tap:hover:not(:disabled) .rc{color:var(--accent);transform:translateX(2px)}

.checks{display:flex;flex-direction:column;gap:10px}
.check{display:flex;gap:10px;font-size:13px;align-items:flex-start;line-height:1.5;color:var(--ink-2)}
.check .cm{flex:none;width:19px;height:19px;border-radius:50%;display:grid;place-items:center;
  font-size:10px;font-weight:700;background:linear-gradient(135deg,var(--p-mint),var(--ok));color:#FFFFFF;
  box-shadow:0 2px 8px -3px color-mix(in srgb,var(--ok) 70%,transparent);margin-top:2px}
.check .cm.off{background:transparent;color:transparent;box-shadow:inset 0 0 0 1.5px var(--line-2)}

/* A live check the customer is waiting on. It reports nothing by itself — the
   sweep says the pack is working, and the label is the pack's own words. */
.scan{height:112px;border-radius:16px;border:1px solid var(--line);position:relative;overflow:hidden;
  background:linear-gradient(135deg,color-mix(in srgb,var(--p-lilac) 22%,transparent),
    color-mix(in srgb,var(--p-sky) 22%,transparent));display:grid;place-items:center}
.scan i.line{position:absolute;left:0;right:0;height:38px;border-radius:50%;
  background:radial-gradient(60% 50% at 50% 50%,color-mix(in srgb,var(--accent) 40%,transparent),transparent 70%);
  animation:sweep 2.4s ease-in-out infinite}
@keyframes sweep{0%,100%{top:4%}50%{top:66%}}
.scan b{position:relative;font-family:"IBM Plex Mono",ui-monospace,monospace;font-size:11px;color:var(--ink-2);
  background:var(--solid);padding:6px 13px;border-radius:999px;border:1px solid var(--line);
  box-shadow:var(--sh-1)}

.inputrow{display:flex;flex-direction:column;gap:6px}
.inputrow label{font-size:11.5px;color:var(--ink-2);font-weight:650}
.inputrow input{border:1px solid var(--line-2);border-radius:13px;padding:11px 13px;background:var(--solid);
  font-size:13.5px;color:var(--ink);width:100%;transition:border-color .16s ease,box-shadow .16s ease}
.inputrow input::placeholder{color:var(--faint)}
.inputrow input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 4px var(--accent-soft)}

/* Items arranged for looking at rather than reading down. */
.tiles{display:grid;grid-template-columns:1fr 1fr;gap:9px}
.strip{display:flex;gap:9px;overflow-x:auto;padding-bottom:4px;scrollbar-width:thin}
.strip .tile{flex:0 0 152px}
.tile{display:flex;flex-direction:column;align-items:flex-start;gap:3px;padding:12px 13px;
  border:1px solid var(--line);border-radius:16px;background:var(--sunken);text-align:left;width:100%}
.tile:nth-child(6n+1){--tint:var(--p-lilac)}
.tile:nth-child(6n+2){--tint:var(--p-mint)}
.tile:nth-child(6n+3){--tint:var(--p-peach)}
.tile:nth-child(6n+4){--tint:var(--p-sky)}
.tile:nth-child(6n+5){--tint:var(--p-blush)}
.tile:nth-child(6n+6){--tint:var(--p-butter)}
.tile.tap{cursor:pointer;transition:border-color .16s ease,background .16s ease,transform .16s cubic-bezier(.32,.72,0,1),box-shadow .16s ease}
.tile.tap:hover:not(:disabled){border-color:color-mix(in srgb,var(--accent) 50%,var(--line));
  background:color-mix(in srgb,var(--tint,var(--p-lilac)) 26%,var(--solid));
  transform:translateY(-3px);box-shadow:var(--sh-1),var(--sh-2)}
.tile.tap:active:not(:disabled){transform:translateY(0) scale(.99)}
.tile.tap:disabled{opacity:.5;cursor:default}
.tile .ti-g{width:30px;height:30px;border-radius:11px;display:grid;place-items:center;margin-bottom:4px;
  font-size:13px;background:linear-gradient(135deg,var(--tint,var(--p-lilac)),transparent);color:var(--ink)}
.tile .ti-t{font-size:13px;font-weight:650;line-height:1.35;color:var(--ink)}
.tile .ti-s{font-size:11.5px;color:var(--muted);line-height:1.45}
.tile .ti-a{font-size:11.5px;font-weight:650;color:var(--accent);margin-top:4px}
.tile .pill{margin-top:5px}

.icontile{display:inline-flex;align-items:center;gap:9px;padding:8px 13px 8px 8px;border-radius:14px;
  border:1px solid var(--line);background:var(--sunken);width:fit-content}
.icontile .it-g{width:30px;height:30px;border-radius:11px;display:grid;place-items:center;flex:none;
  font-size:13px;background:var(--grad-cool);color:var(--ink)}
.icontile .it-l{font-size:13px;font-weight:650}

.rating{display:flex;flex-direction:column;gap:5px}
.stars{display:flex;gap:3px}
.star{font-size:21px;line-height:1;color:var(--line-2);background:none;border:0;padding:1px 2px}
.star.on{color:var(--warn)}
button.star{cursor:pointer;transition:color .12s ease,transform .12s ease}
button.star:disabled{cursor:default;opacity:.5}
/* Hovering the row lights every star; the ones past the pointer go back out,
   so the row reads as "this many" rather than "this one". */
.stars:hover button.star{color:var(--warn)}
.stars button.star:hover{transform:scale(1.22)}
.stars button.star:hover~button.star{color:var(--line-2);transform:none}

/* A block this client has never seen. Shown, not swallowed: a pack that ships
   a new component should leave a visible gap here, not a silent one. */
.unknown{font-family:"IBM Plex Mono",ui-monospace,monospace;font-size:11px;color:var(--faint);
  border:1px dashed var(--line-2);border-radius:12px;padding:9px 12px;line-height:1.5}

/* ---------- composer ----------
 *
 * The one control on the screen that is always live, so it is the one thing
 * allowed a moving edge: focus lights a slow rainbow around the box. It is
 * masked to the border, so it reads as a lit outline rather than a lit card.
 * ------------------------------- */
.composer{flex:none;padding:10px 24px 20px;
  background:linear-gradient(180deg,transparent,color-mix(in srgb,var(--ground) 78%,transparent) 42%)}
.cbox{position:relative;max-width:768px;margin:0 auto;display:flex;align-items:flex-end;gap:8px;
  border:1px solid var(--line-2);background:var(--raised);border-radius:24px;padding:9px 9px 9px 18px;
  backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
  box-shadow:var(--shadow);
  transition:border-color .18s ease,box-shadow .18s ease}
@property --ring{syntax:"<angle>";inherits:false;initial-value:0deg}
.cbox::before{content:"";position:absolute;inset:-1.5px;border-radius:inherit;padding:1.5px;
  background:conic-gradient(from var(--ring),var(--p-lilac),var(--p-blush),var(--p-peach),
    var(--p-butter),var(--p-mint),var(--p-sky),var(--p-lilac));
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  mask-composite:exclude;
  opacity:0;pointer-events:none;transition:opacity .3s ease}
.cbox:focus-within::before{opacity:1;animation:ring 6s linear infinite}
@keyframes ring{to{--ring:360deg}}
.cbox:focus-within{border-color:transparent;box-shadow:var(--glow),var(--sh-2)}
.cbox textarea{flex:1;border:none;background:none;resize:none;outline:none;font-size:15.5px;line-height:1.55;
  max-height:184px;padding:6px 0;position:relative}
.cbox textarea::placeholder{color:var(--faint)}
.send{position:relative;width:38px;height:38px;border-radius:14px;background:var(--grad-brand);color:var(--accent-ink);
  display:grid;place-items:center;flex:none;box-shadow:var(--glow);
  transition:filter .16s ease,transform .14s cubic-bezier(.32,.72,0,1),background .16s ease,box-shadow .16s ease}
.send svg{width:17px;height:17px;stroke-width:2.2}
.send:hover:not(:disabled){filter:brightness(1.07) saturate(1.1);transform:translateY(-1px) scale(1.04)}
.send:active:not(:disabled){transform:scale(.93)}
.send:disabled{background:var(--sunken);color:var(--faint);box-shadow:none}
.foot{max-width:768px;margin:11px auto 0;text-align:center;font-size:11px;color:var(--faint);line-height:1.5}

/* ---------- inspector ----------
 *
 * A panel for whoever is building the pack, not for the customer: dense,
 * monospaced where the value is an identifier, and never guessing. Everything
 * in it either came off the wire or was measured in this browser. The palette
 * is the same, one notch quieter — it is a tool, not a surface.
 * ---------------------------------- */
.inspector{background:var(--side);border-left:1px solid var(--line);display:flex;flex-direction:column;min-height:0;
  backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur)}
/* `display:flex` above outranks the UA rule for [hidden], so restate it. */
.inspector[hidden]{display:none}
.ins-head{display:flex;align-items:center;height:62px;flex:none;padding:0 12px 0 16px;border-bottom:1px solid var(--line)}
.ins-head h2{margin:0;font-size:13.5px;font-weight:650;letter-spacing:-.01em}
.ins-head .icon{margin-left:auto}

.ins-stats{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;padding:12px;border-bottom:1px solid var(--line)}
.ins-stat{background:var(--raised);border:1px solid var(--line);border-radius:13px;padding:9px 10px}
.ins-stat .v{font-family:"IBM Plex Mono",ui-monospace,monospace;font-size:15px;font-weight:600;
  font-variant-numeric:tabular-nums;line-height:1.2;letter-spacing:-.02em}
.ins-stat .k{font-size:8.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--faint);
  font-family:"IBM Plex Mono",ui-monospace,monospace;margin-top:3px}

.ins-body{flex:1;overflow-y:auto;overscroll-behavior:contain;padding:12px;display:flex;flex-direction:column;gap:10px}
.ins-empty{display:flex;flex-direction:column;align-items:center;text-align:center;gap:8px;
  padding:34px 14px;margin:0;color:var(--faint)}
.ins-empty svg{width:28px;height:28px;stroke-width:1.6;color:var(--line-2)}
.ins-empty p{margin:0;font-size:13px;font-weight:500;color:var(--muted)}
.ins-empty .ie-sub{font-size:11.5px;font-weight:400;line-height:1.55;color:var(--faint);max-width:250px}

.turn-card{border:1px solid var(--line);border-radius:14px;background:var(--raised);overflow:hidden;
  box-shadow:var(--sh-1);animation:rise .3s ease-out both}
.turn-h{padding:9px 12px;display:flex;align-items:center;gap:8px;border-bottom:1px solid var(--line);font-size:11.5px}
.turn-h.journey{background:var(--ok-soft)} .turn-h.off{background:var(--warn-soft)}
.turn-h .tn{font-size:10px;color:var(--faint);flex:none}
.turn-h .rid{font-family:"IBM Plex Mono",ui-monospace,monospace;font-weight:600;font-size:11px;
  min-width:0;overflow-wrap:anywhere}
.turn-h.journey .rid{color:var(--ok)} .turn-h.off .rid{color:var(--warn)}
.turn-h .ms.live{background:var(--accent-soft);color:var(--accent);font-weight:600;letter-spacing:.04em}
.turn-h .ms{margin-left:auto;flex:none;font-size:10.5px;color:var(--muted);font-variant-numeric:tabular-nums;
  background:color-mix(in srgb,var(--solid) 60%,transparent);border-radius:999px;padding:2px 8px}

.turn-b{padding:11px 12px;display:flex;flex-direction:column;gap:8px;font-size:11.5px}
.turn-b .q{color:var(--ink-2);font-size:12px;line-height:1.5;overflow-wrap:anywhere}
.tl{display:flex;gap:8px}
.tl .k{font-family:"IBM Plex Mono",ui-monospace,monospace;font-size:8.5px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--faint);width:44px;flex:none;padding-top:3px}
.tl .v{color:var(--ink-2);min-width:0;overflow-wrap:anywhere}
.evs{display:flex;flex-wrap:wrap;gap:3px}
.ev{font-family:"IBM Plex Mono",ui-monospace,monospace;font-size:9.5px;letter-spacing:-.01em;
  color:var(--muted);background:var(--sunken);border:1px solid transparent;border-radius:6px;padding:2px 6px}
/* Coloured by family so the shape of a run reads before the words do. */
.ev.run{color:var(--accent);background:var(--accent-soft)}
.ev.tool{color:var(--warn);background:var(--warn-soft)}
.ev.ui{color:var(--ok);background:var(--ok-soft)}
.ev.text{color:var(--ink-2);background:var(--sunken)}
.ev.state{color:var(--muted);background:transparent;border-color:var(--line)}
.ev.stop{color:var(--stop);background:var(--stop-soft)}

.ids{display:flex;flex-wrap:wrap;gap:5px;padding-top:2px}
.idchip{display:inline-flex;align-items:center;gap:6px;max-width:100%;padding:4px 9px;border-radius:8px;
  border:1px solid var(--line);background:var(--sunken);cursor:pointer;transition:.14s}
.idchip:hover{border-color:var(--accent)}
.idchip .ik{font-size:8.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--faint);flex:none}
.idchip .iv{font-size:9.5px;color:var(--ink-2);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.idchip.copied{border-color:var(--ok);background:var(--ok-soft)}
.idchip.copied .iv{color:var(--ok)}

/* ---------- no backend ----------
 *
 * The same composition as the sign-in, because it is the same moment: the
 * customer is at the door and it did not open. What went wrong is quoted, not
 * paraphrased — the message is the one the control-plane client produced.
 * --------------------------------- */
.fail{position:fixed;inset:0;z-index:12;display:grid;place-items:center;padding:32px 24px;
  background:radial-gradient(900px 460px at 50% -8%,color-mix(in srgb,var(--stop) 10%,transparent),transparent 68%),
    color-mix(in srgb,var(--ground) 78%,transparent);
  backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur)}
.fail[hidden]{display:none}
.fail-inner{width:100%;max-width:420px;display:flex;flex-direction:column;align-items:center;
  text-align:center;gap:15px}
.fail-inner h1{margin:2px 0 0;font-size:22px;font-weight:700;letter-spacing:-.024em}
.fail-why{margin:0;font-size:13.5px;line-height:1.6;color:var(--ink-2);background:var(--stop-soft);
  border:1px solid color-mix(in srgb,var(--stop) 24%,var(--line));border-radius:16px;padding:12px 15px;
  overflow-wrap:anywhere}
.fail-how{margin:0;font-size:12px;line-height:1.65;color:var(--faint)}
.fail-how code{font-size:11.5px;background:var(--sunken);border-radius:6px;padding:1.5px 6px}
.fail .signin-go{width:100%;max-width:220px}

/* ---------- settings ----------
 *
 * A page, not a dialog: it covers the conversation the way the sign-in does,
 * and leaves the same way. What it holds is deliberately narrow — this shell
 * can change how it looks and behaves in this browser, and it can report what
 * the backend mounted. It cannot change the pack, so it does not pretend to.
 * ------------------------------- */
.settings{position:fixed;inset:0;z-index:20;display:flex;flex-direction:column;
  background:color-mix(in srgb,var(--ground) 76%,transparent);
  backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur)}
.settings[hidden]{display:none}
.set-head{height:62px;flex:none;display:flex;align-items:center;gap:8px;padding:0 12px;
  border-bottom:1px solid var(--line)}
.set-head h1{margin:0;font-size:16px;font-weight:700;letter-spacing:-.018em}
.set-scroll{flex:1;overflow-y:auto;overscroll-behavior:contain}
.set-wrap{max-width:620px;margin:0 auto;padding:28px 24px 60px;display:flex;flex-direction:column;gap:28px}
.set-sec{display:flex;flex-direction:column;gap:9px}
.set-sec>h2{margin:0 2px;font-size:10.5px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  color:var(--faint)}
.set-card{border:1px solid var(--line);border-radius:20px;background:var(--raised);
  backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
  box-shadow:var(--sh-1);overflow:hidden}
.set-row{display:flex;align-items:center;gap:16px;padding:15px 17px;border-bottom:1px solid var(--line)}
.set-row:last-child{border-bottom:0}
.set-t{min-width:0;flex:1}
.set-l{font-size:13.5px;font-weight:650;letter-spacing:-.008em;line-height:1.4}
.set-d{font-size:12px;color:var(--muted);line-height:1.5;margin-top:3px}
.set-v{flex:none;margin-left:auto;font-size:13px;font-weight:650;text-align:right;
  font-variant-numeric:tabular-nums;max-width:55%;overflow-wrap:anywhere}
.set-v.mono{font-size:11.5px;font-weight:500;color:var(--ink-2)}
.set-note{margin:0 2px;font-size:11.5px;color:var(--faint);line-height:1.6}
.set-caps{display:flex;flex-wrap:wrap;gap:5px;justify-content:flex-end;max-width:60%;margin-left:auto}
.swatch{width:18px;height:18px;border-radius:6px;border:1px solid var(--line);flex:none}
.set-swatch{display:flex;align-items:center;gap:8px;margin-left:auto;flex:none}
.set-swatch .set-v{max-width:none;white-space:nowrap}

.seg{display:flex;gap:2px;padding:3px;border-radius:14px;background:var(--sunken);
  border:1px solid var(--line);flex:none}
.seg button{padding:7px 14px;border-radius:11px;font-size:12.5px;font-weight:650;color:var(--muted);
  transition:color .14s ease,background .14s ease,box-shadow .14s ease}
.seg button:hover{color:var(--ink)}
.seg button[aria-checked="true"]{background:var(--solid);color:var(--ink);box-shadow:var(--sh-1)}

.switch{width:46px;height:27px;border-radius:999px;background:var(--line-2);position:relative;flex:none;
  transition:background .2s ease,box-shadow .2s ease}
.switch::after{content:"";position:absolute;top:3px;left:3px;width:21px;height:21px;border-radius:50%;
  background:#FFFFFF;box-shadow:0 1px 3px rgba(40,25,80,.35);transition:transform .24s cubic-bezier(.32,.72,0,1)}
.switch[aria-checked="true"]{background:var(--grad-brand);box-shadow:var(--glow)}
.switch[aria-checked="true"]::after{transform:translateX(19px)}

.set-btn{border:1px solid var(--line-2);background:var(--raised);border-radius:12px;padding:9px 15px;
  font-size:13px;font-weight:650;color:var(--ink);flex:none;margin-left:auto;transition:.16s}
.set-btn:hover{border-color:var(--accent);color:var(--accent)}
.set-btn.danger{color:var(--stop);border-color:color-mix(in srgb,var(--stop) 32%,var(--line))}
.set-btn.danger:hover{background:var(--stop-soft);color:var(--stop);border-color:var(--stop)}
.set-btn.armed,.set-btn.danger.armed{background:var(--stop);border-color:transparent;color:#FFFFFF}

/* ---------- responsive ---------- */
.mobonly{display:none}
/* No room for the panel, so nothing to toggle. */
@media (max-width:1080px){ .app.ins{grid-template-columns:274px minmax(0,1fr)} .inspector,#inspect{display:none} }
@media (max-width:820px){
  .app,.app.ins{grid-template-columns:minmax(0,1fr)}
  .side{position:fixed;inset:0 auto 0 0;width:min(86vw,300px);z-index:30;transform:translateX(-100%);
    background:color-mix(in srgb,var(--ground) 88%,transparent);
    transition:transform .3s cubic-bezier(.32,.72,0,1)}
  .app.nav .side{transform:none;box-shadow:var(--sh-pop)}
  /* A drawer over the conversation needs something between them, or the page
     behind reads as still tappable. Clicking it closes the drawer. */
  .app.nav::after{content:"";position:fixed;inset:0;z-index:20;background:var(--scrim);
    backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px)}
  .side-top{padding-top:max(16px,env(safe-area-inset-top))}
  .account{padding:9px}
  .acc-out{width:38px;height:38px}
  .side-foot{padding-bottom:max(10px,env(safe-area-inset-bottom))}
  .mobonly{display:grid}

  .bar{height:58px;padding:0 10px 0 6px;gap:8px}
  .icon{width:40px;height:40px}
  .bar-mark svg{width:28px;height:28px}
  .bar-title{gap:8px}
  .bar-title strong{font-size:16px}

  .thread{padding:22px 16px 34px;gap:22px}
  .msg{gap:10px}
  .avatar{width:28px;height:28px;border-radius:10px}
  .msg.user .body{max-width:88%}
  .starters{grid-template-columns:1fr;max-width:none;gap:9px}
  .hero-greet{font-size:14.5px}
  .hero-mark{width:58px;height:58px}
  .hero-name{font-size:24px}

  /* The blobs are sized in `vw`, and a phone's `vw` is small enough that six
     of them stop overlapping and start reading as six circles. */
  .blob{filter:blur(56px) saturate(150%)}
  .b1{width:80vw;height:80vw} .b2{width:70vw;height:70vw} .b3{width:78vw;height:78vw}
  .b4{width:60vw;height:60vw} .b5{width:56vw;height:56vw} .b6{display:none}

  /* A surface should use the width it has here, not sit in a 470px column. */
  .card{max-width:none;width:100%}
  .surface{max-width:none}
  .tiles{grid-template-columns:1fr}
  .chip,.btn{min-height:42px}

  /* Anything under 16px is a signal to iOS that the page wants zooming into
     when it is focused, and the whole layout lurches sideways. */
  .cbox textarea,.inputrow input{font-size:16px}
  .cbox{border-radius:24px;padding:8px 8px 8px 16px}
  .send{width:40px;height:40px}
  .composer{padding:8px 12px max(10px,env(safe-area-inset-bottom))}
  /* Provenance the customer did not ask for, in the space their keyboard
     wants. It stays on the desktop layout, where there is room for it. */
  .foot{display:none}

  /* A setting and its control stop sharing a line: the label needs the width
     more than the row needs to be one line. */
  .set-wrap{padding:20px 16px 48px;gap:22px}
  .set-row{flex-wrap:wrap;gap:12px;padding:15px}
  .set-t{flex:1 1 100%}
  .seg{width:100%}
  .seg button{flex:1;text-align:center;padding:9px 10px}
  .set-v,.set-caps,.set-swatch{max-width:none;margin-left:0}
  .set-caps{justify-content:flex-start}
  .set-btn{margin-left:0}
  .switch{margin-left:auto}
}

/* The tenant is a deployment detail, and it is the first thing to go when the
   name it sits beside has nowhere to wrap. */
@media (max-width:560px){
  .skillpill{display:none}
}

@media (max-width:420px){
  .thread{padding:18px 14px 28px}
  .prose{font-size:15px}
  .msg.user .prose{padding:11px 15px}
}

/* ---------------------------------------------------------------- *
 * Sign in
 *
 * Shown before the chat, and the only screen that is not the pack's
 * agent talking: it exists to establish who the customer is. The name
 * and colour on it are still the pack's — a door should say whose
 * building it is — but the layout, the mark and the copy are the
 * shell's, because there is nobody to ask the pack about yet.
 *
 * It is also the first thing anyone sees, so it is where the ambient
 * layer is loudest: the aurora shows through the card, and the mark
 * and the card drift against the pointer at different depths.
 * ---------------------------------------------------------------- */

.signin{
  position:fixed;inset:0;z-index:10;overflow-y:auto;
  display:grid;place-items:center;padding:40px 24px;
  background:
    radial-gradient(900px 460px at 50% -8%,color-mix(in srgb,var(--accent) 14%,transparent),transparent 68%),
    radial-gradient(700px 420px at 92% 108%,color-mix(in srgb,var(--p-blush) 22%,transparent),transparent 70%),
    color-mix(in srgb,var(--ground) 55%,transparent);
}
.signin[hidden]{display:none}

/* `hidden` is a UA `display:none`, and a class that sets `display` outranks it.
   Both panes need saying explicitly or the chat shows through the sign-in. */
.app[hidden]{display:none}

.signin-inner{width:100%;max-width:396px;display:flex;flex-direction:column;align-items:center;gap:24px;
  transform:translate3d(var(--dx,0px),var(--dy,0px),0)}

.brand{display:flex;flex-direction:column;align-items:center;gap:13px;text-align:center;margin:0}
.brand-mark{width:66px;height:66px;line-height:0;border-radius:20px;
  box-shadow:0 16px 40px -14px color-mix(in srgb,var(--accent) 75%,transparent);
  transform:translate3d(var(--dx,0px),var(--dy,0px),0);
  animation:float 6s ease-in-out infinite alternate}
/* The pack's name in the pack's gradient. */
.brand-name{margin:0;font-size:27px;font-weight:700;letter-spacing:-.028em;line-height:1.2;
  background:var(--grad-brand);-webkit-background-clip:text;background-clip:text;color:transparent}
.brand-tag{margin:-6px 0 0;font-size:14px;color:var(--muted);line-height:1.4}

/* Glass over the aurora, not a white rectangle on top of it. */
.signin-card{
  position:relative;width:100%;display:flex;flex-direction:column;gap:16px;
  background:var(--raised);border:1px solid var(--line);border-radius:26px;padding:30px 28px;
  backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
  box-shadow:var(--sh-1),0 26px 60px -28px color-mix(in srgb,var(--accent) 65%,transparent);
}
/* One pastel highlight along the top edge, the way light lands on glass. */
.signin-card::before{content:"";position:absolute;left:14%;right:14%;top:-1px;height:1px;
  background:linear-gradient(90deg,transparent,color-mix(in srgb,#FFFFFF 80%,transparent),transparent)}
.signin-title{margin:0;font-size:18px;font-weight:700;letter-spacing:-.018em}
.signin-sub{margin:-10px 0 0;color:var(--muted);font-size:13.5px;line-height:1.55}

.field{display:flex;flex-direction:column;gap:7px}
.field[hidden]{display:none}
.field-label{font-size:12.5px;font-weight:650;color:var(--ink-2);letter-spacing:-.004em}
.field input{
  width:100%;height:50px;padding:0 15px;font:inherit;font-size:15.5px;color:var(--ink);
  background:color-mix(in srgb,var(--solid) 62%,transparent);
  border:1px solid var(--line-2);border-radius:15px;outline:none;
  transition:border-color .16s ease,box-shadow .16s ease,background .16s ease;
}
.field-phone{position:relative;display:block}
.field-phone .pfx{position:absolute;left:15px;top:50%;transform:translateY(-50%);pointer-events:none;
  font-size:15.5px;color:var(--muted);font-variant-numeric:tabular-nums}
.field-phone .pfx[hidden]{display:none}
.field-phone:has(.pfx:not([hidden])) input{padding-left:54px}
.field input::placeholder{color:var(--faint)}
.field input:hover{border-color:color-mix(in srgb,var(--accent) 40%,var(--line-2))}
.field input:focus{border-color:var(--accent);background:var(--solid);box-shadow:0 0 0 4px var(--accent-soft)}

/* Six cells, one input. The input carries the value (so autofill and paste
   still work); the cells are painted from it and never hold state. */
.otp{position:relative;display:grid;grid-template-columns:repeat(6,1fr);gap:8px}
/* The input is a hit target stretched over all six cells, not a field — but it
   is inside a `.field`, so it inherits that field's painting, and every bit of
   it has to come back off in every state. The focus treatment especially:
   `.field input:focus` outranks a bare `.otp input`, and it would drop an
   opaque rounded card over the six cells at the exact moment someone starts
   typing into them. Suppressing the focus ring here is safe because there is
   still a visible one — `.otp.on i.at` puts it on the cell the caret is in,
   which is the more useful place for it anyway. */
.otp input,.otp input:hover,.otp input:focus{
  position:absolute;inset:0;width:100%;height:100%;z-index:2;
  background:none;border:0;border-radius:0;box-shadow:none;outline:none;
  color:transparent;caret-color:transparent;
  font-size:16px;letter-spacing:1em;text-indent:.5em;
}
.otp i{
  height:56px;display:grid;place-items:center;font-style:normal;
  font-family:"IBM Plex Mono",ui-monospace,monospace;font-size:20px;font-weight:500;color:var(--ink);
  background:color-mix(in srgb,var(--solid) 62%,transparent);
  border:1px solid var(--line-2);border-radius:14px;
  transition:border-color .16s ease,box-shadow .16s ease,background .16s ease,transform .16s cubic-bezier(.32,.72,0,1);
}
.otp.on i.at{border-color:var(--accent);box-shadow:0 0 0 4px var(--accent-soft);transform:translateY(-2px)}
.otp i.set{border-color:var(--line-2);background:var(--solid)}

.signin-note{margin:0;font-size:12.5px;color:var(--ink-2);line-height:1.55;
  background:linear-gradient(120deg,var(--accent-soft),color-mix(in srgb,var(--p-sky) 20%,transparent));
  border-radius:13px;padding:10px 12px}
.signin-note code{font-family:"IBM Plex Mono",monospace;color:var(--accent);font-weight:600;
  background:none;font-size:13px;letter-spacing:.06em}
.signin-error{margin:0;font-size:12.5px;color:var(--stop);line-height:1.5;
  background:var(--stop-soft);border-radius:13px;padding:10px 12px}
.signin-note[hidden],.signin-error[hidden]{display:none}

.signin-go{
  position:relative;height:50px;display:grid;place-items:center;
  font:inherit;font-size:15px;font-weight:650;letter-spacing:-.008em;
  background:var(--grad-brand);color:var(--accent-ink);border:0;border-radius:15px;cursor:pointer;
  box-shadow:var(--glow);
  transition:filter .16s ease,transform .14s cubic-bezier(.32,.72,0,1),opacity .16s ease,box-shadow .16s ease;
}
.signin-go:hover:not(:disabled){filter:brightness(1.06) saturate(1.08);transform:translateY(-2px);
  box-shadow:var(--glow),var(--sh-2)}
.signin-go:active:not(:disabled){transform:translateY(0) scale(.985)}
.signin-go:disabled{opacity:.5;cursor:default;box-shadow:none}
.signin-go .btn-spin{display:none;position:absolute;width:18px;height:18px;border-radius:50%;
  border:2px solid color-mix(in srgb,var(--accent-ink) 35%,transparent);border-top-color:var(--accent-ink);
  animation:spin .7s linear infinite}
.signin-go.busy .lbl{visibility:hidden}
.signin-go.busy .btn-spin{display:block}

.signin-alt{display:flex;align-items:center;justify-content:center;gap:9px;font-size:13px;color:var(--faint)}
.signin-alt[hidden]{display:none}
.linkbtn{font:inherit;font-size:13px;font-weight:550;color:var(--ink-2);background:none;border:0;
  padding:2px 1px;cursor:pointer;border-radius:6px;transition:color .14s ease}
.linkbtn:hover:not(:disabled){color:var(--accent)}
.linkbtn:disabled{color:var(--faint);cursor:default}

.signin-foot{margin:0;max-width:340px;text-align:center;font-size:12px;line-height:1.55;color:var(--faint)}

@media (max-width:820px){
  /* Anything under 16px tells iOS the page wants zooming into when a field is
     focused, and the whole card lurches sideways as it is tapped. */
  .field input,.otp input{font-size:16px}
  .signin-go{height:52px}
  .linkbtn{padding:6px 2px}
}
@media (max-width:420px){
  /* Centred while it fits, and pinned to the top the moment a keyboard makes
     the viewport shorter than the card — `safe` is what keeps centring from
     cutting the mark off the top. */
  .signin{padding:26px 18px max(26px,env(safe-area-inset-bottom));align-content:safe center}
  .signin-card{padding:26px 21px;border-radius:22px}
  .otp{gap:6px}
  .otp i{height:52px;font-size:19px}
  .brand-name{font-size:23px}
  .brand-mark{width:58px;height:58px}
}
