/* ═══════════════════════════════════════════════════════════════════════════
   Atrium — application stylesheet.

   Every colour, radius, shadow, face and metric comes from tokens.css. Nothing
   below introduces a literal colour; where a tint or an overlay is needed it is
   mixed FROM a token with color-mix(), so both themes stay correct by
   construction rather than by being maintained twice.

   Two structural ideas carry the whole design:
     · Warm chrome, neutral stage. The rail and top bar wear the paper palette
       (--ground / --surface); the pane area is --stage, which is cool and
       quiet, because the panes hold Nextcloud and a cream frame around a cool
       white app makes the seam obvious. tokens.css says this; the layout obeys.
     · Fraunces is the voice, IBM Plex is the interface. The display face is
       used for exactly two things — the wordmark and the pane title — so it
       reads as signature rather than decoration.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 1. derived values ───────────────────────────────────────────────────── */
:root{
  /* Text that sits ON --brand. --surface is the correct answer in BOTH themes:
     near-white on deep teal in light (~6.2:1), near-black on light teal in dark
     (~6.0:1). One variable, no per-theme override needed. */
  --on-brand:var(--surface);

  --hover:color-mix(in srgb, var(--ink) 6%, transparent);
  --press:color-mix(in srgb, var(--ink) 11%, transparent);
  --danger-tint:color-mix(in srgb, var(--danger) 12%, var(--surface));
  --danger-line:color-mix(in srgb, var(--danger) 34%, transparent);

  /* spacing — a workspace is dense; the scale is tighter than the marketing site */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:22px; --s6:30px; --s7:40px; --s8:56px;

  /* type */
  --t-micro:10.5px; --t-xs:11.5px; --t-sm:12.5px; --t-base:13.5px; --t-md:15px;
  --t-lg:20px; --t-xl:28px; --t-display:46px;

  --dur-fast:140ms; --dur:230ms; --dur-slow:480ms;
}

/* ── 2. base ─────────────────────────────────────────────────────────────── */
*,*::before,*::after{box-sizing:border-box}

/* Author styles beat the UA's [hidden] rule, so anything given display: here
   would ignore the attribute. This restores it once, globally.
   NOTE: panes are NEVER hidden with this attribute — see §10. */
[hidden]{display:none!important}

html,body{height:100%}
body{
  margin:0;
  /* explicit token background: the page must never borrow the host's theme */
  background:var(--ground);
  color:var(--ink);
  font-family:var(--body);
  font-size:var(--t-base);
  line-height:1.5;
  overflow:hidden;                    /* the app owns its own scroll regions */
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  text-rendering:optimizeLegibility;
}
h1,h2,p,ul,figure{margin:0}
ul{padding:0;list-style:none}
button,input,a{font:inherit;color:inherit}
button{background:none;border:0;padding:0;cursor:pointer}
a{color:inherit;text-decoration:none}
::selection{background:var(--brand-tint);color:var(--ink)}

/* ── 3. focus & motion ───────────────────────────────────────────────────── */
:focus{outline:none}
:focus-visible{
  outline:2px solid var(--brand);
  outline-offset:2px;
}
.skip-link{
  position:fixed;left:var(--s3);top:var(--s3);z-index:999;
  transform:translateY(-160%);
  background:var(--surface);color:var(--ink);
  padding:10px 14px;border-radius:var(--r-sm);
  border:1px solid var(--line);box-shadow:var(--shadow-md);
  font-size:var(--t-sm);font-weight:600;
  transition:transform var(--dur) var(--ease);
}
.skip-link:focus-visible{transform:translateY(0)}

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

/* ── 4. primitives ───────────────────────────────────────────────────────── */

/* Off-layout rather than display:none — the most compatible way to keep <use>
   references resolving in every engine. */
.sprite{position:absolute;width:0;height:0;overflow:hidden}

.icon{
  width:20px;height:20px;flex:none;
  fill:none;stroke:currentColor;stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round;
}
.icon--xs{width:15px;height:15px;stroke-width:1.8}
.mark{display:block;color:var(--brand)}
.mark--xs{width:20px;height:20px}
.mark--sm{width:26px;height:26px}
.mark--md{width:34px;height:34px}
.mark--xl{width:44px;height:44px}

/* Anything data-shaped: addresses, timestamps, counts, key hints. */
.mono{
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  font-feature-settings:'tnum' 1;
  letter-spacing:-.01em;
}

/* ── 5. buttons ──────────────────────────────────────────────────────────── */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--s2);
  height:38px;padding:0 var(--s4);
  border-radius:var(--r-sm);
  border:1px solid var(--line);
  background:var(--surface);
  color:var(--ink);
  font-size:var(--t-base);font-weight:550;letter-spacing:-.005em;
  box-shadow:var(--shadow-sm);
  transition:background var(--dur-fast) var(--ease),
             border-color var(--dur-fast) var(--ease),
             transform var(--dur-fast) var(--ease),
             box-shadow var(--dur-fast) var(--ease);
}
.btn:hover{background:var(--ground);border-color:var(--line)}
.btn:active{transform:translateY(1px);box-shadow:none}
.btn--small{height:30px;padding:0 var(--s3);font-size:var(--t-sm);border-radius:6px}
.btn--block{width:100%}
.btn--primary{
  height:46px;
  background:var(--brand);
  border-color:transparent;
  color:var(--on-brand);
  font-size:var(--t-md);font-weight:600;
  border-radius:var(--r-sm);
  box-shadow:0 1px 2px var(--brand-glow),0 12px 26px -14px var(--brand-glow);
}
.btn--primary:hover{background:var(--brand-deep);box-shadow:0 2px 6px var(--brand-glow),0 16px 32px -14px var(--brand-glow)}
/* For the one action in a dialog that cannot be taken back lightly. */
.btn--danger{background:var(--danger);border-color:transparent;color:var(--on-brand);font-weight:600}
.btn--danger:hover{background:color-mix(in srgb,var(--danger) 88%,var(--ink))}

/* A disabled primary action that still looks pressable is a trap: sign-in is
   disabled when the browser cannot support it, and the alert above it is
   carrying the reason. */
.btn:disabled{opacity:.45;cursor:not-allowed;box-shadow:none;transform:none}
.btn:disabled:hover{background:var(--surface)}
.btn--primary:disabled:hover{background:var(--brand)}

.iconbtn{
  display:grid;place-items:center;position:relative;
  width:34px;height:34px;border-radius:var(--r-sm);
  color:var(--muted);
  transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease);
}
.iconbtn:hover{background:var(--hover);color:var(--ink)}
.iconbtn:active{background:var(--press)}
.iconbtn--sm{width:26px;height:26px;border-radius:6px}

/* ── 6. tooltips ─────────────────────────────────────────────────────────── */
/* Real elements, not ::after content: the rail tip carries a key hint in the
   mono face, which a pseudo-element cannot style separately. Always
   aria-hidden — the button carries its own aria-label. */
.tip{
  position:absolute;z-index:5;
  display:flex;align-items:center;gap:var(--s2);
  white-space:nowrap;
  padding:6px 9px;border-radius:var(--r-sm);
  background:var(--ink);color:var(--ground);
  font-size:var(--t-sm);font-weight:500;letter-spacing:-.005em;
  box-shadow:var(--shadow-md);
  opacity:0;pointer-events:none;
  transition:opacity var(--dur-fast) var(--ease),transform var(--dur-fast) var(--ease);
}
.tip-key{
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-size:var(--t-micro);line-height:1;
  padding:3px 5px;border-radius:5px;
  background:color-mix(in srgb, var(--ground) 20%, transparent);
  opacity:.85;
}
/* rail: to the right of the bar */
.rail .tip{left:calc(100% + 12px);top:50%;transform:translate(-5px,-50%)}
.navbtn:hover .tip,.navbtn:focus-visible .tip{opacity:1;transform:translate(0,-50%)}
/* top bar: underneath, right-aligned */
.topbar [data-tip]::after{
  content:attr(data-tip);
  position:absolute;top:calc(100% + 9px);right:0;z-index:5;
  white-space:nowrap;
  padding:6px 9px;border-radius:var(--r-sm);
  background:var(--ink);color:var(--ground);
  font-size:var(--t-sm);font-weight:500;
  box-shadow:var(--shadow-md);
  opacity:0;pointer-events:none;transform:translateY(-4px);
  transition:opacity var(--dur-fast) var(--ease),transform var(--dur-fast) var(--ease);
}
.topbar [data-tip]:hover::after,.topbar [data-tip]:focus-visible::after{opacity:1;transform:translateY(0)}

/* ── 7. full-screen stages (boot + sign in) ──────────────────────────────── */
.stage-centre{
  position:fixed;inset:0;
  display:grid;place-items:center;
  /* An `auto` grid column is sized by its MAX-CONTENT, so a long line inside
     made the column wider than the screen and the whole stage scrolled
     sideways on a phone. minmax(0,1fr) is what stops that. */
  grid-template-columns:minmax(0, 1fr);
  padding:var(--s7) var(--s5);
  overflow:auto;
  background:var(--ground);
}
/* The considered background: brand light falling in from the top-left the way
   it falls into the mark, a warm reflection bottom-right, over paper. */
.stage-centre--lit{
  background:
    radial-gradient(1120px 640px at 12% -10%, var(--brand-glow), transparent 62%),
    radial-gradient(820px 560px at 94% 108%, color-mix(in srgb, var(--warm) 13%, transparent), transparent 66%),
    linear-gradient(180deg, var(--surface) 0%, var(--ground) 58%, var(--ground-deep) 100%);
}

.boot-card{display:grid;justify-items:center;gap:var(--s4);opacity:.9}
.boot-msg{font-size:var(--t-sm);color:var(--muted);letter-spacing:.01em}

/* ── 8. the way in ───────────────────────────────────────────────────────────
   The first screen anybody sees, so it carries the whole argument: what this
   is, one thing to press, and a glimpse of the product. Two columns where
   there is room, one where there is not, and the glimpse goes rather than
   shrinking to something unreadable.

   The glimpse is DRAWN, not photographed. A screenshot would be out of date
   the first time the interface moves, and would have to be maintained in two
   places; this is the same tokens the real interface uses, so it cannot drift
   in colour, and it says "a mail list beside a message" without claiming to
   be a particular message. */
.hero{
  width:100%;max-width:1180px;
  display:grid;grid-template-columns:minmax(0,1fr);
  gap:var(--s7);align-items:center;
}
@media (min-width:1000px){
  .hero{grid-template-columns:minmax(380px, 0.95fr) minmax(0, 1.05fr);gap:var(--s8)}
}

.hero-say{max-width:560px}
.hero-brand{display:flex;align-items:center;gap:var(--s3)}
.hero-markwrap{
  width:52px;height:52px;display:grid;place-items:center;
  border-radius:14px;color:var(--brand);
  background:linear-gradient(160deg, var(--brand-tint), color-mix(in srgb, var(--brand-tint) 40%, var(--surface)));
  box-shadow:0 0 0 1px var(--brand-glow), 0 18px 40px -26px var(--brand-glow);
}
.hero-wordmark{
  font-family:var(--display);font-size:26px;font-weight:600;letter-spacing:-.02em;color:var(--ink);
}

.hero-title{
  margin:var(--s6) 0 0;
  font-family:var(--display);
  font-size:clamp(34px, 5.2vw, 56px);
  font-weight:600;letter-spacing:-.03em;line-height:1.06;
  color:var(--ink);text-wrap:balance;
}
/* The break is a DESIGN choice on a wide screen and an overflow on a narrow
   one: at 420px "Your whole working day," on its own line runs off the edge. */
.hero-br{display:inline}
@media (min-width:1000px){ .hero-br{display:block;height:0} }

.hero-sub{
  margin:var(--s4) 0 0;max-width:46ch;
  font-size:var(--t-md);line-height:1.65;color:var(--muted);text-wrap:pretty;
}

.hero-act{margin-top:var(--s6)}
.hero-cta{
  display:inline-flex;align-items:center;gap:10px;
  height:52px;padding:0 var(--s6);
  font-size:var(--t-md);font-weight:650;letter-spacing:-.005em;
  border-radius:999px;
  box-shadow:0 2px 4px var(--brand-glow), 0 18px 38px -18px var(--brand-glow);
}
.hero-cta .icon{width:19px;height:19px;transition:transform var(--dur-fast) var(--ease)}
.hero-cta:hover .icon{transform:translateX(3px)}
.hero-act .signin-fineprint{margin-top:var(--s3);font-size:var(--t-sm);color:var(--faint)}

.preview{
  display:flex;flex-wrap:wrap;gap:var(--s2) var(--s3);
  margin-top:var(--s7);padding-top:var(--s5);
  border-top:1px solid var(--line-soft);
}
.preview li{
  display:flex;align-items:center;gap:8px;
  font-size:var(--t-xs);letter-spacing:.01em;color:var(--muted);
}
.preview-chip{
  width:30px;height:30px;display:grid;place-items:center;
  border-radius:9px;background:var(--surface);
  border:1px solid var(--line-soft);color:var(--brand);
}
.preview-chip .icon{width:16px;height:16px}

/* ── the glimpse ───────────────────────────────────────────────────────────
   A vignette of the product with WORK in it — names, a subject, a sentence,
   people who are around — because grey placeholder bars read as "loading"
   rather than as software. Everything is invented and generic: no real
   person, no real company, nothing that could be mistaken for a record.

   It moves a little, once: a message arrives, somebody is typing, a call
   comes in. That is the argument in three seconds — these things are open
   together. Under prefers-reduced-motion nothing moves and everything is
   simply there, which is the same argument without the motion. */
.hero-show{display:none;position:relative}
@media (min-width:1000px){ .hero-show{display:block} }

.glimpse{
  --glimpse-line:var(--line-soft);
  display:grid;grid-template-columns:54px minmax(0,1fr);
  height:clamp(380px, 48vh, 480px);
  border:1px solid var(--line);border-radius:var(--r-lg);
  background:var(--surface);
  box-shadow:var(--shadow-lg);
  overflow:hidden;
  transform:perspective(1600px) rotateY(-6deg) rotateX(1.5deg);
  transform-origin:left center;
}
.glimpse-rail{
  display:flex;flex-direction:column;align-items:center;gap:var(--s3);
  padding:var(--s3) 0;background:var(--ground);border-right:1px solid var(--glimpse-line);
}
.glimpse-mark{color:var(--brand);opacity:.9}
.glimpse-nav{width:30px;height:30px;display:grid;place-items:center;border-radius:9px;color:var(--faint)}
.glimpse-nav .icon{width:17px;height:17px}
.glimpse-nav.is-on{background:var(--brand-tint);color:var(--brand)}

.glimpse-body{display:grid;grid-template-rows:auto minmax(0,1fr);min-width:0}
.glimpse-bar{
  display:flex;align-items:center;gap:var(--s3);
  height:40px;padding:0 var(--s3);
  border-bottom:1px solid var(--glimpse-line);background:var(--ground);
  font-size:var(--t-xs);
}
.glimpse-where{font-weight:650;color:var(--ink)}
.glimpse-count{color:var(--brand);font-weight:600}
.glimpse-search{
  margin-left:auto;padding:3px 10px;border-radius:999px;
  background:var(--surface);border:1px solid var(--line-soft);color:var(--faint);
}
.glimpse-people{display:flex}
.glimpse-people .g-av{margin-left:-6px;box-shadow:0 0 0 2px var(--ground)}

/* people, as initials in their own tint */
.g-av{
  position:relative;flex:none;
  width:26px;height:26px;display:grid;place-items:center;
  border-radius:50%;font-size:10px;font-weight:700;letter-spacing:.02em;
  background:var(--brand-tint);color:var(--brand-deep);
}
.g-av--xs{width:20px;height:20px;font-size:8px}
.g-av--sm{width:22px;height:22px;font-size:9px}
.g-av--lg{width:38px;height:38px;font-size:13px}
.g-av.t1{background:color-mix(in srgb, var(--brand-tint) 80%, var(--surface));color:var(--brand-deep)}
.g-av.t2{background:color-mix(in srgb, var(--warm-tint) 85%, var(--surface));color:var(--warm)}
.g-av.t3{background:color-mix(in srgb, var(--brand-tint) 55%, var(--ground-deep));color:var(--brand-deep)}
.g-av.t4{background:color-mix(in srgb, var(--warm-tint) 60%, var(--brand-tint));color:var(--warm)}
.g-av.t5{background:color-mix(in srgb, var(--brand-tint) 95%, var(--ink));color:var(--brand-deep)}
.g-av.t6{background:color-mix(in srgb, var(--brand) 22%, var(--surface));color:var(--brand-deep)}
.g-st{
  position:absolute;right:-1px;bottom:-1px;width:7px;height:7px;border-radius:50%;
  box-shadow:0 0 0 2px var(--ground);
}
.g-st--on{background:var(--st-ok)}
.g-st--away{background:var(--st-away)}

.glimpse-cols{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,1.15fr);min-height:0}
.glimpse-list{border-right:1px solid var(--glimpse-line);padding:6px;display:grid;gap:2px;align-content:start;overflow:hidden}
.g-row{
  display:grid;grid-template-columns:26px minmax(0,1fr) auto;
  gap:2px var(--s2);padding:8px;border-radius:10px;
  font-size:var(--t-xs);line-height:1.35;
}
.g-row .g-av{grid-row:1 / span 3}
.g-from{font-weight:600;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.g-time{color:var(--faint);font-size:10px;justify-self:end}
.g-subj{grid-column:2 / span 2;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.g-prev{grid-column:2 / span 2;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.g-row.is-unread .g-from,.g-row.is-unread .g-subj{font-weight:700}
.g-row.is-unread .g-time{color:var(--brand);font-weight:600}
.g-row.is-open{background:var(--brand-tint)}
.g-row.is-open .g-subj{color:var(--brand-deep)}

.glimpse-read{padding:var(--s4);display:grid;gap:var(--s2);align-content:start;background:var(--surface)}
.g-subject{margin:0;font-family:var(--display);font-size:17px;font-weight:600;color:var(--ink);letter-spacing:-.01em}
.g-meta{display:flex;align-items:center;gap:8px;font-size:var(--t-xs);color:var(--ink)}
.g-dim{color:var(--faint)}
.g-body{margin:0;font-size:var(--t-xs);line-height:1.6;color:var(--muted)}
.g-attach{
  justify-self:start;display:inline-flex;align-items:center;gap:6px;
  padding:5px 10px;border-radius:8px;
  background:var(--ground);border:1px solid var(--line-soft);
  color:var(--muted);font-size:10px;
}
.g-attach .icon{width:13px;height:13px;color:var(--brand)}

/* the conversation carrying on beside it */
/* Both cards hang off the window's EDGE rather than sitting on top of it:
   over the content they hide the very thing they are there to show. */
.glimpse-chat{
  position:absolute;left:-52px;bottom:-22px;z-index:2;
  display:grid;gap:6px;justify-items:start;
}
.glimpse-chat-bubble{
  padding:8px 12px;border-radius:14px 14px 14px 4px;
  background:var(--surface);border:1px solid var(--line-soft);
  box-shadow:var(--shadow-md);
  font-size:var(--t-xs);color:var(--ink);
}
.glimpse-chat-typing{
  display:inline-flex;gap:4px;padding:8px 12px;border-radius:14px 14px 14px 4px;
  background:var(--brand);box-shadow:var(--shadow-sm);
}
.glimpse-chat-typing i{width:5px;height:5px;border-radius:50%;background:var(--on-brand);opacity:.6}

/* somebody calling, in front of everything */
.glimpse-call{
  position:absolute;right:-28px;bottom:34px;z-index:3;
  display:flex;align-items:center;gap:var(--s3);
  padding:10px 12px;border-radius:var(--r-md);
  background:var(--surface);border:1px solid var(--line);
  border-top:3px solid var(--danger);
  box-shadow:var(--shadow-lg);
}
.glimpse-call-who{display:grid;line-height:1.25}
.glimpse-call-who strong{font-size:var(--t-sm);color:var(--ink)}
.glimpse-call-who span{font-size:10px;color:var(--muted)}
.glimpse-call-btn{
  padding:6px 14px;border-radius:999px;
  background:var(--brand);color:var(--on-brand);
  font-size:var(--t-xs);font-weight:650;
}

/* ── the three seconds of motion ──────────────────────────────────────── */
.g-row.is-arriving{animation:gArrive 700ms var(--ease) 2.4s both}
@keyframes gArrive{
  from{opacity:0;transform:translateY(-10px) scale(.98)}
  to{opacity:1;transform:none}
}
.glimpse-chat{animation:rise 600ms var(--ease) 1.1s both}
.glimpse-chat-typing i{animation:gType 1.25s ease-in-out infinite}
.glimpse-chat-typing i:nth-child(2){animation-delay:.15s}
.glimpse-chat-typing i:nth-child(3){animation-delay:.3s}
@keyframes gType{0%,60%,100%{opacity:.35;transform:translateY(0)}30%{opacity:1;transform:translateY(-3px)}}
.glimpse-call{animation:gCall 700ms var(--ease) 3.4s both}
@keyframes gCall{
  from{opacity:0;transform:translateX(16px) scale(.97)}
  to{opacity:1;transform:none}
}
.glimpse-call-btn{animation:gPulse 2s var(--ease) 4.1s infinite}
@keyframes gPulse{0%,100%{box-shadow:0 0 0 0 var(--brand-glow)}50%{box-shadow:0 0 0 8px transparent}}
@media (prefers-reduced-motion:reduce){
  .g-row.is-arriving,.glimpse-chat,.glimpse-call,.glimpse-call-btn,.glimpse-chat-typing i{animation:none}
}

/* Small screens: the argument only, and room to breathe. */
@media (max-width:640px){
  .hero-title{font-size:clamp(28px, 8vw, 38px)}
  .hero-cta{width:100%;justify-content:center}
  .preview{margin-top:var(--s6)}
}

/* orchestrated entrance — one sequence, staggered, ending at identity */
@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
.hero [data-seq]{animation:rise var(--dur-slow) var(--ease) both}
.hero [data-seq="1"]{animation-delay:60ms}
.hero [data-seq="2"]{animation-delay:130ms}
.hero [data-seq="3"]{animation-delay:195ms}
.hero [data-seq="4"]{animation-delay:250ms}
.hero [data-seq="5"]{animation-delay:265ms}
.hero [data-seq="6"]{animation-delay:335ms}
.hero [data-seq="7"]{animation-delay:180ms}

/* ── 9. alerts ───────────────────────────────────────────────────────────── */
.alert{
  display:flex;gap:var(--s3);align-items:flex-start;text-align:left;
  margin-top:var(--s5);padding:var(--s3) var(--s4);
  border-radius:var(--r-sm);
  font-size:var(--t-sm);line-height:1.5;
}
.alert--danger{background:var(--danger-tint);border:1px solid var(--danger-line);color:var(--ink)}
.alert--danger .icon{color:var(--danger);margin-top:1px}
.alert-body{display:grid;gap:2px}
.alert-body strong{font-weight:600}
.alert-body span{color:var(--muted)}
.alert-body span:empty{display:none}

/* ── 10. the app shell ───────────────────────────────────────────────────── */
.app{
  display:grid;
  grid-template-columns:var(--rail) minmax(0,1fr);
  grid-template-rows:var(--topbar) minmax(0,1fr);
  grid-template-areas:
    "rail topbar"
    "rail panes";
  height:100vh;height:100dvh;
  background:var(--ground);
  /* explicit containing block for the session toast, which would otherwise
     resolve against the viewport by accident rather than by intent */
  position:relative;
}


/* One orchestrated arrival: the chrome draws itself in from the outside in —
   rail, then top bar, then the stage — and the rail's own buttons follow. It
   runs once, when the app view is first revealed. Nothing here animates a
   mounted frame; at this moment none exists yet. */
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
@keyframes railIn{from{opacity:0;transform:translateX(-10px)}to{opacity:1;transform:none}}
@keyframes navIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.app .rail{animation:railIn 460ms var(--ease) both}
.app .topbar{animation:fadeIn 460ms var(--ease) 70ms both}
.app .panes{animation:fadeIn 460ms var(--ease) 140ms both}
.rail-nav > *{animation:navIn 380ms var(--ease) both}
.rail-nav > *:nth-child(1){animation-delay:150ms}
.rail-nav > *:nth-child(2){animation-delay:185ms}
.rail-nav > *:nth-child(3){animation-delay:220ms}
.rail-nav > *:nth-child(4){animation-delay:255ms}
.rail-nav > *:nth-child(5){animation-delay:290ms}
.rail-nav > *:nth-child(6){animation-delay:325ms}
.rail-nav > *:nth-child(7){animation-delay:360ms}
.rail-nav > *:nth-child(8){animation-delay:395ms}

/* rail ------------------------------------------------------------------- */
.rail{
  grid-area:rail;
  background:var(--ground);
  border-right:1px solid var(--line);
  display:flex;flex-direction:column;align-items:center;
  position:relative;z-index:20;         /* tooltips clear the panes */
}
.rail-brand{
  width:100%;height:var(--topbar);flex:none;
  display:grid;place-items:center;
  /* continues the top bar's bottom border across the corner so the chrome
     reads as one piece rather than two panels */
  border-bottom:1px solid var(--line);
  color:var(--brand);
}
.rail-nav{
  display:flex;flex-direction:column;align-items:center;gap:2px;
  padding:var(--s3) 0;width:100%;
}
.rail-sep{width:24px;height:1px;background:var(--line);margin:var(--s2) 0;flex:none}

.navbtn{
  position:relative;
  width:48px;height:48px;flex:none;
  display:grid;place-items:center;
  border-radius:var(--r-md);
  color:var(--muted);
  transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease);
}
.navbtn .icon{width:22px;height:22px}
/* A count a pane reported (Calls: missed calls; Chat: conversations that
   need you). Drawn by app.js setRailBadge. */
.navbtn-badge{
  position:absolute;top:5px;right:5px;
  min-width:17px;height:17px;padding:0 5px;border-radius:999px;
  background:var(--danger);color:var(--surface);
  font-size:10px;font-weight:700;line-height:17px;text-align:center;
  pointer-events:none;
}
.navbtn:hover{background:var(--hover);color:var(--ink)}
.navbtn:active{background:var(--press)}
/* the active marker at the rail's outer edge */
.navbtn::before{
  content:'';position:absolute;left:-12px;top:50%;
  width:3px;height:24px;margin-top:-12px;
  border-radius:0 3px 3px 0;
  background:var(--brand);
  transform:scaleX(0) scaleY(.4);transform-origin:left center;
  transition:transform var(--dur) var(--ease);
}
.navbtn.is-active{
  background:var(--brand-tint);
  color:var(--brand);
  box-shadow:0 0 0 1px var(--brand-glow),0 6px 16px -10px var(--brand-glow);
}
.navbtn.is-active::before{transform:scaleX(1) scaleY(1)}
.navbtn-label{display:none}

/* top bar ---------------------------------------------------------------- */
.topbar{
  grid-area:topbar;
  display:flex;align-items:center;gap:var(--s2);
  padding:0 var(--s3) 0 var(--s5);
  background:var(--surface);
  border-bottom:1px solid var(--line);
  position:relative;z-index:15;
}
.topbar-mark{display:none;color:var(--brand);flex:none}
.topbar-icon{width:17px;height:17px;color:var(--faint);flex:none}
.topbar-title{
  font-family:var(--display);
  font-size:var(--t-lg);font-weight:600;letter-spacing:-.018em;
  line-height:1;color:var(--ink);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  min-width:0;
}
@keyframes titleIn{from{opacity:0;transform:translateX(-7px)}to{opacity:1;transform:none}}
.topbar-title.swap{animation:titleIn var(--dur) var(--ease) both}

.topbar-actions{margin-left:auto;display:flex;align-items:center;gap:var(--s1)}

/* user ------------------------------------------------------------------- */
.user{position:relative}
.user-btn{
  display:flex;align-items:center;gap:var(--s2);
  height:38px;padding:0 var(--s2) 0 5px;
  border-radius:999px;
  transition:background var(--dur-fast) var(--ease);
}
.user-btn:hover{background:var(--hover)}
.user-btn[aria-expanded="true"]{background:var(--hover)}
.avatar{
  width:28px;height:28px;flex:none;
  display:grid;place-items:center;
  border-radius:50%;
  background:var(--brand-tint);color:var(--brand);
  font-size:var(--t-xs);font-weight:600;letter-spacing:.01em;
  box-shadow:0 0 0 1px var(--brand-glow);
}
/* The person's own picture, when the workspace has one (app.js
   paintUserPicture). Round, covering, and never larger than the circle. */
.avatar img{position:absolute;inset:0;width:100%;height:100%;border-radius:inherit;object-fit:cover}
.avatar.has-picture{position:relative;overflow:hidden;color:transparent}
.avatar.has-picture .avatar-status{color:initial}
/* A person's own availability, on the avatar that is always on screen. */
.avatar{position:relative}
.avatar-status{
  position:absolute;right:-1px;bottom:-1px;
  width:10px;height:10px;border-radius:50%;
  background:var(--faint);
  box-shadow:0 0 0 2px var(--ground);
}
.avatar-status[data-state="online"]{background:var(--brand)}
.avatar-status[data-state="away"]{background:var(--warm)}
.avatar-status[data-state="dnd"]{background:var(--danger)}
/* Busy — set by the workspace while you are in a call. The same "not now" as
   do not disturb, because to anybody deciding whether to interrupt you that is
   what it means. */
.avatar-status[data-state="busy"]{background:var(--danger)}
.avatar-status[data-state="invisible"]{background:transparent;box-shadow:0 0 0 2px var(--ground), inset 0 0 0 2px var(--faint)}

.status-problem{
  margin:2px 0 0;color:var(--danger);font-size:var(--t-xs);line-height:1.4;
}

.user-name{
  max-width:150px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  font-size:var(--t-base);font-weight:500;color:var(--ink);
}
.user-caret{color:var(--faint)}

.menu{
  position:absolute;right:0;top:calc(100% + var(--s2));
  min-width:248px;
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r-md);
  box-shadow:var(--shadow-lg);
  padding:var(--s1);
  z-index:30;
  animation:menuIn 160ms var(--ease) both;
  transform-origin:top right;
}
@keyframes menuIn{from{opacity:0;transform:translateY(-6px) scale(.97)}to{opacity:1;transform:none}}
.menu-head{display:grid;gap:3px;padding:var(--s3) var(--s3) var(--s2)}
.menu-name{font-size:var(--t-base);font-weight:600;color:var(--ink);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.menu-email{font-size:var(--t-xs);color:var(--muted);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.menu-sep{height:1px;background:var(--line-soft);margin:var(--s1) 0}
/* Storage at a glance (storage.js): in the account menu and Mail's rail. */
/* .menu-item.menu-storage (0,2,0) beats .menu-item without !important, so the
   global [hidden]{display:none!important} still hides it while it is empty. */
.menu-item.menu-storage{display:grid;gap:var(--s2);height:auto;padding-block:var(--s2);min-width:220px}
.stor{display:grid;gap:4px;min-width:0}
.stor-line{display:flex;justify-content:space-between;gap:var(--s2);font-size:var(--t-xs)}
.stor-name{color:var(--muted);font-weight:600}
.stor-figure{color:var(--ink);white-space:nowrap}
.stor-bar{height:5px;border-radius:999px;background:var(--line-soft);overflow:hidden}
.stor-fill{display:block;height:100%;border-radius:inherit;background:var(--brand)}
.stor-bar[data-tone="warm"] .stor-fill{background:var(--warm)}
.stor-bar[data-tone="bad"] .stor-fill{background:var(--danger)}
/* ── availability in the account menu (assets/status.js) ──────────────────
   Four states as a row of chips, and one line for what you are doing. The
   dots are the only place in the shell that names a state by colour, so each
   also carries its word — colour alone is not a label. */
.menu-status{display:grid;gap:var(--s2);padding:var(--s2) var(--s3)}
.menu-status-row{display:grid;grid-template-columns:1fr 1fr;gap:4px}
.status-pick{
  display:flex;align-items:center;gap:7px;
  padding:6px 8px;border:1px solid transparent;border-radius:var(--r-sm);
  background:none;color:var(--muted);
  font:inherit;font-size:var(--t-sm);text-align:left;cursor:pointer;
}
.status-pick:hover{background:var(--hover);color:var(--ink)}
.status-pick.is-on{border-color:var(--line);background:var(--ground);color:var(--ink);font-weight:600}
.status-pick:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
.status-dot{
  flex:none;width:9px;height:9px;border-radius:50%;
  background:var(--faint);box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--ink) 12%, transparent);
}
.status-pick[data-tone="ok"] .status-dot{background:var(--st-ok)}
/* The same three as the dots beside people (talk.css .talk-dot): amber with a clock hand, red with a bar. */
.status-pick[data-tone="warm"] .status-dot{
  background-color:var(--st-away);
  background-image:linear-gradient(#fff,#fff),linear-gradient(#fff,#fff);background-repeat:no-repeat;
  background-size:1.5px 38%,34% 1.5px;background-position:50% 22%,70% 50%;
}
.status-pick[data-tone="busy"] .status-dot{
  background-color:var(--st-dnd);
  background-image:linear-gradient(#fff,#fff);background-repeat:no-repeat;background-size:62% 1.5px;background-position:50% 50%;
}
.status-dot{width:12px;height:12px}
.status-pick[data-tone="none"] .status-dot{background:transparent;box-shadow:inset 0 0 0 2px var(--faint)}
.status-line{
  width:100%;height:32px;padding:0 var(--s2);
  border:1px solid var(--line);border-radius:var(--r-sm);
  background:var(--surface);color:var(--ink);font:inherit;font-size:var(--t-sm);
}
.status-line::placeholder{color:var(--faint)}
.status-line:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-glow)}
.status-line.is-failed{border-color:var(--danger)}

/* The accounts this browser knows (assets/accounts.js). Each is a row you
   can switch to, and a small way to forget one. */
.menu-accounts{display:grid;gap:2px;padding:2px 0}
.menu-account-row{position:relative;display:flex}
.menu-account{flex:1;min-width:0;gap:var(--s2);text-align:left}
.menu-account-av{
  flex:none;width:26px;height:26px;display:grid;place-items:center;
  border-radius:50%;background:var(--ground-deep);color:var(--muted);
  font-size:var(--t-xs);font-weight:700;
}
.menu-account-text{min-width:0;display:grid}
.menu-account-text strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600}
.menu-account-text small{color:var(--muted);font-size:var(--t-xs);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.menu-account-forget{
  position:absolute;right:6px;top:50%;transform:translateY(-50%);
  width:24px;height:24px;border:0;border-radius:50%;
  background:none;color:var(--faint);font-size:16px;line-height:1;cursor:pointer;
  opacity:0;transition:opacity var(--dur-fast) var(--ease);
}
.menu-account-row:hover .menu-account-forget,.menu-account-forget:focus-visible{opacity:1}
.menu-account-forget:hover{background:var(--hover);color:var(--ink)}
@media (hover:none){.menu-account-forget{opacity:1}}
.menu-account-add{color:var(--brand);font-weight:600}

/* A line of explanation inside the menu (install.js's manual steps). */
.menu-hint{margin:2px var(--s3) var(--s2);color:var(--muted);font-size:var(--t-sm);line-height:1.45}
.menu-hint--warn{color:var(--warm)}
.menu-identity{border-bottom:1px solid var(--line-soft);padding-bottom:var(--s2);margin-bottom:var(--s2)}

.menu-item{
  width:100%;
  display:flex;align-items:center;gap:var(--s3);
  padding:var(--s2) var(--s3);
  border-radius:var(--r-sm);
  font-size:var(--t-base);font-weight:500;color:var(--ink);
  transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease);
}
.menu-item .icon{width:17px;height:17px;color:var(--faint)}
.menu-item:hover{background:var(--hover)}
.menu-item--danger:hover{color:var(--danger)}
.menu-item--danger:hover .icon{color:var(--danger)}

/* ── 11. panes ───────────────────────────────────────────────────────────── */
.panes{
  grid-area:panes;
  position:relative;
  overflow:hidden;
  background:var(--stage);
}

/*  ╔═══════════════════════════════════════════════════════════════════════╗
    ║  THE ONE RULE THAT MATTERS.                                           ║
    ║                                                                       ║
    ║  A hidden pane is hidden with visibility + opacity ONLY. It is never   ║
    ║  display:none'd, never given content-visibility:hidden, and never      ║
    ║  removed from the DOM. The Chat/Meet pane can be holding a live call   ║
    ║  with the microphone and camera open; every one of those three would   ║
    ║  tear the iframe's document down and drop the call, and the user would ║
    ║  simply see the call end for no stated reason.                         ║
    ║                                                                       ║
    ║  visibility:hidden keeps the document loaded and the media running,    ║
    ║  while still removing the pane from hit-testing and the tab order.     ║
    ║  The delayed visibility transition is what lets the crossfade finish   ║
    ║  before the outgoing pane stops accepting the pointer.                 ║
    ╚═══════════════════════════════════════════════════════════════════════╝ */
.pane{
  position:absolute;inset:0;
  background:var(--stage);
  opacity:1;visibility:visible;
  transition:opacity var(--dur) var(--ease),visibility 0s;
}
.pane.is-hidden{
  opacity:0;
  visibility:hidden;
  pointer-events:none;
  transition:opacity var(--dur-fast) var(--ease),
             visibility 0s linear var(--dur-fast);
}
/* Entry animation lives on the pane and ends at identity, so no transform is
   ever left standing on a frame that is holding a call. */
@keyframes paneIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.pane.is-entering{animation:paneIn var(--dur) var(--ease) both}

.pane-frame{display:block;width:100%;height:100%;border:0;background:var(--stage)}

.pane-load{
  position:absolute;inset:0;z-index:2;
  display:grid;place-items:center;align-content:center;gap:var(--s4);
  background:var(--stage);
  opacity:1;
  transition:opacity var(--dur) var(--ease);
}
.pane-load.is-done{opacity:0;pointer-events:none}
.pane-load-ring{
  width:32px;height:32px;border-radius:50%;
  border:2px solid var(--stage-line);
  border-top-color:var(--brand);
  animation:spin .85s linear infinite;
}
@keyframes spin{to{transform:rotate(360deg)}}
.pane-load-msg{font-size:var(--t-sm);color:var(--muted);text-align:center;max-width:34ch}
.pane-load-link{
  font-size:var(--t-sm);font-weight:600;color:var(--brand);
  text-decoration:underline;text-underline-offset:3px;
  text-decoration-color:color-mix(in srgb, var(--brand) 40%, transparent);
}
.pane-load-link:hover{text-decoration-color:var(--brand)}

/* ── 11b. connect state ──────────────────────────────────────────────────── */
/* Drawn INSTEAD of an iframe when the workspace session is missing. A first-run
   step, composed like one: display face, one obvious action, calm. It sits on
   the stage rather than in the chrome, because it stands in for the pane. */
.pane-connect{
  position:absolute;inset:0;
  display:grid;place-items:center;
  overflow:auto;
  padding:var(--s6) var(--s5);
  background:
    radial-gradient(760px 420px at 50% -14%, var(--brand-glow), transparent 68%),
    var(--stage);
}
.connect-card{
  width:100%;max-width:430px;text-align:center;
  background:var(--surface);
  border:1px solid var(--line-soft);
  border-radius:var(--r-lg);
  box-shadow:var(--shadow-md);
  padding:var(--s7) var(--s6) var(--s6);
  animation:rise var(--dur-slow) var(--ease) both;
}
.connect-chip{
  width:54px;height:54px;margin:0 auto;
  display:grid;place-items:center;
  border-radius:var(--r-md);
  background:var(--brand-tint);color:var(--brand);
  box-shadow:0 0 0 1px var(--brand-glow);
}
.connect-chip .icon{width:25px;height:25px}
.connect-title{
  font-family:var(--display);
  font-size:var(--t-xl);font-weight:600;letter-spacing:-.026em;line-height:1.15;
  margin-top:var(--s5);color:var(--ink);
}
.connect-lede{
  margin:var(--s3) auto 0;max-width:34ch;
  font-size:var(--t-md);line-height:1.6;color:var(--muted);
  text-wrap:pretty;
}
.connect-action{margin-top:var(--s6);width:100%}
.connect-note{margin-top:var(--s3);font-size:var(--t-sm);color:var(--faint)}
.connect-alt{
  margin-top:var(--s5);
  font-size:var(--t-sm);color:var(--muted);
  text-decoration:underline;text-underline-offset:3px;
  text-decoration-color:color-mix(in srgb, var(--muted) 40%, transparent);
  transition:color var(--dur-fast) var(--ease);
}
.connect-alt:hover{color:var(--ink)}

/* ── 12. session toast ───────────────────────────────────────────────────── */
.toast{
  position:absolute;z-index:40;
  top:calc(var(--topbar) + var(--s3));right:var(--s4);
  max-width:min(420px, calc(100vw - var(--s7)));
  display:flex;align-items:center;gap:var(--s3);
  padding:var(--s3) var(--s3) var(--s3) var(--s4);
  background:var(--surface);
  border:1px solid var(--line);
  border-left:3px solid var(--warm);
  border-radius:var(--r-md);
  box-shadow:var(--shadow-lg);
  animation:toastIn 280ms var(--ease) both;
}

/* The note beside the session toast: same object, different job. Its left edge
   is the accent rather than the warning colour, because it reports something
   the person asked for, and it steps down when the session toast is already
   holding that corner. */
.toast--note{border-left-color:var(--brand)}
.toast--note.is-stacked{top:calc(var(--topbar) + var(--s3) + 104px)}
/* ── a new version is ready (assets/version.js) ────────────────────────────
   Quiet on purpose: this is news, not an emergency. Bottom-left, so it never
   sits where the call bar (bottom-centre) or a toast (top-right) goes. */
.update-bar{
  position:fixed;z-index:50;
  left:var(--s4);bottom:var(--s4);
  display:flex;align-items:center;gap:var(--s2);
  max-width:min(380px, calc(100vw - 2 * var(--s4)));
  padding:8px 8px 8px var(--s4);
  border-radius:999px;
  background:var(--surface);color:var(--ink);
  border:1px solid var(--line);
  box-shadow:var(--shadow-md);
  font-size:var(--t-sm);
  animation:rise var(--dur-slow) var(--ease) both;
}
.update-text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.update-reload{
  flex:none;height:30px;padding:0 14px;border:0;border-radius:999px;
  background:var(--brand);color:var(--on-brand);
  font:inherit;font-weight:650;cursor:pointer;
}
.update-reload:hover{background:var(--brand-deep)}
.update-later{
  flex:none;width:28px;height:28px;border:0;border-radius:50%;
  background:none;color:var(--faint);font-size:17px;line-height:1;cursor:pointer;
}
.update-later:hover{background:var(--hover);color:var(--ink)}
.update-reload:focus-visible,.update-later:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
@media (max-width:700px){ .update-bar{bottom:calc(64px + var(--s3));left:var(--s3);right:var(--s3);max-width:none} }

/* ── a call in progress, in every pane (calls/ring.js) ─────────────────────
   Reported 2026-09-11: the only sign of a call was inside Chat, so somebody
   reading Mail had no idea one was happening. A pill at the bottom, over
   everything, in the warning colour rather than the brand's — a call is not
   the same kind of message as "saved". */
.callbar{
  position:fixed;z-index:55;
  left:50%;transform:translateX(-50%);
  bottom:var(--s4);
  display:flex;align-items:center;gap:var(--s3);
  max-width:min(460px, calc(100vw - 2 * var(--s4)));
  padding:8px 10px 8px var(--s4);
  border-radius:999px;
  background:var(--danger);color:var(--surface);
  box-shadow:var(--shadow-lg);
  font-size:var(--t-sm);font-weight:500;
  animation:callbarIn 240ms var(--ease) both;
}
@keyframes callbarIn{from{opacity:0;transform:translate(-50%,12px)}to{opacity:1;transform:translateX(-50%)}}
@media (prefers-reduced-motion:reduce){.callbar{animation:none}}
.callbar-dot{
  flex:none;width:9px;height:9px;border-radius:50%;
  background:var(--surface);
  animation:callbarPulse 1.4s var(--ease) infinite;
}
@keyframes callbarPulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.45;transform:scale(.8)}}
@media (prefers-reduced-motion:reduce){.callbar-dot{animation:none}}
/* ── the call, small, while elsewhere in Atrium (call/mini.js) ────────────── */
.ac-mini{
  position:fixed;z-index:56;
  width:min(240px, calc(100vw - 2 * var(--s4)));
  display:flex;flex-direction:column;
  border-radius:var(--r-lg);overflow:hidden;
  background:var(--call-surface);color:var(--call-ink);
  border:1px solid var(--call-line);
  box-shadow:var(--shadow-lg);
  cursor:pointer;touch-action:none;user-select:none;
  animation:acMiniIn 200ms var(--ease) both;
}
.ac-mini[data-corner="br"]{right:var(--s4);bottom:calc(var(--s4) + env(safe-area-inset-bottom, 0px))}
.ac-mini[data-corner="bl"]{left:var(--s4);bottom:calc(var(--s4) + env(safe-area-inset-bottom, 0px))}
.ac-mini[data-corner="tr"]{right:var(--s4);top:calc(var(--s4) + env(safe-area-inset-top, 0px))}
.ac-mini[data-corner="tl"]{left:var(--s4);top:calc(var(--s4) + env(safe-area-inset-top, 0px))}
.ac-mini.is-dragging{right:auto;bottom:auto;cursor:grabbing;animation:none;transition:none}
.ac-mini:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
@keyframes acMiniIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.ac-mini{animation:none}}
.ac-mini-stage{position:relative;aspect-ratio:16/9;background:var(--call-stage);display:grid;place-items:center}
.ac-mini-video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:none}
.ac-mini.has-video .ac-mini-video{display:block}
.ac-mini.is-screen .ac-mini-video{object-fit:contain}
.ac-mini-face{
  width:52px;height:52px;border-radius:50%;display:grid;place-items:center;
  background:var(--brand);color:var(--call-ink);font-weight:600;font-size:var(--t-md);
}
.ac-mini.has-video .ac-mini-face{display:none}
.ac-mini-who{display:flex;align-items:baseline;gap:var(--s2);padding:var(--s2) var(--s3) 0;font-size:var(--t-sm);min-width:0}
.ac-mini-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500}
.ac-mini-time{flex:none;color:var(--call-muted);font-variant-numeric:tabular-nums}
.ac-mini-bar{display:flex;gap:var(--s2);padding:var(--s2) var(--s3) var(--s3)}
.ac-mini-btn{
  flex:1;height:34px;border:0;border-radius:999px;display:grid;place-items:center;cursor:pointer;
  background:color-mix(in srgb,var(--call-ink) 12%,transparent);color:var(--call-ink);
}
.ac-mini-btn:hover{background:color-mix(in srgb,var(--call-ink) 20%,transparent)}
.ac-mini-btn:focus-visible{outline:2px solid var(--brand);outline-offset:1px}
.ac-mini.is-muted .ac-mini-mic{background:color-mix(in srgb,var(--danger) 30%,transparent)}
.ac-mini-hang{background:var(--danger);color:var(--surface)}
.ac-mini-hang:hover{background:color-mix(in srgb,var(--danger) 85%,var(--call-ink))}
@media (max-width:560px){.ac-mini{width:168px}.ac-mini-face{width:40px;height:40px;font-size:var(--t-sm)}}
.callbar-text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.callbar-join{
  flex:none;height:30px;padding:0 14px;border:0;border-radius:999px;
  background:var(--surface);color:var(--danger);
  font:inherit;font-weight:700;cursor:pointer;
}
.callbar-join:hover{background:var(--ground)}
.callbar-hide{
  flex:none;width:28px;height:28px;border:0;border-radius:50%;
  background:none;color:var(--surface);opacity:.8;
  font-size:18px;line-height:1;cursor:pointer;
}
.callbar-hide:hover{opacity:1;background:color-mix(in srgb, var(--surface) 22%, transparent)}
.callbar-join:focus-visible,.callbar-hide:focus-visible{outline:2px solid var(--surface);outline-offset:2px}
/* Above the bottom rail on a phone. */
@media (max-width:700px){ .callbar{bottom:calc(64px + var(--s3))} }

/* ── someone is calling (calls/ring.js) ────────────────────────────────────
   Over everything, because a call is the one thing that cannot wait for the
   right pane — and appended to <body>, so no pane's stacking context can bury
   it. Answer and Decline are the same size on purpose. */
/* ── an incoming call ────────────────────────────────────────────────────────
   Not a toast in a corner (that was the 2026-09-11 card): the screen a phone
   shows. On a phone it takes the whole screen; on a desktop a large card in
   the middle over a dimmed page. The face sits in rings that pulse in time
   with the ringtone; the two answers are the size of thumbs. */
.ringing{
  position:fixed;z-index:60;
  inset:0;
  display:grid;place-items:center;
  padding:var(--s5);
  background:color-mix(in srgb, var(--ink) 55%, transparent);
  backdrop-filter:blur(6px);
  animation:fadeIn var(--dur-fast) var(--ease) both;
}
.ringing-panel{
  display:grid;justify-items:center;gap:var(--s4);
  width:min(400px,100%);
  padding:var(--s6) var(--s5) var(--s4);
  border-radius:var(--r-lg);
  background:var(--surface);color:var(--ink);
  box-shadow:var(--shadow-lg);
  text-align:center;
}
.ringing-who{display:grid;justify-items:center;gap:var(--s4);width:100%}
.ringing-halo{
  position:relative;width:132px;height:132px;display:grid;place-items:center;
}
.ringing-halo::before,.ringing-halo::after{
  content:"";position:absolute;inset:0;border-radius:50%;
  border:2px solid var(--brand);opacity:0;
  animation:ringHalo 1.6s var(--ease) infinite;
}
.ringing-halo::after{animation-delay:.8s}
@keyframes ringPulse{0%,100%{transform:scale(1)}50%{transform:scale(1.04)}}
@keyframes ringHalo{
  0%{transform:scale(.72);opacity:.75}
  100%{transform:scale(1.25);opacity:0}
}
.ringing-avatar{
  position:relative;width:96px;height:96px;display:grid;place-items:center;
  border-radius:50%;overflow:hidden;
  background:var(--brand-tint);color:var(--brand);
  font-weight:650;font-size:38px;
  box-shadow:0 0 0 4px var(--surface),0 0 0 6px var(--brand-glow);
}
.ringing-avatar img{width:100%;height:100%;object-fit:cover}
.ringing-avatar.has-picture{color:transparent}
.ringing-text{display:grid;gap:4px;min-width:0;width:100%}
.ringing-text strong{font-family:var(--display);font-size:var(--t-xl);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ringing-text span{color:var(--muted);font-size:var(--t-md)}
.ringing-acts{
  display:grid;grid-template-columns:1fr 1fr;gap:var(--s4);
  width:100%;margin-top:var(--s2);
}
.ringing-btn{
  height:56px;border-radius:28px;border:1px solid var(--line);
  background:var(--surface);color:var(--ink);
  font:inherit;font-size:var(--t-md);font-weight:600;cursor:pointer;
  box-shadow:var(--shadow-md);
}
.ringing-btn:hover{background:var(--hover)}
.ringing-btn--answer{background:var(--ok,var(--brand));border-color:transparent;color:var(--on-brand);animation:ringPulse 1.6s var(--ease) infinite}
.ringing-btn--answer:hover{filter:brightness(1.05)}
.ringing-btn--decline{background:var(--danger);border-color:transparent;color:var(--on-brand)}
.ringing-btn:focus-visible{outline:3px solid var(--on-brand);outline-offset:-5px}
.ringing-quiet{
  justify-self:center;
  background:none;border:0;padding:6px 10px;
  color:var(--muted);font:inherit;font-size:var(--t-sm);cursor:pointer;
}
.ringing-quiet:hover:not(:disabled){color:var(--ink);text-decoration:underline}
.ringing-quiet:disabled{cursor:default;opacity:.6}
@media (max-width:700px){
  /* The whole screen: the face in the middle, the buttons at the bottom where
     thumbs are, a safe-area margin under them. */
  .ringing{padding:0;background:var(--stage);backdrop-filter:none;place-items:stretch}
  .ringing-panel{
    width:100%;height:100%;box-sizing:border-box;border-radius:0;box-shadow:none;background:transparent;
    grid-template-rows:1fr auto auto;align-items:end;
    padding:var(--s5) var(--s5) calc(var(--s5) + var(--safe-b));
  }
  .ringing-who{align-self:center}
  .ringing-btn{height:64px;border-radius:32px}
}
@media (prefers-reduced-motion:reduce){
  .ringing-halo::before,.ringing-halo::after,.ringing-btn--answer{animation:none}
  .ringing-halo::before{opacity:.5;transform:none}
}

@keyframes toastIn{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:none}}
.toast-icon{color:var(--warm)}
.toast-body{flex:1 1 auto;display:grid;gap:2px;min-width:0}
.toast-body strong{font-size:var(--t-base);font-weight:600}
.toast-body span{font-size:var(--t-sm);color:var(--muted)}
/* The text is what gives way. Flex items shrink by default, so without these
   the body text squeezed "Sign in again" onto two lines that spilled out of
   its fixed-height button, and could crush the dismiss button to a sliver. */
.toast .btn,.toast .iconbtn{flex:none;white-space:nowrap}

/* ── 13. noscript ────────────────────────────────────────────────────────── */
.noscript{
  max-width:440px;margin:18vh auto 0;padding:var(--s6);
  background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-lg);box-shadow:var(--shadow-md);text-align:center;
}
.noscript h1{font-family:var(--display);font-size:var(--t-xl);font-weight:600;letter-spacing:-.02em}
.noscript p{margin-top:var(--s3);color:var(--muted);line-height:1.6}

/* ── 14. narrow ──────────────────────────────────────────────────────────── */
/* Under 700px the rail becomes a bottom bar. The grid re-flows; nothing is
   rebuilt, so a pane loaded on a wide screen survives a rotate to portrait. */
@media (max-width:700px){
  .app{
    grid-template-columns:minmax(0,1fr);
    grid-template-rows:var(--topbar) minmax(0,1fr) auto;
    grid-template-areas:
      "topbar"
      "panes"
      "rail";
  }
  .rail{
    flex-direction:row;
    border-right:0;
    border-top:1px solid var(--line);
    background:var(--surface);
    /* clears the iOS home indicator without eating pane height above it */
    padding-bottom:var(--safe-b);
  }
  .rail-brand{display:none}
  .rail-sep{display:none}
  .rail-nav{
    flex-direction:row;
    justify-content:space-between;
    gap:0;
    padding:var(--s1) var(--s2);
  }
  .navbtn{
    width:auto;height:auto;
    flex:1 1 0;min-width:0;
    padding:7px 2px 6px;
    gap:4px;
    grid-auto-flow:row;
    border-radius:10px;
  }
  .navbtn .icon{width:24px;height:24px}   /* owner 2026-10-10: "pwa needs bigger icons"; five apps and More leave ~57px+ a slot */
  .navbtn-label{
    display:block;
    font-size:11px;line-height:1;letter-spacing:.005em;font-weight:500;
    max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  }
  /* the marker moves to the top edge of the bar */
  .navbtn::before{
    left:50%;top:-4px;margin:0 0 0 -11px;
    width:22px;height:3px;
    border-radius:0 0 3px 3px;
    transform:scaleX(.4) scaleY(0);transform-origin:center top;
  }
  .navbtn.is-active::before{transform:scaleX(1) scaleY(1)}
  .navbtn.is-active{box-shadow:none}
  .tip{display:none}                    /* labels are on screen; tips would fight */

  .topbar{padding:0 var(--s2) 0 var(--s4);gap:var(--s2)}
  .topbar-mark{display:block}
  .topbar-icon{display:none}
  .topbar-title{font-size:18px}
  .toast{top:auto;bottom:calc(var(--rail) + var(--s3));right:var(--s3);left:var(--s3);max-width:none}
}

/* An open conversation on a phone owns the screen, as in every messenger: the
   app bar and the bottom bar step aside and the conversation's own header (with
   its back button) is the only bar above the messages. Reported 2026-10-06:
   two top bars, the composer and the bottom bar left a strip to read in, and
   with the keyboard up there was nothing at all. */
@media (max-width:700px){
  .app:has(> .panes > .pane:not(.is-hidden) .talk.is-thread){
    grid-template-rows:minmax(0,1fr);
    grid-template-areas:"panes";
  }
  .app:has(> .panes > .pane:not(.is-hidden) .talk.is-thread) > .topbar,
  .app:has(> .panes > .pane:not(.is-hidden) .talk.is-thread) > .rail{display:none}
}
/* Mail on a phone, the same (asked for 2026-10-07: "compaction like what
   happened to chat"): an open message owns the screen. Of 844 px a message
   started at 203 and the bottom bar took 56 more; the reader's own header,
   with its back arrow, is the only bar left above it. Writing is already a
   full-screen sheet (compose.css). */
@media (max-width:700px){
  .app:has(> .panes > .pane:not(.is-hidden) .mail.has-open){
    grid-template-rows:minmax(0,1fr);
    grid-template-areas:"panes";
  }
  .app:has(> .panes > .pane:not(.is-hidden) .mail.has-open) > .topbar,
  .app:has(> .panes > .pane:not(.is-hidden) .mail.has-open) > .rail{display:none}
}

@media (max-width:520px){
  .connect-card{padding:var(--s6) var(--s5) var(--s5);border-radius:var(--r-md)}
  .connect-title{font-size:23px}
  .connect-lede{font-size:var(--t-base)}
  .user-name,.user-caret{display:none}
  .user-btn{padding:0 5px}
  .signin{padding:var(--s7) var(--s5) var(--s6);border-radius:var(--r-lg)}
  .wordmark{font-size:38px}
  .signin-tagline{font-size:var(--t-base)}
  .preview li{width:calc(25% - var(--s1));gap:6px}
}

/* 400px: seven targets still clear 44px of tappable width each. */
@media (max-width:400px){
  .topbar{padding:0 var(--s1) 0 var(--s3)}
  .navbtn-label{font-size:9px}
}

/* The live call, laid over the native chat pane. Atrium's own screen since
   2026-09-12 (assets/call/); the frame below it is the fallback. */
.call-overlay{position:absolute;inset:0;z-index:5;display:flex;flex-direction:column;background:var(--stage)}
/* Only the frame fallback has anything to preload, and it hides rather than
   un-displays: display:none suspends a frame, and the whole point would be
   that it is busy loading. */
.call-overlay.is-preload{visibility:hidden;pointer-events:none}
/* Back, with the call still running: out of sight, still connected, still
   holding the microphone it was given. The shell's call bar is the way back
   (panes.js callState -> visible). Removing it instead would leave a live
   call with no screen attached to it. */
.call-overlay.is-away{visibility:hidden;pointer-events:none}
/* In-call chat (2026-09-14): the call docks to the left and the Chat pane's own
   conversation — every message feature it already has — fills the column on
   the right. Chat is a two-column grid, list | thread, so docking only moves
   that line; the list column sits under the call, out of sight. */
.pane{--call-dock:min(400px,42%)}
.call-overlay.is-docked{right:var(--call-dock);border-right:1px solid var(--line)}
.is-call-docked .talk{grid-template-columns:minmax(0,1fr) var(--call-dock)}
.is-call-docked .talk-nav{visibility:hidden}
.is-call-docked .talk-callslot{display:none}
/* The thread's own "Join call" button, beside the call it would join: it
   restarted the call instead (reported 2026-09-17). The call is right there. */
.is-call-docked .talk-call-btn{display:none}
/* Every sheet Chat opens (a transcript, a confirmation, the people panel's
   dialogs) sits on a scrim over the WHOLE Talk pane and is centred in it. Beside
   a call, the pane's centre is under the call overlay: the person saw the chat
   go dim and nothing appear (reported 2026-09-17: "blur again and show
   nothing"). Confined to the chat column, the sheet lands where the person is
   looking. */
.is-call-docked .talk-scrim{left:calc(100% - var(--call-dock))}
/* The handle between the call and the chat (panes.js addDockGrip). It sits on
   the seam, is wider than it looks so it can actually be grabbed, and shows
   itself on hover or keyboard focus rather than drawing a permanent line. */
.call-dock-grip{
  position:absolute;z-index:5;top:0;bottom:0;
  right:calc(var(--call-dock) - 4px);width:9px;
  cursor:col-resize;touch-action:none;
  background:transparent;
}
.call-dock-grip::after{
  content:"";position:absolute;inset:0 4px;border-radius:2px;
  background:var(--brand);opacity:0;
  transition:opacity var(--dur-fast) var(--ease);
}
.call-dock-grip:hover::after,
.call-dock-grip:focus-visible::after,
.is-dock-resizing .call-dock-grip::after{opacity:.55}
.call-dock-grip:focus-visible{outline:none}
/* While dragging, nothing else should take the pointer or select text. */
.is-dock-resizing{user-select:none}
.is-dock-resizing .call-overlay,
.is-dock-resizing .talk{pointer-events:none}
.is-dock-resizing .call-dock-grip{pointer-events:auto}
.call-overlay-bar{flex:none;display:flex;align-items:center;padding:8px 12px;background:var(--surface);border-bottom:1px solid var(--stage-line)}
.call-overlay .pane-frame{flex:1;width:100%;border:0}
/* Atrium's own screen over the call frame until Talk's call screen is ready
   (panes.js buildCallLoading) — never the workspace's start-up screen. */
.call-loading{
  position:absolute;inset:0;z-index:4;
  display:grid;place-content:center;justify-items:center;gap:var(--s3);
  background:var(--ground);color:var(--ink);text-align:center;
  transition:opacity .3s var(--ease);
}
.call-loading.is-done{opacity:0;pointer-events:none}
.call-loading-mark{width:44px;height:44px;color:var(--brand)}
.call-loading-title{margin:0;font-family:var(--display);font-size:var(--t-lg);font-weight:600}
.call-loading-step{margin:0;color:var(--muted);font-size:var(--t-sm);min-height:1.4em}
.call-loading-bar{width:220px;height:4px;border-radius:999px;background:var(--line-soft);overflow:hidden}
.call-loading-bar span{display:block;height:100%;width:20%;border-radius:inherit;background:var(--brand);transition:inline-size .6s var(--ease);animation:callLoadingPulse 1.4s ease-in-out infinite alternate}
@keyframes callLoadingPulse{from{opacity:.55}to{opacity:1}}
@media (prefers-reduced-motion:reduce){.call-loading-bar span{animation:none}}
.call-overlay-try{margin-left:auto;font-size:var(--t-xs)}
/* The native call spike: Atrium's own call screen (talk/native-call.js). */
.call-overlay.is-native{background:var(--ground)}
.nc{flex:1;min-height:0;display:flex;flex-direction:column;gap:var(--s4);padding:var(--s5);overflow:auto}
.nc-head{display:flex;align-items:center;gap:var(--s3)}
.nc-title{margin:0;font:500 22px/1.2 var(--display)}
.nc-badge{padding:2px 8px;border-radius:999px;background:var(--warm-tint);color:var(--warm);font-size:var(--t-micro);font-weight:700}
.nc-status{margin:0;color:var(--muted);font-size:var(--t-sm)}
.nc[data-state="connected"] .nc-status{color:var(--brand)}
.nc[data-state="failed"] .nc-status{color:var(--danger)}
.nc-tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:var(--s3)}
.nc-tile{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--s2);aspect-ratio:4/3;border-radius:var(--r-md);background:var(--surface);border:1px solid var(--line)}
.nc-tile.is-live{border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-glow)}
.nc-tile.is-muted .nc-initial{opacity:.5}
.nc-initial{display:grid;place-items:center;width:56px;height:56px;border-radius:50%;background:var(--brand-tint);color:var(--brand-deep);font:600 18px/1 var(--body)}
.nc-name{font-size:var(--t-sm);color:var(--muted)}
.nc-controls{display:flex;flex-wrap:wrap;gap:var(--s2)}
.nc-btn{height:38px;padding:0 var(--s4);border-radius:999px;border:1px solid var(--line);background:var(--surface);color:var(--ink);font-weight:600}
.nc-btn:hover{background:var(--hover)}
.nc-btn--leave{background:var(--danger);border-color:var(--danger);color:var(--on-brand)}
.nc-btn--quiet{background:none}
.nc-log{font-size:var(--t-xs);color:var(--muted)}
.nc-log summary{cursor:pointer}
.nc-log .nc-btn{height:28px;margin:var(--s2) 0;font-size:var(--t-xs)}
.nc-log-pre{margin:0;padding:var(--s3);max-height:260px;overflow:auto;border-radius:var(--r-sm);background:var(--surface);border:1px solid var(--line-soft);font:var(--t-xs)/1.5 var(--mono);white-space:pre-wrap}

/* ── a person's card (assets/profile.js) ───────────────────────────────────
   Somebody else's profile, read-only; or your own picture with Replace and
   Remove. One dialog for both. */


.pf-close{
  position:absolute;top:var(--s2);right:var(--s2);width:32px;height:32px;
  border:0;border-radius:50%;background:transparent;color:var(--muted);
  font:inherit;font-size:22px;line-height:1;cursor:pointer;
}
.pf-close:hover{background:var(--hover);color:var(--ink)}
.pf-close:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.pf-body{display:grid;gap:var(--s4);padding:var(--s6) var(--s5) var(--s5)}
.pf-head{display:grid;justify-items:center;gap:var(--s2);text-align:center}
.pf-avatar{
  width:112px;height:112px;display:grid;place-items:center;overflow:hidden;
  border-radius:50%;background:var(--brand-tint);color:var(--brand);
  font-weight:650;font-size:40px;
  box-shadow:0 0 0 1px var(--brand-glow);
}
.pf-avatar img{width:100%;height:100%;object-fit:cover}
.pf-avatar.has-picture{color:transparent}
.pf-name{margin:var(--s2) 0 0;font-family:var(--display);font-size:var(--t-xl);font-weight:600}
.pf-line{margin:0;color:var(--ink);font-size:var(--t-md)}
.pf-line--soft{color:var(--muted);font-size:var(--t-sm)}
.pf-wait,.pf-note{margin:0;text-align:center;color:var(--muted);font-size:var(--t-sm);min-height:1.2em}
.pf-rows{
  margin:0;display:grid;grid-template-columns:auto minmax(0,1fr);gap:var(--s1) var(--s4);
  font-size:var(--t-base);
}
.pf-rows dt{color:var(--muted);font-size:var(--t-sm);padding-top:2px}
.pf-rows dd{margin:0;min-width:0;overflow-wrap:anywhere}
.pf-rows a{color:var(--brand)}
.pf-bio{margin:0;color:var(--ink);font-size:var(--t-base);line-height:1.5;white-space:pre-wrap;overflow-wrap:anywhere}
.pf-acts{display:flex;gap:var(--s4);justify-content:center;flex-wrap:wrap;margin-top:var(--s2)}
/* What you can do with a person: a mark you can hit with a thumb and the
   word under it. The word stays — an icon on its own is a guess, and it is
   what a screen reader would be left with. */
.pf-act{
  display:grid;justify-items:center;gap:6px;
  width:64px;padding:0;border:0;background:none;
  color:var(--muted);font-size:var(--t-xs);cursor:pointer;
}
.pf-act-icon{
  width:44px;height:44px;padding:11px;
  border-radius:50%;
  /* A tint of the text colour rather than a named ground: --ground-deep is
     nearly black in dark mode, so the circles disappeared into the card. This
     is a faint wash of whatever the ink is, in either theme. */
  background:color-mix(in srgb, var(--ink) 9%, transparent);color:var(--ink);
  transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease);
}
.pf-act--primary .pf-act-icon{background:var(--brand);color:var(--on-brand)}
.pf-act:hover .pf-act-icon{background:color-mix(in srgb, var(--ink) 16%, transparent)}
.pf-act--primary:hover .pf-act-icon{background:var(--brand-deep)}
.pf-act:focus-visible{outline:none}
.pf-act:focus-visible .pf-act-icon{outline:2px solid var(--brand);outline-offset:2px}
.pf-act-label{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pf-btn{
  height:40px;padding:0 var(--s4);border-radius:var(--r-sm);
  border:1px solid var(--line);background:var(--surface);color:var(--ink);
  font:inherit;font-weight:600;cursor:pointer;
}
.pf-btn:hover{background:var(--hover)}
.pf-btn--primary{background:var(--brand);border-color:var(--brand);color:var(--on-brand)}
.pf-btn--primary:hover{background:var(--brand-deep)}
.pf-btn:disabled{opacity:.6;cursor:default}
.pf-btn:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
/* An avatar that opens a card looks like it can be pressed. */
.talk-avatar.is-person{cursor:pointer}
.talk-avatar.is-person:hover{box-shadow:0 0 0 2px var(--brand-glow)}
.talk-avatar.is-person:focus-visible{outline:2px solid var(--brand);outline-offset:2px}

/* "… is free to edit now" (files/lockwatch.js). */
.lockwatch-note{position:fixed;left:50%;bottom:var(--s5);transform:translateX(-50%);z-index:80;display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;
  max-width:min(560px,calc(100vw - 32px));padding:var(--s2) var(--s3);border-radius:var(--r-md);background:var(--surface);color:var(--ink);
  border:1px solid var(--line);box-shadow:var(--shadow-lg);font-size:var(--t-sm)}
.lockwatch-note span{flex:1 1 220px}

/* ── 15. the app bar: More and the order editor (appbar.js) ─────────────── */
.navbtn.is-over{display:none}
.rail-nav{flex:1 1 auto;min-height:0;overflow:hidden}
.navbtn--more .icon{stroke:none;fill:currentColor}
.appbar-scrim{position:fixed;inset:0;z-index:90;display:grid;place-items:center;padding:var(--s4);background:color-mix(in srgb,var(--ink) 38%,transparent);animation:fadeIn 160ms var(--ease) both}
.appbar-more{position:fixed;z-index:90;width:288px;padding:var(--s3);border:1px solid var(--line);border-radius:var(--r-lg);background:var(--surface);box-shadow:var(--shadow-md);display:grid;gap:var(--s2);animation:fadeIn 140ms var(--ease) both}
.appbar-moregrid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:4px}
.appbar-app{position:relative;display:grid;justify-items:center;gap:6px;padding:12px 4px 10px;border-radius:var(--r-md);color:var(--muted);font:inherit}
.appbar-app .icon{width:26px;height:26px}
.appbar-app:hover{background:var(--hover);color:var(--ink)}
.appbar-app.is-active{background:var(--brand-tint);color:var(--brand)}
.appbar-app .navbtn-badge{top:6px;right:calc(50% - 26px)}
.appbar-applabel{font-size:var(--t-sm);font-weight:500;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.appbar-edit{height:40px;border-top:1px solid var(--line);margin-top:4px;padding-top:4px;color:var(--brand);font:inherit;font-weight:600;font-size:var(--t-sm)}
.appbar-edit span{display:inline-block;padding:8px 14px;border-radius:var(--r-sm)}
.appbar-edit:hover span{background:var(--hover)}
.appbar-app:focus-visible,.appbar-edit:focus-visible,.appbar-move:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.appbar-editor{width:min(440px,100%);max-height:min(86vh,720px);display:flex;flex-direction:column;gap:var(--s3);padding:var(--s5);border-radius:var(--r-lg);background:var(--surface);color:var(--ink);box-shadow:var(--shadow-md)}
.appbar-title{margin:0;font-family:var(--display);font-size:var(--t-xl);font-weight:600;letter-spacing:-.01em}
.appbar-hint{margin:0;color:var(--muted);font-size:var(--t-sm);line-height:1.5}
.appbar-list{list-style:none;margin:0;padding:0;overflow-y:auto;min-height:0;display:flex;flex-direction:column}
.appbar-row{display:grid;grid-template-columns:28px 24px minmax(0,1fr) 40px 40px;align-items:center;gap:var(--s2);min-height:52px;padding:0 4px;border-radius:var(--r-md);background:var(--surface);transition:transform 120ms var(--ease)}
.appbar-row .icon{width:22px;height:22px;color:var(--muted)}
.appbar-row.is-dragging{position:relative;z-index:2;transition:none;box-shadow:var(--shadow-md);background:var(--surface)}
.appbar-rowlabel{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.appbar-handle{display:grid;gap:3px;justify-content:center;align-content:center;height:40px;cursor:grab;touch-action:none}
.appbar-handle i{display:block;width:16px;height:2px;border-radius:1px;background:var(--muted)}
.appbar-row.is-dragging .appbar-handle{cursor:grabbing}
.appbar-move{width:40px;height:40px;border-radius:var(--r-sm);color:var(--muted);font:inherit;font-size:17px}
.appbar-move:hover:not(:disabled){background:var(--hover);color:var(--ink)}
.appbar-move:disabled{opacity:.3}
.appbar-line{display:flex;align-items:center;gap:var(--s2);margin:6px 0;color:var(--muted);font-size:var(--t-xs);font-weight:600;letter-spacing:.04em;text-transform:uppercase}
.appbar-line::before,.appbar-line::after{content:"";flex:1;height:0;border-top:1px dashed var(--line)}
.appbar-live{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
.appbar-acts{display:flex;gap:var(--s2);justify-content:flex-end;flex-wrap:wrap}
.appbar-reset{margin-right:auto}
@media (max-width:700px){
  .appbar-scrim{place-items:end stretch;padding:0}
  .appbar-more--sheet{position:static;width:auto;border-radius:20px 20px 0 0;border:0;padding:var(--s2) var(--s4) calc(var(--s4) + var(--safe-b));animation:sheetUp 200ms var(--ease) both}
  .appbar-more--sheet .appbar-moregrid{grid-template-columns:repeat(4,minmax(0,1fr))}
  .appbar-grab{width:36px;height:4px;border-radius:2px;background:var(--line);justify-self:center;margin:4px 0 var(--s2)}
  .appbar-editor{width:100%;max-height:88vh;border-radius:20px 20px 0 0;padding:var(--s5) var(--s4) calc(var(--s4) + var(--safe-b));animation:sheetUp 200ms var(--ease) both}
}
@keyframes sheetUp{from{transform:translateY(24px);opacity:0}to{transform:none;opacity:1}}
@media (prefers-reduced-motion:reduce){.appbar-scrim,.appbar-more,.appbar-editor{animation:none}.appbar-row{transition:none}}
/* Rejoin banner after a reload in a call (call/rejoin-banner.js) */
.rejoin-banner{position:fixed;z-index:90;top:12px;left:50%;transform:translateX(-50%);display:flex;align-items:center;gap:var(--s3, 12px);flex-wrap:wrap;
  max-width:min(560px, calc(100vw - 24px));padding:10px 14px;border-radius:14px;background:var(--ink);color:var(--surface);
  box-shadow:0 12px 32px rgba(0,0,0,.28);font-size:var(--t-sm, 14px)}
.rejoin-words{flex:1 1 220px;min-width:0}
.rejoin-btn{height:34px;padding:0 14px;border:1px solid color-mix(in oklab, var(--surface) 40%, transparent);border-radius:999px;background:none;color:inherit;font:inherit;font-weight:600;cursor:pointer}
.rejoin-btn--go{background:var(--brand);border-color:var(--brand);color:#fff}
.rejoin-btn:focus-visible{outline:2px solid #fff;outline-offset:2px}
/* A window that holds one call (call/window.js) */
body.call-window #app, body.call-window #boot{display:none !important}
.call-window-host{position:fixed;inset:0;background:var(--stage, #0b0f14)}
body.call-window .ac-back, body.call-window .ac-chat{display:none}
