@charset "UTF-8";
/* ============================================================================
   jpcerpcloud.com — portals.css

   assets/css/site.css is a verbatim copy of the public website's stylesheet,
   so it is never edited here: refreshing the design system is a straight
   file copy. The handful of classes this one page needs and the public site
   does not — a portal address line, a closing note under a grid — live here
   instead, written in the same tokens.
   ========================================================================= */


/* ── Portal address ───────────────────────────────────────────
   The bare host under a card's wording, so a visitor can see where a
   button goes before pressing it. Monospace, because it is an address.
   ─────────────────────────────────────────────────────────── */
.portal-address{
  margin:0;
  font-family:var(--ff-mono);
  font-size:.75rem;
  font-weight:600;
  letter-spacing:.05em;
  color:var(--pa-ink);
  overflow-wrap:anywhere;
}
.band--wine .portal-address,
.band--deep .portal-address{color:var(--pa-inv)}

.portal-address--empty{
  color:var(--text-muted);
  font-weight:400;
  letter-spacing:.03em;
}
.band--wine .portal-address--empty,
.band--deep .portal-address--empty{color:var(--text-inv-muted)}


/* ── Portal cards ─────────────────────────────────────────────
   The public demo-portals page centres its cards because they carry only
   a badge, a name and a button. These carry a description and an address
   as well, so they read left-aligned like the product grid does.
   ─────────────────────────────────────────────────────────── */
.demo-portal-card > .availability-badge--card{align-self:flex-start}
.demo-portal-card > .product-card__name{text-align:left}
.demo-portal-card > .product-card__short{margin-bottom:var(--s-2)}
.demo-portal-card > .portal-address{margin-bottom:var(--s-2)}


/* ── A tag inside a plain card ────────────────────────────────
   .tag is inline-flex; as a direct child of the card's column flex it
   would otherwise stretch the full width.
   ─────────────────────────────────────────────────────────── */
.card > .tag{align-self:flex-start}


/* ── Closing note under a grid ───────────────────────────────── */
.section-note{
  max-width:var(--cw-prose);
  margin:var(--s-8) 0 0;
  color:var(--text-muted);
  font-size:.9375rem;
  line-height:1.6;
}
.band--wine .section-note,
.band--deep .section-note{color:var(--text-inv-muted)}


/* ── Header actions below the nav breakpoint ──────────────────
   site.css means to drop the second header button under 1024px
   (`.header-buy-button{display:none}`), but that rule is declared
   before `.button{display:inline-flex}` and loses to it at equal
   specificity, so both buttons stay and push the menu toggle off the
   right edge on a phone. Restated here, where it wins.
   ─────────────────────────────────────────────────────────── */
@media (max-width:1023px){
  .header-actions .header-buy-button{display:none}
}


/* ── One-column hero ──────────────────────────────────────────
   The public home page pairs its hero copy with a floating dashboard
   mock; this page has none, so the two-column grid, the wide container
   and the full-viewport height all belong to a layout that is no longer
   there. The copy runs as one centred column instead, so the band reads as a deliberate
   welcome panel rather than a two-column layout with its right half missing.
   ─────────────────────────────────────────────────────────── */
.page-portals .hero__grid{grid-template-columns:minmax(0,1fr)}
.page-portals .hero--home{min-height:min(560px,calc(100vh - var(--utility-h) - var(--header-h)));padding-block:clamp(56px,7vw,104px)}
.page-portals .hero--home > .container{max-width:var(--cw-narrow)}
.page-portals .hero__copy{text-align:center}
.page-portals .hero__title{max-width:22ch;margin-inline:auto}
.page-portals .hero__lead{max-width:62ch;margin-inline:auto}
.page-portals .hero__actions{justify-content:center}
.page-portals .hero__proof{justify-content:center}
