/* ======================================================================
   Maritime Passport — Partner Portal SHELL layer (MAR-816).

   The app frame and everything that positions a page rather than
   decorating its contents: the rounded frame, the sidebar and its nav,
   the main column and page header, the org switcher (pill + dropdown),
   and the ≤820px collapse — which since MAR-1816 is a CSS-only nav drawer
   rather than a horizontal scroll strip.

   THE PUBLIC CHROME HAS ALL LEFT. The marketing footer went to
   portal.public-footer.css in MAR-937, when the header grew the corporate
   nav and the two families stopped fitting one sheet under the ceiling;
   the HEADER followed it into portal.public-nav.css in MAR-1815, which took
   6,775 bytes out of a sheet that had 655 left against the ceiling — room
   the sidebar-drawer work needs. portal.public-nav.css carries the
   arithmetic, and states why the RESULTING headroom is deliberately not
   written down anywhere: it is a byte count of this file, so a note
   asserting it invalidates itself.

   That does NOT make this the signed-in portal's sheet alone: `.pp-page`
   below is declared here and used by all five public pages too, including
   the three that render no chrome. The public pages take their wrapper from
   this sheet and their chrome from the two beside it — which is the whole
   reason the offset had to become a modifier rather than move with the nav.

   For two tickets this note said the header could NOT be split, and the
   reason was real rather than caution: its top-offset rule was
   `.pp-page:has(.pp-public-nav)`, naming the page wrapper and the nav in
   one selector, and `.pp-page` is declared just below — a pp-* class may
   live in only one partner stylesheet, so the dupe test failed whichever
   side of a split that rule landed on. MAR-1815 did not work around that
   guard; it removed the entanglement, replacing the selector with the
   `.pp-page--public` modifier, which portal.public-nav.css owns outright
   and the two public pages set for themselves. `.pp-page` below is
   declared here and nowhere else.

   Worth keeping as a lesson: a "this family cannot be split" note is a
   statement about one selector, not about the family.

   Tokens come from portal.css, linked ahead of this file.

   * a NEW primitive family gets its own portal.<family>.css, linked from
     partner/_head.html — it does not grow this file. That is the rule
     MAR-816 exists to establish: portal.css reached 41 KB and 16 screens
     because every ticket appended to the one shared sheet, so unrelated
     partner tickets contended for a single file.
   ====================================================================== */

/* ════ app frame ════ */
.pp-app { border-radius:var(--r-xl); overflow:hidden; background:var(--bg-surface);
          border:1px solid var(--mp-rule); }
.pp-shell { display:grid; grid-template-columns:214px 1fr;
            min-height:calc(100vh - 2*var(--page-pad)); }
/* the shared page wrapper — replaces the per-template inline style (MAR-707) */
.pp-page { padding:var(--page-pad); min-height:100vh; }

/* ── sidebar: white, minimal, warm-ruled, pill-active ── */
.pp-side { background:var(--bg-surface); padding:20px 12px; display:flex; flex-direction:column; gap:3px;
           border-right:1px solid var(--mp-rule); }
/* MAR-720: wordmark on top, "Partner portal" as a subtitle beneath — left-
   aligned with the nav items, no divider (that belonged to the row layout).
   MAR-781: the full lockup at the specimen's 34px — never below the 32px
   brand floor (readme.md), which is what kept the emblem on the old rail. */
.pp-brand { display:flex; flex-direction:column; align-items:flex-start; gap:6px; padding:0 8px 18px; }
.pp-brand__logo { height:34px; width:auto; flex:none; }
.pp-brand__txt { display:block; line-height:1.15; }
.pp-brand__txt b { font-size:14px; font-weight:600; letter-spacing:-.01em; }
.pp-side__grp { padding:14px 10px 4px; font-size:9px; font-weight:700; letter-spacing:.13em;
                text-transform:uppercase; color:var(--ink-3); }
.pp-nav { display:flex; align-items:center; gap:9px; padding:9px 11px; font-size:13.5px;
          color:var(--ink-2); text-decoration:none; border-radius:var(--r-md); }
.pp-nav:hover { background:var(--tint-hover); color:var(--ink); }
.pp-nav--on { background:var(--mp-beige); color:var(--ink); font-weight:600;
              border:1px solid var(--mp-rule); }
.pp-nav__dot { width:5px; height:5px; border-radius:50%; background:var(--mp-bronze); flex:none; opacity:0; }
.pp-nav--on .pp-nav__dot { opacity:1; }

/* ── main ── */
.pp-main { padding:24px 26px 30px; display:flex; flex-direction:column; gap:20px; min-width:0; }
/* MAR-1576 — the page's primary action sits TOP-RIGHT, on the title's row (the
   epic owner's ruling, restated after MAR-1572 shipped the opposite). The row
   is the DEFAULT again, so MAR-1572's `--split` opt-out is DELETED, not
   inverted: a modifier resolving to nothing invites a carrier back.
   ⚠ RESTORING THE PRE-MAR-1572 RULE VERBATIM FIXES NOTHING — the child rule is
   the only thing separating the two, so do not "simplify" it away. Without it
   each slot resolves `flex-basis:auto` to its MAX-CONTENT width; a title whose
   `.pp-sub` exceeds the row on its own therefore breaks the flex line, putting
   the action on line 2 where `space-between` over one item resolves to
   flex-start — i.e. LEFT. `flex-grow` cannot fix that: the basis is still
   max-content, so the line still breaks. `flex-basis:0` makes the slot's
   hypothetical size 0, so its LENGTH can never break the line, and
   `flex-grow:1` grows it into what the action leaves, wrapping text internally.
   `min-width` is the wrap trigger, and it is bounded BOTH ways — a PERCENTAGE
   so overflow is unreachable, never 0 (that keeps the row only by crushing the
   title), and never raised "to give the title room", because a large floor
   breaks the line exactly as max-content did. `flex-wrap:wrap` STAYS: with the
   basis zeroed it can no longer be triggered by the title, so it costs nothing
   at real widths and is the honest fallback at the ones where the row cannot
   hold both slots. `align-items:flex-start` top-aligns, so a two-line title
   keeps its action level with the heading.
   A CHILD SELECTOR in THIS sheet deliberately: it adds no class name and cannot
   define `.pp-top` in a second file (the two test_partner_css_split.py guards).
   EVERY measured figure behind the above — the geometry table, the min-width
   bounds, the overflow numbers and which rule set each was measured against —
   is in test_partner_portal_shell.py::TestTheHeaderActionSitsTopRight, which
   has no byte ceiling; this comment deliberately does not restate them. Note
   `css_flat()` strips spaces, so this rule keys as `.pp-top>:first-child`. */
.pp-top { display:flex; align-items:flex-start; justify-content:space-between; gap:16px; flex-wrap:wrap; }
.pp-top > :first-child { flex-grow:1; flex-basis:0; min-width:40%; }
.pp-h { margin:0; font-size:24px; font-weight:600; letter-spacing:-.022em; }
/* 600, not 700: every Figma 0.1 heading weight is 600 (tokens/typography.css
   --mp-h1..h4-weight). The micro-label 700s elsewhere in this directory are
   correct and stay — Figma ships --mp-microlabel-weight:700. */
.pp-h--lg { font-size:clamp(26px,3.6vw,38px); font-weight:600; letter-spacing:-.03em; line-height:1.08; }
.pp-sub { margin:4px 0 0; font-size:13.5px; color:var(--ink-2); }
.pp-eyebrow { display:inline-block; font-size:10px; font-weight:700; letter-spacing:.14em;
              text-transform:uppercase; color:var(--mp-navy); padding:6px 12px;
              border-radius:var(--r-pill); background:var(--bg-surface);
              border:1px solid var(--mp-card-border); margin-bottom:14px; }
.pp-lede { margin:12px 0 0; font-size:15px; color:var(--ink-2); max-width:52ch; }

.pp-switch { display:inline-flex; align-items:center; gap:9px; padding:7px 13px;
  border-radius:var(--r-pill); background:var(--bg-surface); border:1px solid var(--mp-card-border);
  font-size:13px; cursor:pointer; }
.pp-switch__m { width:18px; height:18px; border-radius:6px; flex:none;
  background:var(--mp-navy); }
.pp-switch__c { color:var(--ink-3); font-size:10px; }

/* ── header switcher menu (MAR-666) — the .pp-switch pill is a button;
      its dropdown reuses the panel material and existing tokens only ── */
.pp-switch { font-family:inherit; color:var(--ink); }
.pp-switch__wrap { position:relative; }
.pp-switch__menu { position:absolute; right:0; top:calc(100% + 8px); min-width:200px; z-index:5;
  display:flex; flex-direction:column; gap:2px; padding:6px;
  border-radius:var(--r-md); background:var(--bg-surface); border:1px solid var(--mp-card-border); }
/* display:flex above would defeat the hidden attribute's UA display:none */
.pp-switch__menu[hidden] { display:none; }
.pp-switch__menu form { margin:0; }
.pp-switch__item { display:block; width:100%; text-align:left; cursor:pointer;
  font-family:inherit; font-size:13px; color:var(--ink-2);
  padding:9px 11px; border:none; background:transparent; border-radius:var(--r-sm); }
.pp-switch__item:hover { background:var(--tint-hover); color:var(--ink); }
.pp-switch__item--on { font-weight:600; color:var(--ink); }
.pp-switch__item:focus-visible { outline:2px solid var(--mp-navy); outline-offset:2px; }

/* the burger and its state exist only below the collapse breakpoint — above
   it the sidebar is a rail with every item and heading visible, so neither
   is in the tab order (MAR-1816) */
.pp-side__toggle { display:none; }
.pp-side__burger { display:none; }

/* ── ≤820px: the sidebar becomes a CSS-only nav drawer (MAR-1816) ──
   It was a horizontal SCROLLER here, with `.pp-side__grp { display:none }`
   removing the group headings — so up to 17 unlabelled icons had to be
   swiped sideways exactly where the room to read them ran out. The headings
   now travel WITH the items: hidden while the drawer is closed, back when it
   is open.

   820, not 700: it is on the portal's declared scale (portal.css header /
   partner_css.BREAKPOINT_SCALE), and at 768px tablet portrait the 214px rail
   leaves ~554px, from which .pp-main's padding takes another ~52 — against
   the 520-700px min-content the data tables need. The rail is actively
   harmful above 700. portal.account.css's ≤820px block moves with this one;
   its own header says why it has to.

   CSS-ONLY because the portal's CSP is nonce-based and ENFORCED; the full
   reason, and why js/responsive-drawer.js cannot serve, is in _sidebar.html
   beside the markup. The pattern is portal.public-nav.css's, COPIED and not
   shared: a pp-* class may live in only one partner sheet, so each owns its
   own toggle.

   IN-FLOW, not an overlay: `.pp-app { overflow:hidden }` is pinned (it clips
   the rounded frame), so an absolutely positioned panel taller than the
   shell is cut off — and an overlay would need body scroll-locking, i.e.
   script. `flex-wrap:wrap` plus `flex-basis:100%` puts the revealed items on
   their own lines, the shell's `auto 1fr` rows absorb the growth, and the
   page scrolls normally. It has to: 17 items at ~38px exceed a 375×667
   viewport.

   No transition and no animation — `display` is not animatable, so the
   disclosure is instantaneous. Note portal.css kills `transition` under
   prefers-reduced-motion and NOT `animation`, so motion added here later
   must use `transition` or reduced-motion goes unhandled. ── */
@media (max-width:820px) {
  /* auto 1fr: the main row absorbs the viewport min-height (MAR-707) —
     without it the stretched shell inflates the nav row too */
  .pp-shell { grid-template-columns:1fr; grid-template-rows:auto 1fr; }
  .pp-side { flex-direction:row; flex-wrap:wrap; align-items:center;
             padding:10px; border-right:none;
             border-bottom:1px solid var(--mp-rule); }
  /* MAR-720: the bar keeps the wordmark — only the subtitle hides.
     `.pp-side__grp` left this rule in MAR-1816; see the reveal below. */
  .pp-brand__txt { display:none; }
  .pp-brand { flex:none; flex-direction:row; align-items:center; padding:0 8px 0 0; }

  /* visually hidden but focusable — display:none would take the only
     control out of the tab order and off the focus ring below */
  .pp-side__toggle { display:block; position:absolute; opacity:0;
                     width:1px; height:1px; margin:0; pointer-events:none; }
  .pp-side__burger { display:inline-flex; align-items:center; justify-content:center;
                     width:44px; height:44px; flex:none;
                     border-radius:var(--r-md); color:var(--ink-2); cursor:pointer; }
  .pp-side__burger:hover { background:var(--tint-hover); color:var(--ink); }
  .pp-side__toggle:focus-visible ~ .pp-side__burger { outline:2px solid var(--mp-navy);
                                                      outline-offset:2px; }

  /* Closed by default — the state on every page load, and the state a
     followed link resets to, since a checkbox does not survive navigation.
     The general sibling combinator reaches every item because the toggle is
     the nav's FIRST child and they are all siblings within it.
     `white-space:nowrap` stays for the truncation case. */
  .pp-nav, .pp-side__grp { display:none; }
  .pp-nav { white-space:nowrap; }
  .pp-side__toggle:checked ~ .pp-nav { display:flex; flex-basis:100%; }
  .pp-side__toggle:checked ~ .pp-side__grp { display:block; flex-basis:100%; }

  /* The account footer is deliberately NOT revealed from here, and it is a
     constraint rather than an omission: `.pp-side__foot` is declared in
     portal.account.css, so a `:checked ~ .pp-side__foot` rule in THIS sheet
     would define that class in two partner sheets — and the mirror in
     account.css would define `.pp-side__toggle` twice. Either fails
     test_no_class_is_defined_in_two_files. So with the drawer open the
     footer wraps below the revealed items, right-aligned by its existing
     `margin-left:auto`; closed, it sits on the bar as before. The only
     duplicate-safe alternative names no other sheet's class:
     `nav:has(:checked) .pp-side__foot { … }`, in portal.account.css. */

  /* MAR-1817: 26 → 14 is +24px of table reading width, and .pp-shell is
     already 1fr here, so .pp-main owns the viewport. Rhythm and
     min-width:0 untouched; portal.data.css carries the measurements. */
  .pp-main { padding:24px 14px 30px; }
}
