/*
 * App feel: two things every page shares, written once, after the looks and the bars.
 *
 *   1. The hand-off from one document to the next. Every navigation here is a full document load; without help a web view shows
 *      a blank frame and the chrome jumps. With cross-document view transitions (Chrome 126, Safari 18.2) the top bar, the phone
 *      bar, the rail and the ground hold still, and only the stage moves: forward slides in from the right over a fade, Back the
 *      reverse, a tab change cross-fades (data-nav on <html>, written by app-feel.js as a page leaves and read by paint-boot.js
 *      before the next one paints). 180 ms; the keyframes animate transform and opacity only. Reduced motion, Motion: Off and
 *      Save-Data turn the whole transition off: the state changes, nothing travels. A browser without the feature loads as before.
 *   2. The page inside the Publika apps (html.pk-app, with pk-app-ios or pk-app-android, set by paint-boot.js before first paint):
 *      no web-isms (the footer's links live under Settings there, no "get the app" nudge), chrome that cannot be selected or
 *      long-pressed while posts, comments and fields still can, no tap flash, no scrollbars, bars that do not bounce, room for the
 *      system's own edges. Nothing here changes the plain web page.
 *
 * The document's own colour is the ground's night (Matinee: its paper) so that no frame is ever white, whatever is still loading.
 */

html { background-color: var(--paint-night, #0b0810); }

/* ---------------------------------------------------------------- 1 the hand-off between documents */
@view-transition { navigation: auto; }

html body.pk-obsidian .pk-ground { view-transition-name: pk-ground; }
html body.pk-obsidian .pk-top { view-transition-name: pk-top; }
html body.pk-obsidian .pk-rail { view-transition-name: pk-rail; }
html body.pk-obsidian .pk-spaces-label { view-transition-name: pk-burger; }
html body.pk-obsidian .pk-mobile-nav { view-transition-name: pk-bar; }
html body.pk-obsidian .pk-stage { view-transition-name: pk-stage; }

/* The persistent chrome and the ground hold still: the new page's own is shown at once, the old one is not drawn (two full
   copies would add up under the default plus-lighter blend). The leftovers of the document (the root) do the same. */
::view-transition-group(root), ::view-transition-group(pk-ground), ::view-transition-group(pk-top), ::view-transition-group(pk-rail),
::view-transition-group(pk-burger), ::view-transition-group(pk-bar) { animation-duration: 0s; }
::view-transition-old(root), ::view-transition-old(pk-ground), ::view-transition-old(pk-top), ::view-transition-old(pk-rail),
::view-transition-old(pk-burger), ::view-transition-old(pk-bar) { display: none; }
::view-transition-new(root), ::view-transition-new(pk-ground), ::view-transition-new(pk-top), ::view-transition-new(pk-rail),
::view-transition-new(pk-burger), ::view-transition-new(pk-bar) { animation: none; mix-blend-mode: normal; }

/* The stage: forward by default. The group itself does not travel (the two pages' stages are different sizes, laid out from the top). */
::view-transition-group(pk-stage) { animation-duration: 0s; }
::view-transition-old(pk-stage) { animation: pk-stage-leave 180ms var(--pk-ease-state, cubic-bezier(.2, 0, 0, 1)) both; mix-blend-mode: normal; }
::view-transition-new(pk-stage) { animation: pk-stage-arrive 180ms var(--pk-ease-state, cubic-bezier(.2, 0, 0, 1)) both; mix-blend-mode: normal; }
html[data-nav="back"]::view-transition-old(pk-stage) { animation-name: pk-stage-leave-back; }
html[data-nav="back"]::view-transition-new(pk-stage) { animation-name: pk-stage-arrive-back; }
html[data-nav="tab"]::view-transition-old(pk-stage) { animation-name: pk-stage-fade-out; }
html[data-nav="tab"]::view-transition-new(pk-stage) { animation-name: pk-stage-fade-in; }

@keyframes pk-stage-leave { to { opacity: 0; transform: translateX(-16px); } }
@keyframes pk-stage-arrive { from { opacity: 0; transform: translateX(24px); } }
@keyframes pk-stage-leave-back { to { opacity: 0; transform: translateX(16px); } }
@keyframes pk-stage-arrive-back { from { opacity: 0; transform: translateX(-24px); } }
@keyframes pk-stage-fade-out { to { opacity: 0; } }
@keyframes pk-stage-fade-in { from { opacity: 0; } }

/* Off: reduced motion (the at-rule itself), Motion: Off and Save-Data (nothing animates, so the swap is immediate). */
@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
}
html[data-motion="off"]::view-transition-old(pk-stage), html[data-motion="off"]::view-transition-new(pk-stage),
html[data-save="1"]::view-transition-old(pk-stage), html[data-save="1"]::view-transition-new(pk-stage) { animation: none; }
html[data-motion="off"]::view-transition-old(pk-stage), html[data-save="1"]::view-transition-old(pk-stage) { display: none; }

/* ---------------------------------------------------------------- 2 inside the apps */
/* Web-isms: the footer's links live under Settings, Account and help; the Android nudge is for a browser. */
html.pk-app body.pk-obsidian :is(.pk-foot, .pk-android-nudge) { display: none; }
/* Without the footer the last post still clears the phone bar and the home indicator. */
@media (max-width: 759px) {
  html.pk-app body.pk-obsidian .pk-frame { padding-bottom: calc(var(--fin-5, 24px) + 72px + var(--pk-inset-bottom, 0px)); }
}

/* Chrome is not text: no selection, no long-press callout, no tap flash. Posts, comments, names and every field keep theirs. */
html.pk-app { -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; }
html.pk-app body.pk-obsidian :is(.pk-top, .pk-rail, .pk-mobile-nav, .pk-spaces-label, .pk-home-top, .pk-dial, .pk-settings-group, .pk-engage, .pk-post-actions, .fs-button, button, summary, label, [role="tab"], [role="tablist"], [role="menu"], [role="menuitem"]) { -webkit-user-select: none; user-select: none; }
html.pk-app body.pk-obsidian :is(input, textarea, select, [contenteditable], [role="textbox"], .pk-post-body, .pk-comment-body, article p, article blockquote, article li, pre, code) { -webkit-user-select: text; user-select: text; -webkit-touch-callout: default; }
/* A tap is a tap: no 300 ms wait for a second one. The viewport meta (paint-boot.js) already forbids pinch zoom in the app. */
html.pk-app body.pk-obsidian { touch-action: manipulation; }
/* A pointer's focus ring is for keyboards; a finger never sees one. */
html.pk-app body.pk-obsidian :is(a, button, summary, [tabindex]):focus:not(:focus-visible) { outline: none; box-shadow: none; }
/* The bars never bounce with the page; a sheet or a panel scrolls inside itself and never hands the pull to the page under it. */
html.pk-app body.pk-obsidian :is(.pk-top, .pk-mobile-nav, .pk-home-top, .pk-rail) { overscroll-behavior: none; }
html.pk-app body.pk-obsidian :is(.pk-notification-panel, .pk-chat-panel, .pk-account nav, [data-server-sheet], dialog, [role="dialog"]) { overscroll-behavior: contain; }
/* No scrollbars inside the app: the system draws its own indicator for the page. */
html.pk-app body.pk-obsidian * { scrollbar-width: none; }
html.pk-app body.pk-obsidian ::-webkit-scrollbar { display: none; width: 0; height: 0; }
/* Room for the system's edges on the sides (the bars and the footer already take the bottom and the top). */
html.pk-app body.pk-obsidian .pk-stage { padding-left: max(0px, env(safe-area-inset-left)); padding-right: max(0px, env(safe-area-inset-right)); }
/* Offline (every page, app or browser): one calm line over the phone bar with Retry, in the pane tint. app-feel.js shows and removes it. */
html body.pk-obsidian .pk-offline {
  position: fixed; left: 50%; bottom: calc(var(--fin-5, 24px) + 66px + env(safe-area-inset-bottom)); z-index: 60;
  display: flex; align-items: center; gap: var(--fin-3, 12px); max-width: min(92vw, 420px);
  padding: var(--fin-2, 8px) var(--fin-2, 8px) var(--fin-2, 8px) var(--fin-4, 16px); border-radius: 999px;
  background: var(--fin-pane, var(--pk-surface, #121315)); color: var(--pk-ink, #fff); box-shadow: 0 12px 34px rgba(0, 0, 0, .35);
  font-size: .9375rem; line-height: 1.3; transform: translateX(-50%);
}
html body.pk-obsidian .pk-offline button { min-height: 44px; padding: 0 var(--fin-4, 16px); border: 0; border-radius: 999px; background: var(--pk-accent, #e2281a); color: #fff; font: inherit; font-weight: 600; }
@media (min-width: 760px) { html body.pk-obsidian .pk-offline { bottom: var(--fin-5, 24px); } }
/* ---------------------------------------------------------------- 3 the drawer's App section (owner, 5 October 2026) */
/* At the foot of the drawer, over the account row, under the same quiet divider: plain 48 px rows in the drawer's own style. Share
   Publika and My QR code are the apps' (pk-app-only); Settings, Sign out and Delete account are for every signed-in member, so account
   deletion is two taps from any page. Delete account is in the normal ink: the confirmation is its own page. The desktop rail has no drawer. */
@media (max-width: 759px) {
  html body.pk-obsidian .pk-rail > .pk-rail-app {
    display: grid; flex: none; margin: auto 0 0; padding: var(--fin-2, 8px) 0 0;
    background: linear-gradient(var(--fin-rule, rgba(255, 255, 255, .08)), var(--fin-rule, rgba(255, 255, 255, .08))) top / 100% 1px no-repeat;
  }
  html body.pk-obsidian .pk-rail > .pk-rail-app ~ .pk-account { margin-top: 0; }
  html body.pk-obsidian .pk-rail-app form { margin: 0; }
  html body.pk-obsidian .pk-rail-app :is(a, button) {
    display: flex; align-items: center; width: 100%; min-height: 48px; margin: 0; padding: 0 var(--fin-4, 16px);
    border: 0; border-radius: 999px; background: transparent; box-shadow: none; color: var(--pk-ink); font: inherit; font-size: 1rem; font-weight: 600; line-height: 1.25; text-align: left; text-decoration: none;
  }
  html body.pk-obsidian .pk-rail-app :is(a, button):focus-visible { background: color-mix(in srgb, var(--pk-ink) 8%, transparent); }
}
@media (min-width: 760px) { html body.pk-obsidian .pk-rail > .pk-rail-app { display: none; } }
html:not(.pk-app) body.pk-obsidian .pk-rail-app .pk-app-only { display: none; }
/* ---------------------------------------------------------------- 4 the edges (native build 6 / code 9, owner 6 October 2026)
   The apps draw the web view edge to edge: under the status bar and the home indicator. On iPhone env(safe-area-inset-*) are the
   real insets (viewport-fit=cover); the Android shell measures its system bars and writes them on <html> as --pk-safe-* (its
   WebView reports a display cutout at most), so one token, --pk-inset-*, is the larger of the two. The painted ground
   (position: fixed, inset: 0) already covers the whole screen, which is the point: no band of another colour above the header
   or under the phone bar in any Look. The header pads by the top inset and --pk-top-height grows with it, so everything that
   sits under the bar (the Stream's tab pane, the panels, the post page's Back row, the drawer's first row) follows; the compact
   bar still lifts by its own 12 px, never by the inset, and the hamburger stays centred on the 60 px of bar below the inset.
   The phone bar, the frame, the toasts, the offline line and the keyboard bars lift by the bottom inset. A browser is untouched. */
html.pk-app {
  --pk-inset-top: max(env(safe-area-inset-top, 0px), var(--pk-safe-top, 0px));
  --pk-inset-bottom: max(env(safe-area-inset-bottom, 0px), var(--pk-safe-bottom, 0px));
  --pk-inset-left: max(env(safe-area-inset-left, 0px), var(--pk-safe-left, 0px));
  --pk-inset-right: max(env(safe-area-inset-right, 0px), var(--pk-safe-right, 0px));
  --pk-top-height: calc(60px + var(--pk-inset-top));
}
html.pk-app body.pk-obsidian .pk-top { padding-top: calc(7px + var(--pk-inset-top)); }
/* The bar's own chrome continues up over the status bar while the bar has lifted (compact) or the page is pulled down. */
html.pk-app body.pk-obsidian .pk-top::before { content: ""; position: absolute; left: 0; right: 0; bottom: 100%; height: 16px; background: inherit; border: 0; -webkit-backdrop-filter: inherit; backdrop-filter: inherit; pointer-events: none; }
html.pk-app body.pk-obsidian .pk-stage { padding-left: var(--pk-inset-left); padding-right: var(--pk-inset-right); }
html.pk-app body.pk-obsidian .pk-offline { bottom: calc(var(--fin-5, 24px) + 66px + var(--pk-inset-bottom)); }
html.pk-app body.pk-obsidian .pk-incoming { top: max(12px, var(--pk-inset-top)); }
html.pk-app .pk-skip:is(:focus, :focus-visible) { top: max(12px, var(--pk-inset-top)); left: max(12px, var(--pk-inset-left)); }
/* Takeovers that own the whole screen pad by the same token (the viewer, the composer, the media editor). */
html.pk-app .pk-viewer-bar { padding-top: max(8px, var(--pk-inset-top)); padding-left: max(12px, var(--pk-inset-left)); padding-right: max(12px, var(--pk-inset-right)); }
html.pk-app :is(.pk-viewer-dots, .pk-viewer-count) { top: calc(max(8px, var(--pk-inset-top)) + 54px); }
html.pk-app .pk-viewer-duration { top: calc(max(8px, var(--pk-inset-top)) + 58px); }
html.pk-app .pk-viewer-slide--text { padding-top: calc(max(8px, var(--pk-inset-top)) + 64px); padding-bottom: max(16px, var(--pk-inset-bottom)); }
html.pk-app .pk-viewer-info { padding-bottom: max(14px, var(--pk-inset-bottom)); }
html.pk-app .pk-viewer-toast { bottom: max(24px, var(--pk-inset-bottom)); }
html.pk-app .pk-viewer-sheet { padding-bottom: max(14px, var(--pk-inset-bottom)); }
html.pk-app .pk-composer-takeover.is-active .pk-composer-heading { padding-top: calc(14px + var(--pk-inset-top)); }
html.pk-app .pk-composer-takeover.is-active .pk-composer-journey-actions { padding-bottom: calc(16px + var(--pk-inset-bottom)); }
html.pk-app .pk-media-editor-head { padding-top: calc(8px + var(--pk-inset-top)); }
html.pk-app .pk-craft-sheet { padding-bottom: max(24px, var(--pk-inset-bottom)); }
@media (max-width: 899px) {
  html.pk-app body.pk-obsidian .pk-mobile-nav { bottom: calc(12px + var(--pk-inset-bottom)); left: max(var(--paint-space-edge, 14px), var(--pk-inset-left)); right: max(var(--paint-space-edge, 14px), var(--pk-inset-right)); }
  html.pk-app body.pk-obsidian .pk-chat-panel { bottom: calc(74px + var(--pk-inset-bottom)); }
  /* Messages is its own screen: its title row and a conversation's header pad by the top inset; the conversation ends above the bar. */
  html.pk-app body.pk-messages-body .pk-message-inbox { padding-top: calc(16px + var(--pk-inset-top)); padding-bottom: calc(100px + var(--pk-inset-bottom)); }
  html.pk-app body.pk-messages-body .pk-message-thread-head { padding-top: calc(10px + var(--pk-inset-top)); }
  html.pk-app body.pk-messages-body .pk-message-layout.has-conversation { height: calc(100dvh - var(--pk-top-height) - 96px - var(--pk-inset-bottom)); }
}
@media (max-width: 759px) {
  html.pk-app body.pk-obsidian { --tb-lift: calc(60px - var(--tb-compact, 48px)); }
  html.pk-app body.pk-obsidian .pk-spaces-label { top: calc(var(--pk-inset-top) + (60px - var(--pk-hit, 44px)) / 2); left: max(6px, var(--pk-inset-left)); }
  html.pk-app body.pk-obsidian .pk-spaces-toggle ~ .pk-rail { padding-top: var(--pk-top-height); padding-bottom: calc(var(--fin-4, 16px) + var(--pk-inset-bottom)); padding-left: max(var(--fin-3, 12px), var(--pk-inset-left)); }
  html.pk-app body.pk-obsidian .pk-search.is-open { padding-top: calc(10px + var(--pk-inset-top)); }
  html.pk-app body.pk-obsidian .pk-search.is-open :is(.pk-ico, .pk-search-ghost) { top: calc(10px + var(--pk-inset-top) + 22px); }
  html.pk-app body.pk-obsidian .pk-search.is-open .pk-search-close { top: calc(10px + var(--pk-inset-top) + 2px); }
  html.pk-app .pk-toast-region .fs-toast { bottom: calc(82px + var(--pk-inset-bottom)); }
  html.pk-app .pk-inline-auth[data-mode="card"] { bottom: calc(76px + var(--pk-inset-bottom)); }
  html.pk-app .pk-composer-takeover.is-active .pk-composer-heading { padding-top: calc(8px + var(--pk-inset-top)); }
  html.pk-app .pk-composer-takeover.is-active .pk-composer-journey-actions { padding-bottom: calc(12px + var(--pk-inset-bottom)); }
  html.pk-app body.pk-obsidian details[data-menu] > [popover]:popover-open { bottom: calc(var(--fin-2, 8px) + var(--pk-inset-bottom)); }
}
@media (max-width: 480px) {
  html.pk-app .pk-dialog { padding-bottom: calc(18px + var(--pk-inset-bottom)); }
  html.pk-app .pk-claim-sheet { padding-bottom: max(20px, var(--pk-inset-bottom)); }
}
/* The soft keyboard (html.pk-kbd, keyboard.js): the bars that drop onto it sit over the inset the shell still reports, if any. */
@media (pointer: coarse) {
  html.pk-app.pk-kbd :is(.pk-pe-bar, .pk-reply-bar) { bottom: calc(8px + var(--pk-inset-bottom)); }
  html.pk-app.pk-kbd .pk-toast-region .fs-toast { bottom: calc(12px + var(--pk-inset-bottom)); }
}
