/* ⛔ THE SHARED APP VOCABULARY IS THE APP'S SCOPE, NOT THE SHELL'S PAGE MODE.
   Every rule below was `body.os.inthread …` — the card, the tabs, the note, the
   footer, the whole standard's markup — so on the Work OS home, where
   `inthread` is a real view MODE rather than a style hook, an app drawn exactly
   to SPEC-APP-STANDARD got no styling at all and looked bare. That is not a
   theme bug an app can fix in its own file; it is the shared sheet refusing to
   apply anywhere but one surface. Rules hang off `.osApp` — the app root, which
   every app pane carries. The four rules that are genuinely about the shell
   (hiding the conversation underneath) keep their shell selector. */
/* ── an app, opened inside the platform ────────────────────────────────── */
/* ⛔ THE PANE IS NOT AN OPAQUE SLAB (owner, 2026-09-08, on sight of Mail: the
   background effect "kinda ends and makes an ugly looking one"). Measured that
   day: `.osApp` computed `rgb(244,239,230)` — no alpha — at z-index 14 over a
   `.whPlane` fixed at z-index 0. So the pane painted a flat wall across the
   world, and the plane reappeared exactly where the pane stopped: a hard
   vertical seam down both edges, which is what he photographed.
   ⚡ os-thread.css had ALREADY learned this for the home and wrote it down —
      "it is NOT opaque … the blocks bring their own glass and their own lit top
      edge; the page underneath them is the photograph". The app pane never got
      it. One lesson, two surfaces, applied to one — the same shape as the
      pane-edge fix that reached `.osApp` and not `.toolView`.
   ⛔ NOT fully transparent either. An app can open outside `workHomeOpen`,
      where there is no plane and the conversation sits underneath; only four of
      its elements are `visibility:hidden`, so a clear pane would let the rest
      of the page read through the words. A WASH — the same ground colour, most
      of the way opaque, over a blur — is legible on nothing and lets the
      photograph through where there is one, so the seam becomes a transition
      instead of a cut.
   ⚠ The blur is what makes the wash work: without it the plane's detail reads
     through as noise behind small type. */
.osApp{
  position:fixed;top:var(--wh-top,54px);left:var(--app-left,0);right:var(--app-right,0);
  bottom:0;z-index:14;overflow:auto;
  display:flex;flex-direction:column;
  background:color-mix(in srgb,var(--bg) 86%,transparent);
  -webkit-backdrop-filter:blur(26px) saturate(1.06);backdrop-filter:blur(26px) saturate(1.06)}
/* ⛔ A browser without color-mix must not get a TRANSPARENT pane — it would get
   the worst version of this, not the old one. */
@supports not (background:color-mix(in srgb,red 50%,transparent)){
  .osApp{background:var(--bg)}
}
.osApp[hidden]{display:none}
/* ⛔ NO GUTTER LITERALS HERE, AND NO BREAKPOINTS EITHER. This block used to
   carry `@media (min-width:1180px){ .osApp{left:262px;right:324px} }` — two
   numbers that matched neither the rail (268-276px) nor the dock (324-344px),
   so at every width above 1180 the pane overlapped one rail and was overlapped
   by the other, and the owner reported it as the app "covering the elements
   left and right". The column now comes from --app-left / --app-right, which
   the sheet that DRAWS each rail sets in the same media block that shows it.
   The two `body.workHomeOpen.osAppOpen` overrides that lived here existed only
   to undo those literals; they went with them. */
/* ⛔ The conversation is hidden, not destroyed — closing returns to the thread. */
body.os.inthread.osAppOpen .msgs,
body.os.inthread.osAppOpen .composer,
body.os.inthread.osAppOpen .t-head,
body.os.inthread.osAppOpen .sticky{visibility:hidden}

.osApp .osAppCard{
  border:1px solid var(--line);border-radius:var(--r,14px);overflow:hidden;
  background:var(--glass);backdrop-filter:blur(18px);box-shadow:var(--lift)}
/* ⛔ TABS SCROLL, THEY DO NOT CLIP. Measured 2026-08-29 with Passwords open on
   a company with ten collections: the last tab ("Platformas konti") was cut off
   at the card's edge with nothing to say it was there, so a person reads nine
   collections and concludes the tenth does not exist. Wrapping would push the
   card's first row of content down by a line for every extra tab; scrolling
   keeps the header one row tall and keeps the overflow reachable. */
.osApp .osAppCard .tabs{
  display:flex;gap:2px;padding:9px 5px;border-bottom:1px solid var(--line);
  overflow-x:auto;scrollbar-width:thin}
.osApp .osAppCard .tabs button{flex:0 0 auto}
.osApp .osAppCard .tabs button{
  padding:6px 13px;border:0;border-radius:9px;background:none;cursor:pointer;
  font-size:12.5px;color:var(--muted)}
.osApp .osAppCard .tabs button:hover{background:var(--surf)}
.osApp .osAppCard .tabs button.on{background:var(--surf2);color:var(--ink)}
.osApp .osAppBody{padding:16px 18px}
/* ⛔ THE LABEL MUST NEVER TRUNCATE. Three fixed tracks inside a 694px card
   left ~95px for the name, so "Cookie consent" rendered "Cookie c…" — and the
   Latvian "Sīkdatņu piekrišana" is half again as long. A measurement nobody can
   read the name of is not a measurement, so the COLUMN COUNT gives way, never
   the word.
   ⚡ Multi-column, not grid: auto-fit grid put NEEDS WORK and MIDDLING side by
   side and left STRONG alone against an empty half. Columns BALANCE, so two
   tracks fill evenly beside an open dock and three fill when there is room. */
.osApp .osAppCols{columns:3 260px;column-gap:22px}
.osApp .osAppCols section{break-inside:avoid;margin:0 0 20px}
.osApp .osAppCols h3,.osApp .osAppOne h3{
  font:500 9.5px/1 var(--f-body,Inter,sans-serif);letter-spacing:.14em;text-transform:uppercase;
  color:var(--faint);margin:0 0 10px}
.osApp .osAppRow{
  display:grid;grid-template-columns:minmax(0,1fr) 84px 30px;gap:12px;align-items:center;
  padding:7px 0;font-size:13px;color:var(--muted)}
.osApp .osAppRow .k{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink)}
.osApp .osAppRow .v{font:400 12px var(--osMono);text-align:right;color:var(--ink)}
.osApp .osBar{display:block;height:5px;border-radius:99px;background:var(--surf2);overflow:hidden}
.osApp .osBar i{display:block;height:100%;border-radius:99px;background:var(--line2)}
.osApp .osBar.ok i{background:var(--mint)}
.osApp .osBar.bad i{background:var(--amber)}
.osApp .osBar.mid i{background:var(--muted)}
.osApp .osAppOne{max-width:560px}
.osApp .osAppNote{
  margin-top:14px;font:400 11px var(--osMono);color:var(--faint)}
.osApp .osAppFoot{
  display:flex;align-items:center;padding:11px 18px;border-top:1px solid var(--line);
  font:400 11px var(--osMono);color:var(--faint)}
.osApp .osAppFoot .go{margin-left:auto;color:var(--ink);text-decoration:none}
.osApp .osShots{display:flex;gap:18px;align-items:flex-start;flex-wrap:wrap}
.osApp .osShots figure{margin:0}
.osApp .osShots img{
  max-width:460px;width:100%;border:1px solid var(--line);border-radius:10px;display:block}
.osApp .osShots .mob img{max-width:190px}
.osApp .osShots figcaption{
  margin-top:7px;font:400 10.5px var(--osMono);color:var(--faint)}
@media (max-width:900px){ .osAppCols{grid-template-columns:1fr} }

/* ── THE APP HEADER ────────────────────────────────────────────────────────
   Two rows and one identity block, and it is the SAME shape as a dock row
   because it is the same idea at a different size: the object's picture, the
   object, and one quiet line qualifying it.

   ⛔ THE SUBJECT IS THE BIG LINE, THE APP NAME IS THE SUBLINE. The icon and the
   `lietotne` chip already say which app this is; the app's name is identical on
   every screen it ever draws, so spending the loudest slot on it buys nothing.
   The subject is what changes, what `select` switches, and what the person came
   for. (Owner, 2026-08-25 — and it is what the approved prototype did.)

   ⛔ THE HEADER SITS IN THE SAME COLUMN AS THE BODY. It was full-bleed at 18px
   over a card centred in an 880/1060 column, so its left edge missed the card's
   by fifteen pixels — visible immediately and impossible to unsee.

   ⛔ NO FRESHNESS HERE. An as-of belongs beside the number it qualifies; in the
   chrome it reads as a property of the tool, and one date stands in for a body
   that may hold twenty measurements taken on twenty days. It moved to the card
   footer.  specs/SPEC-APP-STANDARD-2026-08-25.md §3
   ────────────────────────────────────────────────────────────────────────── */
/* ⚡ ONE GUTTER, DECLARED ONCE, AND EVERY EDGE DERIVES FROM IT (owner,
   2026-09-08). Measured in a real signed-in browser at 1600/1100/390 before
   touching anything: the header's text sat 34px LEFT of every word under it at
   every width, and on a phone 37px — because `.rhead` and `.wrap` carried two
   different horizontal paddings that were never reconciled.
       wrap box 1060 → card outer at +34 (the wrap's padding) → card TEXT at +53
       head box 1060 → head TEXT at +19
   The note below this one already said the column is the card's CONTENT edge.
   It was right about the intent and wrong about the arithmetic: it counted the
   card's own inset (1px border + 18px) and not the gutter the card is inset BY.
   ⛔ So no literal survives here. `--app-gutter` is the pane's gutter, and the
      header's inner padding is that gutter PLUS the card's inset — which makes
      the phone case correct for free, where three hand-written numbers had it
      wrong in three different ways. */
/* ⚡ THE GUTTER IS A SHARE OF THE PANE, NOT A CONSTANT (owner, 2026-09-08:
   "seems too much spacing on smaller/mid sized screen, could be taking bigger
   area maybe?"). Measured at six window widths with Mail open: a FLAT 108px of
   gutter (34 + 19 each side) at every width under the 1060 cap, so the
   narrower the window the larger the share it ate — 11% of the pane at 1600,
   16% at 1280, where the card was down to 576px for a letter. A percentage
   resolves against the pane (`.osApp` is the containing block of both `.wrap`
   and `.rhIn`), so the gutter shrinks with the pane and needs no new
   breakpoint: 34px on a 1000px pane, ~24px on a 684px one, never under 16.
   ⛔ The 1060 cap on `.wrap.wide` is NOT the defect — a 1400px line of text
      is unreadable, and "apps always have to be in the center" still holds. */
.osApp{--app-gutter:clamp(16px,3.4%,34px);--app-card-inset:19px}
@media (max-width:640px){ .osApp{--app-gutter:16px} }
.osApp .rhead{
  position:static;padding:18px 0;background:none;backdrop-filter:none;
  border-bottom:1px solid var(--line)}
/* ⛔ ONE LEFT EDGE FOR EVERY PIECE OF TEXT ON THIS SCREEN, AND IT IS 281.
   Measured 2026-08-25 — four different edges, which is the whole of why the
   spacing read as ugly:
       262  back chip, icon          (card's OUTER edge)
       288  the first tab's text     (strip padding 12 + button padding 13)
       281  section heads, row labels, note, footer   (card padding 18)
       320  the subject and the app name
   The card's CONTENT column is the real column, not its border box, so the
   header is inset by the card's own padding: 1px border + 18px = 19.
   ⚡ The icon's left edge is what shares the edge; the two text lines beside it
   are indented by icon+gap, which is what makes them read as ONE block hanging
   off that edge rather than as two more stray alignments. */
.osApp .rhIn{max-width:1060px;width:100%;margin:0 auto;
  padding:0 calc(var(--app-gutter) + var(--app-card-inset))}
.osApp .rhTop{
  display:flex;align-items:center;gap:9px;margin-bottom:14px;font-size:12.5px;color:var(--muted)}
.osApp .rhTop .crumb{
  border:1px solid var(--line);border-radius:999px;padding:4px 12px;background:var(--surf);
  color:var(--muted);cursor:pointer;font-size:12.5px}
.osApp .rhTop .crumb:hover{color:var(--ink);border-color:var(--line2)}
.osApp .rhTop .sep{color:var(--faint)}
/* ⛔ THE "LIETOTNE" BADGE IS GONE, IN EVERY APP (owner, 2026-09-08: "why at all
   tell that its app if I know that I'm in the app?"). He is right: it names the
   category of the thing you are already standing in, on every app, forever.
   ⚡ Hidden here rather than deleted from eleven files in one commit: the markup
      `<span class="kind">` is duplicated across os-mail, os-registry,
      os-cadastre, os-xray, os-vault, os-builder, os-image-studio, os-projects,
      os-brand, os-goals and os-team. os-crypto already ships without it, which
      is the proof that absence is safe, and no gate reads `.kind` — the app
      standard requires `rhead` and `osAppCard`, not this. The dead markup comes
      out in its own mechanical commit, reviewable on its own.
   ⛔ Do not give this slot a new occupant casually. The unbuilt design standard
      (SPEC-APP-STANDARD-2026-08-25 §3) reserves it for controls DECLARED in the
      manifest and rendered by the shell — six kinds, and "a seventh kind is a
      design decision, not a CSS one". */
.osApp .rhTop .kind{display:none}
/* the identity block — icon spans both lines, exactly like a dock row */
.osApp .rhId{display:flex;align-items:center;gap:14px}
.osApp .rhIcon{width:44px;height:44px;display:block;flex:none}
.osApp .rhTx{display:flex;flex-direction:column;gap:3px;min-width:0}
.osApp .rhName{
  font:500 20px/1.2 var(--osDisp);color:var(--ink);letter-spacing:-.01em;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.osApp .rhSub{font-size:12.5px;color:var(--muted)}
/* ⛔ THE PANE HAS A GUTTER. `padding-top:22px` overrode the shorthand and
   silently took the 34px horizontal padding with it, so the card ran edge to
   edge into the rail on one side and the dock on the other — every panel
   touching a wall. A one-property override of a shorthand is how that happens
   without anybody writing "0". */
/* ⛔ AN APP IS A COLUMN, NEVER THE WHOLE WIDTH (owner, 2026-09-02: "apps always
   have to be in the center, not in the full screen or something"). `.wrap` and
   `.wrap.wide` carry a max-width and centre themselves — but ONLY in os.css,
   which the product page never loads, so on the one surface people actually use
   an app's content ran from edge to edge of its column. The same two numbers,
   declared where they are read. */
.osApp .wrap{padding:22px var(--app-gutter) 34px;width:100%;max-width:880px;margin:0 auto}
.osApp .wrap.wide{max-width:1060px}
/* ⚠ At a narrow column the max-width is not what limits it, the padding is —
   and 34px of gutter on a phone leaves a strip. */
/* ⚡ the horizontal half comes from --app-gutter now; only the vertical
   rhythm is a phone decision. */
@media (max-width:640px){ .osApp .wrap{padding:16px var(--app-gutter) 26px} }

/* ══ THE STANDARD PARTS EVERY APP USES ══════════════════════════════════════
   ⛔ AN APP THAT INVENTS ITS OWN BAR DRIFTS FROM THE APP BESIDE IT, and the
   drift is not cosmetic: Passwords grew `.osVaultBar` and Site X-ray grew
   `.xrBar`, so one had a pill input flush against a pill button and the other
   had a squared border touching the field beside it. Two apps in one shell must
   not look like two products. Everything below is the shared vocabulary; an app
   stylesheet is for what is genuinely ITS OWN (a password's mask, a score bar),
   never for the frame around it. */

/* One line of input + one primary action. Search, an address, a query. */
.osApp .osAppBar{display:flex;align-items:center;gap:9px;padding:0 0 14px}
.osApp .osAppBar input{
  flex:1;min-width:0;padding:10px 15px;border:1px solid var(--line);border-radius:999px;
  background:var(--surf);color:var(--ink);font:14px/1.4 var(--body)}
.osApp .osAppBar input::placeholder{color:var(--faint)}
.osApp .osAppBar input:focus{outline:none;border-color:var(--line2);background:var(--surf2)}
.osApp .osAppBar input[disabled]{opacity:.6}
.osApp .osAppBar .go{
  flex:none;padding:9px 17px;border:0;border-radius:999px;
  background:var(--fill);color:var(--onfill);font:500 12.5px var(--body);cursor:pointer}
.osApp .osAppBar .go:hover{filter:brightness(1.08)}
.osApp .osAppBar .go[disabled]{opacity:.42;cursor:default;filter:none}
/* ⚡ THE VARIANT, IN THE STANDARD — not re-invented by the app that needed it.
   Mail puts the shell's tabs and a search field on one line; that is a real
   second shape, so it lives here as a modifier rather than as `.mlBar` in a
   private sheet where the next app cannot find it. */
.osApp .osAppBar.withTabs{flex-wrap:wrap;gap:12px}
.osApp .osAppBar.withTabs .tabs{flex:1 1 auto;min-width:0}
.osApp .osAppBar.withTabs input{flex:0 1 260px;min-width:180px;padding:8px 14px}

/* Nothing here yet — and WHY, which is the half that is usually missing. */
.osApp .osAppEmpty{
  padding:26px 4px;text-align:center;color:var(--muted);font-size:13.5px;line-height:1.6}
.osApp .osAppEmpty b{display:block;color:var(--ink);font:500 14.5px var(--osDisp);margin-bottom:6px}

/* A refusal, in the app's own frame. ⛔ Every app renders a refusal the same
   way, because a person should not have to learn what "broken" looks like twice. */
.osApp .osAppRefuse{
  padding:15px 17px;border:1px solid color-mix(in srgb,var(--rose) 40%,var(--line));
  border-radius:12px;background:color-mix(in srgb,var(--rose) 8%,transparent);
  color:var(--ink);font-size:13.5px;line-height:1.5}
.osApp .osAppRefuse b{
  display:block;font:500 12.5px var(--osMono);color:var(--rose);margin-bottom:5px}

/* A list of things the app holds — past runs, saved entries, results. */
.osApp .osAppList{display:flex;flex-direction:column;gap:5px}
.osApp .osAppList .row{
  display:grid;grid-template-columns:minmax(0,1fr) auto;gap:12px;align-items:center;
  padding:10px 12px 10px 14px;border:1px solid var(--line);border-radius:10px;
  background:transparent;color:var(--ink);width:100%;text-align:left;cursor:pointer;font:inherit}
.osApp .osAppList .row:hover{background:var(--surf);border-color:var(--line2)}
.osApp .osAppList .row .t{display:block;font:500 13.5px/1.35 var(--osDisp);color:var(--ink)}
.osApp .osAppList .row .s{
  display:block;font:400 11.5px/1.45 var(--osMono);color:var(--muted);margin-top:3px}
.osApp .osAppList .row .n{font:500 15px var(--osMono);color:var(--ink)}

/* A section inside an app body. */
.osApp .osAppSec{border-top:1px solid var(--line);padding-top:14px;margin-top:14px}
.osApp .osAppSec:first-child{border-top:0;padding-top:0;margin-top:0}
.osApp .osAppSec>h3{
  margin:0 0 10px;font:400 11px var(--osMono);letter-spacing:.04em;
  text-transform:uppercase;color:var(--faint)}

/* ── THE CONTEXT STRIP under an app header (rail v4 §5.2) ───────────────────
   Which room the app was opened in, and which colleagues are attached to it.
   ⛔ Drawn only when there is something in it — an empty row of chrome under
      every app header is the "default placeholder" the rail spent a release
      removing. ⛔ No presence, ever: there is no such data in this product. */
.osApp .rhCtx{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:12px}
.osApp .rhRoom{
  display:inline-flex;align-items:center;gap:6px;
  border:1px solid var(--line);border-radius:999px;padding:4px 12px;background:var(--surf);
  color:var(--muted);cursor:pointer;font:inherit;font-size:12.5px}
.osApp .rhRoom:hover{color:var(--ink);border-color:var(--line2)}
.osApp .rhWith{
  display:inline-flex;align-items:center;gap:6px;
  border:1px solid var(--line);border-radius:999px;padding:3px 10px 3px 3px;background:var(--surf)}
.osApp .rhWith b{font:500 12.5px var(--osDisp);color:var(--ink)}
/* 26px is above the 24px pictorial floor; below it a character is a smudge. */
.osApp .rhFace{
  width:26px;height:26px;border-radius:9px;display:grid;place-items:center;flex:none;
  background:color-mix(in srgb,var(--violet) 16%,var(--panel));color:var(--ink);
  font:700 10px var(--osMono);letter-spacing:.02em;
  background-size:cover;background-position:50% 12%;background-repeat:no-repeat}
/* ⛔ THE DECLARED CAST — add a role only when /art/os/sp-<role>-64.png exists.
   No <img>, no onerror, so an undrawn role keeps its initials rather than
   rendering a torn page. Kept in step with os-dock.css by test-app-header.mjs. */
.osApp .rhFace[data-art="sp-accountant"],
.osApp .rhFace[data-art="sp-company-analyst"],
.osApp .rhFace[data-art="sp-cto"],
.osApp .rhFace[data-art="sp-financial-advisor"],
.osApp .rhFace[data-art="sp-lawyer"],
.osApp .rhFace[data-art="sp-operations-lead"],
.osApp .rhFace[data-art="sp-sales-lead"]{color:transparent}
.osApp .rhFace[data-art="sp-accountant"]{background-image:url(/art/os/sp-accountant-64.png)}
.osApp .rhFace[data-art="sp-company-analyst"]{background-image:url(/art/os/sp-company-analyst-64.png)}
.osApp .rhFace[data-art="sp-cto"]{background-image:url(/art/os/sp-cto-64.png)}
.osApp .rhFace[data-art="sp-financial-advisor"]{background-image:url(/art/os/sp-financial-advisor-64.png)}
.osApp .rhFace[data-art="sp-lawyer"]{background-image:url(/art/os/sp-lawyer-64.png)}
.osApp .rhFace[data-art="sp-operations-lead"]{background-image:url(/art/os/sp-operations-lead-64.png)}
.osApp .rhFace[data-art="sp-sales-lead"]{background-image:url(/art/os/sp-sales-lead-64.png)}
/* ⛔ The permanent AI disclosure, Art. 50(1) — ink on a violet tint, never
   white on violet (os-specialists.css measured --violet on --panel at 4.2:1). */
.osApp .rhWith .spAI{
  font:700 9px/1 var(--osMono);letter-spacing:.1em;font-style:normal;
  padding:3px 5px;border-radius:999px;
  border:1px solid color-mix(in srgb,var(--violet) 55%,var(--line2));
  background:color-mix(in srgb,var(--violet) 14%,var(--panel));color:var(--ink)}
