/* ══════════════════════════════════════════════════════════════════════════════
   PANEL LAYOUT CONTRACT — core-owned. This file is the ONLY authority on the
   geometry of #panel-content. Nothing else, in core or in any module, may set
   width, max-width, margin or padding on that element.
   ══════════════════════════════════════════════════════════════════════════════

   THE BUG THIS REPLACES.
   #panel-container is `display:flex; flex-direction:column`, so #panel-content
   is a flex ITEM and its width is the CROSS axis. public/styles/health.css used
   to ship a global, unscoped

       @media (min-width:1024px){ #panel-content{ max-width:900px;
                                                  margin:0 auto;
                                                  padding:24px 32px } }

   and health.css is a permanent <link> in index.html, so that rule was live for
   EVERY panel whether or not Health was open. An auto margin on the cross axis
   cancels the default align-items:stretch, which makes a flex item SHRINK-TO-FIT
   its max-content width. Every panel therefore ended up a different arbitrary
   width, driven by whatever its longest text run or widest stray control
   happened to be — measured at a 1440px viewport: memory 449px, jobs 663px,
   integrations 714px, settings 784px, health 800px, and files/logs/notifications
   clamped at the 900px cap. Nine different widths across twelve panels, none of
   them chosen by anybody. The Nextcloud module had already diagnosed this and
   was carrying a private per-module workaround to claw its own box back.

   THE CONTRACT.
   1. #panel-content is a FULL-BLEED, FULL-WIDTH scroll host. It stretches. It
      never centres itself, never caps itself, and therefore never shrink-to-fits.
      It owns exactly two things: scrolling, and the outer gutter.
   2. Width decisions belong to the PANEL, and are expressed by core through the
      `data-layout` attribute that nav.js openPanel() stamps on the host. The cap
      is applied to the host's CHILDREN, where a `margin-inline:auto` is an
      ordinary block centring with no flex pathology attached.
   3. A module panel gets `data-layout="full"` by default: full width, standard
      gutter, no cap. A module never has to fight the host to get its own width.
      A module that wants edge-to-edge bleed opts in by zeroing the padding under
      its own scoped host class (see .nc-host in the Nextcloud module) and that
      is the only host property a module may ever touch.

   BREAKPOINTS. Phone is the unstyled base and is deliberately untouched. The
   tablet tier carries `(min-height:500px)` because the app is NOT
   orientation-locked: every current iPhone turned sideways is 844-932px wide and
   would otherwise take the tablet branch. public/styles.css already treats
   `(max-height:500px) and (orientation:landscape)` as the phone-in-landscape
   case and spends chrome to buy vertical space there, so widening on the same
   screen would fight the app's own behaviour. 500 is that existing threshold,
   reused rather than a second one invented here.

     base            phone, single column, 16px gutter
     >=768  + >=500h tablet
     >=1024          iPad portrait
     >=1440          desktop
     >=1800          ultrawide — caps stop growing, gutter absorbs the rest

   DESIGN CONTRACT. No one-sided or asymmetric coloured accent bars anywhere in
   this file: no border-left/border-top stripe used as emphasis. Framed surfaces
   use a symmetric border on all four sides or a light fill. The only accent
   colour is the brand primary via --md-sys-color-primary. Never green, never teal.
*/

:root {
  /* Outer gutter on the host. */
  --panel-gutter: 16px;

  /* Content caps. `wide` is for data surfaces: lists, tables, dashboards, feeds.
     `measure` is for reading and form surfaces that genuinely should not run to
     a 1560px line length. */
  --panel-max-wide: 1560px;
  --panel-max-measure: 900px;

  /* Shared card-grid minimum. Panels override per surface. */
  --panel-grid-min: 340px;

  /* Master/detail aside width. */
  --panel-aside: 340px;
}

@media (min-width: 768px) and (min-height: 500px) {
  :root { --panel-gutter: 20px; }
}

@media (min-width: 1024px) {
  :root { --panel-gutter: 24px; --panel-aside: 360px; }
}

@media (min-width: 1440px) {
  :root { --panel-gutter: 32px; }
}

/* ── The host box ──────────────────────────────────────────────────────────── */

#panel-content {
  /* Geometry. Explicit width:100% and margin:0 are not redundant belt-and-braces
     noise — they are the defence. If any stylesheet loaded after this one sets an
     auto inline margin on the host, an explicit width leaves no free space for
     that margin to consume, so the item cannot collapse to max-content. */
  width: 100%;
  max-width: none;
  margin: 0;
  align-self: stretch;
  box-sizing: border-box;
  padding: var(--panel-gutter);
  min-width: 0;
}

/* The escape hatch referenced by contract rule 3: a module that wants true
   edge-to-edge bleed zeroes THIS ONE PROPERTY from its own stylesheet, under a
   host class it adds on mount and removes on unmount, e.g.
   `#panel-content.nc-host { padding: 0 }`. It must be scoped to that class,
   because a module stylesheet is injected unscoped and stays in <head> after
   unmount — a bare host selector would restyle every panel opened afterwards for
   the rest of the session, which is exactly the health.css failure above. */

/* The More tab's OTHER host box, the tile launcher shown before a panel is
   opened. It lives here for the same reason #panel-content does: it is host
   chrome, so no panel stylesheet owns it. health.css used to pad this. */
#tools-launcher { padding: var(--panel-gutter); }

/* ── Content width ─────────────────────────────────────────────────────────── */

/* min-width:0 lets a grid/flex child actually shrink instead of being floored at
   its max-content width, which is the other half of the same pathology. */
#panel-content > *,
#hub-view > * { min-width: 0; }

/* `full` is the module default and applies NO cap at all — the host hands the
   whole width over and the module decides what to do with it. This is contract
   rule 3: a module never has to fight the host for its own box.

   Fixed-position overlays that happen to be direct children are exempt from the
   capped modes: a max-width on an inset:0 fixed box would pin it to the left
   edge at cap width instead of covering the viewport. */
#panel-content[data-layout='full'] > *:not(.panel-modal):not([data-panel-bleed]),
#hub-view[data-layout='full'] > *:not(.panel-modal):not([data-panel-bleed]) {
  width: 100%;
}

/* A capped mode reads --panel-max-* off the CHILD, and custom properties
   inherit, so a panel narrows its own measure by declaring the variable on its
   own root — e.g. `.settings-panel { --panel-max-wide: 1240px }`. The panel owns
   its measure, core owns the mechanism. */
#panel-content[data-layout='wide'] > *:not(.panel-modal):not([data-panel-bleed]),
#hub-view[data-layout='wide'] > *:not(.panel-modal):not([data-panel-bleed]) {
  width: 100%;
  max-width: var(--panel-max-wide);
  margin-inline: auto;
}

#panel-content[data-layout='measure'] > *:not(.panel-modal):not([data-panel-bleed]),
#hub-view[data-layout='measure'] > *:not(.panel-modal):not([data-panel-bleed]) {
  width: 100%;
  max-width: var(--panel-max-measure);
  margin-inline: auto;
}

/* ── Shared layout vocabulary ──────────────────────────────────────────────────
   Panels compose these from their own stylesheets rather than each re-deriving a
   grid. Applied to a panel's own element, never to the host. */

/* Card grid. Collapses to one column below the tablet tier by inheritance: the
   auto-fill track floor is a minmax, so a 360px phone yields exactly one column. */
.panel-cardgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--panel-grid-min)), 1fr));
  gap: 12px;
  align-items: start;
}

/* Master/detail split. Single column until there is genuinely room for two. */
.panel-split {
  display: grid;
  gap: 16px;
  align-items: start;
}

@media (min-width: 1024px) {
  .panel-split {
    grid-template-columns: minmax(0, var(--panel-aside)) minmax(0, 1fr);
    gap: 24px;
  }
  .panel-split > .panel-split-aside {
    position: sticky;
    top: 0;
    align-self: start;
  }
}

/* A measured column has to look deliberate rather than stranded, so above the
   tablet tier it becomes a framed surface. Symmetric border on all four sides.
   This is a frame, not an accent bar. */
@media (min-width: 1024px) {
  .panel-framed {
    border: 1px solid var(--border, var(--md-sys-color-outline));
    border-radius: var(--md-sys-shape-corner-lg, 16px);
    background: var(--md-sys-color-surface-container-low, var(--bg-secondary));
    padding: 24px 28px;
  }
}
