/* Foundation screens: sign-up call to action, organization sign-up, Home, admin, the bottom sheet.
   Every colour is read from the Studio tokens in index.html; this file defines none of its own. */
.field-label{display:block;margin:14px 2px 6px;font-size:13px;font-weight:500;line-height:1.35;color:var(--text-2)}
.form-submit{margin-top:14px}
/* One error style everywhere: --bad and a leading dot, so a failure never reads like an ordinary status line. */
.status-error{color:var(--bad)}
.status-error:not(:empty)::before{content:"";display:inline-block;width:6px;height:6px;margin:0 8px 1px 0;border-radius:50%;background:currentColor;vertical-align:middle}
.load-failed .retry-btn{margin-top:10px}
/* A failure with no list of its own: Try again under the words, a full-size button. */
.note>.retry-btn,.parley-status>.retry-btn{display:flex;margin-top:8px}
/* Loading placeholders (workspace.js setLoading): bars in the list's own box, shown only after 400ms, pulsing gently. */
.skel{display:grid;gap:10px;grid-column:1/-1}
.skel-card{display:grid;gap:8px;padding:14px 16px;border:1px solid var(--hairline);border-radius:var(--r-inner);background:var(--fill-1)}
.skel-line{display:block;height:12px;border-radius:var(--r-pill);background:var(--fill-2);animation:skel-pulse 1.4s ease-in-out infinite}
.skel-card>.skel-line+.skel-line,.skel-lines>.skel-line+.skel-line{width:60%}
.skel-card>.skel-line:first-child,.skel-lines>.skel-line:first-child{width:85%}
.skel-row{grid-template-columns:40px minmax(0,1fr);align-items:center;gap:12px}
.skel-av{width:40px;height:40px;border-radius:var(--r-avatar);background:var(--fill-2);animation:skel-pulse 1.4s ease-in-out infinite}
.skel-lines{display:grid;gap:8px}
.skel-texts{gap:12px}
.skel-texts>.skel-line:nth-child(3n){width:70%}
.skel-tiles{grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}
/* As tall as a real count tile (tasks-page.css .tasks-count: a 28px number over a 12px label), so nothing jumps when they land. */
.skel-tile{min-height:68px;padding:10px 12px;align-content:start;gap:6px}
.skel-tile>.skel-line:first-child{width:40%;height:28px}
/* As tall as a real Calendar provider row (the name, its state chip and a line under it, beside a 44px Connect). */
#calendarProviders .skel-row{min-height:100px;grid-template-columns:44px minmax(0,1fr)}
#calendarProviders .skel-av{width:44px;height:44px}
.skel-inline{display:inline-block;width:6em;height:10px;vertical-align:middle}
@keyframes skel-pulse{50%{opacity:.45}}
@media (prefers-reduced-motion:reduce){.skel-line,.skel-av{animation:none}}
/* An empty status line takes no space. */
.note[role=status]:empty{display:none}
/* A consequence of saving, not a hint: it reads in the warning colour the warn buttons use. */
.note.warn-note,.warn-text{color:var(--warn)}
/* Staff rows: a sub-line breaks between its parts rather than cutting one, so the access level and the status always
   show; only a part too long for the whole row (a long job title, an email) ends in an ellipsis. */
.staff-lines>span{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.staff-lines>span:not(.staff-email){white-space:normal}
.staff-lines .meta-part{display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}
.list[data-empty]:empty::after{content:'Nothing here yet.';font-size:14px;color:var(--text-2)}
#invitationDetails{user-select:all;overflow-wrap:anywhere}
.row b,.row small,.title h2,.agent-head h3{overflow-wrap:anywhere}
.agent-phone>.panel{margin-top:0}

/* ---- Home ---- */
/* The greeting is Home's title row, beside the profile button; who and where sit under it as free text, no card. */
.home-head{margin:-4px 4px 16px}
.home-head .note{margin:2px 0 0}
.home-head .note:first-child{margin-top:0}
.home-head .note:empty{display:none}
/* Who and where on one line, "Director · Admin · YouVerse", breaking at a separator when it must (02-31). */
/* Each part stays whole; a separator sits before each part, and the one that would start a line is clipped away. */
.home-head .home-who{display:flex;flex-wrap:wrap;margin-left:-1.6em;clip-path:inset(0 0 0 1.6em)}
.home-who>span{max-width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.home-who>span::before{content:"·";display:inline-block;width:1.6em;text-align:center}
.home-who>span:empty{display:none}
.home-who:not(:has(>span:not(:empty))){display:none}
#homeTitle{text-wrap:balance}
/* My tasks, empty: reading text in Geist Mono, with the way to Tasks under it (02-28). */
#homeTaskList .card.empty p{font-family:var(--mono);font-weight:400;letter-spacing:normal}
#homeTaskList .card.empty .btn{margin-top:10px}
/* Team pulse, compact (02-29): an admin's department picker is a small chip in the header, and the people rows are tight.
   The chip has no fill of its own, so the card stays one colour; its outline and chevron mark it. */
.pulse-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:8px}
.pulse-head .k{margin:0}
.pulse-picker{flex:none;max-width:60%;min-height:44px;padding:0 30px 0 12px;border:1px solid var(--line);border-radius:999px;
  background:var(--select-chevron) no-repeat right 10px center/16px 16px,transparent;
  color:var(--text);font:inherit;font-size:16px;font-weight:500;text-overflow:ellipsis;-webkit-appearance:none;appearance:none;cursor:pointer}
.pulse-picker option{background:var(--glass-solid);color:var(--text)}
#teamPulseSummary{margin-top:0}
#staffList{gap:0}
#staffList>.row{grid-template-columns:36px minmax(0,1fr) auto;gap:12px;padding:10px 0}
#staffList .av{width:36px;height:36px;font-size:12px}
#staffList .row small{margin-top:1px;line-height:1.35}
#homeScreen>.title .k{margin-bottom:4px}
#homeKpis{margin-top:12px}
.stopwatch{margin:10px 0;font-size:24px;font-weight:700;letter-spacing:-.02em;line-height:1.15;font-variant-numeric:tabular-nums}
#workStatusCard .btn{min-width:76px}
/* Home's work status, a full-width long card under the greeting. The dot is grey while inactive and, only when the
   server says a day is open, green and glowing with the same pulse as the "Listening" dots (meeting-pulse). */
.work-status-row{display:flex;align-items:center;gap:12px}
.work-status-text{flex:1 1 auto;min-width:0;font-size:15px;line-height:1.35;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-variant-numeric:tabular-nums}
/* One line only (the lead, 2026-09-22): the dot, then "Work status · …" beside it, then the button on the right.
   No detail line and no message line, so the card keeps its size in every state and while it is tapped. */
.work-status-row .btn{flex:none;min-width:104px;padding:0 12px;white-space:nowrap}
.work-dot{flex:none;width:12px;height:12px;border-radius:50%;background:var(--track)}
.work-dot.active{background:var(--green);box-shadow:0 0 0 3px color-mix(in srgb,var(--green) 25%,transparent),0 0 12px var(--green);animation:meeting-pulse 1.5s ease-in-out infinite alternate}
/* Reduced motion: the open day's dot stays lit, without the pulse. */
@media (prefers-reduced-motion:reduce){.work-dot.active{animation:none}}
/* Breaks (2026-09-25): icon buttons in place of the worded one, so the row stays one line with two of them; an amber
   dot and the frozen worked time beside the break timer while on a break. */
.work-status-row .btn.work-icon-btn{min-width:44px;width:44px;padding:0}
.work-status-row{gap:8px}
/* On a phone (review, 2026-09-25) the break timer and the worked time are read in full beside the two 44px buttons: tight
   gaps, "Break" and "Work" as the words, the worked time at 12px. The worked time is the frozen one, so it yields first,
   and below 360px, where both cannot fit, it is left out rather than cut (the chevron goes first, below 375px). */
.work-status-worked{flex:0 1000 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;color:var(--text-2);font-size:12px;white-space:nowrap;font-variant-numeric:tabular-nums}
@media (max-width:359px){.work-status-worked{display:none}}
/* D12: the dot and the times are one button that opens today's attendance; it looks like the bar, not like a button. */
.work-status-open{display:flex;align-items:center;gap:6px;flex:1;min-width:0;padding:0;border:0;background:none;color:inherit;font:inherit;text-align:left;cursor:pointer}
.work-status-open:focus-visible{outline:2px solid var(--green);outline-offset:4px;border-radius:6px}
/* UI polish B1: the work day leads Home. A chevron beside the words says the bar opens attendance (02-18); the dot sits
   8px from them. The main button carries its word, "Start my day" or "End my day" (02-19). On narrow phones the chevron
   (the hint) goes first, below 375px; the worked time below 360px; the word only below 340px, or while a break's two
   timers need the room. */
#workStatusPanel{padding-top:14px;padding-bottom:14px}
#workStatusPanel .work-status-text{flex:0 1 auto;font-size:16px;font-weight:600}
.work-status-chev{flex:none;width:16px;height:16px;margin-left:2px;color:var(--text-2)}
#workStatusPanel.break .work-status-chev{display:none}
.work-status-row .btn.work-main-btn{width:auto;min-width:44px;padding:0 16px 0 12px;gap:6px}
.work-main-btn .icon{flex:none;width:18px;height:18px}
.work-btn-word{font-size:14px;font-weight:600}
#workStatusPanel.break .work-main-btn .work-btn-word{display:none}
#workStatusPanel.break .btn.work-main-btn{width:44px;padding:0}
@media (max-width:399px){#workStatusPanel .work-status-text{font-size:15px}.work-status-row .btn.work-main-btn{padding:0 14px 0 10px}}
@media (max-width:374px){#workStatusPanel .work-status-chev{display:none}.work-status-row .btn.work-main-btn{padding:0 12px 0 8px}}
@media (max-width:339px){.work-btn-word{display:none}.work-status-row .btn.work-main-btn{width:44px;padding:0}}
/* With a day open, "End my day" shares the row with Take a break and the running time: under 400px it is the icon alone. */
@media (max-width:399px){#workStatusPanel:has(#workBreakBtn:not(.hidden)) .work-btn-word{display:none}#workStatusPanel:has(#workBreakBtn:not(.hidden)) .btn.work-main-btn{width:44px;padding:0}}
/* On a phone the gaps are 4px, so a worked time of 10 hours or more ("Work 10:59:59") fits beside the break timer at 375px. */
@media (max-width:699px){.work-status-open{gap:4px}.work-status-row{gap:8px}}
#workStatusOpen{gap:8px}#workStatusOpen .work-status-worked{margin-left:-4px}
/* On a break both timers need the room: the tight 4px gaps and 15px words of before. */
/* While a day runs the time is never cut: only the words "Work day ·" may shrink, and below 390px they are "Work ·". */
#workStatusLabel.timed{display:flex;align-items:baseline;overflow:visible}
/* At 320px, beside Take a break and End day, the 8px gaps left "Active · 9:17:59" 1px short ("Activ…"); 6px gaps and the
   chevron flush give it 6px more. */
@media (max-width:374px){#workStatusPanel.active:not(.break) #workStatusOpen{gap:6px}#workStatusPanel.active:not(.break) .work-status-chev{margin-left:0}}
.work-status-word{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.work-status-time{flex:none;white-space:pre}
@media (max-width:389px){#workStatusPanel.active:not(.break) .btn.work-main-btn{padding:0 12px 0 8px}}
/* Below 390px "Active ·" and the running time take one size down, so the time is always read in full beside the buttons. */
@media (max-width:389px){#workStatusLabel.timed{font-size:14px}}
#workStatusPanel.break #workStatusOpen{gap:4px}#workStatusPanel.break .work-status-worked{margin-left:0}#workStatusPanel.break .work-status-text{font-size:15px}
#attendanceList{margin-top:12px}
.attendance-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px}
.attendance-head b{min-width:0;overflow-wrap:anywhere}
.attendance-span{flex:none;font-family:var(--mono);font-size:13px;font-weight:500;color:var(--text-2);font-variant-numeric:tabular-nums}
.attendance-totals{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:10px}
.attendance-totals .tasks-count{background:var(--fill-1);-webkit-backdrop-filter:none;backdrop-filter:none}
/* Display only: the tiles borrow the Tasks tile's look, not its pointer or its press dim. */
.attendance-totals .attendance-total{cursor:default}
.attendance-totals .attendance-total:active{opacity:1}
.attendance-session .attendance-times{margin:10px 0 0;font-variant-numeric:tabular-nums}
.attendance-breaks{margin:10px 0 0;padding:0;list-style:none;font-family:var(--mono);font-size:12px;font-weight:500;color:var(--text-2);font-variant-numeric:tabular-nums}
.attendance-breaks li{padding:8px 0}
.attendance-breaks li+li{border-top:1px solid var(--hairline)}
.work-dot.break{background:var(--warn);box-shadow:0 0 0 3px color-mix(in srgb,var(--warn) 25%,transparent)}
/* Reserved whether or not there is anything to say, so starting or ending the day adds no line to the card. */
/* No reserved space: the Home card says nothing after Start or End (the lead, 2026-09-22); only a failure appears here. */
#workStatusMessage{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}
#workStatusMessage:empty{display:none}
/* Idle attendance: the auto-break and auto-ended notices under the work card, and their tags on attendance rows. */
#autoBreakNotice .note:first-child,#autoEndNotice .note:first-child{margin-top:0;color:var(--text)}
#autoBreakMessage:empty{display:none}
.attendance-tags{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
.attendance-breaks .attendance-tag{margin-left:6px;padding:1px 7px;font-size:10.5px}
/* An end time the viewer may decide: the time asked, then Approve / Send back (the Team tasks buttons). */
.attendance-decide{margin-top:10px;padding-top:10px;border-top:1px solid var(--hairline)}
.attendance-decide .attendance-times{margin:0}
/* Attendance ranges (2026-10-06): the range tabs, the custom dates, the filters, a person's row (a button) and their days. */
#attendanceRange{margin-top:12px}
.attendance-custom{display:grid;grid-template-columns:1fr 1fr;gap:4px 8px;margin-top:10px;align-items:end}
.attendance-custom .field-label{grid-row:1}
.attendance-custom .field{grid-row:2;min-width:0}
.attendance-custom .btn{grid-column:1 / -1;grid-row:3;margin-top:6px}
.attendance-filters{display:flex;gap:8px;margin-top:10px}
.attendance-filters .field{flex:1;min-width:0}
.attendance-person{display:block;width:100%;text-align:left;font:inherit;color:inherit;cursor:pointer}
.attendance-person-head{display:flex;align-items:center;gap:10px;margin-top:12px}
.attendance-person-head b{min-width:0;overflow-wrap:anywhere}
.attendance-summary .attendance-totals{grid-template-columns:repeat(auto-fit,minmax(84px,1fr))}
.attendance-day .attendance-totals{grid-template-columns:repeat(auto-fit,minmax(110px,1fr))}
/* A session today: Worked leads, Breaks is the smaller figure; an open session has the work bar's green dot by its times. */
.attendance-today{grid-template-columns:1.6fr 1fr}
.attendance-today .attendance-total{justify-content:flex-end}
.attendance-today .attendance-total+.attendance-total b{font-size:20px}
.attendance-session.is-open .attendance-span::before{content:"";display:inline-block;width:7px;height:7px;margin-right:6px;border-radius:50%;background:var(--green);vertical-align:1px}
/* Range totals: three or more tiles to a row, so the figure is smaller and stays on one line. */
.attendance-summary .attendance-total b,.attendance-day .attendance-total b{font-size:22px;white-space:nowrap}
/* Export sits under the list, out of the title bar (the lead, 2026-10-07). */
.attendance-foot{display:flex;justify-content:flex-end;margin-top:14px}
.org-panel-head{display:flex;align-items:center;justify-content:space-between;gap:8px}
.workday-days{display:flex;flex-wrap:wrap;gap:6px 12px;margin:4px 0 8px}
.workday-days label{display:flex;align-items:center;gap:6px;font-size:14px}
#teamPulseSummary:empty{display:none}
#workStatusCard .work-started{margin:-4px 0 10px}
/* Tools › Work day: the row holds its own Start my day / End my day button in place of the chevron. */
.work-row .btn{min-width:0;padding:0 14px}
/* The Home card while the organization setup is unfinished: a glass panel marked with a violet left edge. */
#orgSetupCard{position:relative;padding-left:22px}
#orgSetupCard::before{content:"";position:absolute;left:0;top:18px;bottom:18px;width:3px;border-radius:0 3px 3px 0;background:var(--a)}
.banner-title{margin:0 0 4px;font-size:19px}
/* The files an agent already holds, listed in the builder's Context step. */
.file-row{grid-template-columns:44px minmax(0,1fr) 44px;align-items:center}
.file-row .toolbar{margin:0}
.file-row .toolbar:has(.confirm-row){grid-column:1/-1}
.builder-files-head{margin-top:18px}

/* ---- Agents tab: the create card, then a fixed 130px glass card per agent, flowing from the left.
   Glass level set with the panels in index.html. ---- */
/* The cards keep their 130px size, so a row almost never divides the column exactly. The leftover
   is split evenly either side instead of piling up on the right, and auto-fit drops the tracks
   nothing was placed in, so a single card is centred rather than parked in a phantom column.
   Spreading the leftover into the gaps instead would push the cards apart, which reads worse than
   a wider margin: at 390px two columns leave 88px over, which is 44px a side or a 98px gap. */
.agent-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin-top:12px}
/* An agent card (ref/agent_menu.jpeg): the portrait large and square on top, which opens the agent; Follow and the
   heart with its count over the portrait's lower edge; name, role on one line and whose it is under it; Tools and
   Edit for someone who manages the agent. A live agent carries a LIVE mark and a ring. */
.agent-card,.agent-create-card{position:relative;min-width:0;border-radius:var(--r-compact);color:var(--text);text-align:left}
.agent-card{display:flex;flex-direction:column;overflow:hidden;padding:0}
.agent-card.live{box-shadow:0 0 0 2px var(--live),var(--shadow)}
.agent-card-media{position:relative}
.agent-card-open{display:block;width:100%;aspect-ratio:1;padding:0;border:0;background:var(--agent-fill);color:var(--text);transition:opacity .12s ease}
.agent-card-open:active{opacity:.8}
.agent-card-av{display:grid;place-items:center;width:100%;height:100%;overflow:hidden;font-size:30px;font-weight:700}
.agent-card-av img{width:100%;height:100%;object-fit:cover;transition:opacity 200ms var(--ease-out)}
.agent-card-av img.img-wait{opacity:0}
.agent-card-live{position:absolute;top:8px;left:8px;padding:2px 8px;border-radius:var(--r-pill);background:var(--live-fill);color:var(--on-live);font-size:12px;font-weight:700;letter-spacing:.06em}
.agent-card-follow[aria-pressed="true"]{border-color:color-mix(in srgb,var(--b) 55%,transparent);color:var(--b)}
.agent-card-follow:disabled{opacity:.5}
/* The follow colour eases in once the server has said yes (it is set only then). */
.agent-card-follow{transition:opacity .12s ease,color 150ms ease,border-color 150ms ease}
.agent-card-body{display:grid;gap:1px;padding:9px 12px 11px;min-width:0}
.agent-card-name{display:block;font-size:14px;font-weight:700;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.agent-card-role{display:block;font-size:12px;line-height:1.35;color:var(--text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.agent-card-owner{display:block;font-size:12px;line-height:1.35;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.agent-card-icons{display:flex;gap:4px;margin-top:6px}
.agent-card-icon{flex:none;display:grid;place-items:center;width:36px;height:36px;padding:0;border:1px solid var(--line);border-radius:var(--r-small);background:var(--fill-1);color:var(--text);transition:opacity .12s ease}
.agent-card-open.agent-card-icon{width:100%;height:auto;border:0;border-radius:0}
.agent-card-icon .icon{width:18px;height:18px}
.agent-card-icon:active{opacity:.6;background:var(--pressed)}
.agent-create-card{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;width:100%;min-height:170px;padding:12px;font-size:13px;font-weight:600;line-height:1.3;text-align:center;transition:opacity .12s ease}
.agent-create-card .icon{width:28px;height:28px}
.agent-create-card:active{opacity:.72}
/* The Inbox filters stay on one line: each segment takes its label's width. */
#inboxFilters .seg-tab{flex:1 1 auto;min-width:44px;white-space:nowrap}
#agentDepartment{margin-bottom:2px}
/* An admin's Owner and Department filters on the Personal tab, side by side. */
.agent-filters{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
.agent-filters .field{margin-top:6px}

/* ---- Documents: the list from Tools, and the editor as a full page.
   The editor owns the screen: show() hides the top bar and the nav while it is open and the phone column
   stretches, so the sheet reaches the bottom of the viewport. The draft is prose a person reads, so the
   text is Geist at reading size; the chrome around it (buttons, version label) is unchanged. The text is
   plain and selectable; no formatting is applied. ---- */
/* ---- Documents and Templates: the list is Tasks' cards (neutral edge, body opens it, a bin at the end deletes it) and
   Tasks' round + at the bottom right, so the last card clears it as Tasks' does. ---- */
#documentsScreen{--bar:color-mix(in srgb,var(--text-2) 28%,transparent)}
#documentsScreen.active{padding-bottom:calc(92px + 56px + 16px)}
#documentsScreen.active:not(.fab-entered) .tasks-fab{animation:tasks-fab-in .36s var(--spring)}
.doc-cards{display:grid;gap:8px;margin-top:12px}
.task-card.doc-card{grid-template-columns:minmax(0,1fr) 44px;gap:4px;padding-left:10px}
.doc-card .task-title{display:block;overflow-wrap:anywhere}
.doc-card .task-meta{display:block;margin-top:4px}
/* Delete, everywhere (2026-10-03): this 44px bin with "Delete <name>" as its name (.trash-btn). */
.btn.trash-btn{flex:none;display:grid;place-items:center;width:44px;min-width:44px;height:44px;min-height:44px;padding:0;border:0;background:none;box-shadow:none;color:var(--text-2)}
.trash-btn .icon{width:20px;height:20px}
.trash-btn:active:not(:disabled){opacity:.72}
@media (hover:hover) and (pointer:fine){.trash-btn:hover{color:var(--bad)}}
/* An inline add (beside or under a field), everywhere (2026-10-03): a secondary button, the FAB's + and its label. */
.btn.add-btn{min-height:44px}
.add-btn .icon{flex:none;width:18px;height:18px}
.doc-empty{margin:12px 0 0}
body.doc-open .phone{display:flex;flex-direction:column;padding-bottom:max(16px,env(safe-area-inset-bottom))}
#documentScreen.active{flex:1;display:flex;flex-direction:column;min-width:0}
/* The header row stays reachable while the page scrolls, on the same glass as the app's top bar. */
.doc-head{position:sticky;top:calc(max(8px,var(--safe-top)) + 8px);z-index:20;padding:8px;border-radius:var(--r-panel)}
.doc-head-row{display:flex;align-items:center;gap:8px}
.doc-head-row .btn{flex:none}
.doc-head textarea.doc-title{flex:1;min-width:0;min-height:44px;padding:10px 12px;font-size:17px;font-weight:600;line-height:1.3;letter-spacing:-.01em;resize:none;overflow:hidden;field-sizing:content}
/* Preview: the title reads as a heading, not a box. */
.doc-head textarea.doc-title[readonly]{border-color:transparent;background:transparent;box-shadow:none;padding-left:4px;padding-right:4px}
.doc-head .note{margin:8px 2px 2px}
.doc-head .note:empty{display:none}
/* The sheet is the page: it fills the width inside the phone padding, reaches the bottom of the screen and
   grows with the draft. Its inner margin is the paper's margin. */
.doc-sheet{flex:1;display:flex;flex-direction:column;min-height:52vh;margin-top:12px;padding:26px 24px;border-radius:var(--r-panel)}
.doc-body{flex:1 0 auto;display:block;width:100%;margin:0;padding:0;border:0;background:none;color:var(--text);
  font-family:var(--font);font-size:15px;line-height:1.65;caret-color:var(--text);resize:none;overflow:hidden}
.doc-body::placeholder{color:var(--placeholder);opacity:1}
/* The one control in the app without a focus ring: it fills the page, so a ring would draw a box around the
   whole sheet and undo the paper. The caret is the focus, as it is in any document editor. */
.doc-body:focus-visible{outline:none}
#documentVersion,#documentsMessage:empty,#documentMessage:empty{margin-top:8px}
#documentVersion:empty,#documentsMessage:empty,#documentMessage:empty{display:none}
#documentVersion:not(.status-error){font-family:var(--mono);font-weight:500}
/* Rich documents: the page renders the server's sanitised content_html. Document HTML carries no class attribute:
   the server strips it. Its CSS is scoped to .doc-page. Read-only as the preview, contenteditable in the editor. */
.doc-page{min-height:40vh;outline:none;overflow-wrap:anywhere}
.doc-page:empty::before{content:attr(data-placeholder);color:var(--placeholder)}
/* 04-32: no frame inside the paper while editing; the sheet itself takes the focus ring. */
.doc-sheet:has(.doc-page.doc-editing:focus){outline:var(--ring-width,2px) solid var(--ring);outline-offset:var(--ring-offset,2px)}
.doc-page h1{margin:.2em 0 .5em;font-size:24px;line-height:1.25}
.doc-page h2{margin:1em 0 .4em;font-size:19px;line-height:1.3}
.doc-page h3,.doc-page h4,.doc-page h5,.doc-page h6{margin:1em 0 .35em;font-size:16px;line-height:1.35}
.doc-page p,.doc-page div{margin:0 0 .75em}
.doc-page ul,.doc-page ol{margin:0 0 .75em;padding-left:1.4em}
.doc-page a{color:var(--b);text-decoration:underline}
.doc-page table{width:100%;margin:0 0 .75em;border-collapse:collapse}
.doc-page th,.doc-page td{padding:6px 8px;border:1px solid var(--line);text-align:left;vertical-align:top}
.doc-page blockquote{margin:0 0 .75em;padding-left:12px;border-left:3px solid var(--line)}
.doc-page img{max-width:100%;height:auto}
.doc-page pre,.doc-page code{font-family:var(--mono);font-size:13px;white-space:pre-wrap}
/* UI polish B1 (04-21): the title row is Back, the title and one primary button; Export (a menu), Done and History sit on
   the version line; the formatting row is grouped (style · B I U · lists · alignment · link) as joined 44x40 buttons. */
.doc-meta-actions{flex:none;display:flex;align-items:center;gap:6px;margin-top:6px}
.doc-meta-actions .btn{min-height:44px;padding:0 12px;font-size:13px}
.doc-meta .doc-history-btn{margin-top:0}
.doc-actions{position:relative}
.doc-export-btn{gap:4px}
.doc-export-btn .icon{width:16px;height:16px;transform:rotate(90deg);transition:transform .15s ease}
@media (prefers-reduced-motion:reduce){.doc-export-btn .icon{transition:none}}
.doc-export-btn[aria-expanded="true"] .icon{transform:rotate(-90deg)}
.doc-export-menu{position:absolute;top:calc(100% + 8px);right:0;min-width:200px}
.doc-export-menu .hub-menu-item small{margin-left:auto;font-family:var(--mono);font-size:12px;font-weight:500;color:var(--text-2)}
.doc-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:10px}
.doc-toolbar .field{width:auto;min-width:0;min-height:44px;padding:0 26px 0 8px;background-position:right 6px center}
.doc-tool-group{display:inline-flex;border:1px solid var(--line);border-radius:var(--r-inner);background:var(--fill-1)}
.doc-tool-group .btn{width:44px;min-width:44px;min-height:44px;height:44px;padding:0;border:0;border-radius:0;background:none;box-shadow:none;font-size:15px}
.doc-tool-group .btn+.btn{border-left:1px solid var(--line)}
.doc-tool-group .btn:first-child{border-radius:calc(var(--r-inner) - 1px) 0 0 calc(var(--r-inner) - 1px)}
.doc-tool-group .btn:last-child{border-radius:0 calc(var(--r-inner) - 1px) calc(var(--r-inner) - 1px) 0}
.doc-tool-group .btn:only-child{border-radius:calc(var(--r-inner) - 1px)}
.doc-tool-group .btn:focus-visible{position:relative;z-index:1}
.doc-tool-group .btn:active{background:var(--pressed)}
.doc-tool-group .btn .icon{width:20px;height:20px}
.doc-link-row{display:flex;gap:6px;margin-top:8px}
.doc-link-row .field{flex:1;min-width:0}
.check-row{display:flex;align-items:center;gap:8px;margin-top:12px;font-size:13px;line-height:1.4;color:var(--text-2)}
/* A letterhead page (the server's letterhead_html): the locked background at the page's proportions, and only the
   content box on it editable. Its own inline styles place the box; these keep it inside the sheet. */
.doc-page.has-letterhead{padding:0}
.doc-page .yv-doc-visual-template{position:relative;width:100%;max-width:100%;overflow:hidden;background-size:100% 100%;background-repeat:no-repeat}
.doc-page .yv-doc-visual-editable{position:absolute;overflow:auto;outline:none;color:#111;font-size:12px;line-height:1.5}
.doc-page .yv-doc-visual-editable.doc-editing{box-shadow:inset 0 0 0 1px rgba(91,61,245,.5)}
/* The version line carries History at its end. */
/* The version line stays one line: when it and the actions do not fit side by side, the actions move under it. */
.doc-meta{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:0 8px}
.doc-meta .note{min-width:0;white-space:nowrap;font-size:12px}
.doc-meta-actions{margin-left:auto}
.doc-history-btn{flex:none;min-height:44px;margin-top:6px;padding:0 14px;font-size:13px}
/* Version history: one row a version, newest first, the current one tagged. */
.doc-version-row{grid-template-columns:minmax(0,1fr) auto;min-height:56px}
#documentHistoryMessage:empty{display:none}
/* An old version, read-only, where the text was: the bar says which one and offers Restore. */
.doc-old-bar{margin:-8px 0 18px;padding-bottom:14px;border-bottom:1px solid var(--line)}
.doc-old-bar .note{margin:0 0 10px;color:var(--warn)}
.doc-old{white-space:pre-wrap;overflow-wrap:anywhere}

/* ---- Tools: one large "Basic tools" card, every tool a row with its icon, name and live one-line state. ---- */
/* One card only (the lead, 2026-09-23): the rows live directly in the Basic tools panel, with a hairline
   between them. No inner glass box, no border, no shadow, no second blur. */
.basic-tools .glist{margin-top:4px;padding:0;border:0;background:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none;border-radius:0}
.basic-tools .glist-row{min-height:60px;padding:11px 0}
.basic-tools .glist-icon{width:38px;height:38px}
.basic-tools .glist-row b{font-size:15px}
.basic-tools .glist-row.is-off :is(.glist-icon,.glist-text b){opacity:.55}
.basic-tools .glist-row.is-off .chev{visibility:hidden}
.basic-tools .glist-row small{overflow-wrap:anywhere}
.basic-tools .work-row .btn{min-height:44px;padding:0 12px;font-size:13px}
#agentToolsList .tool-group-head{margin:4px 2px 8px}
/* ---- Tasks: one glass panel per list the server sends (the cards themselves are tasks-page.css).
   Titles, notes and buttons in Geist; the due day and where a task came from in the machine voice. ---- */
#tasksLaterNote:empty{display:none}
#tasksLaterNote{margin:12px 4px 0;font-size:12.5px}
/* The count stays left of the fixed profile button (#profileBtn, 56px from the column's right edge) when the list is
   scrolled under it: the card's own inset is about 33px, so 28px more keeps it clear. */
.task-list-head{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin-bottom:2px;padding-right:28px}
.task-list-head .k{margin:0}
.task-list-head .count{color:var(--text-2)}
.task-empty{margin:10px 0 2px;font-size:13px;line-height:1.45;color:var(--text-2)}
.task{padding:14px 0 12px}
.task+.task{border-top:1px solid var(--row-edge)}
.task-top{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
.task-title{display:block;min-width:0;font-size:14.5px;line-height:1.35;overflow-wrap:anywhere}
.task-done .task-title{color:var(--text-2)}
.task-meta{margin:4px 0 0;font-family:var(--mono);font-size:12px;font-weight:500;line-height:1.45;letter-spacing:0;color:var(--text-2);overflow-wrap:anywhere}
.task-summary{margin:6px 0 0;font-size:13px;line-height:1.5;color:var(--text-2);white-space:pre-wrap;overflow-wrap:anywhere}
.task-notes{display:grid;gap:6px;margin:10px 0 0;padding:0;list-style:none}
.task-notes li{padding-left:10px;border-left:2px solid var(--line);font-size:13px;line-height:1.45;overflow-wrap:anywhere}
.task-note-at{display:block;font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:0;color:var(--text-2)}
.task-actions{gap:6px;margin-top:10px}
.task-actions>.btn{padding:0 10px;font-size:13px;box-shadow:none}

/* ---- Live microphone: the always-listening mic in the text bar and the line above it. The green
   "listening" state follows the recognition engine, never the intent. ---- */
.story .composer:has(#liveMicBtn:not(.hidden)){grid-template-columns:44px minmax(0,1fr) 44px 44px}
/* ---- Attach in the text bar (workspace.js, CHAT ATTACHMENTS): the paperclip beside EN, and a chip per file above the bar. ---- */
.story .composer:has(#attachBtn){grid-template-columns:44px 44px minmax(0,1fr) 44px}
.story .composer:has(#attachBtn):has(#liveMicBtn:not(.hidden)){grid-template-columns:44px 44px minmax(0,1fr) 44px 44px}
@media (max-width:399px){
  .story .composer:has(#attachBtn){grid-template-columns:38px 38px minmax(0,1fr) 44px}
  .story .composer:has(#attachBtn):has(#liveMicBtn:not(.hidden)){grid-template-columns:38px 38px minmax(0,1fr) 40px 44px}
  .story .composer #langBtn,.story .composer #attachBtn{width:38px}
  .story .composer:has(#liveMicBtn:not(.hidden)) #liveMicBtn{width:40px}
}
/* At 320 the message box keeps the placeholder on one line (about 133px at 13px): EN, the paperclip and the mic go to
   34px, Send to 38px, 2px apart. */
@media (max-width:359px){
  .story .composer:has(#attachBtn){gap:2px;grid-template-columns:34px 34px minmax(0,1fr) 38px}
  .story .composer:has(#attachBtn):has(#liveMicBtn:not(.hidden)){grid-template-columns:34px 34px minmax(0,1fr) 34px 38px}
  .story .composer #langBtn,.story .composer #attachBtn,.story .composer:has(#liveMicBtn:not(.hidden)) #liveMicBtn{width:34px}
  .story .composer:has(#attachBtn) #sendBtn{width:38px}
  .story .composer:has(#attachBtn) textarea::placeholder{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
}
#attachBtn .icon{width:20px;height:20px}
.chat-attachments{flex:none;display:flex;flex-wrap:wrap;gap:6px;margin:0 0 6px}
.chat-attach{display:inline-flex;align-items:center;gap:6px;max-width:100%;min-height:36px;padding:0 4px 0 12px;border:1px solid var(--line);border-radius:var(--r-pill);background:var(--story-glass,var(--fill-3));color:var(--text);font:500 12px/1.2 var(--font)}
.chat-attach-name{min-width:0;max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chat-attach.photo{padding-left:4px}
.chat-attach-thumb{flex:none;width:28px;height:28px;border-radius:6px;object-fit:cover}
.chat-attach-state{flex:none;font-size:11px;font-weight:600;color:var(--text-2)}
.chat-attach.failed{border-color:var(--bad)}
.chat-attach.failed .chat-attach-state{color:var(--bad)}
.chat-attach.sending{opacity:.6}
.chat-attach-retry{flex:none;min-height:32px;padding:0 8px;border:0;background:none;color:var(--text);font:600 12px/1 var(--font);text-decoration:underline;cursor:pointer}
.chat-attach-remove{flex:none;display:inline-grid;place-items:center;width:32px;height:32px;padding:0;border:0;border-radius:50%;background:none;color:var(--text-2);cursor:pointer}
.chat-attach-remove .icon{width:16px;height:16px}
.msg-attached{display:block;margin-top:4px;font-size:12px;font-weight:500;line-height:1.4;color:var(--text-2);overflow-wrap:anywhere}
#liveMicBtn .icon{width:20px;height:20px}
#liveMicBtn.listening{border-color:var(--green);background:var(--green);box-shadow:none;color:#04241C}
#liveMicBtn.paused{color:var(--text-2)}
.live-mic-status{flex:none;display:flex;align-items:center;gap:6px;margin:0 6px;font-size:12px;font-weight:600;line-height:1.35;color:var(--text-2)}
.live-mic-status:has(#liveMicStatusText:empty):not(:has(#liveListenNow:not(.hidden))){display:none}
/* An offer that a later message left unanswered: its buttons are dead and it says so. */
.tool-confirm.retired{opacity:.6}
.tool-confirm .tool-retired{align-self:center;font-size:12px;color:var(--text-2)}
.live-mic-status .dot{flex:none;width:7px;height:7px;border-radius:50%;background:var(--track)}
.live-mic-status.live{color:var(--green)}
.live-mic-status.live .dot{background:var(--green);animation:meeting-pulse 1.5s ease-in-out infinite alternate}
.live-mic-status.blocked{color:var(--bad)}
.live-mic-status.blocked .dot{background:var(--bad)}
/* On short screens the button column reaches down to the chat; the line keeps clear of it as the chat does. */
@media (max-height:760px){body:not(.verser-open) .live-mic-status{margin-right:52px}}
@media (max-height:600px){body:not(.verser-open) .live-mic-status{margin-right:48px}}
/* Listen now: shown only once a reply has held the microphone for several seconds (workspace.js, LISTEN NOW). */
.listen-now{flex:none;min-height:44px;padding:0 12px;font-size:12px;font-weight:600;box-shadow:none}
.live-mic-status .listen-now{margin-left:auto}
#meetingListenNow{display:block;margin:10px 0 0}
/* The pending count on Live's Inbox button: the server's pendingCount, 99+ above 99. */
#liveInboxBtn{position:relative}
/* The right column on Verser: Go Live, Parley, Tools, Edit and Social, with Meeting (the agent has the meetings tool)
   and Inbox (the person manages the agent). With the stage the full height of the screen, all seven stay 44px in one
   column above the text bar at 390x844 and 375x667; below 600px of height they step down to 40px (index.html). */
.story-badge{position:absolute;top:-3px;right:-3px;min-width:18px;height:18px;padding:0 5px;border-radius:var(--r-pill);background:var(--pink);color:var(--night-floor);font-size:10.5px;font-weight:700;line-height:18px;text-align:center;pointer-events:none}

/* ---- Meeting room: before, recording, minutes, all on one screen.
   What was said is reading text, in Geist Mono like the times and the capacity count. Nothing on this screen plays audio. ---- */
.meeting-head{display:flex;align-items:center;justify-content:space-between;gap:12px}
.meeting-head>div{min-width:0}
.meeting-head .k{margin:0}
.meeting-head b{display:block;margin-top:2px;font-size:17px;line-height:1.3;overflow-wrap:anywhere}
.meeting-head .btn{flex:none}
#meetingMicBtn .icon{width:18px;height:18px}
/* "Listening" is only ever on screen while recognition is actually running: the class follows the
   engine, not the intent, so a paused or refused microphone can never read as listening. */
.meeting-status-row{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 12px;margin-top:14px}
.meeting-status-row>.meeting-status{margin:0}
.meeting-status{display:inline-flex;align-items:center;gap:8px;margin:14px 0 0;padding:6px 12px;border:1px solid var(--line);border-radius:var(--r-pill);background:var(--chip-fill);font-size:12.5px;font-weight:600;line-height:1.3;color:var(--text-2)}
.meeting-status .dot{flex:none;width:8px;height:8px;border-radius:50%;background:var(--track)}
.meeting-status.live{border-color:color-mix(in srgb,var(--green) 45%,transparent);color:var(--green)}
.meeting-status.live .dot{background:var(--green);animation:meeting-pulse 1.5s ease-in-out infinite alternate}
.meeting-status.paused{border-color:color-mix(in srgb,var(--warn) 45%,transparent);color:var(--warn)}
.meeting-status.paused .dot{background:var(--warn)}
.meeting-status.blocked{border-color:color-mix(in srgb,var(--bad) 45%,transparent);color:var(--bad)}
.meeting-status.blocked .dot{background:var(--bad)}
@keyframes meeting-pulse{from{opacity:1}to{opacity:.3}}
.meeting-capacity{margin-top:10px;font-family:var(--mono);font-size:12px;font-weight:500;letter-spacing:0}
.meeting-capacity.status-error{font-family:var(--font);font-weight:500}
/* One spoken line: who said it (Geist), then the words themselves (Geist Mono). */
.meeting-line{display:grid;gap:3px;padding:11px 0}
.meeting-line+.meeting-line{border-top:1px solid var(--row-edge)}
.meeting-who{display:flex;align-items:baseline;gap:8px;font-size:13px;font-weight:600;line-height:1.3;overflow-wrap:anywhere}
.meeting-when{flex:none;font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:0;color:var(--text-2)}
.meeting-said{margin:0;font-family:var(--mono);font-size:15px;font-weight:400;line-height:1.55;letter-spacing:0;overflow-wrap:anywhere}
/* Said but not yet accepted by the server: it stays on screen and says what it is. */
.meeting-line.unsent .meeting-said{color:var(--text-2)}
.meeting-unsent{font-family:var(--font);font-size:11px;font-weight:600;color:var(--warn)}
/* A guess the engine may still change: never posted, and grey at the end of the caption. */
.meeting-said.meeting-guess{color:var(--placeholder)}
/* In the room: one running caption, four lines tall; older words flow off the top, fading as they go. */
.meeting-room-caption{max-height:calc(17px * 1.55 * 4);overflow:hidden}
.meeting-room-caption.overflowing{-webkit-mask-image:linear-gradient(to bottom,transparent,#000 1.6em);mask-image:linear-gradient(to bottom,transparent,#000 1.6em)}
.meeting-room-caption p{margin:0;font-family:var(--mono);font-size:17px;line-height:1.55;letter-spacing:0;overflow-wrap:anywhere}
.meeting-room-caption .meeting-line{display:inline;padding:0;border:0}
.meeting-room-caption .meeting-said{font-size:inherit;line-height:inherit}
/* EN / AR, for a meeting held in both: what this person speaks, on their own screen. */
.meeting-lang{display:flex;flex:none;gap:4px}
.meeting-lang .btn{min-width:44px;padding-left:10px;padding-right:10px}
.meeting-lang .btn[aria-pressed="true"]{border-color:var(--ring);background:var(--pressed);box-shadow:inset 0 0 0 1px var(--ring);color:var(--text)}
.meeting-rec{margin-top:14px}
.meeting-rec b{display:block;font-size:13px;line-height:1.35}
.meeting-rec ul{margin:6px 0 0;padding-left:20px}
.meeting-rec li{margin-top:5px;font-size:13.5px;line-height:1.5;color:var(--text-2);overflow-wrap:anywhere}
.meeting-rec-at{margin-top:12px;font-family:var(--mono);font-size:11px;font-weight:500;letter-spacing:0;color:var(--text-2)}
/* The risk level is a quiet label beside its heading: no colour, no alarm. */
.meeting-rec-head{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
.meeting-risk{flex:none;font-size:11px;font-weight:500;line-height:1.35;color:var(--text-2);opacity:.8}
.meeting-rec-none{margin:6px 0 0;font-size:13px;line-height:1.45;color:var(--text-2)}
.meeting-rec-auto{margin-top:8px}
.meeting-rec-auto:empty{display:none}
/* A proposed task is a proposal: a dashed card, a Proposal chip, and no control that gives it to anybody.
   Before approval the organiser may delete one. */
.meeting-task{margin-top:10px;padding:14px;border:1px dashed var(--line);border-radius:var(--r-inner);background:var(--fill-1)}
.meeting-task-top{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
.meeting-task b{display:block;font-size:14px;line-height:1.35;overflow-wrap:anywhere}
.meeting-task p{margin:6px 0 0;font-size:12.5px;line-height:1.45;color:var(--text-2)}
/* Approved with the minutes: a solid edge and an Open chip, still with nothing to tap. */
.meeting-task.open{border-style:solid}
.meeting-task.removed{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:8px 14px;font-size:13px;color:var(--text-2)}
.meeting-task.removed span{min-width:0;overflow-wrap:anywhere}
.meeting-task-undo{flex:none;min-height:44px;padding:0 14px;font-size:13px;box-shadow:none}
.meeting-quote{margin:8px 0 0;padding-left:10px;border-left:2px solid var(--line);font-family:var(--font);font-size:14px;font-weight:400;line-height:1.5;letter-spacing:0;color:var(--text-2);overflow-wrap:anywhere}
#meetingAttendees .row,#meetingRoster .row{grid-template-columns:44px minmax(0,1fr) auto}
#meetingSummaryHint,#meetingTypedNote,#minutesTasksNote,#minutesReadOnlyNote{margin-top:8px}
#minutesReadOnlyNote:empty,#meetingTypedNote:empty{display:none}
#meetingMinutes textarea.field{min-height:96px;overflow-y:hidden;resize:none}
/* Minutes, one section per page: Back, where you are, Next. */
.minutes-pager .invisible{visibility:hidden}
.minutes-arrow{display:grid;place-items:center;width:44px;min-width:44px;height:44px;padding:0}
.minutes-arrow.next .icon{transform:scaleX(-1)}
/* 04-14: minutes a reader cannot edit read as text, not as fields. */
#meetingMinutes .field[readonly]{min-height:0;padding-left:2px;padding-right:2px;border-color:transparent;background:transparent;box-shadow:none;resize:none}
#minutesReadOnlyNote{margin:0 0 10px}
#minutesReadOnlyNote:empty{display:none}
.minutes-pager{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:10px;margin-top:12px}
#minutesPage{font-size:13px;text-align:center;color:var(--text-2)}
.meeting-task-side{display:flex;flex:none;align-items:center;gap:8px}
.meeting-task-top{flex-wrap:wrap;align-items:center;row-gap:6px}
/* The title has the card's full width; the tag and Delete sit on the line under it, Delete at the end. */
.meeting-task-top>b{flex:1 1 100%}
.meeting-task-side{flex:1 1 100%;justify-content:space-between}
.meeting-task p.meeting-task-meta span{display:block}
#minutesSummary{min-height:132px}
/* Your meetings: one tappable row per meeting, its state in words. */
.meeting-list{display:grid;gap:0;margin-top:8px}
/* Loading, failed or empty is said by #meetingListMessage in words: no "Nothing here yet." underneath it. */
#meetingList:empty{display:none}
.meeting-list-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:10px;width:100%;min-height:56px;padding:10px 0;border:0;border-radius:0;background:none;color:var(--text);font:inherit;text-align:left}
.meeting-list-row+.meeting-list-row{border-top:1px solid var(--row-edge)}
/* The organiser's Edit and Copy link, a line of their own under a scheduled or running meeting's row. */
.meeting-row-tools{grid-column:1/-1;display:flex;flex-wrap:wrap;gap:8px;padding:0 0 10px}
.btn.meeting-row-btn{min-height:44px;padding:0 14px;font-size:13px}
#meetingInviteMore,#meetingCopyLink{margin-top:10px}
.meeting-list-row b{display:block;font-size:14px;line-height:1.35;overflow-wrap:anywhere}
.meeting-list-row small{display:block;margin-top:2px;font-size:12px;line-height:1.45;color:var(--text-2)}
.meeting-list-row:disabled{opacity:.7}
.meeting-done-when{margin:0 0 4px}
/* House press on the rows and links that had none. */
.meeting-list-row,.work-status-open,.linkbtn{transition:opacity 120ms ease}
.meeting-list-row:active:not(:disabled),.work-status-open:active{opacity:.72}
.linkbtn:active{opacity:.6}
#meetingListMessage:empty{display:none}

/* ---- Calendar: one row per provider in the state the server reports, then today and upcoming. ---- */
.calendar-provider{grid-template-columns:44px minmax(0,1fr) auto}
.calendar-provider small{overflow-wrap:anywhere}
.calendar-provider .calendar-mark{background:var(--fill-2);box-shadow:inset 0 0 0 1px var(--line);color:var(--text)}
.calendar-provider .calendar-state{margin:4px 0 2px}
.calendar-provider .calendar-email{margin-top:4px;color:var(--text)}
.calendar-buttons{display:grid;gap:6px;justify-items:end}
/* The Disconnect question takes the row's width under the name, never squeezing the name into a sliver. */
.calendar-buttons:has(.confirm-row){grid-column:2/-1;justify-items:stretch}

/* ---- WhatsApp: the link state, the ban-risk warning before linking, the QR while waiting for the scan. ---- */
.whatsapp-state{margin:6px 0 10px;color:var(--text);overflow-wrap:anywhere}
.whatsapp-phone{display:grid;gap:8px;margin-bottom:12px}
.whatsapp-phone label{color:var(--text-2);font-size:13px}
.whatsapp-code{display:grid;justify-items:center;gap:8px;margin-bottom:12px}
.whatsapp-code-text{font-family:var(--mono);font-size:32px;font-weight:600;letter-spacing:.12em;color:var(--text);user-select:all}
.whatsapp-code .note{margin:0;text-align:center}
.whatsapp-qr{display:grid;justify-items:center;gap:8px;margin-bottom:12px}
.whatsapp-qr-code{width:min(264px,100%);background:#fff;border-radius:var(--r-small);padding:8px}
.whatsapp-qr-code svg{display:block;width:100%;height:auto}
.whatsapp-buttons{display:flex;gap:8px;flex-wrap:wrap}
/* Work chats: one row per chat, the Work chat tick on the right. */
#whatsappChatFilter{margin:4px 0 8px}
.whatsapp-chat{display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:44px;padding:8px 0}
.whatsapp-chat+.whatsapp-chat{border-top:1px solid var(--row-edge)}
.whatsapp-chat-text{display:grid;min-width:0}
.whatsapp-chat-name{color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.whatsapp-chat-text small{color:var(--text-2);font-size:13px}
.whatsapp-chat-mark{display:flex;align-items:center;gap:6px;flex:none;font-size:13px;color:var(--text-2)}
#whatsappMessage:empty{display:none}
.tool-email{flex-basis:100%;margin-top:4px;font-size:12px}
.tool-email summary{min-height:44px;padding:12px 0;line-height:20px;cursor:pointer;color:var(--text-2)}
.tool-email pre{margin:6px 0 0;font-family:var(--mono);font-size:12px;white-space:pre-wrap;overflow-wrap:anywhere}
#calendarMessage:empty,#calendarEventsMessage:empty{display:none}
.calendar-day{margin-top:12px}
.calendar-day>b{display:block;font-size:13px;line-height:1.35;color:var(--text-2)}
.calendar-event{display:grid;gap:2px;padding:10px 0;border-bottom:1px solid var(--row-edge)}
.calendar-event span{font-size:14px;font-weight:600;line-height:1.35;overflow-wrap:anywhere}
.calendar-event small{font-size:12px;line-height:1.45;color:var(--text-2)}
/* A meeting invite: who, when and how long. */
.invite-facts{display:grid;grid-template-columns:auto minmax(0,1fr);gap:4px 12px;margin:10px 0 0;font-size:13px;line-height:1.45}
.invite-facts dt{color:var(--text-2)}
.invite-facts dd{margin:0;overflow-wrap:anywhere}
/* ---- Agent inbox: one card per item, its type and state as chips, the decision buttons on pending items only. ---- */
.inbox-agent{margin:2px 0 0;font-size:12.5px;line-height:1.4;color:var(--text-2)}
.inbox-agent:empty{display:none}
#inboxMessage:empty{display:none}
.inbox-item{margin-top:12px}
.inbox-item.inbox-opens{cursor:pointer}
/* The list, as a mail app's: one short row per item (who and when, the subject, small details); a tap opens it in full. */
.inbox-row{position:relative;display:grid;gap:3px;width:100%;min-height:72px;margin-top:8px;padding:12px 14px 12px 26px;border:1px solid var(--line);border-radius:var(--r-row);background:var(--panel);box-shadow:var(--shadow);color:var(--text);font:inherit;text-align:left;cursor:pointer;transition:transform 160ms var(--ease-out),background-color 120ms ease}
.inbox-row:active{transform:scale(.985);background:var(--pressed)}
@media (hover:hover){.inbox-row:hover{background:var(--fill-1)}}
@media (prefers-reduced-motion:reduce){.inbox-row{transition:none}.inbox-row:active{transform:none}}
.inbox-row.is-pending::before{content:"";position:absolute;left:11px;top:19px;width:8px;height:8px;border-radius:50%;background:var(--b)}
.inbox-row-top{display:flex;align-items:baseline;justify-content:space-between;gap:10px;min-width:0}
.inbox-row-from{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13px;color:var(--text-2)}
.inbox-row-when{flex:none;font-family:var(--mono);font-size:11.5px;color:var(--text-2)}
.inbox-row-subject{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:15px;line-height:1.35;font-weight:500}
.inbox-row.is-pending .inbox-row-subject{font-weight:700}
.inbox-row-details{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--mono);font-size:11.5px;color:var(--text-2)}
.inbox-pager{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:14px}
.inbox-pager[hidden]{display:none}
.inbox-pager .btn{display:inline-flex;align-items:center;gap:4px;min-height:44px}
.inbox-pager .flip{transform:scaleX(-1)}
.inbox-page-label{font-family:var(--mono);font-size:12px;color:var(--text-2)}
/* Reading one item: the tabs, list, pages and Send step aside; the item reads larger. */
#inboxScreen.inbox-reading :is(#inboxFilters,#inboxList,#inboxPager,#inboxComposeFab,#inboxMessage){display:none}
.inbox-full{margin-top:14px;padding:20px}
.inbox-full>b{font-size:20px;line-height:1.3}
.inbox-full .inbox-content{font-size:15px;line-height:1.6}
/* What a notification or a link opened (targetFlash, workspace.js): ringed, then the ring fades. */
.is-target{outline:2px solid var(--ring);outline-offset:3px;animation:target-fade 2.6s var(--ease-out) forwards}
@keyframes target-fade{0%,55%{outline-color:var(--ring)}100%{outline-color:transparent}}
@media (prefers-reduced-motion:reduce){.is-target{animation:none}}
.inbox-item-top{display:flex;flex-wrap:wrap;align-items:center;gap:6px}
/* On a filtered tab the state chip would only repeat the tab. */
#inboxList[data-status=pending] .tag-plain.pending,#inboxList[data-status=approved] .tag-plain.approved,#inboxList[data-status=rejected] .tag-plain.rejected{display:none}
.inbox-item>b{display:block;margin-top:8px;font-size:15px;line-height:1.35;overflow-wrap:anywhere}
.inbox-from,.inbox-meta{margin:4px 0 0;font-family:var(--mono);font-size:12px;font-weight:500;line-height:1.45;letter-spacing:0;color:var(--text-2);overflow-wrap:anywhere}
/* As on Tasks: the line breaks between its parts, never inside a date. */
.inbox-meta .meta-part{display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}
.inbox-item .toolbar .inbox-minutes-private{align-self:center;margin:0}
/* Send from this agent: a row with a chevron; the form opens under it. */
#inboxScreen.active:not(.fab-entered) #inboxComposeFab{animation:tasks-fab-in .36s var(--spring)}
@media (prefers-reduced-motion:reduce){#inboxScreen.active:not(.fab-entered) #inboxComposeFab{animation:tasks-fade .2s ease}}
/* Room under the last row and the pages for the write button, as on Tasks. */
#inboxScreen.active:not(.inbox-reading){padding-bottom:calc(92px + 56px + 16px)}
#inboxSendMessage{margin:12px 0 0}
#inboxSendMessage:empty{display:none}
.inbox-content{margin:8px 0 0;font-size:13.5px;line-height:1.5;white-space:pre-wrap;overflow-wrap:anywhere}
.inbox-item .toolbar{margin-top:12px}
/* Reject/Decline asks in one panel across the card: the question, then Cancel and the verb side by side. The card's
   other buttons (Approve, Open the minutes, Join) step aside until it is answered or cancelled. */
.inbox-item .toolbar:has(>.confirm-row)>:not(.confirm-row){display:none}
.inbox-item .confirm-row{display:grid;flex:1 1 100%;gap:12px;padding:14px;border:1px solid color-mix(in srgb,var(--bad) 30%,transparent);border-radius:var(--r-compact);background:color-mix(in srgb,var(--bad) 9%,transparent)}
.inbox-item .confirm-row:not(:has(.danger)){border-color:var(--row-edge);background:var(--chip-fill)}
.inbox-item .confirm-row small{font-size:13.5px;color:var(--text)}
.inbox-item .confirm-row .toolbar{display:grid;grid-template-columns:1fr 1fr;margin:0}
.inbox-result{margin:10px 0 0;font-size:13px;line-height:1.45}
.inbox-result:empty{display:none}
.inbox-empty{margin:12px 2px 0;font-size:13px;color:var(--text-2)}

/* ---- Inline confirm and the bottom confirm bar ---- */
.confirm-row{display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap}
.confirm-row small{flex-basis:100%;font-size:12.5px;line-height:1.45;color:var(--text-2)}
.confirm-row .toolbar{gap:8px}
/* The bottom confirm is modal: a solid surface (the tour card's) over a light scrim, above an open sheet. */
.confirm-scrim{position:fixed;inset:0;z-index:71;background:color-mix(in srgb,var(--night-floor) 35%,transparent)}
/* The inline question fades in where the button was (opacity only: its width differs). The bottom bar rises 8px and
   fades in; its exit is a copy in confirmBarLeave. The scrim fades in and out under it. Reduced motion: fades only. */
.confirm-row{transition:opacity 150ms var(--ease-out)}
@starting-style{.confirm-row{opacity:0}}
.confirm-scrim{transition:opacity 200ms var(--ease-out)}
@starting-style{.confirm-scrim{opacity:0}}
.confirm-scrim.hidden.leaving{display:block!important;opacity:0;pointer-events:none;transition-duration:150ms}
.confirm-bar{transition:opacity 200ms var(--ease-out),translate 200ms var(--ease-out)}
@starting-style{.confirm-bar{opacity:0;translate:0 8px}}
@media (prefers-reduced-motion:reduce){.confirm-bar{transition-property:opacity}}
.confirm-bar{position:fixed;left:50%;bottom:var(--float-bottom);transform:translateX(-50%);z-index:72;display:grid;gap:12px;width:calc(100% - 32px);max-width:420px;padding:16px;border-radius:var(--r-compact)}
.confirm-bar p{margin:0;font-size:14px;line-height:1.45}
.confirm-bar .toolbar{justify-content:flex-end}
/* While an inline confirm is open in a sheet, the sheet's Cancel/Save step aside: one Cancel on screen. */
.sheet.confirming .sheet-foot{display:none}

/* ---- The glass switch: Sign in / Sign up on login, the three scopes on the Agents tab.
   Glass level set with the bottom nav in index.html. ---- */
.seg{display:flex;gap:4px;margin-top:12px;padding:6px;border-radius:var(--r-compact)}
/* One segmented control everywhere (2026-10-03): the same 13.5px label and 6px inset on every screen. */
.seg-tab{flex:1;min-width:0;min-height:44px;padding:0 6px;border:0;border-radius:var(--r-row);background:none;color:var(--tab-label);font:inherit;font-size:13.5px;font-weight:600;line-height:1.2;transition:transform 160ms var(--ease-out),opacity 120ms ease}
.seg-tab:active{opacity:.72}
.seg-tab[aria-selected="true"]{background:var(--tab-active);box-shadow:inset 0 0 0 1px var(--tab-edge);color:var(--text)}

/* ---- Organization sign-up: login CTA, 4-step wizard, review ---- */
.features{display:grid;gap:14px;margin:18px 0 4px}
.feature{display:grid;grid-template-columns:24px minmax(0,1fr);gap:12px;align-items:start}
.feature-icon{color:var(--text)}
.feature-icon svg{display:block;width:24px;height:24px;fill:none;stroke:currentColor;stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round}
.feature b{display:block;font-size:14px;line-height:1.35}
.feature p{margin:2px 0 0;font-size:12.5px;line-height:1.45;color:var(--text-2)}
.field-hint{margin:6px 2px 0;font-size:12.5px}
.req{color:var(--bad)}
.linkbtn{display:inline-block;margin:-12px -6px;padding:12px 6px;border:0;background:none;color:var(--link);font:inherit;font-size:inherit;font-weight:600;text-decoration:underline;text-underline-offset:3px}
.counter{margin:6px 2px 0;text-align:right;font-variant-numeric:tabular-nums}
.notice-admin{margin-top:16px}
.plan-list{margin-top:12px}
.plan{width:100%;text-align:left;color:var(--text)}
.plan-top{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
.plan-top .tag{padding:0;border:0;background:none;font-size:12.5px;font-weight:600;color:var(--text-2);text-align:right}
.review-group{margin-top:10px}
.review-head{display:flex;align-items:center;justify-content:space-between;gap:10px}
.review-row{display:grid;grid-template-columns:minmax(88px,38%) minmax(0,1fr);gap:10px;margin:0;padding-top:9px;font-size:12.5px;line-height:1.45;color:var(--text-2)}
.review-row b{font-size:14px;font-weight:500;color:var(--text);overflow-wrap:anywhere}
.field-invalid{border-color:var(--bad);box-shadow:0 0 0 1px var(--bad)}

/* ---- Per-agent tool selection ---- */
.tool-row{grid-template-columns:minmax(0,1fr) auto;min-height:64px;cursor:pointer}
.tool-row input{width:24px;height:24px;margin:0 2px 0 0}

/* ---- Admin hub, detail screens and the bottom sheet ---- */
.hub-card{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:12px;width:100%;text-align:left}
.glist-row.hub-card{grid-template-columns:auto minmax(0,1fr) auto;gap:14px}
.hub-card>div{min-width:0}
.hub-card p{margin:2px 0 0}
.screen>.hub-card{min-height:72px}
/* 04-20: an Add card's + is a 44px solid chip, so the card reads as the button it is. */
.hub-card .chev.add-chip{display:grid;place-items:center;width:44px;height:44px;border-radius:50%;background:var(--primary);box-shadow:none;color:var(--on-primary)}
.hub-card:disabled .chev.add-chip{background:var(--fill-2);box-shadow:none;color:var(--text-2)}
/* Counts in the hub list speak in the machine voice; a failure line stays in Geist. */
#hubDepartmentsNote:not(.status-error),#hubStaffNote:not(.status-error){font-family:var(--mono);font-size:13px;font-weight:500}
/* A disabled card is dimmed, but the line saying WHY it is disabled has to stay readable. Opacity on
   the button dims its whole subtree, so it is applied only to the parts that carry no reason. */
.hub-card:disabled>div>b,.hub-card:disabled>div>p:not([role=status]),.hub-card:disabled .chev.add-chip{opacity:.55}
.hub-card:disabled .chev:not(.add-chip){opacity:.3}
.hub-card:disabled{cursor:default}
.detail-list{margin-top:2px}
.detail-list .review-row{align-items:baseline;padding:11px 0}
.detail-list .review-row+.review-row{border-top:1px solid var(--hairline)}
.detail-list .review-row b{white-space:pre-wrap}
.sheet-backdrop{position:fixed;inset:0;z-index:60;display:flex;align-items:flex-end;justify-content:center}
/* The scrim fades on its own layer: an opacity on the backdrop itself would cut the sheet's frost off from the page while it fades. */
.sheet-backdrop::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--scrim);transition:opacity 200ms var(--ease-out)}
.sheet{width:100%;max-width:var(--phone);max-height:88dvh;display:flex;flex-direction:column;padding:4px 16px max(14px,env(safe-area-inset-bottom));border-bottom:0;border-radius:var(--r-panel) var(--r-panel) 0 0;transition:transform 300ms var(--ease-drawer)}
.sheet:focus{outline:none}
/* Enter and exit: the sheet rises on the drawer curve and goes back down the same way, a little faster. */
.sheet-backdrop.entering::before,.sheet-backdrop.closing::before{opacity:0}
.sheet-backdrop.entering .sheet,.sheet-backdrop.closing .sheet{transform:translateY(100%)}
.sheet-backdrop.closing{pointer-events:none}
.sheet-backdrop.closing::before,.sheet-backdrop.closing .sheet{transition-duration:220ms}
.sheet-handle{flex:none;width:40px;height:5px;margin:8px auto 10px;border-radius:var(--r-pill);background:var(--handle)}
.sheet h3{margin:0 calc(2px + var(--ring-space)) 6px;font-size:19px}
/* The header: the title, and the optional action openSheet puts at its end (the task sheet's Edit), as a screen's
   header action sits. A long unbroken title wraps instead of widening the sheet. */
.sheet-head{display:flex;align-items:center;gap:8px;min-width:0}
/* Drag down from the handle or head to close (workspace.js, dragToDismiss): the sheet follows the finger with no transition,
   and those parts take the vertical touch instead of the page. */
.sheet.dragging{transition:none}
.sheet :is(.sheet-handle,.sheet-head){touch-action:none}
.sheet-head h3{min-width:0;overflow-wrap:anywhere}
.sheet-head-action{flex:none;margin:0 0 6px auto}
@media (min-width:700px){.sheet-head-action{margin-top:14px}}
.sheet-body{flex:1;overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;padding:var(--ring-space) calc(2px + var(--ring-space)) calc(6px + var(--ring-space));scroll-padding:var(--ring-space) 0}
.sheet-body>.field-label:first-child{margin-top:1px}
.sheet-foot{margin-top:8px;padding-top:12px;border-top:1px solid var(--hairline)}
.sheet-foot .note{margin:0 2px 10px}
.sheet-foot .note:empty{display:none}
.sheet-foot .toolbar{justify-content:flex-end}
.sheet-foot .btn{min-width:96px}
.field-error{margin:6px 2px 0}
.field-error:empty{display:none}
body.sheet-open{position:fixed;left:0;right:0;width:100%;overflow:hidden}
/* Wider screens: the sheet is a centred modal. */
@media (min-width:700px){.sheet-backdrop{align-items:center;padding:24px}.sheet{max-width:520px;max-height:min(88dvh,820px);padding-bottom:16px;border-bottom:1px solid var(--line);border-radius:var(--r-panel);transition:opacity 200ms var(--ease-out),transform 200ms var(--ease-out)}.sheet-handle{display:none}.sheet h3{margin-top:14px}
  .sheet-backdrop.entering .sheet,.sheet-backdrop.closing .sheet{opacity:0;transform:scale(0.97)}.sheet-backdrop.closing .sheet{transition-duration:150ms}}
@media (prefers-reduced-motion:reduce){.sheet{transition:opacity 200ms var(--ease-out)}.sheet-backdrop.entering .sheet,.sheet-backdrop.closing .sheet{transform:none;opacity:0}}

/* ---- Departments and Staff screens ---- */
.field[readonly]{color:var(--text-2);background:var(--fill-1)}
.card .mono{margin:10px 0;padding:12px 14px;border-radius:var(--r-small);background:var(--fill-2)}
.reset-code{user-select:all;overflow-wrap:anywhere}
/* A field error replaces its own rule hint rather than printing the same sentence twice. */
.sheet-body .field-error:not(:empty)+.field-hint{display:none}

/* ---- Machine voice: Geist Mono for subtitles (the line under a title or name) and nav labels ----
   Not for field labels, hints, status or error lines, privacy text, sheet copy or eyebrows. */
.brand span,#profileLabel,#workspaceLabel,#departmentLabel,#jobTitleLabel,.glist-row small,.glist-row p:not(.status-error),.row small,.card p:not(.status-error),.feature p,
#homeKpis>.card p,.hub-card p:not(.status-error),.agent-meta,.agent-card-role,:is(h1,h2,h3)+.note:not([role=status]):not(.status-error){font-family:var(--mono);font-weight:500;letter-spacing:0}
/* The tagline shares the bar with Refresh: sized so all 29 characters fit at 375px. */
.brand span{font-size:10.5px;letter-spacing:-.02em}
.tab{font-family:var(--mono);font-size:12px;font-weight:500;letter-spacing:0}
/* 320px: the labels keep a gap between them (02-32). */
@media (max-width:359px){.bottom{grid-template-columns:minmax(0,1fr) minmax(0,1fr) 68px minmax(0,1fr) minmax(0,1fr);padding:8px 6px}}

/* VERSER NEWS: "Tap to hear" under the agent's news when the browser would not play it without a tap. */
.news-hear{display:inline-flex;align-items:center;gap:6px;min-height:44px;margin-top:8px;padding:0 14px;border:1px solid var(--line);border-radius:var(--r-pill);background:var(--fill-3);color:var(--text);font:600 12.5px/1 var(--font);cursor:pointer}
.news-hear::before{content:'';width:0;height:0;border-left:8px solid currentColor;border-top:5px solid transparent;border-bottom:5px solid transparent}
.news-hear:disabled{opacity:.6;cursor:default}
.news-hear:disabled::before{display:none}
.news-hear + .news-hear{margin-left:8px}
.news-join::before{display:none}

/* SOURCE CHIPS: what a reply found in the organization's brain, under it; a tap opens it (workspace.js,
   attachSourceChips). The floating agent shows the newest reply's above its bubble. */
.source-chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
.source-chip{position:relative;display:inline-flex;align-items:center;gap:4px;max-width:100%;min-height:32px;padding:0 12px;border:1px solid var(--line);border-radius:var(--r-pill);background:var(--fill-3);color:var(--text);font:500 12px/1 var(--font);text-align:start;cursor:pointer}
.source-chip::after{content:"";position:absolute;inset:-4px 0}
.source-chip b{flex:none;color:var(--text-2);font-weight:600}
.source-chip b::after{content:" ·"}
.source-chip span{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.agent-fab-sources{display:flex;flex-wrap:wrap;gap:6px;max-width:100%}
.agent-fab-sources .source-chip{background:var(--glass-solid);box-shadow:var(--shadow-control)}

/* ---- First-run tour (workspace.js, FIRST-RUN TOUR) ---- */
/* The scrim takes every click off the page; the ring's shadow dims everything but the target. */
.tour-scrim{position:fixed;inset:0;z-index:90;background:transparent}
.tour-ring{position:fixed;z-index:91;border:2px solid var(--ring);border-radius:var(--r-inner);box-shadow:0 0 0 9999px var(--scrim),0 0 18px var(--brand-glow);pointer-events:none}
.tour-card{position:fixed;z-index:92;width:min(340px,calc(100vw - 24px));padding:16px;border:1px solid var(--line);border-radius:var(--r-compact);background:var(--gloss),var(--glass-solid);background-origin:border-box;box-shadow:var(--shadow);color:var(--text)}
/* The tour dims in and its card rises 6px into place once, when it starts. Only opacity and transform move: the ring and
   card follow their target through left/top every frame, which must stay instant. Reduced motion: fades only. */
.tour-ring{transition:opacity 250ms var(--ease-out)}
.tour-card{transition:opacity 250ms var(--ease-out),transform 250ms var(--ease-out)}
@starting-style{.tour-ring{opacity:0}.tour-card{opacity:0;transform:translateY(6px)}}
@media (prefers-reduced-motion:reduce){.tour-card{transition-property:opacity}}
.tour-card h3{margin:10px 0 4px;font-size:17px;line-height:1.3}
.tour-card p{margin:0;font-size:14px;line-height:1.45;color:var(--text-2)}
.tour-dots{display:flex;gap:6px}
.tour-dots i{width:6px;height:6px;border-radius:3px;background:var(--track)}
.tour-dots i.on{width:18px;background:var(--text)}
.tour-actions{display:flex;gap:8px;margin-top:14px}
.tour-actions #tourSkip{margin-right:auto}

/* ---- UI polish B1: Back is a left arrow before the title on every sub-screen (02-35), a 44px circle on the glass the
   title row's buttons use; the title follows it on the same left edge. Top-level tabs have no Back. */
.title.has-back{justify-content:flex-start}
.title.has-back>.back-btn+div{flex:1 1 auto}
.screen>.title.has-back{margin-left:0}
.back-btn{flex:none;display:grid;place-items:center;width:44px;min-width:44px;height:44px;min-height:44px;padding:0;border-radius:50%}
.back-btn .icon{width:20px;height:20px}
/* The profile button scrolls away with the title row instead of floating over the first card (02-13). */
.profile-btn{position:absolute}

/* ---- UI polish B1: Agents tab cards. No portrait: a shorter picture area holding a small agent tile (rounded square,
   cyan ring) with the initials, not initials across the whole square. Tools and Edit are 44px targets (03-7). */
.agent-card.no-portrait .agent-card-open{aspect-ratio:4/3}
.agent-card.no-portrait .agent-card-av{width:64px;height:64px;margin:auto;border-radius:var(--r-inner);background:var(--fill-2);box-shadow:0 0 0 2px var(--b);font-size:20px;letter-spacing:.02em}
.agent-card.no-portrait .agent-card-open{display:grid;place-items:center}
.agent-card-body{flex:1 1 auto}
.agent-card-icons{gap:8px;margin-top:auto;padding-top:8px}
.agent-card-icon:not(.agent-card-open){width:44px;height:44px;border-radius:var(--r-inner)}
.agent-card-icon:not(.agent-card-open) .icon{width:20px;height:20px}

/* ---- UI polish B1: Verser's agent tab strip fades at its right edge while more tabs sit past it (03-20). */
.agent-tabs.more-right{-webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 32px),transparent);mask-image:linear-gradient(90deg,#000 calc(100% - 32px),transparent)}

.staff-remove-note{margin-top:18px}
/* An old version is read only: its header has no Save to dim, only Done and History. */
#documentScreen:has(#documentOldBar:not(.hidden)) #documentSave{display:none}
/* AGENT FAB (workspace.js): the person's own agent, bottom left on the same line as the round + (which is bottom right),
   above the nav. While it shows (body.agent-fab-on) the page keeps more room at the bottom so the last row scrolls
   above it; it steps aside under a sheet like the +. Its bubble opens to its right; a sheet closes it. It is the +'s
   size and corner (56px, --r-compact, 2026-10-03), so the two read as one pair. */
.agent-fab-btn{position:fixed;left:max(16px,calc(50% - var(--phone) / 2 + 16px));bottom:calc(var(--nav-bottom) + 92px);z-index:45;display:grid;place-items:center;width:56px;height:56px;padding:0;border:2px solid var(--line);border-radius:var(--r-compact);background:var(--glass-solid);box-shadow:var(--shadow-control);color:var(--text);cursor:pointer}
.agent-fab-face{display:grid;place-items:center;width:100%;height:100%;overflow:hidden;border-radius:calc(var(--r-compact) - 2px);font:700 15px/1 var(--font)}
.agent-fab-face img{width:100%;height:100%;object-fit:cover}
.agent-fab-btn.speaking{border-color:var(--b);animation:agent-fab-ring 1.4s ease-out infinite}
.agent-fab-btn.has-news::after{content:"";position:absolute;top:1px;right:1px;width:12px;height:12px;border:2px solid var(--glass-solid);border-radius:50%;background:var(--pink)}
.agent-fab-btn{transition:transform 160ms var(--ease-out)}
.agent-fab-btn:active{transform:scale(.97)}
.agent-fab-btn[aria-expanded="true"]{border-color:var(--ring)}
@keyframes agent-fab-ring{0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--b) 55%,transparent)}100%{box-shadow:0 0 0 12px transparent}}
body.sheet-open .agent-fab-btn{display:none}
/* The keyboard is up over a fixed-bottom text field (body.kb-field, index.html): the bubble, a bottom sheet and the
   reels comment bar sit on top of it instead of under it. */
body.kb-field .agent-fab-panel{bottom:calc(var(--kb-field-lift,0px) + 8px)}
body.kb-field .sheet-backdrop{bottom:var(--kb-field-lift,0px)}
body.kb-field .sheet{max-height:calc(100dvh - var(--kb-field-lift,0px) - 16px)}
body.agent-fab-on:not(.verser-open) .phone{padding-bottom:calc(var(--nav-bottom) + 156px)}
/* The bubble (2026-10-02, hb1) is a slim pill to the right of the button, on its line: its first line is centred on the
   button and it grows upwards with the draft, to about four lines. It ends 16px from the screen's edge, or 8px before
   the round + on the screens that have one. The agent's replies are not written in it, only heard; a confirm row's
   question with Yes and Not now, and Tap to hear, sit just above it. A dot pulses on the button while a reply comes. */
.agent-fab-panel{transform-origin:left center;--af-side:max(16px,calc(50% - var(--phone) / 2 + 16px));position:fixed;left:calc(var(--af-side) + 64px);right:var(--af-side);bottom:calc(var(--nav-bottom) + 92px - var(--af-status-half,0px));z-index:61;display:block;min-height:52px;padding:5px;border:1px solid var(--line);border-radius:26px;background:var(--glass-solid);box-shadow:var(--shadow)}
body:has(.screen.active .tasks-fab) .agent-fab-panel{right:calc(var(--af-side) + 64px)}
/* The one-line bubble (56px, like the button) shares the button's bottom; a status line over the draft (its 2px + 16px + 4px)
   drops it by half that, so the bubble stays centred on the button's line. */
.agent-fab-panel:has(> .agent-fab-status:not(:empty)){--af-status-half:11px}
.agent-fab-above{position:absolute;left:0;right:0;bottom:calc(100% + 8px);display:flex;flex-direction:column;align-items:flex-start;gap:6px}
.agent-fab-status{margin:2px 12px 4px;overflow:hidden;color:var(--text-2);font-size:12px;font-weight:600;line-height:16px;white-space:nowrap;text-overflow:ellipsis}
.agent-fab-status:empty{display:none}
.agent-fab-status.failed{color:var(--bad)}
.agent-fab-hear{position:relative;min-height:32px;padding:0 12px;border:1px solid var(--line);border-radius:var(--r-pill);background:var(--glass-solid);box-shadow:var(--shadow-control);color:var(--text);font:600 12px/1 var(--font)}
.agent-fab-hear::after{content:"";position:absolute;inset:-6px -2px}
.agent-fab-confirm{align-self:stretch;display:flex;flex-direction:column;gap:6px;padding:8px 10px;border:1px solid var(--line);border-radius:var(--r-compact);background:var(--glass-solid);box-shadow:var(--shadow)}
.agent-fab-question{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;margin:0;overflow:hidden;font-size:13px;line-height:1.35;overflow-wrap:anywhere}
.agent-fab-confirm-btns{display:flex;flex-wrap:wrap;gap:8px}
.agent-fab-confirm .btn{min-height:44px;padding:0 12px;font-size:13px}
.agent-fab-confirm-note{color:var(--muted);font-size:12px}
.agent-fab-row{display:flex;align-items:flex-end;gap:4px;margin:0}
.agent-fab-row textarea.agent-fab-input{flex:1;min-width:0;min-height:40px;height:40px;max-height:98px;padding:8px 8px;border:1px solid transparent;border-radius:20px;background:transparent;box-shadow:none;line-height:20px;resize:none;overflow-y:hidden;field-sizing:fixed}
.agent-fab-mic,.agent-fab-send{flex:none;display:grid;place-items:center;width:44px;height:44px;padding:0;border:1px solid var(--line);border-radius:50%;background:var(--fill-2);color:var(--text)}
.agent-fab-send{border:0;background:var(--primary);color:var(--on-primary)}
.agent-fab-mic .icon,.agent-fab-send .icon{width:18px;height:18px}
.agent-fab-mic.on{border-color:var(--green);color:var(--green)}
.agent-fab-mic.listening{background:var(--green);color:#04241C}
.agent-fab-btn.thinking::before{content:"";position:absolute;top:1px;left:1px;width:12px;height:12px;border:2px solid var(--glass-solid);border-radius:50%;background:var(--b);animation:agent-fab-think 1s ease-in-out infinite alternate}
@keyframes agent-fab-think{from{opacity:.35;transform:scale(.8)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.agent-fab-btn{transition:opacity 160ms var(--ease-out)}.agent-fab-btn:active{transform:none;opacity:.8}.agent-fab-btn.speaking{animation:none;box-shadow:0 0 0 3px color-mix(in srgb,var(--b) 55%,transparent)}.agent-fab-btn.thinking::before{animation:none}}
/* Account basics: the profile photo fills the sidebar circle; Resend invite sits beside Edit on a staff row awaiting first sign-in. */
.side-av{overflow:hidden}.side-av img{width:100%;height:100%;object-fit:cover}
#adminStaffList .row-resend{flex:none;min-height:36px;padding:0 12px;font-size:13px;white-space:nowrap}
/* Admin settings filters (Staff, Activity): the search across the row, the pickers two to a row on a phone. */
.admin-filters{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin:8px 0 10px}
.admin-filters input[type=search]{grid-column:1/-1}
.admin-filters .field{min-width:0;margin:0}
.import-preview{max-height:320px;overflow:auto;margin-top:8px}
.import-preview .bad{color:var(--bad)}
.import-preview .import-admin{display:block}
.import-preview .import-admin-row{box-shadow:inset 3px 0 0 var(--warn)}
.activity-line small{display:block}

/* Home's My tasks: five cards, then this link-like button to the rest on Tasks (workspace.js, renderHomeTasks). */
.btn.home-task-all{justify-self:start;min-height:44px;margin-top:2px;padding:0 4px;border:0;background:none;box-shadow:none;color:var(--text-2);font-weight:600}
/* Toolbox with no tools chosen: Agent tools sits under the note, at its start. */
#toolsEmpty .btn{justify-self:start}
/* Settings > Signed in with: one row per Google, Microsoft or Apple login, the brand mark on its white tile (as on
   the sign-in buttons), the name, and Remove. Remove's question takes the row's full width under the name. */
.siw{margin-top:14px;padding-top:12px;border-top:1px solid var(--hairline)}
.siw-title{margin:0 2px 6px}
.siw-row{display:flex;align-items:center;flex-wrap:wrap;gap:12px;min-height:52px;padding:6px 12px;min-width:0}
.siw-mark{flex:none;display:grid;place-items:center;width:32px;height:32px;border-radius:8px;background:#FFFFFF;color:#000000}
.siw-mark svg{width:18px;height:18px}
.siw-apple svg{width:15px;height:18px}
.siw-name{flex:1 1 auto;min-width:0;font-size:15px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.siw-remove{flex:none;min-height:36px;padding:0 14px}
.siw-row .confirm-row{flex:1 1 100%;min-width:0}
/* Add Google / Microsoft / Apple: the whole row is the button, its mark on the same white tile. */
.siw-add{width:100%;border:0;border-radius:var(--r-inner);background:none;color:var(--text-2);text-align:left;font:inherit}
.siw-add .siw-name{color:var(--text-2);font-weight:500}
.siw-add:active{background:var(--fill-1)}
.siw-add:disabled{opacity:.5}
.siw-said{margin:6px 2px 0}
/* Sign-up's Join screen (#invite=, helpers_invites.py) and Staff's invite links: a link wraps anywhere, never past its card. */
.invite-title{margin:0 0 6px;font-size:20px;overflow-wrap:anywhere}
.invite-link-text{user-select:all;overflow-wrap:anywhere;word-break:break-all;white-space:pre-wrap;font-size:13px}
.invite-actions{flex-wrap:wrap}
.signup-invites{display:grid;gap:8px;margin-bottom:12px}
.signup-invites .note{margin:0}
#signupPanel.inviting #signupDetailsStep .sso{display:none}
