/* ============================================
   PetVaxCard — Portal app global styles
   Uses tokens from /css/theme-tokens.css.
   ============================================ */

html, body {
    margin: 0;
    padding: 0;
    min-height: 100vh;
    background: var(--pet-bg-page);
    color: var(--pet-text-primary);
    font-family: var(--pet-font-family);
    font-size: 14px;
}

h1, h2, h3, h4, h5, h6 {
    color: var(--pet-text-primary);
}

a {
    color: var(--pet-text-link);
    text-decoration: none;
}
a:hover {
    color: var(--pet-text-link-hover);
    text-decoration: underline;
}

h1:focus {
    outline: none;
}

.validation-message {
    color: var(--pet-error);
    font-size: 0.85rem;
    margin-top: var(--pet-space-xs);
}

.blazor-error-boundary {
    background: var(--pet-error);
    color: var(--pet-text-on-primary);
    padding: var(--pet-space-md);
    border-radius: var(--pet-radius-md);
}
.blazor-error-boundary::after {
    content: "Ha ocurrido un error.";
}

/* CR-072 — hide the runtime error banner by default on EVERY layout. The
   display:none rule previously lived only in MainLayout.razor.css (scoped), so
   PublicLayout (POR-01 login / POR-00 selector) showed the banner permanently
   on a normal page load. Blazor's runtime sets display:block inline on an
   actual circuit error, which still wins over this global default. */
#blazor-error-ui {
    display: none;
}

/* ============================================
   Authenticated shell (POR-02..POR-14)
   ============================================ */

/* ----------------------------------------------------------------------------
   THEME MIGRATION (2026-05-28) — 3-state sidebar via WIDTH transition only.

   The sidebar is a SIBLING of .portal-main (.pv-main-content). A single custom
   property --sidebar-w is the source of truth: the fixed sidebar reads it as
   its `width`, and the main content reads it as `margin-left`, so the content
   tracks the sidebar exactly. State machine (desktop, ≥1024px):
       expanded   --sidebar-w: 256px
       collapsed  --sidebar-w: 48px   (icon rail — set by .portal-shell--collapsed)
   Below 1024px the sidebar becomes an off-canvas drawer (--sidebar-w: 0 so the
   content is full-width) that slides in over a scrim.

   The collapse is NEVER display:none / visibility:hidden — only width. The
   transition uses the mandated `width var(--duration-normal) var(--curve-easy-ease)`.
---------------------------------------------------------------------------- */
.portal-shell {
    --sidebar-w: 256px;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

/* Collapsed desktop rail — width transition only. */
.portal-shell--collapsed {
    --sidebar-w: 48px;
}

.portal-topbar {
    background: var(--pet-bg-card);
    border-bottom: 1px solid var(--pet-border);
    box-shadow: var(--pet-shadow-sm);
    padding: 0;
    --neutral-fill-layer-rest: var(--pet-bg-card);
}


.portal-topbar-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: var(--pet-space-md) var(--pet-space-xl);
    box-sizing: border-box;
    gap: var(--pet-space-md);
}

.portal-brand {
    display: flex;
    align-items: center;
    gap: var(--pet-space-sm);
    color: var(--pet-primary);
    flex-wrap: wrap;
}

.portal-brand-name {
    color: var(--pet-primary);
}

.portal-brand-icon {
    font-size: 1.4rem;
}

.portal-brand-divider {
    height: 24px;
    margin: 0 var(--pet-space-sm);
}

.portal-tenant-label {
    color: var(--pet-text-secondary);
}

.portal-topbar-actions {
    display: flex;
    align-items: center;
    gap: var(--pet-space-md);
    flex-wrap: wrap;
}

.portal-body {
    flex: 1 1 auto;
    position: relative;
    width: 100%;
}

/* Sidebar — a FIXED sibling of .portal-main. Its width is the --sidebar-w
   source of truth (256px expanded / 48px collapsed), transitioned per the
   mandate. It uses the .pv-sidebar component skin (brand-coloured slab in
   light, neutral surface in dark) supplied by themes/components.css. */
.portal-sidebar {
    position: fixed;
    top: 3.25rem;            /* below the sticky 48px appbar */
    left: 0;
    bottom: 0;
    width: var(--sidebar-w);
    box-sizing: border-box;
    overflow: hidden;        /* hide labels as the rail narrows — NOT display:none */
    z-index: var(--pet-z-sticky);
    transition: width var(--duration-normal) var(--curve-easy-ease);
}

/* FluentNavMenu host fills the rail. Its own inline width:100% resolves to
   "100% of --sidebar-w" because the <nav> wrapper is the sized column. */
.portal-nav-menu {
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
    flex: 1 1 auto;
    overflow-y: auto;
}

/* Main content is the sibling whose margin-left TRACKS the sidebar width, so
   the two stay perfectly adjacent through the width transition. */
.portal-main {
    margin-left: var(--sidebar-w);
    padding: var(--pet-space-xl);
    box-sizing: border-box;
    overflow-x: hidden;
    transition: margin-left var(--duration-normal) var(--curve-easy-ease);
}

/* CR-070 — Fluent's design-token provider injects a hard-coded LIGHT
   --neutral-foreground-rest (#1a1a1a) inline onto some layout containers (e.g.
   .portal-kpi-grid) at runtime regardless of data-theme. FluentLabel renders as
   <p class="fluent-typography" style="color: var(--neutral-foreground-rest)">,
   so on the dark surface the inherited (light) token darkened the text
   (dark-on-dark, AA fail). The component's color is an inline style, which only
   a class rule with !important can beat. Re-assert the body/neutral text colour
   on FluentLabel typography inside the MAIN content (never the sidebar). */
.portal-main .fluent-typography {
    color: var(--color-neutral-fg-1) !important;
}

/* Collapsed rail: keep the nav icons but fade the text labels + group headers
   + plan card. Visibility/opacity on CHILDREN is fine; the sidebar itself only
   ever changes WIDTH. */
.portal-shell--collapsed .portal-nav-group,
.portal-shell--collapsed .portal-plan-card,
.portal-shell--collapsed .portal-nav-menu .fluent-nav-text {
    opacity: 0;
    pointer-events: none;
}

/* FluentNavMenu sits on the brand-teal .pv-sidebar slab (light) / neutral
   surface (dark). Drive its v4 nav-link custom props so labels + icons read as
   the sidebar foreground token and the active/hover states use the brand. */
.portal-sidebar,
.portal-nav-menu {
    --neutral-foreground-rest: var(--shell-sidebar-fg);
    --neutral-foreground-hover: var(--shell-sidebar-active-fg);
    --neutral-foreground-active: var(--shell-sidebar-active-fg);
    --neutral-fill-stealth-hover: color-mix(in srgb, var(--shell-sidebar-fg) 10%, transparent);
    --neutral-fill-stealth-active: color-mix(in srgb, var(--shell-sidebar-fg) 16%, transparent);
    --accent-fill-rest: var(--shell-sidebar-active-bg);
}

.portal-sidebar .fluent-nav-link,
.portal-sidebar a {
    color: var(--shell-sidebar-fg);
}

.portal-sidebar .fluent-nav-link:hover {
    background: color-mix(in srgb, var(--shell-sidebar-fg) 10%, transparent);
    color: var(--shell-sidebar-active-fg);
}

/* Active route — brand-filled pill matching the prototype .nav-item.active.
   CR-071 — force the label + icon to the active foreground (white) so the
   active item never renders with a near-invisible label on the brand pill. */
.portal-sidebar .fluent-nav-link.active {
    background: var(--shell-sidebar-active-bg);
    color: var(--shell-sidebar-active-fg);
}
.portal-sidebar .fluent-nav-link.active,
.portal-sidebar .fluent-nav-link.active .fluent-nav-text,
.portal-sidebar .fluent-nav-link.active svg {
    color: var(--shell-sidebar-active-fg) !important;
    fill: currentColor;
}

/* Sidebar nav group label — matches the prototype "Principal" / "Cuenta". */
.portal-nav-group {
    font-size: var(--font-size-100);
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--shell-sidebar-fg-muted);
    padding: var(--pet-space-md) var(--pet-space-md) var(--pet-space-xs);
    font-weight: 600;
    white-space: nowrap;
}

/* Plan card pinned to the sidebar bottom — matches the prototype panel. */
.portal-plan-card {
    margin: var(--pet-space-sm) var(--pet-space-sm) var(--pet-space-md);
    padding: var(--pet-space-sm) var(--pet-space-md);
    background: color-mix(in srgb, var(--shell-sidebar-fg) 12%, transparent);
    border-radius: var(--pet-radius-md);
    color: var(--shell-sidebar-fg);
    font-size: var(--font-size-200);
    white-space: nowrap;
}

.portal-plan-card-head {
    display: flex;
    align-items: center;
    gap: var(--pet-space-xs);
    font-weight: 600;
    margin-bottom: var(--pet-space-xs);
}

.portal-plan-card-meta {
    color: var(--shell-sidebar-fg-muted);
    margin-bottom: var(--pet-space-sm);
}

.portal-plan-card-bar {
    height: 4px;
    border-radius: 2px;
    background: color-mix(in srgb, var(--shell-sidebar-fg) 18%, transparent);
    overflow: hidden;
}

.portal-plan-card-bar-fill {
    height: 100%;
    border-radius: 2px;
    background: var(--pet-secondary);
}

/* CR-047 / theme-migration — hamburger collapse toggle is ALWAYS available
   (drives the 256⇄48px rail at desktop and the drawer below 1024px). */
.portal-nav-toggle {
    display: inline-flex;
}

/* CR-065 — keep the hamburger tappable while the drawer is open. FluentHeader
   renders <header class="header portal-topbar">; raising only the toggle does
   NOT win over the open z-index:400 fixed drawer in this DOM, so instead the
   whole topbar is lifted above the drawer (element+class specificity beats the
   library `header.header { z-index:10 }` rule), AND the drawer is offset to
   start BELOW the topbar (see the <1024px block) so the lifted topbar never
   covers the drawer's nav items. */
header.header.portal-topbar {
    position: sticky;
    top: 0;
    z-index: calc(var(--pet-z-overlay) + 1);
    /* CR-071 — FluentHeader's library `header.header` rule paints the topbar in
       the Fluent accent (teal), but the prototype PortalTopbar is a WHITE bar
       with dark brand text (prototype/styles.css `.portal-shell .topbar`).
       Element+class specificity beats the library single-class rule, so force
       the prototype's white surface + bottom border here. */
    background: var(--pet-bg-card);
    color: var(--pet-text-primary);
    border-bottom: 1px solid var(--pet-border);
}

/* CR-071 — collapse toggle reads as a discoverable brand icon button on the
   white topbar (was a low-contrast dark glyph when the bar was teal). */
.portal-nav-toggle {
    background: transparent;
    color: var(--pet-primary);
}
.portal-nav-toggle:hover {
    background: color-mix(in srgb, var(--pet-primary) 12%, transparent);
    color: var(--pet-primary);
}
.portal-nav-toggle:focus-visible {
    outline: 2px solid var(--pet-primary);
    outline-offset: 2px;
}

.portal-drawer-backdrop {
    display: none;
}

/* ============================================
   Public shell (POR-01 login, POR-00 selector)
   ============================================ */

.portal-public-shell {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    background: var(--pet-bg-page);
}

.portal-public-header {
    background: var(--pet-bg-card);
    border-bottom: 1px solid var(--pet-border);
    box-shadow: var(--pet-shadow-sm);
    position: sticky;
    top: 0;
    z-index: var(--pet-z-sticky);
    padding: 0;
    --neutral-fill-layer-rest: var(--pet-bg-card);
}

.portal-public-header-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: var(--pet-space-md) var(--pet-space-xl);
    box-sizing: border-box;
    gap: var(--pet-space-md);
}

.portal-public-header-actions {
    display: flex;
    align-items: center;
    gap: var(--pet-space-md);
    flex-wrap: wrap;
}

.portal-brand-subtitle {
    color: var(--pet-text-secondary);
    margin-left: var(--pet-space-sm);
}

.portal-step-indicator {
    color: var(--pet-text-secondary);
}

.portal-public-main {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: var(--pet-space-xl) var(--pet-space-md);
    width: 100%;
    box-sizing: border-box;
}

.portal-public-container {
    width: 100%;
    max-width: 880px;
    display: flex;
    flex-direction: column;
    gap: var(--pet-space-lg);
}

.portal-public-container--narrow {
    max-width: 480px;
}

.portal-public-footer {
    display: flex;
    justify-content: center;
    padding: var(--pet-space-lg) 0;
}

/* ============================================
   Generic page chrome (used in POR-02..POR-04)
   ============================================ */

.portal-page {
    display: flex;
    flex-direction: column;
    gap: var(--pet-space-lg);
    max-width: 1280px;
    margin: 0 auto;
}

.portal-page-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--pet-space-md);
    flex-wrap: wrap;
}

.portal-page-title {
    color: var(--pet-text-primary);
    margin: 0;
}

.portal-card {
    background: var(--pet-bg-card);
    border: 1px solid var(--pet-border);
    border-radius: var(--pet-radius-md);
    box-shadow: var(--pet-shadow-sm);
    padding: var(--pet-space-lg);
    display: flex;
    flex-direction: column;
    gap: var(--pet-space-md);
}

.portal-card--center {
    align-items: center;
    text-align: center;
}

.portal-card-title {
    color: var(--pet-primary-dark);
    margin: 0;
}

.portal-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--pet-space-md);
}

/* ============================================
   Forms (login + POR-04 panel)
   ============================================ */

.portal-form-stack {
    display: flex;
    flex-direction: column;
    gap: var(--pet-space-md);
}

.portal-form-row {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--pet-space-md);
}

.portal-form-field {
    display: flex;
    flex-direction: column;
    gap: var(--pet-space-xs);
}

.portal-form-field fluent-text-field,
.portal-form-field fluent-select,
.portal-form-field fluent-combobox,
.portal-form-field fluent-date-picker,
.portal-form-field fluent-number-field,
.portal-form-field fluent-text-area,
.portal-form-field fluent-search {
    width: 100%;
}

.portal-form-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--pet-space-md);
    margin-top: var(--pet-space-sm);
}

.portal-login-extra {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--pet-space-sm);
    text-align: center;
    margin-top: var(--pet-space-md);
}

/* ============================================
   POR-00 Company selector cards
   ============================================ */

.portal-company-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: var(--pet-space-lg);
}

.portal-company-card {
    --fill-color: var(--pet-bg-card);
    --neutral-fill-card-rest: var(--pet-bg-card);
    --neutral-stroke-card-rest: var(--pet-border);
    border-radius: var(--pet-radius-md);
    box-shadow: var(--pet-shadow-sm);
    transition: box-shadow var(--pet-transition-normal),
                background var(--pet-transition-normal),
                transform var(--pet-transition-normal);
}

.portal-company-card:hover {
    box-shadow: var(--pet-shadow-md);
    --fill-color: var(--pet-bg-card-hover);
    transform: translateY(-2px);
}

.portal-company-card-button {
    width: 100%;
    background: transparent;
    border: none;
    cursor: pointer;
    padding: var(--pet-space-lg);
    display: flex;
    flex-direction: column;
    gap: var(--pet-space-md);
    text-align: left;
    color: inherit;
    font-family: inherit;
    font-size: inherit;
    border-radius: var(--pet-radius-md);
}

.portal-company-card-button:focus-visible {
    outline: none;
    box-shadow: var(--pet-focus-ring);
}

.portal-company-card-button:disabled {
    cursor: progress;
    opacity: 0.7;
}

.portal-company-card-header {
    display: flex;
    align-items: center;
    gap: var(--pet-space-md);
}

.portal-company-card-name {
    color: var(--pet-text-primary);
    margin: 0;
}

.portal-company-card-roles {
    display: flex;
    flex-wrap: wrap;
    gap: var(--pet-space-xs);
}

.portal-role-badge {
    --accent-fill-rest: var(--pet-primary-bg);
    --accent-foreground-rest: var(--pet-primary-dark);
}

.portal-company-card-meta {
    display: flex;
    flex-direction: column;
    gap: var(--pet-space-xs);
    color: var(--pet-text-secondary);
}

.portal-company-card-meta fluent-icon {
    margin-right: var(--pet-space-xs);
    vertical-align: middle;
}

.portal-company-card-progress {
    align-self: flex-end;
}

/* ============================================
   POR-02 Dashboard KPI cards
   ============================================ */

.portal-kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: var(--pet-space-md);
}

.portal-kpi-card {
    --fill-color: var(--pet-bg-card);
    --neutral-fill-card-rest: var(--pet-bg-card);
    --neutral-stroke-card-rest: var(--pet-border);
    border-radius: var(--pet-radius-md);
    box-shadow: var(--pet-shadow-sm);
    padding: var(--pet-space-lg);
    display: flex;
    flex-direction: column;
    gap: var(--pet-space-sm);
    align-items: flex-start;
    transition: box-shadow var(--pet-transition-normal);
}

.portal-kpi-card:hover {
    box-shadow: var(--pet-shadow-md);
}

.portal-kpi-card-icon {
    width: 48px;
    height: 48px;
    border-radius: var(--pet-radius-pill);
    display: flex;
    align-items: center;
    justify-content: center;
}

.portal-kpi-card-icon--primary {
    background: var(--pet-primary-bg);
}

.portal-kpi-card-icon--secondary {
    background: var(--pet-secondary-bg);
}

.portal-kpi-card-icon--success {
    background: var(--pet-success-bg);
}

.portal-kpi-card-icon--dog {
    background: var(--pet-primary-bg);
}

.portal-kpi-value {
    color: var(--pet-text-primary);
    margin: 0;
}

.dashboard-chart-placeholder {
    background: var(--pet-bg-page);
    border: 1px dashed var(--pet-border-strong);
    border-radius: var(--pet-radius-md);
    padding: var(--pet-space-2xl);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--pet-space-sm);
    color: var(--pet-text-secondary);
}

/* ============================================
   POR-03 Pet list
   ============================================ */

.portal-filters-card {
    padding: var(--pet-space-md) var(--pet-space-lg);
}

.portal-filters-row {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr;
    gap: var(--pet-space-md);
    align-items: end;
}

.portal-species-cell {
    display: inline-flex;
    align-items: center;
    gap: var(--pet-space-xs);
    color: var(--species-color, var(--pet-text-primary));
    font-weight: 600;
}

.portal-muted {
    color: var(--pet-text-secondary);
}

.portal-pagination-summary {
    margin-top: var(--pet-space-md);
    text-align: right;
}

.portal-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--pet-space-sm);
    padding: var(--pet-space-2xl);
    color: var(--pet-text-secondary);
    text-align: center;
}

/* ============================================
   POR-04 Person search box
   ============================================ */

.person-search-box {
    display: flex;
    flex-direction: column;
    gap: var(--pet-space-xs);
}

.person-search-box fluent-combobox {
    width: 100%;
}

.person-search-item {
    display: flex;
    flex-direction: column;
}

.person-search-item-name {
    color: var(--pet-text-primary);
    font-weight: 600;
}

.person-search-item-doc {
    color: var(--pet-text-secondary);
    font-size: 0.85rem;
}

.person-search-selected {
    display: flex;
    align-items: center;
    gap: var(--pet-space-xs);
    padding: var(--pet-space-xs) var(--pet-space-sm);
    background: var(--pet-primary-bg);
    color: var(--pet-primary-dark);
    border-radius: var(--pet-radius-sm);
    font-size: 0.9rem;
}

/* ============================================
   POR-07 Wizard (issue carnet)
   ============================================ */

.portal-card--inline {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
}

.por-07-forbidden {
    align-items: center;
    text-align: center;
    padding: var(--pet-space-2xl);
}

.por-07-stepper-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--pet-space-md);
}

.por-07-step {
    display: flex;
    align-items: center;
    gap: var(--pet-space-sm);
    padding: var(--pet-space-sm) var(--pet-space-md);
    border-radius: var(--pet-radius-md);
    border: 1px solid var(--pet-border);
    background: var(--pet-bg-card);
    color: var(--pet-text-secondary);
    font-weight: 500;
}

.por-07-step.is-current {
    background: var(--pet-primary-bg);
    border-color: var(--pet-primary);
    color: var(--pet-primary-dark);
}

.por-07-step.is-done {
    background: var(--pet-success-bg);
    border-color: var(--pet-success-border);
    color: var(--pet-success);
}

.por-07-step-index {
    width: 28px;
    height: 28px;
    border-radius: var(--pet-radius-pill);
    background: var(--pet-bg-page);
    border: 1px solid var(--pet-border-strong);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    flex-shrink: 0;
}

.por-07-step.is-current .por-07-step-index {
    background: var(--pet-primary);
    color: var(--pet-text-on-primary);
    border-color: var(--pet-primary);
}

.por-07-step.is-done .por-07-step-index {
    background: var(--pet-success);
    color: var(--pet-text-on-primary);
    border-color: var(--pet-success);
}

.por-07-step-body {
    min-height: 200px;
}

.por-07-step-title {
    margin: 0 0 var(--pet-space-xs) 0;
    color: var(--pet-primary-dark);
}

.por-07-step-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--pet-space-md);
    flex-wrap: wrap;
}

.por-07-pick-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--pet-space-xs);
}

.por-07-pick-list--cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: var(--pet-space-sm);
}

.por-07-pick-item {
    width: 100%;
    display: flex;
    align-items: center;
    gap: var(--pet-space-sm);
    padding: var(--pet-space-sm) var(--pet-space-md);
    border-radius: var(--pet-radius-md);
    border: 1px solid var(--pet-border);
    background: var(--pet-bg-card);
    color: var(--pet-text-primary);
    cursor: pointer;
    text-align: left;
    font-family: inherit;
    font-size: inherit;
    transition: background var(--pet-transition-fast),
                border-color var(--pet-transition-fast);
}

.por-07-pick-item:hover {
    background: var(--pet-bg-card-hover);
    border-color: var(--pet-primary-light);
}

.por-07-pick-item.is-selected {
    background: var(--pet-primary-bg);
    border-color: var(--pet-primary);
}

.por-07-pick-item:focus-visible {
    outline: none;
    box-shadow: var(--pet-focus-ring);
}

.por-07-pick-item--card {
    padding: var(--pet-space-md);
}

.por-07-pick-title {
    color: var(--pet-text-primary);
    font-weight: 600;
}

.por-07-pick-sub {
    color: var(--pet-text-secondary);
    font-size: 0.85rem;
}

.por-07-selected {
    display: inline-flex;
    align-items: center;
    gap: var(--pet-space-xs);
    background: var(--pet-success-bg);
    color: var(--pet-success);
    padding: var(--pet-space-xs) var(--pet-space-sm);
    border-radius: var(--pet-radius-sm);
    margin-top: var(--pet-space-sm);
}

.por-07-nav {
    /* Inherits .portal-card spacing; just needs row layout. */
}

.por-07d-review-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: var(--pet-space-md);
}

.por-07d-review-block {
    display: flex;
    flex-direction: column;
    gap: var(--pet-space-xs);
    padding: var(--pet-space-sm) var(--pet-space-md);
    background: var(--pet-bg-page);
    border: 1px solid var(--pet-border);
    border-radius: var(--pet-radius-md);
}

/* ============================================
   DLG-12 add vaccine
   ============================================ */

.dlg-12-vaccine-results {
    list-style: none;
    margin: 0;
    padding: 0;
    max-height: 240px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: var(--pet-space-xs);
}

.dlg-12-vaccine-pick {
    width: 100%;
    text-align: left;
    background: var(--pet-bg-card);
    border: 1px solid var(--pet-border);
    border-radius: var(--pet-radius-sm);
    padding: var(--pet-space-sm) var(--pet-space-md);
    cursor: pointer;
    display: flex;
    flex-direction: column;
    gap: var(--pet-space-xs);
    color: var(--pet-text-primary);
    font-family: inherit;
    font-size: inherit;
}

.dlg-12-vaccine-pick:hover {
    background: var(--pet-bg-card-hover);
    border-color: var(--pet-primary-light);
}

.dlg-12-vaccine-pick.is-selected {
    background: var(--pet-primary-bg);
    border-color: var(--pet-primary);
}

.dlg-12-vaccine-pick:focus-visible {
    outline: none;
    box-shadow: var(--pet-focus-ring);
}

.dlg-12-vaccine-name {
    font-weight: 600;
}

.dlg-12-vaccine-coverage {
    color: var(--pet-text-secondary);
    font-size: 0.85rem;
}

.dlg-12-selected {
    display: inline-flex;
    align-items: center;
    gap: var(--pet-space-xs);
    background: var(--pet-success-bg);
    color: var(--pet-success);
    padding: var(--pet-space-xs) var(--pet-space-sm);
    border-radius: var(--pet-radius-sm);
}

/* ============================================
   DLG-03 sign carnet
   ============================================ */

.dlg-03-signing {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--pet-space-md);
    padding: var(--pet-space-xl);
    text-align: center;
}

.dlg-03-summary {
    display: flex;
    flex-direction: column;
    gap: var(--pet-space-md);
}

.dlg-03-meta-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--pet-space-sm);
}

.dlg-03-meta-list li {
    display: flex;
    align-items: center;
    gap: var(--pet-space-sm);
    color: var(--pet-text-primary);
}

.dlg-03-error {
    display: flex;
    align-items: flex-start;
    gap: var(--pet-space-sm);
    background: var(--pet-error-bg);
    color: var(--pet-text-primary);
    border: 1px solid var(--pet-error-border);
    border-radius: var(--pet-radius-md);
    padding: var(--pet-space-md);
}

.dlg-03-error-code {
    font-family: var(--pet-font-mono, monospace);
    font-size: 0.85rem;
    color: var(--pet-text-secondary);
}

/* ============================================
   DLG-02 Revoke carnet dialog (CR-031)
   ============================================ */

.dlg-02-body {
    display: flex;
    flex-direction: column;
    gap: var(--pet-space-sm);
    color: var(--pet-text-primary);
}

.dlg-02-counter {
    font-size: 0.85rem;
    text-align: right;
    color: var(--pet-text-secondary);
}

.dlg-02-error {
    display: flex;
    align-items: flex-start;
    gap: var(--pet-space-sm);
    background: var(--pet-error-bg);
    color: var(--pet-text-primary);
    border: 1px solid var(--pet-error-border);
    border-radius: var(--pet-radius-md);
    padding: var(--pet-space-md);
}

/* ============================================
   POR-08 Carnets list
   ============================================ */

.por-08-status-cell {
    display: inline-flex;
    align-items: center;
    gap: var(--pet-space-xs);
}

.por-08-status-cell--issued {
    color: var(--pet-success);
}

.por-08-status-cell--revoked {
    color: var(--pet-error);
}

.por-08-status-cell--draft {
    color: var(--pet-text-secondary);
}

.por-08-status-cell--superseded {
    color: var(--pet-warning);
}

/* ============================================
   POR-09 Carnet detail
   ============================================ */

/* The whole carnet reads as ONE Fluent 2 card surface. */
.por-09-carnet {
    background: var(--pet-bg-card);
    border: 1px solid var(--pet-border);
    border-radius: var(--pet-radius-md);
    box-shadow: var(--pet-shadow-md);
    padding: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

/* Status header band at the top of the card. */
.por-09-band {
    background: var(--pet-primary-bg);
    border-bottom: 1px solid var(--pet-border);
    padding: var(--pet-space-lg);
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--pet-space-md);
}

.por-09-band-status {
    display: flex;
    flex-direction: column;
    gap: var(--pet-space-xs);
    min-width: 0;
}

.por-09-band-state {
    font-size: 1.05rem;
    font-weight: 700;
}

.por-09-band-token {
    word-break: break-all;
}

.por-09-band-token-value {
    color: var(--pet-text-primary);
    font-family: var(--pet-font-mono, monospace);
    font-weight: 600;
}

.por-09-band-meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--pet-space-lg);
    margin: 0;
}

/* Card body: vaccine region + QR sub-card, 2-col desktop / stacked mobile. */
.por-09-grid {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    gap: var(--pet-space-lg);
    padding: var(--pet-space-lg);
}

@media (max-width: 1024px) {
    .por-09-grid {
        grid-template-columns: 1fr;
    }
}

.por-09-region {
    display: flex;
    flex-direction: column;
    gap: var(--pet-space-md);
    min-width: 0;
}

/* QR sub-card: a nested surface inside the carnet card. */
.por-09-qr-block {
    background: var(--pet-bg-page);
    border: 1px solid var(--pet-border);
    border-radius: var(--pet-radius-md);
    padding: var(--pet-space-md);
    text-align: center;
}

.por-09-signature-status {
    display: inline-flex;
    align-items: center;
    gap: var(--pet-space-xs);
    justify-content: center;
}

.por-09-summary-block {
    display: flex;
    flex-direction: column;
    gap: var(--pet-space-xs);
}

.por-09-summary-label {
    color: var(--pet-text-secondary);
    font-size: 0.85rem;
}

.por-09-summary-value {
    color: var(--pet-text-primary);
    font-weight: 600;
    margin: 0;
}

.por-09-public-url {
    background: var(--pet-bg-page);
    border: 1px solid var(--pet-border);
    border-radius: var(--pet-radius-sm);
    padding: var(--pet-space-xs) var(--pet-space-sm);
    color: var(--pet-text-primary);
    word-break: break-all;
    text-align: left;
    font-family: var(--pet-font-mono, monospace);
    font-size: 0.85rem;
}

.por-09-signature-block {
    background: var(--pet-bg-card);
    border: 1px solid var(--pet-border);
    border-radius: var(--pet-radius-sm);
    padding: var(--pet-space-md);
    text-align: left;
}

.por-09-signature-meta {
    color: var(--pet-text-secondary);
    font-size: 0.85rem;
    word-break: break-all;
}

.por-09-payload-canonical {
    background: var(--pet-bg-page);
    border: 1px solid var(--pet-border);
    border-radius: var(--pet-radius-sm);
    padding: var(--pet-space-sm);
    color: var(--pet-text-primary);
    font-family: var(--pet-font-mono, monospace);
    font-size: 0.8rem;
    max-height: 240px;
    overflow: auto;
    white-space: pre-wrap;
    word-break: break-all;
}

/* ============================================
   QrCodeViewer shared component
   ============================================ */

.qr-viewer {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--pet-space-sm);
    color: var(--pet-text-primary);
}

.qr-viewer-svg {
    width: 192px;
    height: 192px;
    background: var(--pet-bg-card);
    border: 1px solid var(--pet-border);
    border-radius: var(--pet-radius-md);
    padding: var(--pet-space-xs);
    display: flex;
    align-items: center;
    justify-content: center;
}

.qr-viewer-svg svg {
    width: 100%;
    height: 100%;
}

.qr-viewer-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--pet-space-xs);
    padding: var(--pet-space-lg);
    color: var(--pet-text-secondary);
}

.qr-viewer-caption {
    font-family: var(--pet-font-mono, monospace);
    color: var(--pet-text-secondary);
    word-break: break-all;
}

.portal-field-label {
    color: var(--pet-text-secondary);
    font-size: 0.85rem;
}

/* ============================================
   RequireSession placeholder (CR-042)
   ============================================ */

.portal-session-restore {
    display: inline-flex;
    align-items: center;
    gap: var(--pet-space-sm);
    padding: var(--pet-space-sm) var(--pet-space-md);
    margin-bottom: var(--pet-space-md);
    border-radius: var(--pet-radius-md);
    background-color: var(--pet-primary-bg);
    color: var(--pet-text-secondary);
}

/* ============================================
   Responsive
   ============================================ */

/* ----------------------------------------------------------------------------
   CR-047 — Collapsed sidebar is a bounded DRAWER below the tablet boundary.

   docs/ui-spec/Design.md specifies the collapsible sidebar at < 1024px (the
   tablet boundary), NOT 768px. Below this breakpoint the sidebar must NOT
   become a full-width overlay and the body must NOT stack vertically — that
   pushed the nav on top of all content and hid the page (the regression this
   CR fixes). Instead the sidebar becomes a fixed, ~280px-wide drawer that
   slides OVER the main content behind a token-based backdrop, toggled by the
   hamburger in the topbar. The main content keeps its row layout and stays
   fully visible/usable underneath.
---------------------------------------------------------------------------- */
@media (max-width: 1024px) {
    /* Hidden-mobile state: the rail collapses to 0px WIDTH (never display:none)
       so the main content is full-width; margin-left tracks --sidebar-w to 0. */
    .portal-shell,
    .portal-shell--collapsed {
        --sidebar-w: 0px;
    }

    /* Off-canvas drawer: the 0-width rail expands to a bounded drawer that
       slides OVER the content (behind a scrim) only while the open class is
       present. Still a WIDTH change — the rail width goes 0 → drawer width.
       CRITICAL (CR-068): the .pv-sidebar skin adds horizontal padding (4px each
       side) + a 1px right border, which with box-sizing:border-box and width:0
       still rendered a ~9px sliver at the left edge. While CLOSED we zero the
       inline padding + right border and clip overflow so the drawer occupies a
       true 0px (E2E asserts box.x + box.width <= 2). NOT display:none /
       visibility:hidden / translateX — purely a WIDTH collapse to 0. */
    .portal-sidebar {
        width: 0;
        max-width: 80vw;
        padding-left: 0;
        padding-right: 0;
        border-right-width: 0;
        overflow: hidden;
        z-index: var(--pet-z-overlay);
        box-shadow: var(--pet-shadow-lg);
        transition: width var(--duration-normal) var(--curve-easy-ease);
    }

    /* Open state: expand the drawer to its bounded width and reveal the scrim.
       This is the ONLY place the mobile sidebar shows; closing returns it to
       0px (overlay dismissed). Restore the .pv-sidebar skin padding + border so
       the open drawer looks identical to the desktop rail. */
    .portal-body--drawer-open .portal-sidebar {
        width: 280px;
        padding-left: var(--space-xs);
        padding-right: var(--space-xs);
        border-right-width: var(--stroke-thin);
    }

    /* Backdrop scrim — uses the nav surface token so it dims content in BOTH
       themes (light: brand slab, dark: neutral surface). */
    .portal-drawer-backdrop {
        display: block;
        position: fixed;
        inset: 0;
        z-index: calc(var(--pet-z-overlay) - 1);
        background: color-mix(in srgb, var(--pet-bg-nav) 60%, transparent);
        opacity: 0;
        visibility: hidden;
        transition: opacity var(--duration-normal) var(--curve-easy-ease),
                    visibility var(--duration-normal) var(--curve-easy-ease);
    }
    .portal-body--drawer-open .portal-drawer-backdrop {
        opacity: 1;
        visibility: visible;
    }

    /* Below the tablet boundary the labels are always shown inside the open
       drawer (the collapsed-rail fade only applies at desktop). */
    .portal-nav-group,
    .portal-plan-card,
    .portal-nav-menu .fluent-nav-text {
        opacity: 1 !important;
        pointer-events: auto;
    }
}

/* Narrow-mobile content adjustments (single-column forms, stacked topbar,
   tighter padding, vertical wizard). Unrelated to the drawer; unchanged. */
@media (max-width: 768px) {
    .portal-form-row {
        grid-template-columns: 1fr;
    }
    .portal-filters-row {
        grid-template-columns: 1fr;
    }
    .portal-public-header-inner,
    .portal-topbar-inner {
        padding: var(--pet-space-sm) var(--pet-space-md);
        flex-direction: column;
        align-items: flex-start;
    }
    .portal-main {
        padding: var(--pet-space-md);
    }
    .por-07-stepper-list {
        grid-template-columns: 1fr;
    }
}
