:root {
  color-scheme: dark;
  --ink: #edf0f8; --dim: #9da8be; --faint: #6f7c95;
  --paper: #171b27; --line: #30394e; --accent: #a8d6ff; --mine: #344f82;
  --tool: #1d2432; --danger: #ff9c9c;
}
* { box-sizing: border-box; }
/* The one size everything else is a multiple of: the text-size control in
   the account menu writes px here, and the whole UI follows. */
html { font-size: 15px; }
body { margin: 0; min-height: 100dvh; background: #10131c; color: var(--ink); font: 1rem/1.5 Inter, ui-sans-serif, system-ui, sans-serif; }

/* The app is one full-height column: only the message list scrolls, so the
   composer stays reachable however long the conversation gets. */
.app { display: flex; flex-direction: column; gap: 10px; max-width: 860px; height: 100dvh; margin: auto; padding: 8px 12px; }
header { display: flex; justify-content: space-between; align-items: center; min-height: 36px; color: var(--dim); font-size: 0.8667rem; }
.brand { display: inline-block; color: var(--ink); font-weight: 750; text-decoration: none; letter-spacing: -.04em; font-size: 1.3333rem; }
.brand::after { content: "by FlowCart"; display: block; text-align: right; color: var(--dim); font-size: 0.6667rem; font-weight: 400; letter-spacing: normal; line-height: 1; }
.brand span { color: var(--accent); }

.account { position: relative; }
.identity { display: grid; place-items: center; width: 1.8667rem; height: 1.8667rem; padding: 0; border: 1px solid var(--line);
            border-radius: 50%; background: var(--tool); color: var(--dim); font: inherit; font-size: 0.8667rem;
            font-weight: 700; line-height: 1; text-transform: uppercase; cursor: pointer; }
.identity:hover, .identity[aria-expanded="true"] { border-color: var(--accent); color: var(--ink); }
.account-menu { position: absolute; z-index: 2; right: 0; top: calc(100% + 7px); display: none; min-width: 150px; max-width: min(74vw, 260px); padding: 5px; border: 1px solid var(--line); border-radius: 9px; background: #222a3a; box-shadow: 0 10px 24px #0007; }
.account-menu.open { display: block; }
.account-menu::before { content: ""; position: absolute; top: -5px; right: 16px; width: 8px; height: 8px; background: #222a3a; border-left: 1px solid var(--line); border-top: 1px solid var(--line); transform: rotate(45deg); }
.account-menu form { display: block; padding: 0; border: 0; }
.account-menu button { position: relative; width: 100%; padding: 7px 10px; border-radius: 6px; background: transparent; color: var(--ink); font-size: 0.8667rem; text-align: left; }
.account-menu button:hover { background: #303b52; }
.menu-who { display: block; padding: 6px 10px 8px; margin-bottom: 4px; border-bottom: 1px solid var(--line);
            overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--dim); font-size: 0.8rem; }
.menu-size { display: flex; align-items: center; gap: 6px; padding: 5px 10px 7px;
             margin-bottom: 4px; border-bottom: 1px solid var(--line);
             color: var(--faint); font-size: 0.8rem; }
.menu-size .label { flex: 1; }
.menu-size button { width: 1.4rem; padding: 0; border: 1px solid var(--line); border-radius: 6px;
                    background: transparent; color: var(--ink); font-size: 0.9rem; line-height: 1.4;
                    text-align: center; }
.menu-size button:disabled { opacity: .35; cursor: default; }
.menu-size .now { min-width: 3.4em; color: var(--dim); font-variant-numeric: tabular-nums;
                  text-align: center; }
.menu-note { display: block; padding: 7px 10px; color: var(--faint); font-size: 0.8333rem; }

.card { border: 1px solid var(--line); border-radius: 18px; background: var(--paper); padding: clamp(18px, 4vw, 30px); box-shadow: 0 20px 60px #0004; }
.card.center { text-align: center; color: var(--dim); }
.hidden { display: none !important; }
.eyebrow { margin: 0 0 8px; color: var(--accent); font-size: 0.7333rem; letter-spacing: .12em; font-weight: 700; }
h1 { margin: 0; letter-spacing: -.04em; font-size: clamp(30px, 7vw, 48px); line-height: 1.05; }
p { color: var(--dim); }
.button, button { display: inline-block; border: 0; border-radius: 10px; background: var(--accent); color: #101828; padding: 11px 16px; font: inherit; font-weight: 700; text-decoration: none; cursor: pointer; }
button:disabled { opacity: .55; cursor: default; }

/* ---- permissions ---- */
/* One icon per service, and a toggle to put the row away. The icon is the
   whole control: its state says what is granted, clicking it asks for the
   rest -- or asks again, when a grant has been revoked. */
.masthead { display: flex; align-items: center; gap: 14px; min-width: 0; }
.permissions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 0 2px; }
.grant { display: inline-grid; place-items: center; width: 1.7333rem; height: 1.7333rem; border: 1px solid var(--line);
         border-radius: 9px; background: var(--tool); color: var(--faint); text-decoration: none;
         padding: 0; font: inherit; cursor: pointer; }
span.grant { cursor: default; }
.grant:hover { border-color: var(--accent); color: var(--accent); }
.grant.full { border-color: #2f6b4d; color: #6ee7a8; }
.grant.partial { border-color: #6b5a2f; color: #e7c96e; }

/* ---- landing ---- */
.landing { max-width: 640px; margin: clamp(24px, 9vh, 90px) auto 0; }
.landing .lede { margin: 18px 0 26px; font-size: 1.1333rem; line-height: 1.55; }
.landing h1 { font-size: clamp(34px, 8vw, 54px); }
.button.google { display: inline-flex; align-items: center; gap: 10px; background: #fff; color: #1f2430; padding: 12px 20px; }
.button.google:hover { background: #e9eefb; }
.points { margin: 34px 0 0; padding: 0; list-style: none; display: grid; gap: 14px; }
.points li { padding-left: 18px; position: relative; color: var(--dim); font-size: 1rem; line-height: 1.5; }
.points li::before { content: ""; position: absolute; left: 0; top: 9px; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
.points strong { color: var(--ink); font-weight: 650; }

/* ---- the browser, handed over inline on a message ---- */
/* Only ever rendered on the newest message, when the agent has stopped and
   asked for something it cannot do itself. */
.message.asking { max-width: 100%; border-color: #ffd479; }
.handoff { margin-top: 10px; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; background: #0b0e15; }
.handoff-bar { display: flex; align-items: center; gap: 8px; padding: 8px 10px; background: var(--tool); }
.handoff-hint { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--faint); font-size: 0.8333rem; }
.icon { padding: 4px 9px; border: 1px solid var(--line); border-radius: 8px; background: transparent; color: var(--dim); font-size: 0.9333rem; line-height: 1; }
.icon:hover { border-color: var(--accent); color: var(--accent); }
/* Words, not a glyph: ⇞ and ⇟ are missing from enough fonts to show as
   a box, and there is room for four letters. */
.icon.page { font-size: 0.7333rem; letter-spacing: .04em; }
/* Handing the browser back: under the frame, because that is where you are
   looking when you have finished doing what was asked of you. */
.handoff-foot { display: flex; justify-content: flex-end; padding: 8px 10px; border-top: 1px solid var(--line); }
.continue { padding: 5px 14px; border-radius: 999px; border: 0; background: #6ee7a8; color: #101828; font-size: 0.8667rem; font-weight: 700; }
.continue:hover { background: #8df0be; }
.continue.small { padding: 3px 10px; font-size: 0.8rem; }

/* Where the browser actually is, which is the one thing a picture cannot say. */
/* Sits where the address does, because it is the newest thing the browser
   has to say and it is on its way out again. */
.handoff-notice { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: #ffd479; font-size: 0.8rem; }

.handoff-url { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
               direction: rtl; text-align: left; color: var(--dim); font-size: 0.8333rem;
               font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }

/* Keystrokes are read from a real input, off the side of the screen: a canvas
   holds no caret, so a phone offers no keyboard for one. Not display:none and
   not hidden -- either makes it unfocusable, which is the whole point of it. */
.key-catcher { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; border: 0; padding: 0; }

/* The canvas must keep the frame's own aspect ratio: clicks are sent as a
   fraction of this element's box and mapped onto the frame server-side, so
   stretching it would land every one of them somewhere else. Bounded by
   height rather than width because the frame is nearly square and a
   full-width canvas would push the conversation off the screen. */
.handoff-body { position: relative; display: flex; justify-content: center; cursor: zoom-in; }
/* Until the first frame lands there is a black rectangle where the page will
   be, which reads as something broken rather than something starting. */
.live-loading { position: absolute; inset: 0; display: flex; align-items: center;
                justify-content: center; gap: 6px; background: var(--paper);
                color: var(--faint); font-size: 0.8667rem; }
.live-loading span:last-child { margin-left: 4px; }
.handoff.enlarged .handoff-body { cursor: default; }
/* object-fit rather than a box shaped to match: a canvas paints its bitmap to
   fill the content box, so any box whose shape differs from the frame's
   stretches the picture. Contain keeps the frame's own shape whatever shape
   the box ends up -- and the pointer mapping accounts for the bars it leaves,
   or every click would land somewhere else. */
.live-canvas { display: block; max-width: 100%; max-height: 40vh; width: auto; height: auto;
               object-fit: contain; cursor: default; touch-action: none; }
.live-canvas.holding { cursor: crosshair; }
.live-canvas:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Enlarged: the same element, over everything, with the room to actually
   read a login form. */
.handoff.enlarged { position: fixed; inset: 16px; z-index: 20; margin: 0; display: flex;
                    flex-direction: column; box-shadow: 0 30px 90px #000a; }
.handoff.enlarged .handoff-body { flex: 1; min-height: 0; align-items: center; }
/* Fill the overlay and let object-fit keep the shape. Sizing it with
   height:100% and width:auto looked right until the box was narrower than the
   frame: max-width clamped the width, the definite height did not follow, and
   the picture came out stretched -- which is what a phone always is. */
.handoff.enlarged .live-canvas { width: 100%; height: 100%; max-width: 100%; max-height: 100%; }

.fineprint { margin: 26px 0 0; color: var(--faint); font-size: 0.8667rem; }
.fineprint a { color: inherit; }
.fineprint a:hover { color: var(--accent); }

/* ---- attachments ---- */
/* The chips sit above the box on their own row, so a long file name never
   squeezes the place you are typing. */
.attachments { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }
.chip { display: inline-flex; align-items: center; gap: 6px; max-width: 240px; padding: 4px 6px 4px 10px;
        border: 1px solid var(--line); border-radius: 999px; background: var(--tool); font-size: 0.8333rem; }
.chip-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); }
.chip-size { color: var(--faint); }
.chip button { border: 0; padding: 0 4px; background: transparent; color: var(--faint);
               font-size: 1rem; line-height: 1; cursor: pointer; }
.chip button:hover { color: var(--danger); }
.chip.pending { color: var(--faint); }
.picker { display: none; }
/* Two small squares in a column beside the box. Sized so the pair is no
   taller than the one-line textarea they sit next to -- the point of moving
   them here was to give the conversation the height back, not to spend it. */
.composer-actions { display: flex; flex-direction: column; gap: 2px; }
.icon-button { display: grid; place-items: center; width: 1.4667rem; height: 1.4667rem; padding: 0;
               border: 1px solid var(--line); border-radius: 8px; background: transparent;
               color: var(--dim); cursor: pointer; }
.icon-button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
/* The glyphs are sized in text too. The svg carries its own width and
   height attributes, and these are what override them. */
.icon-button svg { width: .9em; height: .9em; }
.grant svg { width: 1.15em; height: 1.15em; }
/* Sits with the connectors, and is gone once the app is installed. */
.icon-button.install { width: 1.7333rem; height: 1.7333rem; color: var(--accent); }
.icon-button:disabled { opacity: .4; cursor: default; }
.icon-button.send { border-color: transparent; background: var(--accent); color: #101828; }
.icon-button.send:hover:not(:disabled) { background: #c9e6ff; }

/* ---- chat ---- */
.chat { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 10px; padding: clamp(10px, 1.8vw, 16px); }
.messages { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; display: flex; flex-direction: column; gap: 10px; padding-right: 6px; scrollbar-width: thin; }
.empty { margin: auto; max-width: 30ch; text-align: center; color: var(--faint); }

/* The agent thinking out loud: no bubble, no label, just a line you can skim
   past on the way to the answer. */
/* Not a turn in the conversation but a line about it -- a schedule firing, a
   page moving under a parked turn. Centred so it reads as a divider rather
   than as something either side said. */
.aside { align-self: center; display: flex; align-items: baseline; gap: 8px; max-width: 88%; margin: 0; color: var(--faint); font-size: 0.7667rem; text-align: center; }
.aside time { flex: none; font-size: 0.7rem; font-variant-numeric: tabular-nums; opacity: .8; }
/* A schedule that found nothing: quieter still than the rest of the asides,
   because there are more of these than of anything else. */
.aside.quiet { gap: 6px; opacity: .72; font-size: 0.7333rem; font-style: italic; }

.earlier { align-self: center; text-align: center; opacity: .7; }

.note { align-self: stretch; margin: -4px 2px; color: var(--faint); font-size: 0.8rem; line-height: 1.5; }
.note > * { white-space: normal; }
.note > :first-child { margin-top: 0; }
.note > :last-child { margin-bottom: 0; }
.note p { margin: 0 0 4px; }
.note code { padding: 1px 4px; border-radius: 4px; background: #10131c; font-size: 0.9em; }

/* One turn: the bubble, and its time hanging underneath. The width and the
   side of the conversation belong to the column now, not to the bubble. */
.turn { display: flex; flex-direction: column; align-items: flex-start; max-width: 88%; }
.turn.user { align-self: flex-end; align-items: flex-end; }
.turn.asking { max-width: 100%; align-self: stretch; }
.turn > .stamp { margin: 2px 6px 0; color: var(--faint); font-size: 0.6667rem; font-variant-numeric: tabular-nums; }
/* One that has something behind it says so, faintly: what the turn cost is
   worth finding if you are looking for it and worth nothing if not. */
.turn > .stamp.costed { position: relative; border-bottom: 1px dotted var(--faint);
                        -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.turn > .stamp.costed:focus { outline: none; }
/* The counts themselves. Shown on focus as well as hover, which is the whole
   point of not using a title attribute: a phone cannot hover, and a tap
   focuses. Kept out of the flow so it cannot move the conversation. */
.stamp .cost { position: absolute; z-index: 3; bottom: calc(100% + 6px); left: 0;
               width: max-content; max-width: min(15rem, 76vw); padding: 7px 9px;
               border: 1px solid var(--line); border-radius: 9px; background: #222a3a;
               box-shadow: 0 10px 24px #0007; color: var(--dim); font-size: 0.7333rem;
               line-height: 1.5; white-space: pre; text-align: left; cursor: default;
               opacity: 0; visibility: hidden; transition: opacity .12s ease; }
/* Anchored to whichever side its bubble is on, so it opens inwards. */
.turn.user .stamp .cost { left: auto; right: 0; }
/* :active as well as :focus, on every kind of screen. Focus is the path a tap
   takes and the one that stays open, but a browser that will not focus a
   <time> on touch still gives it :active while the finger is down, so the
   counts are reachable by press-and-hold whatever happens. */
.stamp:focus .cost, .stamp:focus-within .cost, .stamp:active .cost {
  opacity: 1; visibility: visible; }
/* Hover only where there is a real pointer. A touch screen reports a hover
   that sticks to whatever was tapped last and never lifts, so on a phone this
   rule would open the tooltip on the first tap and never close it: measured,
   the element still matched :hover after three taps elsewhere. There, focus is
   the whole mechanism -- tap to open, tap again or anywhere else to close. */
@media (hover: hover) and (pointer: fine) {
  .stamp:hover .cost { opacity: 1; visibility: visible; }
}

.message { max-width: 100%; padding: 8px 12px; border: 1px solid transparent; border-radius: 14px; background: #232b3c; }
.message .who { display: block; margin-bottom: 3px; color: var(--accent); font-size: 0.7333rem; letter-spacing: .12em; font-weight: 700; }
.message .body { white-space: pre-wrap; overflow-wrap: anywhere; }
/* Rendered markdown. The body is pre-wrap for the plain-text case, so every
   block element has to reset that or parsed output inherits the source's
   newlines on top of its own spacing. */
.message .body > * { white-space: normal; }
.message .body > :first-child { margin-top: 0; }
.message .body > :last-child { margin-bottom: 0; }
.message .body p, .message .body ul, .message .body ol, .message .body blockquote { margin: 0 0 10px; }
.message .body ul, .message .body ol { padding-left: 22px; }
.message .body li { margin: 2px 0; }
.message .body h1, .message .body h2, .message .body h3 { margin: 14px 0 6px; font-size: 1.05em; line-height: 1.3; letter-spacing: 0; }
.message .body a { color: var(--accent); }
.message .body code { padding: 1px 5px; border-radius: 5px; background: #10131c; font: 0.88em/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; }
.message .body pre { margin: 0 0 10px; padding: 10px; overflow-x: auto; border-radius: 8px; background: #10131c; }
.message .body pre code { padding: 0; background: none; }
.message .body blockquote { padding-left: 10px; border-left: 2px solid var(--line); color: var(--dim); }
.message .body table { display: block; overflow-x: auto; border-collapse: collapse; margin: 0 0 10px; }
.message .body th, .message .body td { padding: 5px 9px; border: 1px solid var(--line); text-align: left; }
.message .body hr { border: 0; border-top: 1px solid var(--line); margin: 12px 0; }
.message .body img { max-width: 100%; border-radius: 8px; }

.message.user { background: var(--mine); }
.message.user .who { color: #d9e8ff; }
/* Asked for, not yet running: the same bubble, held back. */
.turn.waiting .message { opacity: 0.6; border: 1px dashed #d9e8ff; }
.message.error { border-color: #d98686; }
.message.error .who { color: var(--danger); }

/* A tool call is a footnote to the answer, not a message: narrower, quieter,
   and collapsed until someone wants the detail. */
.tool { align-self: stretch; max-width: 100%; border: 1px solid var(--line); border-radius: 12px; background: var(--tool); font-size: 0.8667rem; }
.tool[open] { background: #212a3b; }
.tool > summary { display: flex; align-items: center; gap: 8px; padding: 6px 10px; color: var(--dim); cursor: pointer; list-style: none; }
.tool > summary::-webkit-details-marker { display: none; }
.tool > summary::before { content: "▸"; color: var(--faint); transition: transform .12s; }
.tool[open] > summary::before { transform: rotate(90deg); }
.tool .name { color: var(--ink); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.8333rem; }
.tool .arg { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--faint); font-size: 0.8333rem; }
.tool.failed { border-color: #7d4a4a; }
.tool.failed .name { color: var(--danger); }
.tool .detail { padding: 0 10px 10px; }
.tool pre { margin: 0 0 8px; padding: 10px; max-height: 320px; overflow: auto; border-radius: 8px; background: #10131c; color: var(--dim); font: 0.8rem/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; white-space: pre-wrap; overflow-wrap: anywhere; }
.tool .label { margin: 0 0 4px; color: var(--faint); font-size: 0.7333rem; letter-spacing: .1em; font-weight: 700; }

.files { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.files a { display: block; text-decoration: none; }
.files img { display: block; max-width: 260px; max-height: 200px; border: 1px solid var(--line); border-radius: 8px; background: #0b0e15; }
.files .file { display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px; border: 1px solid var(--line); border-radius: 8px; color: var(--accent); font-size: 0.8333rem; }

.working { display: flex; align-items: center; gap: 6px; color: var(--faint); font-size: 0.8333rem; }
.working .dot, .live-loading .dot { width: 5px; height: 5px; border-radius: 50%; background: var(--faint); animation: pulse 1.2s infinite; }
.working .dot:nth-child(2), .live-loading .dot:nth-child(2) { animation-delay: .2s; }
.working .dot:nth-child(3), .live-loading .dot:nth-child(3) { animation-delay: .4s; }
.working span:last-child { margin-left: 4px; }
.working.stalled { color: var(--danger); }
.working.stalled span { margin-left: 0; }
@keyframes pulse { 0%, 60%, 100% { opacity: .25; } 30% { opacity: 1; } }

form { display: flex; flex-wrap: wrap; align-items: end; gap: 10px; border-top: 1px solid var(--line); padding-top: 10px; }
textarea { flex: 1; min-width: 0; max-height: 100vh; resize: none; overflow-y: auto; background: #10131c; color: var(--ink); border: 1px solid var(--line); border-radius: 10px; padding: 10px; font: inherit; }
textarea:focus-visible { outline: 2px solid var(--accent); outline-offset: -1px; }

@media (max-width: 520px) {
  /* The icons say it on their own once the window is this narrow. */
  .masthead { gap: 8px; }
  .app { padding: 8px; }
  .message { max-width: 95%; }
  /* The composer keeps its shape here: stacking it put a full-width button
     on a row of its own, which is exactly the height this was meant to save.
     Side by side rather than stacked, though -- a thumb needs more than 22px,
     and across the box there is room to give it without costing a line. */
  .composer-actions { flex-direction: column; gap: 6px; }
  .icon-button { width: 2.2667rem; height: 2.2667rem; }
  .chip button { width: auto; }
}
