/*!****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\
  !*** css ./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[14].oneOf[2].use[1]!./node_modules/next/dist/build/webpack/loaders/next-font-loader/index.js??ruleSet[1].rules[14].oneOf[2].use[2]!./node_modules/next/font/google/target.css?{"path":"app/layout.tsx","import":"Bricolage_Grotesque","arguments":[{"subsets":["latin"],"variable":"--font-display","weight":["500","600","700","800"],"display":"swap"}],"variableName":"display"} ***!
  \****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
/* vietnamese */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 500;
  font-stretch: 100%;
  font-display: swap;
  src: url(/_next/static/media/93a6e477e1480c92-s.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 500;
  font-stretch: 100%;
  font-display: swap;
  src: url(/_next/static/media/c7e0cf6c760983e7-s.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 500;
  font-stretch: 100%;
  font-display: swap;
  src: url(/_next/static/media/9d5a263311222317-s.p.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* vietnamese */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url(/_next/static/media/93a6e477e1480c92-s.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url(/_next/static/media/c7e0cf6c760983e7-s.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url(/_next/static/media/9d5a263311222317-s.p.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* vietnamese */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 700;
  font-stretch: 100%;
  font-display: swap;
  src: url(/_next/static/media/93a6e477e1480c92-s.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 700;
  font-stretch: 100%;
  font-display: swap;
  src: url(/_next/static/media/c7e0cf6c760983e7-s.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 700;
  font-stretch: 100%;
  font-display: swap;
  src: url(/_next/static/media/9d5a263311222317-s.p.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* vietnamese */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 800;
  font-stretch: 100%;
  font-display: swap;
  src: url(/_next/static/media/93a6e477e1480c92-s.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 800;
  font-stretch: 100%;
  font-display: swap;
  src: url(/_next/static/media/c7e0cf6c760983e7-s.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 800;
  font-stretch: 100%;
  font-display: swap;
  src: url(/_next/static/media/9d5a263311222317-s.p.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}@font-face {font-family: 'Bricolage Grotesque Fallback';src: local("Arial");ascent-override: 88.21%;descent-override: 25.61%;line-gap-override: 0.00%;size-adjust: 105.43%
}.__className_b227bf {font-family: 'Bricolage Grotesque', 'Bricolage Grotesque Fallback';font-style: normal
}.__variable_b227bf {--font-display: 'Bricolage Grotesque', 'Bricolage Grotesque Fallback'
}

/*!*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\
  !*** css ./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[14].oneOf[2].use[1]!./node_modules/next/dist/build/webpack/loaders/next-font-loader/index.js??ruleSet[1].rules[14].oneOf[2].use[2]!./node_modules/next/font/google/target.css?{"path":"app/layout.tsx","import":"Inter","arguments":[{"subsets":["latin"],"variable":"--font-body","display":"swap"}],"variableName":"body"} ***!
  \*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
/* cyrillic-ext */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/ba9851c3c22cd980-s.woff2) format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/21350d82a1f187e9-s.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/c5fe6dc8356a8c31-s.woff2) format('woff2');
  unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/19cfc7226ec3afaa-s.woff2) format('woff2');
  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/df0a9ae256c0569c-s.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/8e9860b6e62d6359-s.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/_next/static/media/e4af272ccee01ff0-s.p.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}@font-face {font-family: 'Inter Fallback';src: local("Arial");ascent-override: 90.44%;descent-override: 22.52%;line-gap-override: 0.00%;size-adjust: 107.12%
}.__className_485876 {font-family: 'Inter', 'Inter Fallback';font-style: normal
}.__variable_485876 {--font-body: 'Inter', 'Inter Fallback'
}

/*!*************************************************************************************************************************************************************************************************************************************************************!*\
  !*** css ./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[14].oneOf[10].use[2]!./node_modules/next/dist/build/webpack/loaders/postcss-loader/src/index.js??ruleSet[1].rules[14].oneOf[10].use[3]!./app/globals.css ***!
  \*************************************************************************************************************************************************************************************************************************************************************/
:root {
  --ivory: #fffdf8;
  --paper: #ffffff;
  --ink: #14201b;
  --jade: #3e9c7c;
  --muted: #69706c;
  --line: #e7e5df;
  --line-strong: #d8d8d1;
  --pandan: #176b54;
  --pandan-deep: #115441;
  --pandan-pale: #e8f4ee;
  --mango: #f4c95d;
  --mango-ink: #9a6f1a;
  --mango-pale: #fff7d9;
  --coral: #d85f45;
  --shadow: 0 16px 46px rgb(39 52 46 / 8%);
  --sidebar: 272px;
  --display: var(--font-display), ui-sans-serif, system-ui, sans-serif;
  font-family: var(--font-body), Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  color: var(--ink);
  background: var(--ivory);
  font-synthesis: none;
}

* { box-sizing: border-box; }
html, body { width: 100%; height: 100%; margin: 0; }
body { background: var(--ivory); color: var(--ink); -webkit-font-smoothing: antialiased; }
button, textarea, select { font: inherit; color: inherit; }
button, select { -webkit-tap-highlight-color: transparent; }
button { border: 0; }
button:focus-visible, a:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 3px solid rgb(23 107 84 / 24%);
  outline-offset: 2px;
}
a { color: var(--pandan); text-underline-offset: 3px; }
.sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }

.app-shell { position: fixed; inset: 0; display: flex; width: 100%; overflow: hidden; }
.chat-panel { min-width: 0; flex: 1 1; display: flex; flex-direction: column; position: relative; background: var(--ivory); isolation: isolate; }
.topbar {
  height: 64px; flex: 0 0 64px; display: flex; align-items: center; justify-content: space-between;
  padding: 0 18px; background: linear-gradient(to bottom, rgb(255 253 248 / 78%), rgb(255 253 248 / 0%)); z-index: 10;
}
.topbar-brand { display: none; padding: 4px 6px; margin-left: -6px; border-radius: 9px; background: transparent; cursor: pointer; }
.topbar-actions { display: flex; align-items: center; gap: 8px; }
.icon-button { width: 42px; height: 42px; border-radius: 12px; background: transparent; display: grid; place-items: center; cursor: pointer; }
.icon-button svg { width: 20px; height: 20px; }
.icon-button:hover { background: var(--pandan-pale); }
.language-select { height: 38px; display: flex; align-items: center; gap: 2px; border: 1px solid var(--line); border-radius: 999px; padding: 0 10px 0 13px; background: var(--paper); cursor: pointer; }
.language-select select { border: 0; -webkit-appearance: none; -moz-appearance: none; appearance: none; outline: 0; background: transparent; font-size: 13px; font-weight: 670; cursor: pointer; }
.language-select svg { color: var(--muted); pointer-events: none; }

.thread { position: relative; z-index: 1; min-height: 0; flex: 1 1; overflow-y: auto; overscroll-behavior: contain; scrollbar-gutter: stable; position: relative; }
.thread-inner { width: min(100%, 820px); min-height: 100%; margin: 0 auto; padding: 24px 24px 10px; display: flex; flex-direction: column; }
.thread-inner.has-messages { justify-content: flex-start; padding-top: 36px; padding-bottom: 28px; }
.empty-chat { width: min(100%, 620px); flex: 1 1; display: flex; flex-direction: column; margin: 0 auto; animation: rise .4s ease both; }

/* Holds the fold on its own. The footer that follows is therefore always below
   it — a scroll away, never competing with the question. */
.empty-stage { flex: 1 1; min-height: 0; display: flex; flex-direction: column; justify-content: center; padding-bottom: 96px; text-align: center; }
.empty-stage h1 { margin: 0; font-family: var(--display); font-weight: 600; font-size: clamp(30px, 5.2vw, 46px); line-height: 1.04; letter-spacing: -.045em; }
.empty-stage p { margin: 14px auto 0; max-width: 62ch; color: var(--muted); line-height: 1.55; font-size: 15px; text-wrap: balance; }

/* Text, not cards. Four ways in, weighing about as much as one sentence. */
.quick-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 30px; }
.quick-actions button { min-height: 38px; display: inline-flex; align-items: center; gap: 7px; padding: 0 15px 0 13px; border: 1px solid rgb(23 107 84 / 16%); border-radius: 999px; background: rgb(255 255 255 / 55%); color: var(--pandan-deep); font-size: 13.5px; font-weight: 550; cursor: pointer; transition: background .16s ease, border-color .16s ease, transform .16s ease; }
.quick-actions button:hover { background: var(--paper); border-color: rgb(23 107 84 / 34%); transform: translateY(-1px); }
.quick-actions svg { flex: 0 0 auto; color: var(--pandan); opacity: .7; }
.quick-actions button:hover svg { opacity: 1; }

.message { display: grid; grid-template-columns: 34px minmax(0, 1fr); grid-gap: 12px; gap: 12px; margin-bottom: 27px; animation: message-in .22s ease both; }
.message.user { display: flex; justify-content: flex-end; }
.assistant-mark { margin-top: 1px; color: var(--pandan); }
.message-main { min-width: 0; max-width: 100%; }
.message.user .message-main { max-width: min(78%, 600px); }
.user-bubble { padding: 11px 15px; border-radius: 18px 18px 5px 18px; background: var(--pandan-pale); color: #183d31; line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere; }
.assistant-content { max-width: 72ch; font-size: 15px; line-height: 1.72; overflow-wrap: anywhere; }
.assistant-content.pending-answer { min-height: 32px; }

.pending-answer-status { display: block; width: 1px; height: 32px; }
.assistant-content > :first-child { margin-top: 0; }
.assistant-content > :last-child { margin-bottom: 0; }
.assistant-content h1, .assistant-content h2, .assistant-content h3 { letter-spacing: -.025em; line-height: 1.25; margin: 1.35em 0 .55em; }
.assistant-content h1 { font-size: 22px; }.assistant-content h2 { font-size: 18px; }.assistant-content h3 { font-size: 16px; }
.assistant-content p { margin: 0 0 .9em; }
.assistant-content ul, .assistant-content ol { padding-left: 1.35em; margin: .4em 0 1em; }
.assistant-content li { margin: .24em 0; padding-left: .16em; }
.assistant-content blockquote { margin: 1em 0; padding: 3px 0 3px 14px; border-left: 3px solid var(--mango); color: #515854; }
.assistant-content code { padding: 2px 5px; background: #f0f2ef; border-radius: 5px; font-size: .9em; }
.assistant-content pre { max-width: 100%; overflow-x: auto; padding: 15px; background: #1f2824; color: #f5f7f6; border-radius: 13px; line-height: 1.55; }
.assistant-content pre code { padding: 0; background: transparent; color: inherit; }
/* ── tables in an answer ───────────────────────────────────────────────────
   Gigi reaches for a table whenever it is comparing things, so this is read
   often. The header used to sit on #f5f6f3 — a hair off the page colour, so it
   did not read as a header at all, and the whole thing dissolved into the
   background it was sitting on. It now has the brand's own pale pandan behind
   it and a real rule under it. */
.table-scroll {
  max-width: 100%; overflow-x: auto; margin: 1.15em 0;
  border: 1px solid var(--line-strong); border-radius: 13px;
  background: var(--paper);
}
.assistant-content table { width: 100%; border-collapse: collapse; min-width: 360px; font-size: 13.5px; }

.assistant-content th, .assistant-content td {
  padding: 11px 14px; text-align: left; vertical-align: top;
  border-bottom: 1px solid var(--line);
  /* NOT `anywhere`, which .assistant-content sets for long URLs in prose. In a
     narrow table column it broke ordinary words down the middle — "TomaListo"
     came out as "TomaList" / "o". `break-word` only breaks a word that cannot
     fit on a line of its own, so the column widens instead. */
  overflow-wrap: break-word;
}

.assistant-content thead th {
  background: var(--pandan-pale);
  color: var(--pandan-deep);
  font-size: 11.5px; font-weight: 760; letter-spacing: .05em; text-transform: uppercase;
  border-bottom: 1px solid rgb(14 100 78 / 20%);
  white-space: nowrap;
}

/* Banding rather than a line per row: at this density the stripes do the
   scanning work and the rules can stay quiet. */
.assistant-content tbody tr:nth-child(even) { background: rgb(14 100 78 / 3.5%); }
.assistant-content tbody tr:last-child td { border-bottom: 0; }

/* The first column is nearly always the thing being named. */
.assistant-content tbody td:first-child { font-weight: 640; color: var(--ink); }
.assistant-content tbody td { color: #3c4642; }
.sent-attachments { display: flex; gap: 6px; justify-content: flex-end; flex-wrap: wrap; margin-bottom: 7px; }
.sent-attachments span { display: inline-flex; align-items: center; gap: 6px; border: 1px solid #cee1d8; background: white; border-radius: 10px; padding: 6px 9px; color: #43534d; font-size: 11px; max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.message-actions { display: flex; gap: 3px; margin-top: 8px; }
.message-actions button { display: inline-flex; align-items: center; gap: 5px; min-height: 32px; padding: 0 8px; background: transparent; border-radius: 8px; color: var(--muted); font-size: 11px; cursor: pointer; }
.message-actions button:hover { background: #f0f1ed; color: var(--ink); }
.message-actions button:disabled { opacity: .45; cursor: default; }
.trust-note { max-width: 640px; margin-top: 12px; padding: 9px 11px; display: flex; gap: 8px; align-items: flex-start; border-left: 3px solid var(--mango); background: var(--mango-pale); color: #5a4c20; border-radius: 5px 10px 10px 5px; font-size: 12px; line-height: 1.45; }
.trust-note svg { flex: 0 0 auto; margin-top: 1px; }
.demo-label { display: inline-block; margin-top: 9px; padding: 3px 7px; border-radius: 6px; background: #f0f1ee; color: var(--muted); font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; }
.sources { margin-top: 18px; max-width: 660px; }
.sources-title { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; font-size: 12px; font-weight: 720; }
.source-grid { display: grid; grid-template-columns: 1fr 1fr; grid-gap: 7px; gap: 7px; }
.source-card { min-width: 0; display: flex; flex-direction: column; gap: 4px; padding: 11px 12px; border: 1px solid var(--line); border-radius: 12px; color: var(--ink); text-decoration: none; background: var(--paper); }
.source-card:hover { border-color: #b8d5c8; box-shadow: 0 8px 24px rgb(39 52 46 / 7%); }
.source-name { font-size: 12px; font-weight: 660; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.source-domain { color: var(--muted); font-size: 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.jump-latest { position: -webkit-sticky; position: sticky; bottom: 12px; left: 50%; transform: translateX(-50%); min-height: 36px; padding: 0 13px; border: 1px solid var(--line); border-radius: 999px; background: var(--paper); box-shadow: 0 8px 28px rgb(39 52 46 / 12%); color: var(--muted); font-size: 11px; cursor: pointer; }

.composer-wrap { position: relative; z-index: 1; flex: 0 0 auto; width: min(calc(100% - 40px), 780px); margin: 0 auto; padding-bottom: max(9px, env(safe-area-inset-bottom)); position: relative; }
.composer { min-height: 58px; display: flex; align-items: flex-end; gap: 7px; padding: 8px; border: 1px solid var(--line-strong); border-radius: 21px; background: var(--paper); box-shadow: 0 12px 40px rgb(39 52 46 / 9%); transition: border-color .15s, box-shadow .15s; }
.composer:focus-within { border-color: #8ab9a6; box-shadow: 0 12px 42px rgb(23 107 84 / 12%); }
.composer textarea { min-width: 0; flex: 1 1; resize: none; border: 0; outline: 0; background: transparent; padding: 9px 4px 8px; line-height: 1.45; font-size: 16px; max-height: 144px; }
.composer textarea::placeholder { color: #8a918d; }
.composer textarea:disabled { opacity: .7; }
.attach-button, .send-button { flex: 0 0 42px; width: 42px; height: 42px; border-radius: 14px; display: grid; place-items: center; cursor: pointer; }
.attach-button { background: transparent; color: var(--muted); }
.attach-button:hover { color: var(--pandan); background: var(--pandan-pale); }
.send-button { background: var(--pandan); color: white; }
.send-button:hover { background: var(--pandan-deep); }.send-button:disabled { background: #d8dbd8; color: #8e9490; cursor: default; }
.send-button.stop { background: var(--ink); }
.composer-note { margin: 6px 0 0; text-align: center; color: #818783; font-size: 10px; }
.attachment-strip { display: flex; gap: 8px; overflow-x: auto; padding: 0 2px 8px; }
.attachment { min-width: 190px; max-width: 250px; height: 56px; display: flex; align-items: center; gap: 9px; padding: 7px; border: 1px solid var(--line); border-radius: 13px; background: var(--paper); }
.attachment img, .file-thumb { width: 40px; height: 40px; flex: 0 0 40px; border-radius: 9px; object-fit: cover; background: var(--pandan-pale); display: grid; place-items: center; color: var(--pandan); }
.attachment-name { min-width: 0; flex: 1 1; display: flex; flex-direction: column; gap: 2px; }
.attachment-name strong { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: 11px; }.attachment-name small { color: var(--muted); font-size: 9px; }
.attachment > button { width: 28px; height: 28px; flex: 0 0 28px; display: grid; place-items: center; border-radius: 8px; background: transparent; cursor: pointer; color: var(--muted); }
.attachment > button:hover { background: #f0f1ed; color: var(--ink); }
.composer-error { margin: 0 4px 7px; color: #8b321f; font-size: 12px; }
.composer-context { display: flex; align-items: center; margin: 0 4px 7px; }
.composer-context span { padding: 5px 9px; border-radius: 8px; background: var(--pandan-pale); color: var(--pandan-deep); font-size: 10px; font-weight: 680; }
.intent-chips { display: flex; gap: 7px; overflow-x: auto; padding: 2px 2px 9px; scrollbar-width: none; }
.intent-chips::-webkit-scrollbar { display: none; }
.intent-chips button { flex: 0 0 auto; min-height: 36px; padding: 0 12px; border: 1px solid var(--line); border-radius: 999px; background: var(--paper); font-size: 12px; cursor: pointer; }
.intent-chips button:hover { border-color: #9fc5b5; background: var(--pandan-pale); }

.sidebar { width: var(--sidebar); flex: 0 0 var(--sidebar); display: flex; flex-direction: column; background: #f7f7f3; border-right: 1px solid var(--line); padding: 14px 10px 11px; z-index: 30; }
.sidebar-head { height: 46px; display: flex; align-items: center; justify-content: space-between; padding: 0 4px; }
.sidebar-brand { display: flex; align-items: center; gap: 9px; padding: 5px 7px; margin-left: -7px; border-radius: 10px; background: transparent; font-size: 15px; cursor: pointer; text-align: left; }
.close-drawer { display: none; }
/* No fill, but still a hover state — and one that means something.
 *
 * A background here competed with the history rows an inch below, which use one
 * to say "this is the chat you are in": the same tint doing two different jobs
 * a finger's width apart. So the feedback is the icon instead.
 *
 * THE PLUS TURNS A QUARTER AND LANDS EXACTLY WHERE IT STARTED. A plus is
 * rotationally symmetric at 90°, so the whole gesture resolves to no change at
 * all — which is what a new chat is. Nothing is added and nothing is lost; you
 * simply get the blank page back. Stopping at 45° would draw an ×, and an × on
 * this button would promise to close something.
 *
 * The label deepens at the same time, so the state does not depend on the
 * motion. Under prefers-reduced-motion the global rule above collapses every
 * transition to nothing — and because a plus at 90° is the same plus, that
 * leaves no snap to flinch at. The gesture simply is not there, and the colour
 * still says the button is live. */
.new-chat { height: 40px; margin: 10px 0 14px; display: flex; align-items: center; gap: 8px; padding: 0 12px; border: 0; border-radius: 10px; background: transparent; color: var(--pandan-deep); cursor: pointer; font-weight: 660; font-size: 12.5px; transition: color .14s ease; }
.new-chat svg { transition: transform .34s cubic-bezier(.34, 1.42, .64, 1); }
.new-chat:hover { color: #0a3f30; }
/* Overshoots a few degrees and settles back, which is what makes a quarter turn
   read as a turn rather than a jump. */
.new-chat:hover svg { transform: rotate(90deg); }
.history-label { margin: 8px 10px 7px; color: var(--muted); font-size: 9.5px; font-weight: 720; text-transform: uppercase; letter-spacing: .07em; }
.history-list { min-height: 0; flex: 1 1; overflow-y: auto; }
.history-row { min-height: 38px; position: relative; display: flex; align-items: center; border-radius: 9px; }
.history-row.active { background: #e7e9e3; }.history-row:hover { background: #ecece7; }
.history-open { min-width: 0; flex: 1 1; height: 38px; display: flex; align-items: center; gap: 8px; padding: 0 8px 0 9px; text-align: left; background: transparent; cursor: pointer; }
.history-open svg { flex: 0 0 auto; color: var(--muted); }.history-open span { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: 12px; }
.history-more { width: 34px; height: 34px; display: grid; place-items: center; border-radius: 8px; background: transparent; color: var(--muted); cursor: pointer; opacity: 0; }
.history-row:hover .history-more, .history-more:focus-visible { opacity: 1; }
.delete-chat { position: absolute; top: 37px; right: 2px; z-index: 4; min-width: 112px; height: 38px; display: flex; align-items: center; gap: 7px; padding: 0 11px; border: 1px solid var(--line); border-radius: 10px; background: var(--paper); color: #8b321f; box-shadow: var(--shadow); cursor: pointer; font-size: 12px; }
.history-empty { margin: 7px 10px; max-width: 22ch; color: var(--muted); font-size: 10.5px; line-height: 1.5; }
.sidebar-footer-links { display: flex; flex-wrap: wrap; gap: 9px 16px; margin: 12px 6px 0; padding: 13px 4px 3px; border-top: 1px solid var(--line); }
.sidebar-footer-links a { color: var(--muted); font-size: 10.5px; text-decoration: none; }
.sidebar-footer-links a:hover { color: var(--pandan); }
.drawer-scrim { display: none; }
.menu-button { visibility: hidden; }

.info-page { width: min(calc(100% - 40px), 680px); margin: 0 auto; min-height: 100vh; min-height: 100dvh; padding: 13vh 0 60px; }
.info-brand { display: inline-flex; align-items: center; gap: 11px; margin-bottom: 48px; text-decoration: none; font-weight: 700; }
.info-brand .wordmark { width: 164px; }
.info-page h1 { font-size: clamp(34px, 8vw, 54px); margin: 0 0 22px; letter-spacing: -.05em; }
.info-page p { max-width: 62ch; color: #444b47; line-height: 1.8; font-size: 17px; }
.info-page > a:last-child { display: inline-block; margin-top: 20px; }

.feedback-page {
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 44px 20px;
  background:
    radial-gradient(62% 60% at 14% 18%, #dcefe4 0%, transparent 66%),
    radial-gradient(58% 52% at 86% 26%, #fae8b6 0%, transparent 64%),
    var(--ivory);
}
.feedback-card { position: relative; width: min(100%, 620px); padding: clamp(26px, 6vw, 48px); border: 1px solid rgb(14 100 78 / 12%); border-radius: 26px; background: rgb(255 253 248 / 90%); box-shadow: 0 24px 80px rgb(41 57 49 / 11%); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); }
/* Sits in the card's own corner, clear of the wordmark. 44px because it is
   the first thing a thumb reaches for on a phone. */
.feedback-close {
  position: absolute; top: clamp(14px, 3vw, 22px); right: clamp(14px, 3vw, 22px);
  width: 44px; height: 44px; display: grid; place-items: center;
  border-radius: 12px; background: transparent; color: var(--muted); cursor: pointer;
  transition: background .16s ease, color .16s ease;
}
.feedback-close:hover { background: var(--pandan-pale); color: var(--pandan-deep); }

.feedback-brand { display: inline-flex; align-items: center; gap: 10px; color: var(--pandan); text-decoration: none; }
.feedback-brand .wordmark { width: 154px; }
.feedback-heading { margin: 42px 0 30px; }
.feedback-heading > p { margin: 0 0 9px; color: var(--pandan); font-size: 11px; font-weight: 760; letter-spacing: .09em; text-transform: uppercase; }
.feedback-heading h1 { margin: 0; max-width: 13ch; font-family: var(--display); font-size: clamp(32px, 7vw, 48px); font-weight: 620; line-height: 1.02; letter-spacing: -.045em; }
.feedback-heading > span { display: block; margin-top: 13px; color: var(--muted); font-size: 14px; }
.feedback-form { display: grid; grid-gap: 19px; gap: 19px; }
.feedback-form label { display: grid; grid-gap: 8px; gap: 8px; color: #26322d; font-size: 12px; font-weight: 690; }
.feedback-form label > span { color: var(--muted); font-weight: 500; }
.feedback-form input, .feedback-form select, .feedback-form textarea { width: 100%; border: 1px solid #d9ded9; border-radius: 12px; background: #fffefa; color: var(--ink); font: inherit; font-size: 14px; font-weight: 450; outline: 0; transition: border-color .16s ease, box-shadow .16s ease; }
.feedback-form input, .feedback-form select { height: 46px; padding: 0 13px; }
.feedback-form textarea { resize: vertical; min-height: 150px; padding: 13px; line-height: 1.55; }
.feedback-form input:focus-visible, .feedback-form select:focus-visible, .feedback-form textarea:focus-visible { border-color: var(--pandan); box-shadow: 0 0 0 3px rgb(14 100 78 / 12%); }
.feedback-honeypot { position: absolute !important; left: -10000px !important; width: 1px !important; height: 1px !important; overflow: hidden !important; }
.feedback-error { margin: -3px 0 0; color: #8b321f; font-size: 12px; }
.feedback-submit { min-height: 48px; display: flex; align-items: center; justify-content: center; gap: 8px; border-radius: 12px; background: var(--pandan); color: white; font-size: 13px; font-weight: 720; cursor: pointer; }
.feedback-submit:hover { background: var(--pandan-deep); }
.feedback-submit:disabled { opacity: .62; cursor: wait; }
.feedback-success { min-height: 280px; display: flex; align-items: flex-start; gap: 16px; padding: 26px; border-radius: 18px; background: var(--pandan-pale); color: var(--pandan-deep); }
.feedback-success > svg { width: 30px; height: 30px; flex: 0 0 auto; }
.feedback-success h2 { margin: 1px 0 7px; font-size: 22px; letter-spacing: -.025em; }
.feedback-success p { margin: 0; color: #456057; }
.feedback-success button { margin-top: 24px; padding: 10px 13px; border: 1px solid rgb(14 100 78 / 22%); border-radius: 10px; background: rgb(255 255 255 / 58%); color: var(--pandan-deep); font-size: 12px; font-weight: 680; cursor: pointer; }

@keyframes rise { from { opacity: 0; transform: translateY(7px); } }
@keyframes message-in { from { opacity: 0; transform: translateY(5px); } }

@media (max-width: 860px) {
  .sidebar { position: fixed; inset: 0 auto 0 0; width: min(84vw, 310px); transform: translateX(-102%); transition: transform .22s ease; box-shadow: 20px 0 50px rgb(22 30 26 / 18%); }
  .sidebar.open { transform: translateX(0); }
  .close-drawer { display: grid; }
  .drawer-scrim { display: block; position: fixed; z-index: 29; inset: 0; width: 100%; height: 100%; background: rgb(23 28 25 / 35%); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); }
  .menu-button { visibility: visible; }
  .topbar-brand { display: flex; align-items: center; }
  .history-more { opacity: 1; }
  .thread-inner { padding-left: 18px; padding-right: 18px; }
}

@media (max-width: 600px) {
  .topbar { height: 57px; flex-basis: 57px; padding: 0 8px; }
  .topbar-brand { position: absolute; left: 55px; }
  .language-select { height: 36px; padding: 0 8px 0 11px; }
  .thread-inner { padding: 16px 15px 6px; }
  .thread-inner.has-messages { padding-top: 24px; padding-bottom: 18px; }
  .empty-stage h1 { font-size: 29px; }
  .empty-stage p { font-size: 13.5px; max-width: 34ch; margin-top: 12px; }
  .quick-actions { margin-top: 24px; grid-gap: 7px; gap: 7px; display: grid; grid-template-columns: 1fr 1fr; }
  .quick-actions button { min-height: 42px; font-size: 13px; padding: 0 12px; gap: 6px; justify-content: center; }
  .composer-wrap { width: calc(100% - 20px); }
  .composer { border-radius: 19px; min-height: 55px; padding: 6px; }
  .attach-button, .send-button { width: 42px; height: 42px; flex-basis: 42px; }
  .composer-note { margin-top: 5px; }
  .message { grid-template-columns: 30px minmax(0, 1fr); gap: 9px; margin-bottom: 23px; }
  .assistant-mark { width: 29px !important; height: 29px !important; }
  .assistant-content { font-size: 14.5px; line-height: 1.68; }
  .message.user .message-main { max-width: 86%; }
  .user-bubble { font-size: 14px; padding: 10px 13px; }
  .source-grid { grid-template-columns: 1fr; }
  .message-actions button { min-height: 38px; }
  .intent-chips button { min-height: 38px; }
  .feedback-page { padding: 0; place-items: stretch; }
  .feedback-card { min-height: 100vh; min-height: 100dvh; border: 0; border-radius: 0; padding: 25px 19px 36px; }
  .feedback-heading { margin: 34px 0 26px; }
}

@media (max-width: 350px) {
  .topbar-brand .wordmark { width: 81px; }
  .language-select select { font-size: 12px; }
  .empty-stage h1 { font-size: 25px; }
  .empty-stage p { max-width: 30ch; }
  .quick-actions button { padding: 0 10px; font-size: 12.5px; gap: 5px; }
}

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

/* ── the vector identity ───────────────────────────────────────────────────
   One geometry everywhere: filled rounded letter outlines, the smiling G,
   and the mango chat bubble. No font load can change the proportions. */
.wordmark { width: 137px; display: inline-flex; color: var(--pandan); line-height: 0; white-space: nowrap; }
.brand-wordmark-svg { width: 100%; height: auto; display: block; overflow: visible; }
.gigi-mark { flex: 0 0 auto; display: block; color: var(--pandan); line-height: 0; }
.gigi-mark-svg { width: 100%; height: 100%; display: block; overflow: visible; }
.sidebar-brand .wordmark { width: 135px; }
.topbar-brand .wordmark { width: 95px; }

/* The smile is not in this list. It is one shape with the G's crossbar in the
   artwork, so nothing is allowed to move or redraw it. */
.logo-bubble, .logo-eye { transform-box: fill-box; transform-origin: center; }

/* Idle: the bubble is the only part of the logotype that is about speech, so
   it is the part that thinks. A rise and a fade, no bounce. */
.is-animated .logo-bubble { animation: bubble-breathe 2.4s cubic-bezier(.37, 0, .28, 1) infinite; }

/* One eye, not two. Both eyes closing is a blink and reads as idle; one eye is
   a wink and reads as a character who noticed you. */
.is-animated .logo-eye-right { animation: logo-wink 4.6s cubic-bezier(.3, 0, .2, 1) infinite; }

/* At avatar size the bubble is about five pixels across, so the small mark
   carries its own signal — opacity, which survives any size. */
.gigi-mark-svg.is-animated { animation: mark-breathe 2.4s ease-in-out infinite; }

.opening-loader {
  position: fixed; inset: 0; z-index: 100; display: grid; place-items: center;
  background:
    radial-gradient(52% 55% at 19% 22%, #dcefe4 0%, transparent 68%),
    radial-gradient(52% 50% at 82% 30%, #f8e8b9 0%, transparent 65%),
    var(--ivory);
}
.opening-loader.app-opening.is-leaving { animation: opening-veil 420ms ease both; }
.opening-logo { position: relative; width: min(374px, 56vw); line-height: 0; }
.opening-wordmark { width: 100%; color: var(--pandan); }

/* The shine. A narrow band of light, clipped to the letterforms by the mask,
   sliding across a mark that never changes its own opacity. */
.opening-shine {
  position: absolute; inset: 0; width: 100%;
  opacity: .62; pointer-events: none;
  -webkit-mask-image: linear-gradient(105deg, transparent 42%, #000 50%, transparent 58%);
  mask-image: linear-gradient(105deg, transparent 42%, #000 50%, transparent 58%);
  -webkit-mask-size: 320% 100%; mask-size: 320% 100%;
  -webkit-mask-position: 130% 0; mask-position: 130% 0;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
}

/* Opening the app, in order: the name arrives, a light passes over it, the
   bubble pops, Gigi winks, the veil lifts. Every one of them finishes — the
   old opening looped a 2.4s sheen inside a 920ms screen, so it could only ever
   be seen being cut off. */
.app-opening .opening-logo { animation: wordmark-in 460ms cubic-bezier(.2, .9, .28, 1) both; }
.app-opening .opening-shine { animation: logo-shine 900ms cubic-bezier(.4, 0, .2, 1) 300ms both; }
.app-opening .logo-bubble { animation: bubble-pop 640ms cubic-bezier(.34, 1.4, .5, 1) 540ms both; }
.app-opening .logo-eye-right { animation: opening-wink 440ms cubic-bezier(.3, 0, .2, 1) 940ms both; }
.app-opening .logo-eye-left { animation: none; }

/* Waiting on a route, where nobody knows how long it will be. A loop is the
   honest shape for an unknown wait, and nothing removes this mid-sweep. */
.route-loading .opening-shine { animation: logo-shine 1.9s cubic-bezier(.4, 0, .2, 1) infinite; }

/* Hovering the name winks, rather than lighting a chip behind it. A tinted
   rectangle says "button", which is the least interesting thing about the one
   element on the page with a face.

   The opening's light sweep and bubble-pop were here too, and came out: three
   things firing at once on a 137px logo is a flourish, and only one of them is
   the character. No delay either — the wink was third in a sequence during the
   boot, and there is no sequence left for it to wait its turn in. */
.sidebar-brand:hover .logo-eye-right,
.sidebar-brand:focus-visible .logo-eye-right,
.topbar-brand:hover .logo-eye-right,
.topbar-brand:focus-visible .logo-eye-right { animation: opening-wink 400ms cubic-bezier(.3, 0, .2, 1) both; }

@keyframes bubble-breathe {
  0%, 100% { transform: translateY(1px) scale(.94); opacity: .5; }
  50% { transform: translateY(-4px) scale(1.06); opacity: 1; }
}
/* Shut, then a little overshoot on the way back open — the part that makes it
   read as deliberate rather than a rendering glitch. */
@keyframes logo-wink {
  0%, 86%, 100% { transform: scaleY(1); }
  90% { transform: scaleY(.08); }
  94% { transform: scaleY(1.14); }
}
@keyframes opening-wink {
  0%, 100% { transform: scaleY(1); }
  38% { transform: scaleY(.08); }
  72% { transform: scaleY(1.16); }
}
@keyframes wordmark-in {
  from { transform: translateY(12px) scale(.955); }
  to { transform: none; }
}
@keyframes bubble-pop {
  0% { transform: translateY(8px) scale(.3) rotate(-16deg); }
  100% { transform: none; }
}
@keyframes logo-shine {
  from { -webkit-mask-position: 130% 0; mask-position: 130% 0; }
  to { -webkit-mask-position: -30% 0; mask-position: -30% 0; }
}
@keyframes mark-breathe {
  0%, 100% { opacity: .74; }
  50% { opacity: 1; }
}
@keyframes opening-veil {
  from { opacity: 1; }
  to { opacity: 0; }
}

/* ── the backdrop ──────────────────────────────────────────────────────────
   The CSS gradient is the floor, not decoration: it is what a reader sees if
   WebGL is unavailable or the shader chunk is still in flight, and it is close
   enough to the shader's resting state that the swap is not a flash. */
.mesh-backdrop {
  position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none;
  background:
    radial-gradient(60% 55% at 18% 22%, #dcf0e4 0%, transparent 62%),
    radial-gradient(55% 50% at 82% 30%, #f7e6b6 0%, transparent 60%),
    radial-gradient(70% 60% at 50% 92%, #cfe9dc 0%, transparent 66%),
    var(--ivory);
  transition: opacity .6s ease;
}
.mesh-backdrop .mesh-canvas { position: absolute; inset: 0; width: 100%; height: 100%; }

/* Ink wins over atmosphere. The scrim lifts the middle of the page, where the
   headline and every answer are read. */
.mesh-backdrop::after {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(96% 62% at 50% 44%, rgb(255 253 248 / 84%) 0%, rgb(255 253 248 / 42%) 52%, rgb(255 253 248 / 0%) 100%);
}

/* Reading a reply, not being welcomed.
   The gradient is the welcome screen's job. Once there is a conversation on
   top of it, it is background in the literal sense — paper, not atmosphere —
   so it drops to a tint that reads as a warm ground rather than a picture
   competing with the words. The motion has already slowed in the component. */
.mesh-backdrop.quiet { opacity: .06; }

/* The scrim's job on the welcome screen is to lift the middle so the headline
   reads; it deliberately lets the corners keep their colour. In a conversation
   there is no headline and the text runs the whole height, so it flattens to an
   even wash instead — otherwise the corners stay the most saturated part of a
   screen that is supposed to be paper. */
.mesh-backdrop.quiet::after { background: rgb(255 253 248 / 45%); }

@media (prefers-reduced-motion: reduce) {
  .mesh-backdrop { transition: none; }
  .is-animated .logo-bubble,
  .is-animated .logo-eye-right,
  .opening-shine,
  .app-opening .opening-logo,
  .app-opening .logo-bubble,
  .app-opening .logo-eye-right,
  .route-loading .opening-shine,
  .sidebar-brand:hover .logo-eye-right,
  .topbar-brand:hover .logo-eye-right,
  .gigi-mark-svg.is-animated { animation: none !important; transform: none; opacity: 1; }
  .opening-shine { display: none; }
  /* Motion was the entire hover state, so where motion is off the chip is the
     only affordance left — it comes back rather than leaving a dead logo. */
  .sidebar-brand:hover, .topbar-brand:hover { background: rgb(23 107 84 / 7%); }
  .opening-loader.app-opening.is-leaving { opacity: 0; }
}


/* ── the greeting, being written ───────────────────────────────────────────
   Layout first: the hidden copy holds the finished sentence's height so a line
   breaking mid-type cannot shove the hero down. The typed copy sits over it. */
/* One flow, no overlay. Every character occupies its final space from the
   start, so the sentence wraps once — where it will end up — and nothing is
   positioned on top of anything else. */
.typed { display: block; }
.typed-line { display: block; }
.typed-word { display: inline-block; white-space: pre; }

/* Each character lands: low, blurred, and slightly small, resolving over
   240ms. Because they appear in sequence the tail of the sentence is still
   settling while the head is already sharp. */
.typed-char {
  position: relative;
  display: inline-block;
  white-space: pre;
  /* Holding its space while invisible is what keeps the line from reflowing. */
  visibility: hidden;
}
.typed-char.is-in {
  visibility: visible;
  animation: char-land 240ms cubic-bezier(.22, .9, .3, 1) backwards;
}

/* The caret rides the last revealed character, so it moves and wraps with the
   write head without being positioned by hand. */
.typed-char.is-head::after {
  content: ""; position: absolute; left: 100%; top: .1em;
  width: .055em; height: .8em; border-radius: 2px;
  background: var(--mango);
  animation: caret-blink 1s steps(1, end) infinite;
}
.typed.is-done .typed-char.is-head::after { animation: caret-leave 420ms ease forwards; }
@keyframes char-land {
  from { opacity: 0; transform: translateY(.36em) scale(.92); filter: blur(5px); }
  to { opacity: 1; transform: none; filter: blur(0); }
}

@keyframes caret-blink { 0%, 55% { opacity: 1; } 56%, 100% { opacity: 0; } }
/* The sentence is finished; the caret has no more work to do. */
@keyframes caret-leave { to { opacity: 0; transform: scaleY(.4); } }

/* The rest of the hero follows the sentence, staggered. */
.empty-stage p,
.empty-stage .quick-actions button { opacity: 0; }
.empty-stage.is-written p,
.empty-stage.is-written .quick-actions button {
  opacity: 1;
  animation: hero-follow 420ms cubic-bezier(.22, .9, .3, 1) backwards;
}
.empty-stage.is-written .quick-actions button:nth-child(1) { animation-delay: 90ms; }
.empty-stage.is-written .quick-actions button:nth-child(2) { animation-delay: 145ms; }
.empty-stage.is-written .quick-actions button:nth-child(3) { animation-delay: 200ms; }
.empty-stage.is-written .quick-actions button:nth-child(4) { animation-delay: 255ms; }
@keyframes hero-follow {
  from { opacity: 0; transform: translateY(9px); }
  to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .typed-char,
  .empty-stage.is-written p,
  .empty-stage.is-written .quick-actions button { animation: none !important; }
  .typed-char { visibility: visible; }
  .typed-char.is-head::after { display: none; }
  .empty-stage p, .empty-stage .quick-actions button { opacity: 1; }
}

/* ── the Next.js dev overlay ───────────────────────────────────────────────
   hfs2s serves every app with `next dev` on purpose, so that a saved file hot
   reloads. The consequence is that Next's error indicator — the red "N Issues"
   pill — is not shown to a developer running a local server. It is shown to
   whoever the customer sends their link to, floating over the composer.

   `devIndicators: false` in next.config.mjs hides the idle badge but NOT this
   one; the error indicator is rendered regardless. So it is hidden here, at the
   only layer that can reach it.

   Nothing is being silenced: errors still go to the browser console and to the
   container's dev-server log, which is where anyone working on this app is
   already looking. What goes away is a framework debug affordance appearing on
   a stranger's phone. */
nextjs-portal,
[data-nextjs-toast],
[data-next-badge-root],
[data-nextjs-dev-tools-button],
#__next-build-watcher,
#__next-prerender-indicator { display: none !important; }

/* ── analytics ─────────────────────────────────────────────────────────────
   The owner's own surface, so it wears the product's clothes rather than a
   dashboard's: same pandan, same mango, same two typefaces. Nothing here is a
   chart library — the bars are divs, which at this size is both lighter and
   easier to read than an axis.

   The loud thing is the quote at the top. Les already knows roughly how busy
   the app is; what he cannot know without opening this page is what people are
   actually bringing to Gigi, so a real question in someone's own words leads,
   and the counting sits underneath it. */

.admin, .admin-gate {
  --rule: rgb(14 100 78 / 13%);
  min-height: 100vh; min-height: 100dvh;
  background: var(--ivory);
  color: var(--ink);
}
.admin { width: min(100% - 36px, 940px); margin: 0 auto; padding: 30px 0 72px; }

.admin-top { display: flex; align-items: center; gap: 14px; padding-bottom: 22px; }
.admin-top .wordmark { width: 138px; }
.admin-signout {
  min-height: 34px; padding: 0 12px; border: 1px solid var(--rule); border-radius: 10px;
  background: rgb(255 255 255 / 60%); color: var(--muted);
  font-size: 12px; font-weight: 640; cursor: pointer;
}
.admin-signout:hover { color: var(--pandan-deep); border-color: rgb(14 100 78 / 30%); }

/* The signature element. */
.admin-latest {
  padding: 30px clamp(20px, 4vw, 38px) 26px;
  border: 1px solid var(--rule); border-left: 3px solid var(--mango);
  border-radius: 4px 20px 20px 4px; background: rgb(255 255 255 / 72%);
}
.admin-label {
  margin: 0 0 14px; color: var(--muted);
  font-size: 10.5px; font-weight: 740; letter-spacing: .1em; text-transform: uppercase;
}
.admin-latest blockquote {
  margin: 0; font-family: var(--display); font-weight: 550;
  font-size: clamp(21px, 3.1vw, 31px); line-height: 1.24; letter-spacing: -.03em;
  text-wrap: balance;
}
.admin-latest-meta { display: flex; flex-wrap: wrap; gap: 7px; margin: 18px 0 0; }
.admin-latest-meta span {
  padding: 4px 9px; border-radius: 999px; background: rgb(14 100 78 / 7%);
  color: var(--pandan-deep); font-size: 11.5px; font-weight: 620;
}
.admin-latest-meta .is-bad { background: rgb(216 95 69 / 12%); color: #8b321f; }
.admin-latest-meta .is-good { background: rgb(14 100 78 / 11%); }
.admin-empty blockquote { color: var(--muted); font-weight: 500; }

.admin-figures {
  display: grid; grid-template-columns: repeat(4, 1fr); grid-gap: 1px; gap: 1px;
  margin-top: 26px; border: 1px solid var(--rule); border-radius: 16px;
  background: var(--rule); overflow: hidden;
}
.admin-figure { padding: 18px 16px; background: rgb(255 255 255 / 72%); }
.admin-figure strong {
  display: block; font-family: var(--display); font-weight: 640;
  font-size: clamp(24px, 3.4vw, 32px); letter-spacing: -.04em; line-height: 1;
}
.admin-figure span { display: block; margin-top: 7px; color: var(--muted); font-size: 11.5px; }

.admin-panel {
  margin-top: 20px; padding: 22px clamp(18px, 3.4vw, 26px) 24px;
  border: 1px solid var(--rule); border-radius: 18px; background: rgb(255 255 255 / 66%);
}
.admin-panel h2 {
  margin: 0 0 18px; font-family: var(--display); font-weight: 620;
  font-size: 15px; letter-spacing: -.02em;
}
.admin-none { margin: 0; color: var(--muted); font-size: 13px; }

/* Fourteen columns, no axis. The count sits on the bar it belongs to. */
.admin-days { display: grid; grid-template-columns: repeat(14, 1fr); grid-gap: 5px; gap: 5px; align-items: end; }
.admin-day { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.admin-day-track { width: 100%; height: 96px; display: flex; align-items: flex-end; }
.admin-day-fill {
  width: 100%; min-height: 2px; border-radius: 5px 5px 2px 2px;
  background: var(--pandan); opacity: .82;
  transform-origin: bottom; animation: admin-grow 520ms cubic-bezier(.2, .9, .3, 1) backwards;
}
.admin-day.is-today .admin-day-fill { background: var(--mango); opacity: 1; }
.admin-day-n { color: var(--pandan-deep); font-size: 10.5px; font-weight: 700; min-height: 13px; }
.admin-day-label { color: var(--muted); font-size: 10px; }
@keyframes admin-grow { from { transform: scaleY(0); } to { transform: scaleY(1); } }

.admin-pair { display: grid; grid-template-columns: 1fr 1fr; grid-gap: 20px; gap: 20px; }
.admin-pair .admin-panel { margin-top: 20px; }
.admin-split { list-style: none; margin: 0; padding: 0; display: grid; grid-gap: 11px; gap: 11px; }
.admin-split li { display: grid; grid-template-columns: 82px 1fr 30px; align-items: center; grid-gap: 11px; gap: 11px; }
.admin-split-name { font-size: 12.5px; font-weight: 600; }
.admin-split-bar { height: 8px; border-radius: 999px; background: rgb(14 100 78 / 9%); overflow: hidden; }
.admin-split-bar i {
  display: block; height: 100%; min-width: 3px; border-radius: 999px;
  background: var(--pandan); animation: admin-widen 620ms cubic-bezier(.2, .9, .3, 1) backwards;
}
.admin-split-n { color: var(--muted); font-size: 11.5px; text-align: right; }
@keyframes admin-widen { from { transform: scaleX(0); transform-origin: left; } }

.admin-trouble { border-color: rgb(216 95 69 / 26%); background: rgb(216 95 69 / 5%); }
.admin-trouble p { margin: 0; color: #7c3a28; font-size: 13.5px; line-height: 1.6; }

/* The transcript. Question in the reader's own words, answer beneath it,
   joined by a rule so the pair reads as one exchange. */
.admin-turns { list-style: none; margin: 0; padding: 0; display: grid; grid-gap: 2px; gap: 2px; }
.admin-turns li { padding: 16px 0; border-top: 1px solid var(--rule); }
.admin-turns li:first-child { border-top: 0; padding-top: 0; }
.admin-turn-head { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 9px; }
.admin-turn-head span, .admin-turn-head time { color: var(--muted); font-size: 10.5px; font-weight: 620; }
.admin-turn-head time { margin-left: auto; }
.admin-turn-prompt {
  margin: 0 0 9px; padding-left: 13px; border-left: 2px solid var(--pandan);
  font-size: 14.5px; line-height: 1.55; font-weight: 500; white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.admin-turn-reply, .admin-turn-error {
  margin: 0; padding-left: 13px; color: var(--muted);
  font-size: 13px; line-height: 1.6; white-space: pre-wrap; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden;
}
.admin-turn-error { color: #8b321f; }
.admin-turns li.is-failed .admin-turn-prompt { border-left-color: var(--coral); }

.admin-foot { margin-top: 26px; }
.admin-foot p { margin: 0; max-width: 62ch; color: var(--muted); font-size: 11.5px; line-height: 1.65; }

/* ── the gate ──────────────────────────────────────────────────────────── */
.admin-gate { display: grid; place-items: center; padding: 24px; }
.admin-gate-card {
  width: min(100%, 440px); padding: clamp(26px, 5vw, 40px);
  border: 1px solid var(--rule); border-radius: 24px;
  background: rgb(255 253 248 / 88%); box-shadow: 0 24px 80px rgb(41 57 49 / 10%);
  -webkit-backdrop-filter: blur(14px);
          backdrop-filter: blur(14px);
}
.admin-gate-card .wordmark { width: 150px; }
.admin-gate-card h1 {
  margin: 30px 0 12px; font-family: var(--display); font-weight: 620;
  font-size: clamp(27px, 5vw, 34px); letter-spacing: -.04em;
}
.admin-gate-card p { margin: 0; color: var(--muted); font-size: 13.5px; line-height: 1.62; }
.admin-gate-button {
  width: 100%; min-height: 48px; margin-top: 22px;
  display: flex; align-items: center; justify-content: center; gap: 9px;
  border-radius: 13px; background: var(--pandan); color: #fff;
  font-size: 13.5px; font-weight: 700; cursor: pointer;
}
.admin-gate-button:hover { background: var(--pandan-deep); }
.admin-gate-button:disabled { opacity: .62; cursor: wait; }
.admin-gate-note { margin-top: 14px; color: #8b321f; font-size: 12.5px; }
.admin-gate-sent {
  margin-top: 22px; padding: 14px 15px; border-radius: 13px;
  background: var(--pandan-pale); color: var(--pandan-deep);
  font-size: 13px; line-height: 1.55;
}

@media (max-width: 720px) {
  .admin-figures { grid-template-columns: 1fr 1fr; }
  .admin-pair { grid-template-columns: 1fr; gap: 0; }
  .admin-days { gap: 3px; }
  .admin-day-track { height: 72px; }
  .admin-day-label { font-size: 9px; }
  .admin-split li { grid-template-columns: 68px 1fr 26px; }
}

@media (prefers-reduced-motion: reduce) {
  .admin-day-fill, .admin-split-bar i { animation: none !important; transform: none; }
}

/* ── the owner's desk ────────────────────────────────────────────────────────
   Four sections behind one sign-in. Everything here is built from the tokens
   the customer-facing app already uses — this is the same product seen from
   behind, not a second design.

   Two accents carry meaning rather than decoration, and both are reused rather
   than invented. Mango already means "now" (it is today's bar in the fourteen
   day chart), so it marks the section you are standing in. The three-pixel
   left rule already means "this is a document someone wrote" (it is the edge of
   the last-asked question), so it is the edge of a plan and of a piece of
   feedback too. */

.admin-nav { margin-right: auto; display: flex; flex-wrap: wrap; align-items: center; gap: 1px; }
.admin-nav-link {
  position: relative; display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 10px 8px; border-radius: 9px;
  color: var(--muted); font-size: 12.5px; font-weight: 660; text-decoration: none;
  transition: color .16s ease, background .16s ease;
}
.admin-nav-link:hover { color: var(--pandan-deep); background: rgb(14 100 78 / 6%); }

/* Colour is never the only signal: the current section also darkens to full
   ink, so the underline is confirmation rather than the whole message. */
.admin-nav-link.is-current { color: var(--ink); }
.admin-nav-link.is-current::after {
  content: ''; position: absolute; left: 10px; right: 10px; bottom: 2px;
  height: 2px; border-radius: 2px; background: var(--mango);
}
.admin-nav-count {
  padding: 1px 7px; border-radius: 999px;
  background: var(--mango); color: var(--mango-ink);
  font-size: 10.5px; font-weight: 780; font-feature-settings: "tnum"; font-variant-numeric: tabular-nums;
}
.admin-home { display: inline-flex; border-radius: 8px; }

.plan-intro { padding: 2px 0 0; }
.plan-intro h1 {
  margin: 0; font-family: var(--display); font-weight: 600;
  font-size: clamp(26px, 4.4vw, 38px); line-height: 1.08; letter-spacing: -.042em;
  text-wrap: balance;
}
.plan-intro-note {
  margin: 13px 0 0; max-width: 62ch;
  color: var(--muted); font-size: 13.5px; line-height: 1.62;
}

/* ── shared controls ─────────────────────────────────────────────────────── */

.plan-quiet, .plan-save, .plan-danger, .plan-start {
  min-height: 34px; display: inline-flex; align-items: center; gap: 7px;
  padding: 0 13px; border-radius: 10px;
  font-size: 12.5px; font-weight: 650; cursor: pointer;
  transition: background .16s ease, color .16s ease, border-color .16s ease;
}
.plan-quiet {
  border: 1px solid var(--rule); background: rgb(255 255 255 / 60%); color: var(--muted);
}
.plan-quiet:hover { color: var(--pandan-deep); border-color: rgb(14 100 78 / 30%); }
.plan-save { border: 1px solid var(--pandan); background: var(--pandan); color: #fff; }
.plan-save:hover { background: var(--pandan-deep); border-color: var(--pandan-deep); }
.plan-danger { border: 1px solid rgb(216 95 69 / 34%); background: rgb(216 95 69 / 8%); color: #8b321f; }
.plan-danger:hover { background: var(--coral); border-color: var(--coral); color: #fff; }
.plan-quiet:disabled, .plan-save:disabled, .plan-danger:disabled { opacity: .55; cursor: wait; }

.plan-start {
  margin-top: 24px; border: 1px dashed rgb(14 100 78 / 30%);
  background: rgb(255 255 255 / 50%); color: var(--pandan-deep);
}
.plan-start:hover { background: var(--pandan-pale); border-style: solid; }

.plan-error { margin: 14px 0 0; color: #8b321f; font-size: 12.5px; }

/* ── writing a plan ──────────────────────────────────────────────────────── */

.plan-form {
  margin-top: 24px; padding: 22px clamp(18px, 3.4vw, 26px) 20px;
  border: 1px solid var(--rule); border-radius: 18px; background: rgb(255 255 255 / 74%);
}
.plan-field { display: block; margin-bottom: 16px; }
.plan-field > span {
  display: block; margin-bottom: 7px;
  color: var(--muted); font-size: 10.5px; font-weight: 740;
  letter-spacing: .1em; text-transform: uppercase;
}
.plan-field input, .plan-field textarea {
  width: 100%; padding: 11px 13px;
  border: 1px solid var(--line); border-radius: 11px; background: var(--paper);
  font-size: 14px; line-height: 1.6; color: var(--ink);
}
.plan-field textarea { resize: vertical; font-size: 13.5px; }
.plan-field input:focus-visible, .plan-field textarea:focus-visible { border-color: var(--pandan); }

.plan-form-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.plan-form-actions { margin-left: auto; display: flex; gap: 8px; }
.plan-status-picker { display: inline-flex; align-items: center; gap: 8px; }
.plan-status-picker > span {
  color: var(--muted); font-size: 10.5px; font-weight: 740;
  letter-spacing: .1em; text-transform: uppercase;
}
.plan-status-picker select {
  min-height: 34px; padding: 0 10px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--paper); font-size: 12.5px; font-weight: 640; cursor: pointer;
}

/* ── the index ───────────────────────────────────────────────────────────── */

.plan-list { list-style: none; margin: 26px 0 0; padding: 0; display: grid; grid-gap: 10px; gap: 10px; }
.plan-row-link {
  display: block; padding: 17px clamp(16px, 3vw, 22px) 19px;
  border: 1px solid var(--rule); border-left: 3px solid rgb(14 100 78 / 22%);
  border-radius: 4px 16px 16px 4px; background: rgb(255 255 255 / 66%);
  color: inherit; text-decoration: none;
  transition: background .16s ease, border-color .16s ease, transform .16s ease;
}
.plan-row-link:hover {
  background: var(--paper); border-color: rgb(14 100 78 / 30%);
  border-left-color: var(--pandan); transform: translateY(-1px);
}
.plan-row.is-stale .plan-row-link { border-left-color: var(--coral); }
.plan-row.is-stale .plan-row-link:hover { border-left-color: var(--coral); }
.plan-row-head { display: flex; align-items: center; gap: 10px; margin-bottom: 11px; }
.plan-row-head time { margin-left: auto; color: var(--muted); font-size: 11px; font-weight: 620; }
.plan-row-link h2 {
  margin: 0; font-family: var(--display); font-weight: 600;
  font-size: 17.5px; letter-spacing: -.025em; line-height: 1.25;
}
.plan-row-excerpt {
  margin: 8px 0 0; color: var(--muted); font-size: 13px; line-height: 1.6;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.plan-row-stale { margin: 10px 0 0; color: #8b321f; font-size: 11.5px; font-weight: 620; }
.plan-empty { margin-top: 26px; max-width: 54ch; line-height: 1.6; }

.plan-chip {
  padding: 4px 10px; border-radius: 999px; border: 0;
  font-size: 11px; font-weight: 720; letter-spacing: .01em; white-space: nowrap;
}
.plan-chip.is-thinking { background: rgb(14 100 78 / 9%); color: var(--pandan-deep); }
.plan-chip.is-doing { background: var(--mango-pale); color: var(--mango-ink); }
.plan-chip.is-done { background: rgb(105 112 108 / 13%); color: var(--muted); }
select.plan-chip { -webkit-appearance: none; -moz-appearance: none; appearance: none; padding-right: 10px; cursor: pointer; }
select.plan-chip:disabled { cursor: wait; }

/* ── one plan ────────────────────────────────────────────────────────────── */

.plan-back {
  display: inline-flex; align-items: center; gap: 4px; margin-bottom: 16px;
  color: var(--muted); font-size: 12.5px; font-weight: 640; text-decoration: none;
}
.plan-back:hover { color: var(--pandan-deep); }

.plan-doc {
  padding: clamp(24px, 4vw, 40px) clamp(20px, 4vw, 44px) 30px;
  border: 1px solid var(--rule); border-radius: 20px; background: var(--paper);
  box-shadow: var(--shadow);
}
.plan-doc-head { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-bottom: 22px; }
.plan-doc-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.plan-doc-dates { color: var(--muted); font-size: 11.5px; font-weight: 600; }
.plan-doc-head > .plan-quiet { margin-left: auto; }
.plan-status-inline { display: inline-flex; }

.plan-doc-title {
  margin: 0 0 22px; font-family: var(--display); font-weight: 600;
  font-size: clamp(27px, 4.4vw, 40px); line-height: 1.08; letter-spacing: -.042em;
  text-wrap: balance;
}
.plan-doc-body { max-width: 68ch; font-size: 15px; line-height: 1.75; }
.plan-doc-body h1, .plan-doc-body h2, .plan-doc-body h3 {
  font-family: var(--display); font-weight: 620; letter-spacing: -.028em; line-height: 1.2;
  margin: 30px 0 10px;
}
.plan-doc-body h1 { font-size: 24px; }
.plan-doc-body h2 { font-size: 20px; }
.plan-doc-body h3 { font-size: 16.5px; }
.plan-doc-body p, .plan-doc-body li { margin: 0 0 12px; }
.plan-doc-body ul, .plan-doc-body ol { margin: 0 0 14px; padding-left: 22px; }
.plan-doc-body li { margin-bottom: 6px; }
.plan-doc-body blockquote {
  margin: 16px 0; padding: 2px 0 2px 16px;
  border-left: 3px solid var(--mango); color: var(--muted);
}
.plan-doc-body code {
  padding: 2px 5px; border-radius: 5px; background: rgb(14 100 78 / 8%);
  font-size: .88em;
}
.plan-doc-body pre {
  padding: 14px 16px; border-radius: 12px; background: #14201b; color: #eef3f0;
  overflow-x: auto; font-size: 12.5px; line-height: 1.6;
}
.plan-doc-body pre code { padding: 0; background: none; color: inherit; }
.plan-doc-body hr { margin: 26px 0; border: 0; border-top: 1px solid var(--rule); }
.plan-doc-body table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.plan-doc-body th, .plan-doc-body td {
  padding: 9px 11px; border-bottom: 1px solid var(--rule); text-align: left; vertical-align: top;
}
.plan-doc-body th { color: var(--muted); font-size: 11px; font-weight: 720; letter-spacing: .06em; text-transform: uppercase; }

.plan-doc-title-input, .plan-doc-body-input {
  width: 100%; padding: 12px 14px; margin-bottom: 14px;
  border: 1px solid var(--line); border-radius: 12px; background: var(--ivory); color: var(--ink);
}
.plan-doc-title-input {
  font-family: var(--display); font-weight: 600; font-size: 22px; letter-spacing: -.03em;
}
.plan-doc-body-input {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px; line-height: 1.68; resize: vertical;
}
.plan-doc-title-input:focus-visible, .plan-doc-body-input:focus-visible { border-color: var(--pandan); }
.plan-doc-actions { display: flex; justify-content: flex-end; gap: 8px; }
.plan-doc-foot { margin-top: 28px; padding-top: 18px; border-top: 1px solid var(--rule); }
.plan-confirm { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.plan-confirm > span { color: #8b321f; font-size: 12.5px; font-weight: 640; }

/* ── feedback ────────────────────────────────────────────────────────────── */

.fb-filter { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 26px; }
.fb-filter button {
  min-height: 34px; display: inline-flex; align-items: center; gap: 8px; padding: 0 13px;
  border: 1px solid var(--rule); border-radius: 999px; background: rgb(255 255 255 / 60%);
  color: var(--muted); font-size: 12.5px; font-weight: 650; cursor: pointer;
  transition: background .16s ease, color .16s ease, border-color .16s ease;
}
.fb-filter button:hover { color: var(--pandan-deep); border-color: rgb(14 100 78 / 30%); }
.fb-filter button span {
  padding: 1px 7px; border-radius: 999px; background: rgb(14 100 78 / 9%);
  font-size: 11px; font-weight: 740; font-feature-settings: "tnum"; font-variant-numeric: tabular-nums;
}
.fb-filter button.is-on { background: var(--pandan); border-color: var(--pandan); color: #fff; }
.fb-filter button.is-on span { background: rgb(255 255 255 / 26%); color: #fff; }

.fb-list { list-style: none; margin: 18px 0 0; padding: 0; display: grid; grid-gap: 10px; gap: 10px; }
.fb-item {
  padding: 16px clamp(15px, 3vw, 21px) 14px;
  border: 1px solid var(--rule); border-left: 3px solid var(--pandan);
  border-radius: 4px 16px 16px 4px; background: rgb(255 255 255 / 70%);
}
.fb-item.is-handled { border-left-color: rgb(14 100 78 / 18%); background: rgb(255 255 255 / 42%); }
.fb-item.is-handled .fb-message { color: var(--muted); }
.fb-item-head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 10px; }
.fb-item-head time { margin-left: auto; color: var(--muted); font-size: 11px; font-weight: 620; }
.fb-tag {
  padding: 3px 9px; border-radius: 999px;
  font-size: 10.5px; font-weight: 740; letter-spacing: .04em; text-transform: uppercase;
}
.fb-tag.is-idea { background: rgb(14 100 78 / 10%); color: var(--pandan-deep); }
.fb-tag.is-problem { background: rgb(216 95 69 / 12%); color: #8b321f; }
.fb-tag.is-other { background: rgb(105 112 108 / 13%); color: var(--muted); }
.fb-reply { font-size: 12px; font-weight: 620; }
.fb-noreply { color: var(--muted); font-size: 12px; }
.fb-unsent {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px; border-radius: 999px; background: var(--mango-pale);
  color: var(--mango-ink); font-size: 11px; font-weight: 680;
}
.fb-message {
  margin: 0; font-size: 14px; line-height: 1.62;
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.fb-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 13px; }
.fb-confirm { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.fb-done {
  min-height: 34px; display: inline-flex; align-items: center; gap: 7px; padding: 0 13px;
  border: 1px solid rgb(14 100 78 / 26%); border-radius: 10px;
  background: var(--pandan-pale); color: var(--pandan-deep);
  font-size: 12.5px; font-weight: 650; cursor: pointer;
}
.fb-done:hover { background: var(--pandan); color: #fff; border-color: var(--pandan); }
.fb-done:disabled { opacity: .55; cursor: wait; }

/* ── settings ────────────────────────────────────────────────────────────── */

.set-panel { padding: 0; overflow: hidden; }
.set-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; grid-gap: 24px; gap: 24px;
  padding: 21px clamp(18px, 3.4vw, 26px);
  border-top: 1px solid var(--rule);
}
.set-row:first-child { border-top: 0; }
.set-panel .set-row-text h2 {
  margin: 0 0 6px; font-family: var(--display); font-weight: 620;
  font-size: 15px; letter-spacing: -.02em;
}
.set-row-text p { margin: 0; max-width: 56ch; color: var(--muted); font-size: 12.5px; line-height: 1.6; }

.set-choice {
  display: inline-flex; gap: 2px; padding: 3px;
  border: 1px solid var(--rule); border-radius: 12px; background: rgb(255 255 255 / 70%);
}
.set-choice button {
  min-height: 32px; padding: 0 13px; border-radius: 9px; background: transparent;
  color: var(--muted); font-size: 12.5px; font-weight: 650; cursor: pointer;
  transition: background .16s ease, color .16s ease;
}
.set-choice button:hover { color: var(--pandan-deep); }
.set-choice button.is-on { background: var(--pandan); color: #fff; }

.set-switch {
  position: relative; width: 50px; height: 30px; flex: 0 0 auto;
  border-radius: 999px; background: rgb(105 112 108 / 24%); cursor: pointer;
  transition: background .18s ease;
}
.set-switch.is-on { background: var(--pandan); }
.set-switch:disabled { opacity: .4; cursor: not-allowed; }
.set-switch-knob {
  position: absolute; top: 3px; left: 3px; width: 24px; height: 24px;
  border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgb(20 32 27 / 22%);
  transition: transform .18s ease;
}
.set-switch.is-on .set-switch-knob { transform: translateX(20px); }

.set-purge { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; justify-content: flex-end; }
.set-state {
  margin: 0; padding: 0 clamp(18px, 3.4vw, 26px) 16px;
  min-height: 18px; color: var(--muted); font-size: 12px; font-weight: 620;
}
.set-state .is-bad { color: #8b321f; }
.set-note { margin: -6px 0 16px; color: var(--muted); font-size: 12.5px; line-height: 1.55; }
.set-wiring {
  list-style: none; margin: 0; padding: 0; display: grid; grid-gap: 1px; gap: 1px;
  border: 1px solid var(--rule); border-radius: 12px; background: var(--rule); overflow: hidden;
}
.set-wiring li {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 11px 14px; background: rgb(255 255 255 / 80%); font-size: 12.5px;
}
.set-wiring-label { color: var(--muted); font-weight: 620; }
.set-wiring-value { color: var(--pandan-deep); font-weight: 650; text-align: right; }
.set-wiring-value.is-off { color: #8b321f; }

@media (max-width: 720px) {
  .admin-top { flex-wrap: wrap; row-gap: 10px; }
  .admin-nav { order: 3; width: 100%; margin-right: 0; }
  .admin-nav-link { padding-left: 0; padding-right: 14px; }
  .admin-nav-link.is-current::after { left: 0; right: 14px; }
  .admin-signout { margin-left: auto; }
  .set-row { grid-template-columns: 1fr; gap: 14px; align-items: start; }
  .set-purge, .plan-form-actions { justify-content: flex-start; margin-left: 0; }
  .plan-doc-head > .plan-quiet { margin-left: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .plan-row-link, .set-switch, .set-switch-knob, .fb-filter button { transition: none; }
  .plan-row-link:hover { transform: none; }
}

/* ── voice mode ──────────────────────────────────────────────────────────────
   A conversation with no reading in it. Everything here answers one question
   the person cannot ask out loud: whose turn is it right now.

   The answer is the orb, and the orb says it twice — once in the colour and
   motion of the smoke, once in the label under it — so it survives both a
   glance and a screen reader. There is deliberately NO transcript on this
   screen. Words appearing and correcting themselves as you speak pull the eye
   straight back into reading, which is the one thing this screen exists to
   avoid; the written version of the whole exchange is waiting in the thread
   when voice mode closes. */

.voice-screen {
  position: fixed; inset: 0; z-index: 60;
  display: grid; grid-template-rows: auto 1fr auto;
  background:
    radial-gradient(58% 48% at 18% 12%, #dcefe4 0%, transparent 70%),
    radial-gradient(52% 44% at 84% 22%, #f8e8b9 0%, transparent 66%),
    var(--ivory);
  animation: voice-enter .34s cubic-bezier(.3, 0, .2, 1) both;
}

.voice-top {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px max(6px, env(safe-area-inset-top));
}

/* An eyebrow that names the mode, because this screen replaces the whole app
   and somebody arriving at it mid-thought should not have to work that out. */
.voice-eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  color: var(--pandan-deep); font-size: 11px; font-weight: 760;
  letter-spacing: .1em; text-transform: uppercase;
}
.voice-eyebrow .gigi-mark { width: 19px; height: 19px; }

.voice-stage {
  min-height: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  padding: 8px 24px 0; text-align: center;
}

/* ── the orb ─────────────────────────────────────────────────────────────────
   --level is written from an animation frame with the live RMS of whichever
   voice currently has the floor, 0 to 1. The shader reads a throttled copy of
   it through React; everything in this file reads it directly, because a
   custom property is composited and costs nothing per frame. */
.voice-orb {
  --level: 0;
  --ring: var(--pandan);
  position: relative;
  width: clamp(210px, 44vw, 292px); aspect-ratio: 1;
  display: grid; place-items: center;
  flex: 0 0 auto;
}
.voice-orb[data-state='speaking'] { --ring: var(--mango); }
.voice-orb[data-state='thinking'] { --ring: var(--jade); }

/* Painted UNDER the shader, and on its own.
   This is the fallback as much as it is a glow: where WebGL is missing the
   canvas renders nothing at all, and without this the orb would be an empty
   square with a logo in it. Here, the state colour and the live amplitude
   still read. */
.voice-orb::before {
  content: ''; position: absolute; inset: 4%;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 50%, var(--ring) 0%, transparent 70%);
  opacity: calc(.08 + var(--level) * .26);
  transition: opacity .09s linear;
}

.voice-smoke { position: absolute; inset: 0; border-radius: 50%; overflow: hidden; }
.voice-smoke-canvas { width: 100%; height: 100%; display: block; }

.voice-orb-face {
  position: relative; z-index: 1;
  width: 38%; line-height: 0;
  color: var(--pandan-deep);
  /* A breath, not a bounce. Small enough that a loud syllable never makes the
     letterform wobble. */
  transform: scale(calc(1 + var(--level) * .05));
  transition: transform .07s linear;
}
.voice-orb-face .gigi-mark-svg { width: 100%; height: 100%; }

/* THE METER. The mark already carries one piece of punctuation about speech,
   so the bubble is the part that moves with the voice — it inflates and lifts.
   It stays mango in every state: the brand has one warm accent, and the smoke
   is where state colour lives, so the bubble is never asked to mean two things
   at once. */
.voice-orb .logo-bubble {
  transform: scale(calc(1 + var(--level) * .45)) translateY(calc(var(--level) * -4px));
  transition: transform .07s linear;
}
.voice-orb[data-state='thinking'] .logo-bubble {
  animation: bubble-think 1.25s cubic-bezier(.4, 0, .3, 1) infinite;
}

@keyframes bubble-think {
  0%, 100% { transform: scale(1) translateY(0); }
  45% { transform: scale(1.13) translateY(-3px); }
}
@keyframes voice-enter { from { opacity: 0; transform: scale(.985); } }

/* The orb is the stop button while there is something to stop.
   It is a plain wrapper the rest of the time — no border, no background, and
   no cursor change — so it never advertises an action it will not perform. */
.voice-orb-tap {
  display: block; padding: 0; margin: 0; background: none; border: 0;
  border-radius: 50%; cursor: default; -webkit-tap-highlight-color: transparent;
}
.voice-orb-tap:not(:disabled) { cursor: pointer; }
.voice-orb-tap:disabled { opacity: 1; }
.voice-orb-tap:focus-visible { outline: 3px solid rgb(23 107 84 / 24%); outline-offset: 4px; }

/* ── what the orb is saying, in words ────────────────────────────────────── */
.voice-state {
  margin: 26px 0 0;
  font-family: var(--display); font-weight: 600;
  font-size: clamp(25px, 5.6vw, 33px); line-height: 1.1; letter-spacing: -.035em;
  color: var(--ink);
}

.voice-hint { margin: 11px 0 0; max-width: 32ch; color: #7d847f; font-size: 13px; line-height: 1.5; text-wrap: balance; }

.voice-notice {
  margin: 18px auto 0; max-width: 40ch;
  padding: 10px 13px; border-left: 3px solid var(--mango);
  background: var(--mango-pale); color: #5a4c20;
  border-radius: 5px 11px 11px 5px; font-size: 13px; line-height: 1.5; text-align: left;
}

.voice-code {
  margin: 9px auto 0; color: #a2a8a4; font-size: 11px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .02em;
}

/* ── controls ────────────────────────────────────────────────────────────────
   Two, because the premise of the screen is that you do not operate it. Mute
   is here for the moment someone else walks into the room; end is here because
   every call needs a way out that is not the back button. */
.voice-controls {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  padding: 18px 24px max(20px, env(safe-area-inset-bottom));
}
.voice-button {
  min-height: 50px; display: inline-flex; align-items: center; gap: 9px;
  padding: 0 21px; border-radius: 999px;
  border: 1px solid var(--line-strong); background: var(--paper);
  color: var(--ink); font-size: 14.5px; font-weight: 600; cursor: pointer;
  box-shadow: 0 8px 26px rgb(39 52 46 / 7%);
  transition: background .15s ease, border-color .15s ease, transform .15s ease, color .15s ease;
}
.voice-button:hover { transform: translateY(-1px); border-color: #8ab9a6; }
.voice-button[aria-pressed='true'] {
  background: var(--pandan-pale); border-color: rgb(23 107 84 / 30%); color: var(--pandan-deep);
}
.voice-button.end { background: var(--pandan); border-color: var(--pandan); color: #fff; }
.voice-button.end:hover { background: var(--pandan-deep); border-color: var(--pandan-deep); }
.voice-button:disabled { opacity: .5; cursor: default; transform: none; }

@media (max-width: 420px) {
  .voice-button { padding: 0 17px; font-size: 14px; }
  .voice-state { margin-top: 20px; }
}

/* Short landscape phones: the orb is the first thing to give up its size. */
@media (max-height: 560px) {
  .voice-orb { width: clamp(132px, 30vh, 190px); }
  .voice-state { margin-top: 14px; font-size: clamp(21px, 4vw, 26px); }
  .voice-hint { font-size: 12.5px; }
}

@media (prefers-reduced-motion: reduce) {
  .voice-screen { animation: none; }
  .voice-orb .logo-bubble { animation: none !important; }
  .voice-orb-face, .voice-orb .logo-bubble { transform: none; transition: none; }
  .voice-orb::before { transition: none; }
  /* The shader is held still by the component, so the glow becomes the only
     thing separating the states and it is given a fixed depth per state
     instead of an amplitude it is no longer allowed to follow. */
  .voice-orb[data-state='idle']::before { opacity: .1; }
  .voice-orb[data-state='listening']::before { opacity: .26; }
  .voice-orb[data-state='thinking']::before { opacity: .18; }
  .voice-orb[data-state='speaking']::before { opacity: .32; }
  .voice-button:hover { transform: none; }
}

/* The way in, on the composer. */
.mic-button {
  flex: 0 0 auto; width: 42px; height: 42px; border-radius: 12px;
  display: grid; place-items: center; background: transparent;
  color: var(--pandan); cursor: pointer; transition: background .15s ease;
}
.mic-button:hover { background: var(--pandan-pale); }
.mic-button:disabled { opacity: .4; cursor: default; }

