/*
 * Presets the height wa-page otherwise only learns after its init
 * ResizeObserver measurement, so sticky-region offsets are correct from
 * the first rendered frame instead of jumping once JS measures the real
 * header. Measured on .app-header as built (brand + locale switcher,
 * single line); update this if the header's content ever grows.
 */
wa-page {
  --header-height: 47px;
  --menu-width: auto;
}

/* Desktop sidebar width for AppNavComponent (Hard rule 5).
   Conditional on a nav actually being slotted, because wa-page keeps its
   desktop navigation region in the grid either way — its empty slot falls
   back to a bare <div>, so a fixed width reserves (and, with the dark
   surface below, paints) an empty column on every page that renders no nav
   at all: signed out, the base-host dashboard and account, the public forms.
   `:has([slot='navigation'])` is the same condition wa-page itself uses to
   decide disable-navigation-toggle.

   The mobile rule stays after this one on purpose: same specificity, so
   source order is what lets it win — there the sidebar becomes the drawer
   and the column must collapse whether or not a nav exists. */
wa-page:has([slot="navigation"]) {
  --menu-width: 16rem;
}

wa-page[view="mobile"] {
  --menu-width: auto;
}

/* Same reason as --header-height above, for AppSubheaderComponent's
   breadcrumb bar: the menu/aside sticky offset is calc(--header-top +
   --subheader-top), so the 0px default parks the sidebar under the bar
   until JS measures it. Scoped with :has() because — unlike the header —
   the bar is conditional (AppSubheaderComponent renders exactly where the
   nav does), and presetting a height for a slot with nothing in it would
   offset the sticky regions of every signed-out and public page by 38px.
   Where :has() is unsupported this falls back to wa-page's own 0px, which
   is the harmless direction.

   38px is 2 * --wa-space-xs + --wa-font-size-s * --wa-line-height-normal,
   which is also what wa-page's ResizeObserver rounds to; app_shell_test.rb
   asserts it against the height the browser actually reports. */
wa-page:has(.app-subheader) {
  --subheader-height: 38px;
}

/* AppNavComponent sidebar: a permanently dark island regardless of the
   page's own light/dark theme — re-point the specific semantic tokens
   app-nav.css consumes (border, quiet text, active-link fill) rather than
   the raw background alone, since those tokens are otherwise still bound
   to the light theme's values inside this part. --wa-color-surface-default
   must be included: wa-page's own stylesheet paints every slotted
   navigation/navigation-header element with `background-color:
   var(--wa-color-surface-default)` (a light-DOM element sitting visually
   on top of this part's own background) — left at its light-theme white,
   it repaints an opaque white box over the slotted <nav>'s full content
   area, hiding this dark background everywhere except inside
   .app-nav-link--active's own (separately painted) pill.

   --wa-color-text-normal matters for the same kind of reason, one layer in:
   the links are `color: inherit`, and inside a collapsible group they inherit
   from wa-details' own shadow DOM, which paints itself
   `color: var(--wa-color-text-normal)`. Left at the light theme's near-black,
   every grouped entry goes invisible on this dark surface while the
   ungrouped ones (inheriting from the part itself) stay white. */
wa-page::part(navigation) {
  background-color: var(--wa-color-neutral-05);
  color: var(--wa-color-neutral-95);

  --wa-color-surface-default: transparent;
  --wa-color-text-normal: var(--wa-color-neutral-95);
  --wa-color-text-quiet: var(--wa-color-neutral-60);
  --wa-color-surface-border: var(--wa-color-neutral-30);
  --wa-color-neutral-fill-quiet: var(--wa-color-neutral-20);
}

/* AppSubheaderComponent's breadcrumb bar: the same permanently dark island
   the sidebar is, so the two navigation surfaces read as one piece of dark
   chrome wrapping the light content area — the bar runs the full width above
   the sidebar, and a light bar between the header and the sidebar would cut
   that in two. Re-points the two text tokens app-subheader.css consumes,
   which is why that file never names a neutral step: it asks for quiet text
   and normal text, and this decides what those mean inside this region.
   --wa-color-surface-default is here for the same reason it is on the
   navigation part above — wa-page paints every slotted region with it, and
   left at the light theme's white it would repaint an opaque white box over
   this background.

   Custom properties reach slotted light-DOM content through the FLAT tree,
   so declaring them on the part does reach .app-subheader and, through it,
   the shadow roots of the wa-breadcrumb-items inside. Measured contrast on
   this surface: quiet 6.2:1, normal 16.7:1, and the untouched
   --wa-color-focus 6.3:1. */
wa-page::part(subheader) {
  background-color: var(--wa-color-neutral-05);
  color: var(--wa-color-neutral-95);

  --wa-color-surface-default: transparent;
  --wa-color-text-normal: var(--wa-color-neutral-95);
  --wa-color-text-quiet: var(--wa-color-neutral-60);
}

/* Sits before <main> inside wa-page's (now unpadded) main region. */
.flash-messages {
  padding-inline: var(--wa-space-l);
}

/* Opacity is a plain host-level compositing property, not shadow-DOM
   styling, so it's safe to set directly on wa-callout. flash_controller.js
   adds data-dismissing once the TTL elapses and removes the element on
   transitionend. */
.flash-messages wa-callout[data-dismissing] {
  transition: opacity var(--wa-transition-slow, 200ms) var(--wa-transition-easing, ease-out);
  opacity: 0;
}
