/* ======================================================================
   Partner Portal — per-screen layer: sign-in (MAR-835, BRIEF screen 1).

   Loaded after the shared layer by partner/_head.html when the page sets
   screen_css = 'sign-in'. See the convention note at the top of portal.css:
   this file owns ONLY what this one screen owns. Everything else — the panel
   material, the page frame, the eyebrow/heading/lede type, the buttons, the
   status notes, the help text — comes from the shared layer, so no shared
   class is named here (a class defined in two partner sheets fails
   test_no_class_is_defined_in_two_files, and cascade order between the files
   would start to matter).

   Material is Maritime Passport Design 0.1 (MAR-777): white, warm hairlines,
   flat. No shadow, no gradient, no backdrop-filter, no dark fill. Colour
   arrives only as var(--token) or color-mix() over one — this file declares
   no :root block, so it carries no colour literal at all.

   Layout is the prototype's (screens/partner-portal.html lines 522-530):
   a two-column panel, copy left and code right, collapsing to one column
   under 760px.
   ====================================================================== */

/* ── the panel's own measure and grid. The panel material and the outer
      frame come from the shared layer; this rule owns the column split and
      the density padding, so the template carries no inline style. ── */
.pp-signin { width:100%; max-width:860px; margin:0 auto;
  padding:var(--pp-card-padding);
  display:grid; grid-template-columns:1fr 1fr; gap:28px; align-items:center; }
@media (max-width:820px) { .pp-signin { grid-template-columns:1fr; } }

/* js/partner/sign_in.js toggles every state, the disclosure and the retry
   through the hidden attribute. The shared status-note and button primitives
   carry display:flex/inline-flex, which silently overrides the UA's
   [hidden] { display:none } — an author rule beats a UA rule whatever the
   specificity. Same guard, same reason, as the pp-switch__menu /
   pp-upload-panel / pp-inv precedents. Without it the panel renders every
   state at once. */
.pp-signin [hidden] { display:none; }

.pp-signin__copy { min-width:0; }

/* The full lockup, never the emblem and never below the 32px brand floor
   (MAR-777/781, docs/design/partner-portal/BRIEF.md § Logo) — the specimen's
   34px, matching the sidebar's treatment of the same asset. */
.pp-signin__logo { display:block; height:34px; width:auto; margin:0 0 20px; }

/* The prototype carries this gap as an inline style (margin-top:20px on the
   actions row); it belongs in the sheet. */
.pp-signin__acts { margin-top:20px; }

/* MAR-1871 — the app-open action is a PHONE affordance, hidden by DEFAULT and
   revealed inside the one media query above. On a wide viewport the QR already
   serves the "the app is on my other device" case, and following this link on
   a desktop just navigates the visitor off the sign-in page to Digidentity's
   own. `display:none` also takes it out of the accessibility tree, so a
   desktop keyboard or screen-reader user is never offered a link that would
   strand them.

   WRITTEN THIS WAY ROUND FOR TWO REASONS, and the first is a repo rule rather
   than a preference. `test_media_query_widths_are_on_the_breakpoint_scale`
   holds every portal width literal to the scale (600, 700, 820, 1024), so the
   obvious complement — `@media (min-width:821px) { display:none }` — is off
   the scale and fails, and its "round UP to the nearest scale value" remedy is
   written for a max-width collapse and would land on 1024 here, showing the
   button on every laptop. Hanging the reveal off the EXISTING max-width rule
   needs no second literal at all. Second, it leaves this screen with exactly
   one viewport rule to reason about, and removes the 820/821 seam entirely:
   at 820px the columns collapse and the action appears, together.

   It composes with the `.pp-signin [hidden]` guard above rather than fighting
   it. An ATTRIBUTE selector counts in the same column as a class, so that
   guard is (0,2,0) — not (0,1,1) — against (0,1,0) for both selectors below,
   and `hidden` wins comfortably. That is what keeps the action invisible on a
   phone whose socket has sent no `app_link|` frame yet.

   Leave these as bare class selectors. `a.pp-signin__applink` would be
   (0,1,1), which still loses to (0,2,0) — so raising them buys nothing, and
   it puts a reader one column-counting slip away from believing the guard can
   be outranked from here. There is no source-order tie to reason about in
   either form. */
.pp-signin__applink { display:none; }
@media (max-width:820px) {
  .pp-signin__applink { display:inline-flex; }
  /* …and the help line takes the whole row. `.pp-acts` is a wrapping flex row
     whose items may SHRINK, so without this the sentence competes with the
     pill for width and the CTA's label wraps to two lines inside a 45px-high
     button. Caught in the render at 390px, not by reading it. Its own class
     because the two elements want different display values — the anchor is a
     `.pp-btn`, the help line a paragraph. */
  .pp-signin__applink-help { display:block; flex-basis:100%; margin:0; }
}

/* ── the route out for someone without the app. A disclosure rather than a
      second panel: it is the minority path, and the BRIEF asks for a route
      out, not a competing call to action. Separated by a hairline, which is
      how Design 0.1 divides anything. ── */
.pp-signin__getapp { margin-top:20px; padding-top:18px;
  border-top:1px solid var(--mp-rule);
  display:flex; flex-direction:column; gap:12px; }
.pp-signin__step { margin:0; font-size:13.5px; color:var(--ink-2); max-width:52ch; }

/* Store links are text pills from the shared button vocabulary, not the
   official badge images: img-src is 'self' data: … (core/middleware.py) and
   the Apple/Google badge CDNs are not on it. They share the row and stack
   cleanly once it runs out. */
.pp-store { display:flex; flex-wrap:wrap; gap:10px; }
.pp-store__link { flex:1 1 auto; }

/* ── the code. The SVG is injected by js/partner/sign_in.js from the
      websocket's `qr_code|<svg>` frame, so the frame reserves its own height:
      without it the panel visibly jumps when the code lands. ── */
.pp-qr { display:flex; flex-direction:column; align-items:center; gap:14px;
  min-width:0; }
/* The reserved box is square and sized for the 176px code plus its 14px
   padding. BOTH minimums are load-bearing: the frame is empty until the
   socket delivers, and with only a min-height it collapsed to a 28px-wide
   vertical sliver that reads as a broken image rather than a code on its
   way. */
.pp-qr__frame { padding:14px; border-radius:var(--r-md);
  background:var(--bg-surface); border:1px solid var(--mp-card-border);
  min-width:204px; min-height:204px; max-width:100%;
  display:grid; place-items:center; }
.pp-qr__frame svg { display:block; width:176px; height:auto; }
/* Dimmed only when the code really is dead — expired or a socket failure.
   Never on `pending`, which arrives milliseconds after connecting and does
   NOT mean "scanned" (see js/partner/sign_in.js). */
.pp-qr__frame--dim { opacity:.28; filter:grayscale(1); }
.pp-qr__cap { font-size:12px; color:var(--ink-3); text-align:center; max-width:24ch; }

/* ── the status region: one panel, one visible state at a time (the
      prototype's four state CARDS are a documentation device, not the
      screen). ── */
.pp-signin__status { display:flex; flex-direction:column; gap:10px; width:100%; }
.pp-signin__state { margin:0; }
p.pp-signin__state { text-align:center; max-width:34ch; margin-inline:auto; }

.pp-signin__retry { align-self:center; }
