/*
 * Mirror Portal Stylesheet — Round 10.57 MIRROR-PORTAL-BRAND-APPLICATION.
 *
 * Productionizes the approved Mirror Atelier OS visual direction
 * (source-of-truth: public/assets/design/mirror-portal-preview.css
 * via the hidden /design/mirror-portal-preview route) onto the
 * existing .portal-* + .metric* class hierarchy already used by
 * all 15 portal Livewire component view templates:
 *   provider:  ProviderDashboardComponent, ProviderBookingsListComponent,
 *              ProviderBookingDetailComponent, ProviderSalonComponent,
 *              ProviderServicesListComponent, ProviderServiceDetailComponent,
 *              ProviderEmployeesListComponent, ProviderGalleryComponent,
 *              ProviderWorkingHoursComponent, ProviderDealsComponent,
 *              ProviderReviewsComponent, ProviderSubscriptionComponent.
 *   account:   AccountProfileComponent, AccountWishlistComponent,
 *              AccountBookingsListComponent, AccountBookingDetailComponent.
 *
 * Loaded by the portal master layouts at:
 *   - resources/views/layouts/portal/master-provider.blade.php
 *   - resources/views/layouts/portal/master-account.blade.php
 *
 * Asset chain (preserved from Round 10.55): Bootstrap base resets +
 * form/button/table/heading defaults → Font Awesome icon font →
 * THIS stylesheet → @livewireStyles last so Livewire's per-component
 * CSS injection wins on conflicts.
 *
 * Round 10.57 supersedes the prior Round 10.56 burgundy with the
 * approved Atelier OS preview pin (deeper, more saturated). The
 * pre-Round-10.56 generic-blue dark-header and accent-blue colors
 * remain forbidden per V4.7-case-3 anti-admin-leak guard preserved
 * in PortalIdentityTest (literal hex values intentionally NOT
 * repeated here so the grep regression test does not false-positive
 * on this docblock).
 */

/* ─────────────────────────────────────────────────────────────
   Mirror Atelier OS palette (Round 10.57 — sourced from
   public/assets/design/mirror-portal-preview.css :root).
   ───────────────────────────────────────────────────────────── */

:root {
    /* Primary brand — now an ALIAS chain into the Mirror token layer.
       Phase 0 / decision D1: the brand colour is the Flutter apps'
       Constants.mainColor #711D43, not a web-side value. This replaces
       the Round 10.57 burgundy chain. Round 10.59 kept "the Mirror
       burgundy as the brand accent"; D1 only settles WHICH burgundy.
       INTENDED VISIBLE DIFF — see gate G3. */
    --portal-brand: var(--mirror-brand);
    --portal-brand-dark: var(--mirror-brand-dark);
    --portal-brand-light: var(--mirror-brand-light);
    --portal-rose: var(--mirror-legacy-brand-rose);   /* identical value — no diff */

    /* Surface chain — feminine atelier neutrals */
    --portal-blush: #f6d9e4;          /* soft pink (table row hover, review tags) */
    --portal-petal: #fff0f5;          /* lightest pink-cream (empty states, table thead) */
    --portal-cream: #fff8f1;          /* warm cream (page body, panel surfaces) */
    --portal-pearl: #fbf4ef;          /* pearl (sidebar surface fallback) */
    --portal-ivory: #fffdf9;          /* lightest ivory (panel inner gradient stop) */
    --portal-champagne: #f8dfb7;      /* gold-cream (top-accent line gradient) */

    /* Operational chain — navy + ink for contrast */
    --portal-navy: #13283f;           /* sidebar gradient base */
    --portal-ink: #241923;            /* primary body text */
    --portal-muted: #776775;          /* secondary muted text */
    --portal-line: #eadde4;           /* hairline borders on cards/panels */

    /* Status surfaces — aliases into the semantic token layer.
       Values are identical to what shipped, so no visual diff here;
       the change is that they now resolve through one definition. */
    --portal-mint: var(--mirror-success-bg);
    --portal-mint-ink: var(--mirror-success-fg);
    --portal-honey: var(--mirror-warning-bg);
    --portal-honey-ink: var(--mirror-warning-fg);
    --portal-sky: var(--mirror-info-bg);
    --portal-gold: #f2c06b;           /* gold accent (sidebar rule, eyebrow) */

    /* Round 10.56 token compatibility — kept for downstream compatibility */
    --portal-accent: #d4a574;         /* legacy gold token (Round 10.56) — kept for compatibility; --portal-gold is the Atelier OS primary */
    --portal-accent-light: #f0dcc8;
    --portal-bg: var(--portal-cream); /* page-bg now resolves to atelier cream */
    --portal-bg-cool: var(--portal-pearl);
    --portal-surface: #ffffff;
    --portal-text: var(--portal-ink);
    --portal-text-body: var(--portal-muted);
    --portal-text-muted: var(--portal-muted);
    --portal-border: var(--portal-line);
    --portal-success-bg: var(--portal-mint);
    --portal-success-fg: var(--portal-mint-ink);
    --portal-success-border: var(--portal-mint-ink);
    /* PHASE 0 CORRECTION (step 0.3) — these previously aliased the
       WARNING honey pair, so the error role could not render red on any
       portal surface. Now bound to the semantic error role. The red is
       not new: it already shipped hard-coded at the cancelled status
       badge below. INTENDED VISIBLE DIFF — see gate G4. */
    --portal-error-bg: var(--mirror-error-bg);
    --portal-error-fg: var(--mirror-error-fg);
    --portal-error-border: var(--mirror-error-fg);

    /* Shadow + radius tokens */
    --shadow-soft: 0 24px 70px rgba(43, 22, 35, .12);
    --shadow-small: 0 10px 24px rgba(43, 22, 35, .08);
    /* Phase 0: aliases into the shared radius scale. Values unchanged
       (8px) so buttons, panels, flashes and tables do not shift. Form
       controls take --mirror-radius-input (12px, the apps' value) via a
       dedicated rule further down. */
    --radius-panel: var(--mirror-radius-panel);
    --radius-soft: var(--mirror-radius-md);
}

/* ─────────────────────────────────────────────────────────────
   Base + reset — page body uses the preview's atelier gradient.
   ───────────────────────────────────────────────────────────── */

html {
    min-width: 320px;
    scroll-behavior: smooth;
}

html, body {
    margin: 0;
    padding: 0;
    color: var(--portal-ink);
    background:
        linear-gradient(135deg, rgba(var(--mirror-brand-rgb), .07), rgba(248, 223, 183, .10) 42%, rgba(255, 248, 241, 0) 72%),
        repeating-linear-gradient(90deg, rgba(var(--mirror-brand-rgb), .030) 0 1px, transparent 1px 42px),
        var(--portal-cream);
    font-family: 'Sora', Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    line-height: 1.55;
    min-height: 100vh;
}

body * { box-sizing: border-box; }

a { color: var(--portal-brand); text-decoration: none; }
a:hover { color: var(--portal-brand-dark); text-decoration: underline; }

h1 {
    font-family: Georgia, "Times New Roman", Marcellus, serif;
    font-size: clamp(28px, 4vw, 42px);
    font-weight: 700;
    line-height: 1.05;
    margin: 0 0 1rem;
    color: var(--portal-ink);
}
h2 {
    font-family: Georgia, "Times New Roman", Marcellus, serif;
    font-size: 1.45rem;
    font-weight: 700;
    margin: 1.5rem 0 0.75rem;
    color: var(--portal-ink);
}
h3 {
    font-family: Georgia, "Times New Roman", Marcellus, serif;
    font-size: 1.15rem;
    font-weight: 700;
    margin: 1.25rem 0 0.5rem;
    color: var(--portal-ink);
}

/* ─────────────────────────────────────────────────────────────
   Top-level header — Atelier OS topbar with burgundy/plum/navy
   gradient + brand-lockup logo + Atelier OS subtitle + gradient
   sign-out button.
   ───────────────────────────────────────────────────────────── */

.portal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 18px;
    padding: 22px 28px;
    background:
        linear-gradient(135deg, rgba(var(--mirror-brand-rgb), .98), rgba(75, 23, 50, .96) 48%, rgba(19, 40, 63, .96)),
        var(--portal-brand);
    color: #fff;
    box-shadow: var(--shadow-soft);
    border-bottom: 1px solid rgba(248, 223, 183, .24);
    position: sticky;
    top: 0;
    z-index: 100;
}

.portal-logo {
    display: grid;
    grid-template-columns: 56px minmax(0, 1fr);
    align-items: center;
    gap: 14px;
    color: #fff;
    text-decoration: none;
    min-height: 64px;
}
.portal-logo:hover { color: var(--portal-champagne); text-decoration: none; }

.portal-logo-img {
    width: 56px;
    height: 56px;
    padding: 7px;
    background: #fff;
    border: 1px solid rgba(248, 223, 183, .70);
    border-radius: var(--radius-soft);
    box-shadow: 0 14px 32px rgba(0, 0, 0, .18), inset 0 0 0 3px rgba(255, 248, 241, .86);
    object-fit: contain;
    display: block;
    /* Round 10.57: brand mark renders as native burgundy logo on white plate (NOT inverted) for the Atelier OS framed-mark look. */
    filter: none;
}

.portal-logo-text {
    display: block;
    font-family: Georgia, "Times New Roman", serif;
    font-size: 22px;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: .2px;
}

/* Round 10.57 Atelier OS subtitle — small all-caps "Atelier OS"
   under the brand text, completing the brand-lockup look. */
.portal-logo-subtitle {
    display: block;
    margin-top: 4px;
    color: rgba(255, 255, 255, .68);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    font-family: 'Sora', Inter, sans-serif;
}

.portal-header-right {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    justify-content: flex-end;
}

.portal-user {
    color: rgba(255, 255, 255, .82);
    font-size: 14px;
    font-weight: 600;
    letter-spacing: .15px;
}

/* Sign out POST form sits inside the portal header right-side. */
.portal-logout-form {
    display: inline-block;
    margin: 0;
}
.portal-logout-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    background: linear-gradient(135deg, var(--portal-brand), var(--portal-rose));
    color: #fff;
    border: 1px solid var(--portal-brand);
    border-radius: var(--radius-soft);
    padding: 0 18px;
    font-weight: 700;
    font-size: 14px;
    letter-spacing: .15px;
    cursor: pointer;
    box-shadow: 0 14px 28px rgba(var(--mirror-brand-rgb), .22);
    transition: transform .12s ease, box-shadow .12s ease;
}
.portal-logout-button:hover {
    transform: translateY(-1px);
    box-shadow: 0 18px 36px rgba(var(--mirror-brand-rgb), .30);
    color: #fff;
}
.portal-logout-button:active { transform: translateY(0); }

/* ─────────────────────────────────────────────────────────────
   Sidebar — Atelier OS navy/plum gradient with gold-tinted
   vertical accent rule + white nav text.
   ───────────────────────────────────────────────────────────── */

.page-body-wrapper {
    display: flex;
    min-height: calc(100vh - 96px);
}

.portal-sidebar {
    flex: 0 0 240px;
    position: relative;
    padding: 28px 16px;
    background:
        linear-gradient(180deg, rgba(19, 40, 63, .98), rgba(75, 23, 50, .96)),
        var(--portal-navy);
    color: #fff;
    border-right: none;
    border-left: none;
    box-shadow: 0 24px 70px rgba(43, 22, 35, .14);
}

/* Gold-tinted vertical accent rule on the inner edge */
.portal-sidebar::after {
    content: "";
    position: absolute;
    top: 22px;
    right: 0;
    bottom: 22px;
    width: 1px;
    background: linear-gradient(180deg, transparent, rgba(248, 223, 183, .76), transparent);
    pointer-events: none;
}
[dir="rtl"] .portal-sidebar::after {
    right: auto;
    left: 0;
}

.portal-sidebar ul {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 6px;
}
.portal-sidebar li { margin: 0; }

.portal-sidebar li a {
    display: block;
    padding: 10px 14px;
    color: rgba(255, 255, 255, .78);
    text-decoration: none;
    font-weight: 600;
    font-size: 14px;
    letter-spacing: .15px;
    border-radius: var(--radius-soft);
    border-left: none;
    border-right: none;
    transition: background .12s ease, color .12s ease;
}
.portal-sidebar li a:hover {
    background: rgba(255, 255, 255, .11);
    color: #fff;
    text-decoration: none;
}
[dir="rtl"] .portal-sidebar li a {
    text-align: right;
}

.page-body {
    flex: 1;
    padding: 32px 36px;
    overflow-x: auto;
}

/* ─────────────────────────────────────────────────────────────
   Dashboard metrics grid (provider) — Atelier OS metric tiles
   with top-accent line + serif numerals.
   ───────────────────────────────────────────────────────────── */

.portal-dashboard h1 { margin-bottom: 0.5rem; }

.dashboard-month {
    color: var(--portal-muted);
    margin: 0 0 1.75rem;
    font-size: 0.9rem;
    letter-spacing: .25px;
    text-transform: uppercase;
    font-weight: 700;
}

.metrics-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 1.25rem;
    margin: 0 0 2rem;
}

.metric {
    position: relative;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .96), rgba(255, 253, 249, .92)),
        rgba(255, 255, 255, .92);
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-panel);
    padding: 22px;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-height: 142px;
    box-shadow: var(--shadow-small);
    transition: box-shadow .15s ease, transform .15s ease;
}
/* Top burgundy→champagne accent line (Atelier OS signature). */
.metric::before {
    content: "";
    display: block;
    width: 42px;
    height: 2px;
    margin-bottom: 14px;
    background: linear-gradient(90deg, var(--portal-brand), var(--portal-champagne));
}
.metric:hover {
    transform: translateY(-1px);
    box-shadow: 0 18px 36px rgba(43, 22, 35, .14);
}
.metric-label {
    color: var(--portal-muted);
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
}
.metric-value {
    color: var(--portal-brand);
    font-family: Georgia, "Times New Roman", serif;
    font-size: 2rem;
    font-weight: 700;
    line-height: 1.05;
}

/* ─────────────────────────────────────────────────────────────
   Generic portal shell + content blocks — Atelier OS surface
   with cream-pearl gradient + hairline border + soft shadow +
   top burgundy→champagne accent line.
   ───────────────────────────────────────────────────────────── */

.portal-shell,
.portal-salon,
.portal-detail,
.portal-summary,
.portal-bookings-list,
.portal-services-list,
.portal-reviews-list,
.portal-service-detail,
.portal-booking-detail,
.portal-active-subscription,
.portal-just-initiated-payment,
.portal-pending-payment {
    position: relative;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .96), rgba(255, 253, 249, .92)),
        rgba(255, 255, 255, .92);
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-panel);
    padding: 28px 30px;
    margin-bottom: 1.5rem;
    box-shadow: var(--shadow-small);
}
.portal-shell::before,
.portal-salon::before,
.portal-bookings-list::before,
.portal-services-list::before,
.portal-reviews-list::before,
.portal-active-subscription::before {
    content: "";
    display: block;
    width: 42px;
    height: 2px;
    margin-bottom: 16px;
    background: linear-gradient(90deg, var(--portal-brand), var(--portal-champagne));
}

/* ─────────────────────────────────────────────────────────────
   Forms (.portal-form, .portal-salon-form, .portal-cancel-form)
   ───────────────────────────────────────────────────────────── */

.portal-form,
.portal-salon-form,
.portal-cancel-form {
    display: flex;
    flex-direction: column;
    gap: 1.1rem;
    max-width: 640px;
}

.portal-field,
.portal-form fieldset,
.portal-salon-form fieldset {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    border: none;
    padding: 0;
    margin: 0;
}

.portal-field label,
.portal-form label,
.portal-salon-form legend,
.portal-cancel-reason-label {
    font-weight: 700;
    color: var(--portal-ink);
    font-size: 13px;
    letter-spacing: .15px;
}

.portal-field input:not([type="checkbox"]):not([type="radio"]),
.portal-field select,
.portal-field textarea,
.portal-salon-form input:not([type="checkbox"]):not([type="radio"]),
.portal-salon-form textarea,
.portal-cancel-reason {
    width: 100%;
    padding: 0.65rem 0.85rem;
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-soft);
    font-size: 14px;
    font-family: inherit;
    color: var(--portal-ink);
    background: #fff;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.portal-field input:not([type="checkbox"]):not([type="radio"]):focus,
.portal-field select:focus,
.portal-field textarea:focus,
.portal-salon-form input:not([type="checkbox"]):not([type="radio"]):focus,
.portal-salon-form textarea:focus,
.portal-cancel-reason:focus {
    outline: none;
    border-color: var(--portal-brand);
    box-shadow: 0 0 0 3px rgba(var(--mirror-brand-rgb), .15);
}

/* PHASE 0 (step 0.3): field validation messages were amber (warning).
   Now the semantic error role. INTENDED VISIBLE DIFF — see gate G4.

   .portal-form-error is used by
   livewire/account/account-booking-detail-component.blade.php and
   livewire/account/account-reviews-component.blade.php but was defined
   in NO stylesheet, so those review errors rendered as unstyled default
   text. Phase 0 finding A5.2 — folded in here rather than left broken. */
.portal-validation-error,
.portal-form-error {
    color: var(--mirror-error-fg);
    font-size: 13px;
    margin-top: 0.15rem;
    font-weight: 600;
}

.portal-existing-file {
    color: var(--portal-muted);
    font-size: 13px;
    margin: 0.25rem 0 0;
    font-style: italic;
}

/* ─────────────────────────────────────────────────────────────
   Buttons — Atelier OS primary uses burgundy→rose gradient with
   shadow lift; danger keeps a tonal red.
   ───────────────────────────────────────────────────────────── */

.portal-button-primary,
.portal-button-danger,
button[type="submit"].portal-button-primary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    padding: 0 22px;
    border-radius: var(--radius-soft);
    font-weight: 700;
    font-size: 14px;
    letter-spacing: .15px;
    cursor: pointer;
    transition: transform .12s ease, box-shadow .12s ease;
    color: #fff;
    border: 1px solid transparent;
}
.portal-button-primary {
    background: linear-gradient(135deg, var(--portal-brand), var(--portal-rose));
    border-color: var(--portal-brand);
    box-shadow: 0 14px 28px rgba(var(--mirror-brand-rgb), .22);
}
.portal-button-primary:hover {
    transform: translateY(-1px);
    box-shadow: 0 18px 36px rgba(var(--mirror-brand-rgb), .28);
}
.portal-button-danger {
    background: #c53030;
    border-color: #c53030;
    box-shadow: 0 14px 28px rgba(197, 48, 48, .20);
}
.portal-button-danger:hover {
    background: #9b2c2c;
    transform: translateY(-1px);
}
.portal-button-primary:active,
.portal-button-danger:active { transform: translateY(0); }

.portal-button-primary[disabled],
.portal-button-primary[aria-disabled="true"] {
    cursor: not-allowed;
    opacity: .72;
    transform: none;
    box-shadow: none;
}

.portal-action-link {
    color: var(--portal-brand);
    font-weight: 700;
    text-decoration: underline;
}
.portal-action-link:hover { color: var(--portal-brand-dark); }

/* ─────────────────────────────────────────────────────────────
   Flash messages — Atelier OS soft mint/honey surfaces.
   ───────────────────────────────────────────────────────────── */

.portal-flash,
.portal-flash-success,
.portal-flash-error {
    padding: 0.95rem 1.15rem;
    border-radius: var(--radius-soft);
    margin-bottom: 1rem;
    font-weight: 600;
    border-left: 4px solid;
}
[dir="rtl"] .portal-flash,
[dir="rtl"] .portal-flash-success,
[dir="rtl"] .portal-flash-error {
    border-left: none;
    border-right: 4px solid;
}
.portal-flash-success {
    background: var(--portal-mint);
    color: var(--portal-mint-ink);
    border-color: var(--portal-mint-ink);
}
/* PHASE 0 (step 0.3): was hard-wired to the honey/warning pair, so
   customers and providers saw errors rendered as warnings. Now uses the
   semantic error role. INTENDED VISIBLE DIFF — see gate G4. */
.portal-flash-error {
    background: var(--portal-error-bg);
    color: var(--portal-error-fg);
    border-color: var(--portal-error-border);
}

/* PHASE 0 (step 0.3): the error rewire exposed a semantic bug — two
   banners carried .portal-flash-error while being informational guidance,
   not errors. Both were marked role="status" (never role="alert"), which
   is the tell. They only looked correct because the error token was
   mis-aliased to the warning pair.

   .portal-flash-notice gives that guidance its own role, so it keeps the
   amber treatment it always had while genuine errors go red. Applied to:
     livewire/provider/provider-salon-component.blade.php  (no-salon notice)
     livewire/provider/partials/publication-status.blade.php (readiness banner)
   Every other .portal-flash-error usage is role="alert" — a real error. */
.portal-flash-notice {
    background: var(--mirror-warning-bg);
    color: var(--mirror-warning-fg);
    border-color: var(--mirror-warning-fg);
}

/* ─────────────────────────────────────────────────────────────
   Tables (.portal-table) — petal <thead> with burgundy uppercase
   labels; row hover uses petal tint.
   ───────────────────────────────────────────────────────────── */

.portal-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    background: #fff;
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-panel);
    overflow: hidden;
    box-shadow: var(--shadow-small);
}
.portal-table th,
.portal-table td {
    padding: 0.85rem 1rem;
    text-align: start;
    border-bottom: 1px solid var(--portal-line);
}
.portal-table thead {
    background: var(--portal-petal);
    color: var(--portal-brand);
    font-size: 12px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .08em;
}
.portal-table thead th { font-weight: 800; }
.portal-table tbody tr:hover { background: var(--portal-petal); }
.portal-table tbody tr:last-child td { border-bottom: none; }

/* ─────────────────────────────────────────────────────────────
   Empty state + pagination — petal-cream + burgundy chips.
   ───────────────────────────────────────────────────────────── */

.portal-empty {
    background: var(--portal-petal);
    color: var(--portal-muted);
    padding: 1.75rem;
    border-radius: var(--radius-panel);
    text-align: center;
    font-style: italic;
    margin: 0;
    border: 1px dashed rgba(var(--mirror-brand-rgb), .18);
}

.portal-pagination { margin-top: 1.25rem; }
.portal-pagination nav { display: flex; gap: 0.5rem; }
.portal-pagination a, .portal-pagination span {
    padding: 0.45rem 0.8rem;
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-soft);
    color: var(--portal-brand);
    text-decoration: none;
    font-weight: 600;
}
.portal-pagination .active span,
.portal-pagination .active a {
    background: var(--portal-brand);
    color: #fff;
    border-color: var(--portal-brand);
}

/* ─────────────────────────────────────────────────────────────
   Gallery + thumbs — Atelier OS gallery cards.
   ───────────────────────────────────────────────────────────── */

.portal-gallery-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 1rem;
    margin-top: 1rem;
}
.portal-gallery-item {
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .96), rgba(255, 253, 249, .92)),
        #fff;
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-panel);
    padding: 0.85rem;
    text-align: center;
    box-shadow: var(--shadow-small);
}
.portal-gallery-thumb,
.portal-thumb {
    max-width: 100%;
    height: auto;
    border-radius: var(--radius-soft);
    display: block;
    margin: 0 auto;
}

/* ─────────────────────────────────────────────────────────────
   Reviews — atelier review cards.
   ───────────────────────────────────────────────────────────── */

.portal-review-card {
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .96), rgba(255, 253, 249, .92)),
        #fff;
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-panel);
    padding: 1.25rem 1.45rem;
    margin-bottom: 1rem;
    box-shadow: var(--shadow-small);
}
.portal-review-response {
    background: var(--portal-petal);
    padding: 0.95rem 1.1rem;
    border-radius: var(--radius-soft);
    margin-top: 0.85rem;
    font-size: 0.95rem;
    color: var(--portal-muted);
    border-left: 3px solid var(--portal-rose);
    font-style: italic;
}
[dir="rtl"] .portal-review-response {
    border-left: none;
    border-right: 3px solid var(--portal-rose);
}

/* ─────────────────────────────────────────────────────────────
   Responsive — Atelier OS-aligned breakpoints (1100px sidebar
   collapse + 760px tighter mobile).
   ───────────────────────────────────────────────────────────── */

@media (max-width: 1100px) {
    .page-body-wrapper { flex-direction: column; }
    .portal-sidebar {
        flex: 0 0 auto;
        width: 100%;
        padding: 18px;
    }
    .portal-sidebar::after { display: none; }
    .portal-sidebar ul {
        grid-auto-flow: column;
        grid-auto-columns: minmax(120px, 1fr);
        overflow-x: auto;
    }
    .page-body { padding: 24px; }
    .metrics-grid { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }
}

@media (max-width: 760px) {
    .portal-header {
        flex-direction: column;
        align-items: stretch;
        padding: 18px 20px;
        gap: 14px;
    }
    .portal-logo { min-height: 56px; grid-template-columns: 48px minmax(0, 1fr); }
    .portal-logo-img { width: 48px; height: 48px; padding: 6px; }
    .portal-header-right { justify-content: flex-end; }
    .portal-logout-button { flex: 1; min-height: 48px; }
    .page-body { padding: 18px; }
    .metrics-grid { grid-template-columns: 1fr 1fr; gap: 0.85rem; }
    .portal-shell,
    .portal-salon,
    .portal-detail,
    .portal-summary,
    .portal-bookings-list,
    .portal-services-list,
    .portal-reviews-list,
    .portal-service-detail,
    .portal-booking-detail,
    .portal-active-subscription,
    .portal-just-initiated-payment,
    .portal-pending-payment { padding: 20px; }
    .portal-sidebar ul {
        grid-auto-flow: row;
        grid-template-columns: 1fr 1fr;
    }
}

/* ─────────────────────────────────────────────────────────────
   Round 10.58 Item 2 — Provider Dashboard professionalization
   (CareBot panel + dashboard controls + booking pulse + upcoming
   bookings preview).
   ───────────────────────────────────────────────────────────── */

.portal-eyebrow {
    margin: 0 0 6px;
    color: var(--portal-brand);
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .12em;
    text-transform: uppercase;
}

.portal-dashboard-header {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 1.75rem;
}

.portal-dashboard-controls {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .96), rgba(255, 253, 249, .92)),
        rgba(255, 255, 255, .92);
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-soft);
    box-shadow: var(--shadow-small);
}

.portal-dashboard-controls label {
    color: var(--portal-muted);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
}

.portal-dashboard-controls select {
    padding: 8px 10px;
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-soft);
    color: var(--portal-ink);
    background: #fff;
    font-size: 14px;
    font-weight: 600;
    min-height: 38px;
}
.portal-dashboard-controls select:focus {
    outline: none;
    border-color: var(--portal-brand);
    box-shadow: 0 0 0 3px rgba(var(--mirror-brand-rgb), .15);
}

/* CareBot insight panel — atelier surface with burgundy/champagne signature. */
.portal-carebot-panel {
    position: relative;
    margin-bottom: 1.75rem;
    padding: 24px 26px;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .96), rgba(255, 240, 245, .82)),
        rgba(255, 255, 255, .92);
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-panel);
    box-shadow: var(--shadow-small);
}
.portal-carebot-panel::before {
    content: "";
    display: block;
    width: 42px;
    height: 2px;
    margin-bottom: 14px;
    background: linear-gradient(90deg, var(--portal-brand), var(--portal-champagne));
}

.portal-carebot-header {
    display: grid;
    grid-template-columns: 56px minmax(0, 1fr);
    align-items: center;
    gap: 14px;
    margin-bottom: 14px;
}

.portal-carebot-glyph {
    display: grid;
    place-items: center;
    width: 56px;
    height: 56px;
    background: linear-gradient(135deg, var(--portal-brand), var(--portal-rose));
    color: #fff;
    border-radius: var(--radius-soft);
    font-size: 24px;
    font-weight: 800;
    box-shadow: 0 14px 28px rgba(var(--mirror-brand-rgb), .22);
}

.portal-carebot-panel h2 {
    margin: 0;
    font-family: Georgia, "Times New Roman", serif;
    font-size: 22px;
    font-weight: 700;
    color: var(--portal-ink);
}

.portal-carebot-insights {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 10px;
}
.portal-carebot-insights li {
    padding: 12px 14px;
    background: var(--portal-petal);
    border: 1px solid var(--portal-line);
    border-left: 3px solid var(--portal-rose);
    border-radius: var(--radius-soft);
    color: var(--portal-ink);
    font-size: 14px;
    line-height: 1.55;
}
[dir="rtl"] .portal-carebot-insights li {
    border-left: 1px solid var(--portal-line);
    border-right: 3px solid var(--portal-rose);
}

/* Booking pulse — 3-segment CSS flex bar. */
.portal-booking-pulse-section {
    margin-bottom: 1.75rem;
}
.portal-booking-pulse-section header {
    margin-bottom: 12px;
}
.portal-booking-pulse-section h3 {
    margin: 0 0 4px;
    font-family: Georgia, "Times New Roman", serif;
}
.portal-booking-pulse-section header p {
    margin: 0;
    color: var(--portal-muted);
    font-size: 13px;
}

.portal-booking-pulse {
    display: flex;
    width: 100%;
    min-height: 78px;
    gap: 4px;
    border-radius: var(--radius-panel);
    overflow: hidden;
    box-shadow: var(--shadow-small);
}
.portal-pulse-segment {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
    padding: 14px 18px;
    color: var(--portal-ink);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    min-width: 0;
    overflow: hidden;
}
.portal-pulse-segment strong {
    font-family: Georgia, "Times New Roman", serif;
    font-size: 22px;
    font-weight: 700;
    letter-spacing: 0;
    text-transform: none;
    color: var(--portal-ink);
}
.portal-pulse-segment small {
    color: var(--portal-muted);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .08em;
}
.portal-pulse-segment--completed { background: var(--portal-mint); }
.portal-pulse-segment--confirmed { background: var(--portal-sky); }
.portal-pulse-segment--cancelled { background: var(--portal-blush); }

/* Status badges (used by dashboard upcoming + bookings list). */
.portal-status-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 26px;
    padding: 0 10px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
    background: var(--portal-petal);
    color: var(--portal-brand);
    border: 1px solid var(--portal-line);
}
.portal-status-badge--pending { background: var(--portal-honey); color: var(--portal-honey-ink); border-color: rgba(155, 105, 24, .2); }
.portal-status-badge--confirmed { background: var(--portal-sky); color: #1f4a6b; border-color: rgba(31, 74, 107, .2); }
.portal-status-badge--completed { background: var(--portal-mint); color: var(--portal-mint-ink); border-color: rgba(31, 116, 80, .25); }
/* PHASE 0 (finding A5.3): the cancelled/user_cancel/provider_cancel rule
   that stood here was DEAD CODE — it was shadowed later in this same file
   by the hard-coded red rule, which is what actually rendered. Removed so
   the cancelled badge has exactly one definition. No visual diff. */
.portal-status-badge--no_show { background: var(--portal-line); color: var(--portal-muted); border-color: var(--portal-line); }

/* Upcoming bookings preview list. */
.portal-upcoming-bookings header {
    margin-bottom: 12px;
}
.portal-upcoming-bookings h3 {
    margin: 0 0 4px;
    font-family: Georgia, "Times New Roman", serif;
}
.portal-upcoming-bookings header p {
    margin: 0;
    color: var(--portal-muted);
    font-size: 13px;
}
.portal-upcoming-bookings-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 10px;
}
.portal-upcoming-booking-item {
    display: grid;
    grid-template-columns: 120px minmax(0, 1fr) auto;
    align-items: center;
    gap: 14px;
    padding: 14px 18px;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .96), rgba(255, 253, 249, .92)),
        rgba(255, 255, 255, .92);
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-soft);
    box-shadow: var(--shadow-small);
}
.portal-upcoming-booking-when strong,
.portal-upcoming-booking-who strong {
    display: block;
    color: var(--portal-ink);
    font-weight: 700;
}
.portal-upcoming-booking-when small {
    display: block;
    color: var(--portal-muted);
    font-size: 12px;
}

/* ─────────────────────────────────────────────────────────────
   Round 10.58 Item 3 — Provider Bookings professionalization
   (toolbar with search + status filter chips + month filter +
   status badges + mobile card fallback).
   ───────────────────────────────────────────────────────────── */

.portal-bookings-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
    margin-bottom: 16px;
    padding: 14px 16px;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .96), rgba(255, 253, 249, .92)),
        rgba(255, 255, 255, .92);
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-soft);
    box-shadow: var(--shadow-small);
}
.portal-bookings-toolbar input[type="search"],
.portal-bookings-toolbar input[type="text"] {
    flex: 1 1 220px;
    min-height: 40px;
    padding: 8px 12px;
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-soft);
    color: var(--portal-ink);
    background: #fff;
    font-size: 14px;
}
.portal-bookings-toolbar input:focus {
    outline: none;
    border-color: var(--portal-brand);
    box-shadow: 0 0 0 3px rgba(var(--mirror-brand-rgb), .15);
}
.portal-bookings-toolbar select {
    min-height: 40px;
    padding: 8px 10px;
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-soft);
    color: var(--portal-ink);
    background: #fff;
    font-size: 14px;
    font-weight: 600;
}
/* PHASE 3 STEP K (G18) — .portal-bookings-status-chips / .portal-bookings-status-chip
   RETIRED. Step I replaced the provider bookings chip row with the app's tab bar
   (bookings_screen.dart:11-12), leaving these rules with ZERO consumers repo-wide.
   They were declared TWICE at equal specificity — here and again in the Round 10.59
   admin skin — the same shape as the .portal-gallery-thumb trap that shipped a live
   regression for two steps. BOTH declaration sites were removed in ONE edit, per
   Step I acceptance condition 13 and owner ruling K-OD-6; deleting only the later
   block would have silently resurrected this one.
   ⚠️ The ranges carried in the record (:1133-1155 and :2293-2310) were TRUNCATED at
   each block's final selector line; the true blocks were :1133-1160 and :2293-2314. */

.portal-bookings-table-wrapper {
    overflow-x: auto;
}
.portal-booking-row-cards {
    display: none;
}
.portal-booking-row-card {
    padding: 14px 16px;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .96), rgba(255, 253, 249, .92)),
        rgba(255, 255, 255, .92);
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-soft);
    box-shadow: var(--shadow-small);
    margin-bottom: 10px;
}
.portal-booking-row-card-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    margin-bottom: 8px;
}
.portal-booking-row-card-meta {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 4px 12px;
    margin-bottom: 10px;
    color: var(--portal-muted);
    font-size: 13px;
}
.portal-booking-row-card-meta strong {
    color: var(--portal-ink);
    font-weight: 700;
}

@media (max-width: 760px) {
    .portal-bookings-table-wrapper { display: none; }
    .portal-booking-row-cards { display: grid; }
}

/* ─────────────────────────────────────────────────────────────
   Round 10.58 Item 4 — Provider Subscription redesign
   (explanation panel + plan cards + state-aware CTAs +
   calmer professional palette).
   ───────────────────────────────────────────────────────────── */

.portal-subscription-explanation {
    margin-bottom: 1.75rem;
    padding: 24px 26px;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .96), rgba(255, 248, 241, .92)),
        rgba(255, 255, 255, .92);
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-panel);
    box-shadow: var(--shadow-small);
}
.portal-subscription-explanation::before {
    content: "";
    display: block;
    width: 42px;
    height: 2px;
    margin-bottom: 14px;
    background: linear-gradient(90deg, var(--portal-brand), var(--portal-champagne));
}
.portal-subscription-explanation h2 {
    margin: 0 0 12px;
    font-family: Georgia, "Times New Roman", serif;
    color: var(--portal-ink);
}
.portal-subscription-explanation-points {
    margin: 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 8px;
    color: var(--portal-ink);
    font-size: 14px;
    line-height: 1.55;
}
.portal-subscription-explanation-points li {
    padding-left: 22px;
    position: relative;
}
.portal-subscription-explanation-points li::before {
    content: "✦";
    position: absolute;
    left: 0;
    color: var(--portal-brand);
    font-weight: 700;
}
[dir="rtl"] .portal-subscription-explanation-points li {
    padding-left: 0;
    padding-right: 22px;
}
[dir="rtl"] .portal-subscription-explanation-points li::before {
    left: auto;
    right: 0;
}

.portal-plan-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 16px;
    margin-top: 16px;
}

.portal-plan-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 22px;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .96), rgba(255, 253, 249, .92)),
        rgba(255, 255, 255, .92);
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-panel);
    box-shadow: var(--shadow-small);
    transition: transform .12s ease, box-shadow .12s ease;
}
.portal-plan-card::before {
    content: "";
    display: block;
    width: 42px;
    height: 2px;
    margin-bottom: 8px;
    background: linear-gradient(90deg, var(--portal-brand), var(--portal-champagne));
}
.portal-plan-card:hover {
    transform: translateY(-1px);
    box-shadow: 0 18px 36px rgba(43, 22, 35, .14);
}
.portal-plan-card.--current {
    border-color: var(--portal-mint-ink);
    background:
        linear-gradient(180deg, rgba(223, 244, 232, .8), rgba(255, 255, 255, .92)),
        rgba(255, 255, 255, .92);
}
.portal-plan-card.--pending {
    border-color: rgba(31, 74, 107, .35);
    background:
        linear-gradient(180deg, rgba(226, 240, 247, .82), rgba(255, 255, 255, .92)),
        rgba(255, 255, 255, .92);
}
.portal-plan-card.--disabled {
    opacity: .55;
    pointer-events: none;
}

.portal-plan-card-badge {
    position: absolute;
    top: 14px;
    right: 14px;
    display: inline-flex;
    align-items: center;
    min-height: 24px;
    padding: 0 10px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
}
[dir="rtl"] .portal-plan-card-badge {
    right: auto;
    left: 14px;
}
.portal-plan-card.--current .portal-plan-card-badge {
    background: var(--portal-mint-ink);
    color: #fff;
}
.portal-plan-card.--pending .portal-plan-card-badge {
    background: #1f4a6b;
    color: #fff;
}
.portal-plan-card.--scheduled .portal-plan-card-badge {
    background: var(--portal-brand);
    color: #fff;
}

.portal-plan-name {
    margin: 0;
    font-family: Georgia, "Times New Roman", serif;
    font-size: 22px;
    font-weight: 700;
    color: var(--portal-ink);
}
.portal-plan-description {
    margin: 0;
    color: var(--portal-muted);
    font-size: 14px;
    line-height: 1.55;
}
.portal-plan-price {
    margin: 4px 0;
    color: var(--portal-brand);
    font-family: Georgia, "Times New Roman", serif;
    font-size: 30px;
    font-weight: 700;
    line-height: 1.05;
}
.portal-plan-price small {
    display: inline-block;
    margin-left: 6px;
    color: var(--portal-muted);
    font-family: 'Sora', Inter, sans-serif;
    font-size: 13px;
    font-weight: 600;
}
[dir="rtl"] .portal-plan-price small {
    margin-left: 0;
    margin-right: 6px;
}
.portal-plan-meta {
    display: grid;
    gap: 4px;
    color: var(--portal-muted);
    font-size: 13px;
}
.portal-plan-meta dt {
    display: inline;
    font-weight: 700;
    color: var(--portal-ink);
}
.portal-plan-meta dd {
    display: inline;
    margin: 0 0 0 6px;
}
[dir="rtl"] .portal-plan-meta dd {
    margin: 0 6px 0 0;
}
.portal-plan-cta {
    margin-top: auto;
    align-self: stretch;
}
.portal-plan-cta button,
.portal-plan-cta a {
    width: 100%;
    text-align: center;
}

.portal-plan-cta-note {
    display: block;
    margin-top: 8px;
    color: var(--portal-admin-muted);
    font-size: 12px;
    font-weight: 700;
    line-height: 1.45;
    text-align: center;
}

/* ─────────────────────────────────────────────────────────────
   Round 10.58 Item 5 — Customer Profile + Bookings + Booking
   Detail concierge UX (account summary + booking cards +
   stepper + cancel section).
   ───────────────────────────────────────────────────────────── */

.portal-account-summary {
    position: relative;
    display: grid;
    grid-template-columns: 84px minmax(0, 1fr);
    gap: 18px;
    padding: 22px 24px;
    margin-bottom: 1.75rem;
    background:
        linear-gradient(135deg, rgba(var(--mirror-brand-rgb), .92), rgba(75, 23, 50, .88) 48%, rgba(19, 40, 63, .92)),
        var(--portal-brand);
    color: #fff;
    border-radius: var(--radius-panel);
    box-shadow: var(--shadow-soft);
}
.portal-account-summary-avatar {
    display: grid;
    place-items: center;
    width: 84px;
    height: 84px;
    background: rgba(255, 255, 255, .12);
    border: 1px solid rgba(248, 223, 183, .35);
    border-radius: var(--radius-panel);
    color: var(--portal-champagne);
    font-family: Georgia, "Times New Roman", serif;
    font-size: 32px;
    font-weight: 700;
    overflow: hidden;
}
.portal-account-summary-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.portal-account-summary-greeting {
    color: rgba(255, 255, 255, .68);
    font-size: 12px;
    font-weight: 800;
    letter-spacing: .12em;
    text-transform: uppercase;
}
.portal-account-summary h1 {
    margin: 4px 0 8px;
    font-family: Georgia, "Times New Roman", serif;
    font-size: clamp(22px, 3.5vw, 32px);
    font-weight: 700;
    color: #fff;
    line-height: 1.05;
}
.portal-account-summary-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    color: rgba(255, 255, 255, .82);
    font-size: 14px;
}
.portal-account-summary-meta span strong {
    display: inline-block;
    margin-right: 6px;
    color: rgba(255, 255, 255, .98);
}

.portal-profile-section {
    margin: 0 0 1.5rem;
    padding: 22px 24px;
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-panel);
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .96), rgba(255, 253, 249, .92)),
        rgba(255, 255, 255, .92);
    box-shadow: var(--shadow-small);
}
.portal-profile-section legend {
    padding: 0 6px;
    font-family: Georgia, "Times New Roman", serif;
    font-size: 18px;
    font-weight: 700;
    color: var(--portal-ink);
}

/* Customer booking cards. */
.portal-booking-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 14px;
}
.portal-booking-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 18px 20px;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .96), rgba(255, 253, 249, .92)),
        rgba(255, 255, 255, .92);
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-panel);
    box-shadow: var(--shadow-small);
}
.portal-booking-card--upcoming {
    border-color: var(--portal-mint-ink);
    background:
        linear-gradient(180deg, rgba(223, 244, 232, .8), rgba(255, 255, 255, .92)),
        rgba(255, 255, 255, .92);
}
.portal-booking-card--upcoming::before {
    content: "" attr(data-eyebrow);
    position: absolute;
    top: -12px;
    left: 18px;
    padding: 4px 10px;
    background: var(--portal-mint-ink);
    color: #fff;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
}
.portal-booking-card-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 12px;
}
.portal-booking-card-when {
    display: flex;
    flex-direction: column;
}
.portal-booking-card-when strong {
    font-family: Georgia, "Times New Roman", serif;
    font-size: 18px;
    font-weight: 700;
    color: var(--portal-ink);
}
.portal-booking-card-when small {
    color: var(--portal-muted);
    font-size: 13px;
    margin-top: 2px;
}
.portal-booking-card-services {
    color: var(--portal-muted);
    font-size: 13px;
    line-height: 1.55;
}
.portal-booking-card-actions {
    display: flex;
    gap: 8px;
    align-items: center;
}

/* Customer booking detail — appointment summary + stepper. */
.portal-booking-detail-summary {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 18px;
    padding: 22px 24px;
    margin-bottom: 1.5rem;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .96), rgba(255, 253, 249, .92)),
        rgba(255, 255, 255, .92);
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-panel);
    box-shadow: var(--shadow-small);
}
.portal-booking-detail-summary h1 {
    margin: 4px 0 8px;
    font-family: Georgia, "Times New Roman", serif;
    color: var(--portal-ink);
}
.portal-booking-detail-when {
    display: flex;
    gap: 18px;
    color: var(--portal-muted);
    font-size: 14px;
}
.portal-booking-detail-when strong {
    color: var(--portal-ink);
    font-weight: 700;
}

.portal-booking-stepper {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 12px 18px;
    margin-bottom: 1.5rem;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .96), rgba(255, 253, 249, .92)),
        rgba(255, 255, 255, .92);
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-soft);
    box-shadow: var(--shadow-small);
}
.portal-booking-stepper-step {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 8px;
    border-radius: var(--radius-soft);
    color: var(--portal-muted);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
}
.portal-booking-stepper-step::before {
    content: attr(data-step);
    display: grid;
    place-items: center;
    width: 28px;
    height: 28px;
    border-radius: 999px;
    background: var(--portal-line);
    color: var(--portal-muted);
    font-size: 12px;
    font-weight: 800;
    margin-bottom: 4px;
}
.portal-booking-stepper-step.--past {
    color: var(--portal-mint-ink);
}
.portal-booking-stepper-step.--past::before {
    background: var(--portal-mint-ink);
    color: #fff;
    content: "✓";
}
.portal-booking-stepper-step.--current {
    color: var(--portal-brand);
}
.portal-booking-stepper-step.--current::before {
    background: var(--portal-brand);
    color: #fff;
}
.portal-booking-stepper-step.--cancelled {
    color: var(--portal-brand);
}
.portal-booking-stepper-step.--cancelled::before {
    background: var(--portal-rose);
    color: #fff;
    content: "×";
}

.portal-services-section {
    margin-bottom: 1.5rem;
    padding: 22px 24px;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .96), rgba(255, 253, 249, .92)),
        rgba(255, 255, 255, .92);
    border: 1px solid var(--portal-line);
    border-radius: var(--radius-panel);
    box-shadow: var(--shadow-small);
}
.portal-services-section h2 {
    margin: 0 0 12px;
    font-family: Georgia, "Times New Roman", serif;
}
.portal-services-section-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 8px;
}
.portal-services-section-list li {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 12px;
    background: var(--portal-petal);
    border-radius: var(--radius-soft);
}

.portal-cancel-section {
    margin-top: 2rem;
    padding: 18px 22px;
    border: 1px dashed rgba(var(--mirror-brand-rgb), .25);
    border-radius: var(--radius-panel);
    background: rgba(255, 255, 255, .6);
}
.portal-cancel-section h3 {
    margin: 0 0 6px;
    font-family: Georgia, "Times New Roman", serif;
    font-size: 16px;
    color: var(--portal-ink);
}
.portal-cancel-section p {
    margin: 0 0 12px;
    color: var(--portal-muted);
    font-size: 13px;
}
.portal-button-secondary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 40px;
    padding: 0 18px;
    background: #fff;
    color: var(--portal-brand);
    border: 1px solid var(--portal-brand);
    border-radius: var(--radius-soft);
    font-weight: 700;
    font-size: 13px;
    cursor: pointer;
    transition: background .12s ease, color .12s ease;
}
.portal-button-secondary:hover {
    background: var(--portal-brand);
    color: #fff;
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        scroll-behavior: auto !important;
        transition-duration: .01ms !important;
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
    }
}

/* ─────────────────────────────────────────────────────────────
   Round 10.59 — Admin-inspired operational portal skin.

   Dr. Khaled preferred the existing admin dashboard language over
   the warmer Atelier data surfaces. Keep the Mirror burgundy as the
   brand accent, but move provider/customer operations to a cleaner
   dashboard system: cool gray canvas, white cards, compact tables,
   professional filters, and restrained chart/insight panels.
   ───────────────────────────────────────────────────────────── */

:root {
    /* Phase 0: aliases into the LEGACY section of mirror-tokens.css.
       Values are byte-identical to what shipped, so there is no visual
       diff — the point is that they now have one definition.

       PARITY NOTE: these operational neutrals have NO counterpart in the
       Flutter apps, whose scaffold is plain white with #023047 headings
       and #3B3B3B body text. They are labelled legacy-pending-migration,
       not a target. Reconciling this skin with the app palette is an open
       product question (decisions doc A2/A7), not settled here. */
    --portal-admin-bg: var(--mirror-legacy-canvas);
    --portal-admin-bg-soft: var(--mirror-legacy-canvas-soft);
    --portal-admin-surface: var(--mirror-surface);
    --portal-admin-line: var(--mirror-legacy-line);
    --portal-admin-ink: var(--mirror-legacy-ink);
    --portal-admin-muted: var(--mirror-legacy-muted);
    --portal-admin-navy: var(--mirror-legacy-navy);
    --portal-admin-sidebar: #ffffff;
    --portal-admin-sidebar-active: #f3f6fb;
    --portal-admin-shadow: 0 10px 28px rgba(18, 32, 51, .07);
    --portal-admin-shadow-card: 0 3px 12px rgba(18, 32, 51, .05);
}

html,
body {
    background: var(--portal-admin-bg);
    color: var(--portal-admin-ink);
    font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

a {
    color: var(--portal-brand);
}

.portal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    min-height: 82px;
    padding: 14px 32px;
    background: var(--portal-admin-surface);
    border-bottom: 1px solid var(--portal-admin-line);
    box-shadow: 0 1px 0 rgba(18, 32, 51, .02);
}

.portal-logo {
    display: inline-flex;
    align-items: center;
    gap: 14px;
    color: var(--portal-admin-ink);
    text-decoration: none;
}

.portal-logo:hover {
    color: var(--portal-admin-ink);
    text-decoration: none;
}

.portal-logo-img {
    width: 54px;
    height: 54px;
    object-fit: contain;
    padding: 7px;
    background: #fff;
    border: 1px solid var(--portal-admin-line);
    border-radius: 12px;
    box-shadow: var(--portal-admin-shadow-card);
}

.portal-logo-text {
    display: block;
    font-family: Inter, ui-sans-serif, system-ui, sans-serif;
    font-size: 20px;
    font-weight: 800;
    line-height: 1.1;
    color: var(--portal-admin-ink);
}

.portal-logo-subtitle {
    display: block;
    margin-top: 4px;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0;
    text-transform: uppercase;
    color: var(--portal-brand);
}

.portal-header-right {
    display: inline-flex;
    align-items: center;
    gap: 14px;
}

.portal-user {
    color: var(--portal-admin-muted);
    font-weight: 700;
}

.portal-logout-button,
.portal-button-primary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 42px;
    padding: 0 18px;
    background: var(--portal-brand);
    color: #fff;
    border: 1px solid var(--portal-brand);
    border-radius: 8px;
    box-shadow: 0 8px 18px rgba(var(--mirror-brand-rgb), .16);
    font-weight: 800;
    letter-spacing: 0;
    text-decoration: none;
    cursor: pointer;
}

.portal-logout-button:hover,
.portal-button-primary:hover {
    background: var(--portal-brand-dark);
    color: #fff;
    text-decoration: none;
}

.portal-button-secondary {
    min-height: 40px;
    border-radius: 8px;
    border-color: var(--portal-admin-line);
    color: var(--portal-admin-ink);
    box-shadow: none;
}

.page-body-wrapper {
    display: flex;
    align-items: stretch;
    min-height: calc(100vh - 82px);
    background: var(--portal-admin-bg);
}

.portal-sidebar {
    flex: 0 0 238px;
    width: 238px;
    padding: 22px 18px;
    background: var(--portal-admin-sidebar);
    border-right: 1px solid var(--portal-admin-line);
    box-shadow: 1px 0 0 rgba(18, 32, 51, .02);
}

[dir="rtl"] .portal-sidebar {
    border-right: 0;
    border-left: 1px solid var(--portal-admin-line);
}

.portal-sidebar ul {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 6px;
}

.portal-sidebar li a,
.portal-sidebar a {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding: 0 14px;
    color: var(--portal-admin-ink);
    border-radius: 8px;
    font-size: 14px;
    font-weight: 700;
    text-decoration: none;
}

.portal-sidebar li a:hover,
.portal-sidebar li a:focus,
.portal-sidebar a:hover,
.portal-sidebar a:focus {
    color: var(--portal-brand);
    background: var(--portal-admin-sidebar-active);
    text-decoration: none;
}

.portal-sidebar li a.is-active,
.portal-sidebar li a[aria-current="page"],
.portal-sidebar a.is-active,
.portal-sidebar a[aria-current="page"] {
    color: #fff;
    background: var(--portal-brand);
    box-shadow: inset 3px 0 0 var(--portal-gold);
}

[dir="rtl"] .portal-sidebar li a.is-active,
[dir="rtl"] .portal-sidebar li a[aria-current="page"],
[dir="rtl"] .portal-sidebar a.is-active,
[dir="rtl"] .portal-sidebar a[aria-current="page"] {
    box-shadow: inset -3px 0 0 var(--portal-gold);
}

.page-body {
    flex: 1;
    min-width: 0;
    padding: 34px 40px 56px;
    background: var(--portal-admin-bg);
}

.portal-shell,
.portal-dashboard,
.portal-bookings-list,
.portal-booking-detail {
    max-width: 1420px;
    margin: 0 auto;
}

.portal-dashboard-header,
.portal-admin-page-title {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 24px;
    margin: 0 0 24px;
    padding: 0;
    background: transparent;
    border: 0;
    box-shadow: none;
}

.portal-dashboard-header h1,
.portal-admin-page-title h1 {
    margin: 0;
    color: var(--portal-admin-ink);
    font-family: Inter, ui-sans-serif, system-ui, sans-serif;
    font-size: clamp(28px, 3vw, 38px);
    font-weight: 800;
    letter-spacing: 0;
}

.portal-eyebrow,
.metric-label {
    letter-spacing: 0;
    color: var(--portal-admin-muted);
    font-size: 12px;
    font-weight: 800;
    text-transform: uppercase;
}

.dashboard-month {
    margin: 8px 0 0;
    color: var(--portal-admin-muted);
    font-size: 14px;
    font-weight: 700;
}

.portal-dashboard-controls {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    background: var(--portal-admin-surface);
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    box-shadow: var(--portal-admin-shadow-card);
}

.portal-dashboard-controls label {
    margin: 0;
    color: var(--portal-admin-muted);
    font-size: 13px;
    font-weight: 800;
}

/* PHASE 0: this is the rule that actually wins for portal form controls
   (it overrides the earlier .portal-field block). Radius moves 8px → 12px
   to match the Flutter apps' input_decoration_theme.dart:17,23,29, which
   use 12 on all four states. INTENDED VISIBLE DIFF — see gate G3.
   Scoped to form controls only: --radius-soft stays 8px so buttons,
   panels, flashes and tables are untouched. */
.portal-dashboard-controls select,
.portal-bookings-toolbar select,
.portal-bookings-toolbar input[type="search"],
.portal-field input:not([type="checkbox"]):not([type="radio"]),
.portal-field select,
.portal-field textarea,
/* Phase 0 fix: the salon form and cancel-reason box were missed by the
   first pass, leaving 8px controls next to 12px ones on the same page. */
.portal-salon-form input:not([type="checkbox"]):not([type="radio"]),
.portal-salon-form select,
.portal-salon-form textarea,
.portal-cancel-reason {
    min-height: 42px;
    background: var(--mirror-surface);
    color: var(--portal-admin-ink);
    border: 1px solid var(--portal-admin-line);
    border-radius: var(--mirror-radius-input);
    box-shadow: none;
}

.metrics-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 18px;
    margin: 0 0 24px;
}

.metric {
    position: relative;
    min-height: 132px;
    padding: 24px 26px;
    background: var(--portal-admin-surface);
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    box-shadow: var(--portal-admin-shadow-card);
    transition: transform .14s ease, box-shadow .14s ease;
}

.metric:hover {
    transform: translateY(-2px);
    box-shadow: var(--portal-admin-shadow);
}

.metric::before,
.portal-shell::before,
.portal-bookings-list::before,
.portal-plan-card::before {
    content: "";
    display: block;
    width: 48px;
    height: 3px;
    margin-bottom: 18px;
    background: linear-gradient(90deg, var(--portal-brand), var(--portal-champagne));
    border-radius: 999px;
}

.metric-value {
    display: block;
    margin-top: 10px;
    color: var(--portal-brand);
    font-family: Inter, ui-sans-serif, system-ui, sans-serif;
    font-size: 34px;
    font-weight: 800;
    line-height: 1;
}

.portal-admin-dashboard-row {
    display: grid;
    grid-template-columns: minmax(0, 1.35fr) minmax(320px, .85fr);
    gap: 24px;
    margin-bottom: 24px;
}

.portal-booking-pulse-section,
.portal-carebot-panel,
.portal-upcoming-bookings,
.portal-shell,
.portal-bookings-list,
.portal-booking-detail-summary,
.portal-booking-stepper,
.portal-services-section,
.portal-profile-section,
.portal-account-summary,
.portal-subscription-explanation,
.portal-active-subscription,
.portal-pending-payment,
.portal-just-initiated-payment {
    background: var(--portal-admin-surface);
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    box-shadow: var(--portal-admin-shadow-card);
}

.portal-booking-pulse-section,
.portal-carebot-panel,
.portal-upcoming-bookings,
.portal-shell {
    padding: 24px 26px;
}

.portal-booking-pulse-section header,
.portal-upcoming-bookings header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 18px;
    margin-bottom: 18px;
}

.portal-booking-pulse-section h3,
.portal-upcoming-bookings h3,
.portal-carebot-panel h2 {
    margin: 0;
    color: var(--portal-admin-ink);
    font-family: Inter, ui-sans-serif, system-ui, sans-serif;
    font-size: 20px;
    font-weight: 800;
}

.portal-booking-pulse-section p,
.portal-upcoming-bookings p {
    margin: 0;
    color: var(--portal-admin-muted);
    font-size: 13px;
}

.portal-booking-pulse {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 12px;
    min-height: 150px;
}

.portal-pulse-segment {
    min-width: 0;
    padding: 18px;
    background: var(--portal-admin-bg-soft);
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    color: var(--portal-admin-ink);
}

.portal-pulse-segment strong {
    display: block;
    color: var(--portal-admin-ink);
    font-size: 30px;
    font-weight: 800;
}

.portal-pulse-segment small {
    color: var(--portal-admin-muted);
    font-weight: 800;
}

.portal-pulse-segment--completed { border-top: 4px solid var(--portal-mint-ink); }
.portal-pulse-segment--confirmed { border-top: 4px solid #3b82f6; }
.portal-pulse-segment--cancelled { border-top: 4px solid #ef4444; }

.portal-carebot-panel {
    color: var(--portal-admin-ink);
    background: linear-gradient(180deg, #fff, #f9fbfd);
}

.portal-carebot-panel::before {
    display: none;
}

.portal-carebot-header {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 16px;
}

.portal-carebot-glyph {
    display: grid;
    place-items: center;
    width: 42px;
    height: 42px;
    border-radius: 50%;
    background: rgba(var(--mirror-brand-rgb), .10);
    color: var(--portal-brand);
    font-weight: 800;
}

.portal-carebot-insights {
    display: grid;
    gap: 10px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.portal-carebot-insights li {
    padding: 12px 14px;
    background: #fff;
    border: 1px solid var(--portal-admin-line);
    border-left: 4px solid var(--portal-brand);
    border-radius: 8px;
    color: var(--portal-admin-muted);
    font-size: 14px;
}

[dir="rtl"] .portal-carebot-insights li {
    border-left: 1px solid var(--portal-admin-line);
    border-right: 4px solid var(--portal-brand);
}

.portal-upcoming-bookings-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 10px;
}

.portal-booking-row-cards {
    list-style: none;
    margin: 0;
    padding: 0;
    display: none;
    gap: 10px;
}

.portal-upcoming-booking-item,
.portal-booking-row-card {
    display: grid;
    grid-template-columns: 160px minmax(0, 1fr) auto;
    gap: 14px;
    align-items: center;
    padding: 14px 16px;
    background: #fff;
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
}

.portal-upcoming-booking-when strong,
.portal-upcoming-booking-who strong {
    color: var(--portal-admin-ink);
    font-weight: 800;
}

.portal-upcoming-booking-when small {
    display: block;
    color: var(--portal-admin-muted);
    margin-top: 2px;
}

.portal-admin-toolbar,
.portal-bookings-toolbar {
    display: grid;
    grid-template-columns: minmax(260px, 1fr) minmax(320px, 1.4fr) minmax(180px, .5fr);
    gap: 14px;
    align-items: center;
    margin-bottom: 18px;
    padding: 16px;
    background: var(--portal-admin-surface);
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    box-shadow: var(--portal-admin-shadow-card);
}

.portal-list-summary {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 14px;
    margin-bottom: 18px;
}

.portal-list-summary-card {
    min-height: 86px;
    padding: 18px 20px;
    background: #fff;
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    box-shadow: var(--portal-admin-shadow-card);
}

.portal-list-summary-card strong {
    display: block;
    margin-top: 6px;
    color: var(--portal-admin-ink);
    font-size: 22px;
    font-weight: 800;
}

.portal-bookings-table-wrapper {
    overflow: auto;
    background: #fff;
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    box-shadow: var(--portal-admin-shadow-card);
}

.portal-table {
    width: 100%;
    margin: 0;
    background: #fff;
    border: 0;
    border-collapse: collapse;
}

.portal-table thead {
    background: #f5f7fb;
}

.portal-table th,
.portal-table td {
    padding: 15px 18px;
    border-bottom: 1px solid var(--portal-admin-line);
    color: var(--portal-admin-ink);
    vertical-align: middle;
}

.portal-table th {
    color: var(--portal-admin-muted);
    font-size: 12px;
    font-weight: 800;
    letter-spacing: 0;
    text-transform: uppercase;
}

.portal-table tbody tr:hover {
    background: #fafbfd;
}

.portal-status-badge {
    display: inline-flex;
    align-items: center;
    min-height: 28px;
    padding: 0 10px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 800;
    letter-spacing: 0;
}

/* PHASE 3 STEP I — the raw-hex overrides for pending / confirmed / completed
   are retired in favour of the token roles (G2). Measured contrast, before ->
   after: pending 4.40:1 -> 4.45:1, confirmed 6.59:1 -> 8.02:1, completed
   6.49:1 -> 4.97:1. All pass AA except pending, which lands exactly on the
   already-open E6 pair (#9B6918 on #FFF7E7 = 4.45:1). Pending was ALREADY
   sub-AA here at 4.40:1, so this is a marginal improvement that converges the
   occurrence onto E6 rather than creating a second one. E6 stays OPEN and no
   token value was altered.

   ⚠️ DO NOT delete the earlier block at :1033-1040 as "dead code". The rules
   here declare background and color ONLY, so the border-color declared there
   is NOT overridden and IS what renders. Removing it changes every badge's
   border. */
.portal-status-badge--pending { background: var(--portal-honey); color: var(--portal-honey-ink); }
.portal-status-badge--confirmed { background: var(--portal-sky); color: var(--mirror-info-fg); }
.portal-status-badge--completed { background: var(--portal-mint); color: var(--portal-mint-ink); }
/* PHASE 0: was hard-coded #fee2e2/#991b1b. This is the rule that actually
   won at runtime (it shadows the pink Atelier rule earlier in this file,
   now removed). Same values, now expressed as the semantic error role —
   no visual diff. */
.portal-status-badge--cancelled,
.portal-status-badge--user_cancel,
.portal-status-badge--provider_cancel { background: var(--mirror-error-bg); color: var(--mirror-error-fg); }
/* PHASE 3 STEP I — `expired` and `unknown` both reach the class attribute at
   runtime (provider list blade :12/:135/:158, provider detail :12/:40, account
   list :7/:94/:172) but had NO rule at all, so they fell back to the base
   pink/burgundy pill and were indistinguishable from a recognised status. They
   now share no_show's neutral, which matches the app's single default branch
   (single_booking_screen.dart:141-145): every status the app does not
   recognise gets one grey treatment.

   The neutral deliberately keeps its existing literals instead of moving to
   --portal-line / --portal-muted: that token pair measures 4.01:1 and would
   introduce a NEW sub-AA occurrence. The pair below measures 6.87:1. No new
   hex literal is added — the existing declaration's selector list is extended.
   The app's own Constants.grayColor (#CBCBCB) is NOT reproduced, per the
   standing E7 consequence applied in Steps D-H. */
.portal-status-badge--no_show,
.portal-status-badge--expired,
.portal-status-badge--unknown { background: #f3f4f6; color: #4b5563; }

.portal-action-link {
    color: var(--portal-brand);
    font-weight: 800;
}

.portal-empty {
    padding: 28px;
    color: var(--portal-admin-muted);
    text-align: center;
    background: #fff;
    border: 1px dashed var(--portal-admin-line);
    border-radius: 8px;
}

.portal-subscription-overview {
    display: grid;
    grid-template-columns: minmax(0, 1.4fr) minmax(280px, .8fr);
    gap: 18px;
    margin-bottom: 22px;
}

.portal-subscription-explanation,
.portal-active-subscription,
.portal-pending-payment,
.portal-just-initiated-payment {
    padding: 22px 24px;
}

.portal-subscription-explanation h2 {
    margin: 4px 0 12px;
    font-family: Inter, ui-sans-serif, system-ui, sans-serif;
    font-size: 24px;
    font-weight: 800;
}

.portal-subscription-explanation-points {
    display: grid;
    gap: 10px;
    margin: 0;
    padding-left: 18px;
    color: var(--portal-admin-muted);
}

[dir="rtl"] .portal-subscription-explanation-points {
    padding-left: 0;
    padding-right: 18px;
}

.portal-active-subscription,
.portal-pending-payment,
.portal-just-initiated-payment {
    align-self: stretch;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.portal-active-subscription p,
.portal-pending-payment p,
.portal-just-initiated-payment p {
    margin: 0;
}

.portal-active-subscription strong,
.portal-pending-payment strong {
    display: block;
    color: var(--portal-admin-ink);
    font-size: 20px;
    font-weight: 800;
}

.portal-active-subscription span,
.portal-pending-payment span {
    display: block;
    margin-top: 6px;
    color: var(--portal-admin-muted);
}

.portal-plan-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 18px;
}

.portal-plan-card {
    position: relative;
    padding: 24px;
    background: #fff;
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    box-shadow: var(--portal-admin-shadow-card);
}

.portal-plan-card.--current {
    border-color: rgba(31, 116, 80, .35);
    box-shadow: 0 0 0 3px rgba(31, 116, 80, .08), var(--portal-admin-shadow-card);
}

.portal-plan-card.--pending {
    border-color: rgba(59, 130, 246, .35);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, .08), var(--portal-admin-shadow-card);
}

.portal-plan-card.--disabled {
    opacity: .72;
}

.portal-plan-card-badge {
    position: absolute;
    top: 18px;
    right: 18px;
    padding: 5px 10px;
    background: #f5f7fb;
    color: var(--portal-admin-muted);
    border: 1px solid var(--portal-admin-line);
    border-radius: 999px;
    font-size: 12px;
    font-weight: 800;
}

[dir="rtl"] .portal-plan-card-badge {
    right: auto;
    left: 18px;
}

.portal-plan-name {
    margin: 0 0 8px;
    color: var(--portal-admin-ink);
    font-family: Inter, ui-sans-serif, system-ui, sans-serif;
    font-size: 22px;
    font-weight: 800;
}

.portal-plan-description {
    color: var(--portal-admin-muted);
    font-size: 14px;
}

.portal-plan-price {
    margin: 18px 0;
    color: var(--portal-brand);
    font-size: 34px;
    font-weight: 800;
}

.portal-plan-price s {
    display: inline-block;
    margin-right: 8px;
    color: var(--portal-admin-muted);
    font-size: 18px;
    font-weight: 700;
    text-decoration-thickness: 2px;
}

.portal-plan-price strong {
    color: var(--portal-brand);
    font-weight: 900;
}

.portal-plan-price small {
    color: var(--portal-admin-muted);
    font-size: 13px;
    font-weight: 700;
}

.portal-plan-discount {
    display: inline-flex;
    width: fit-content;
    min-height: 26px;
    align-items: center;
    padding: 0 10px;
    background: rgba(16, 122, 88, .10);
    border: 1px solid rgba(16, 122, 88, .22);
    border-radius: 999px;
    color: #107a58;
    font-size: 12px;
    font-weight: 900;
}

.portal-plan-meta {
    display: grid;
    gap: 8px;
    margin: 0 0 20px;
}

.portal-plan-meta div {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 0;
    border-bottom: 1px solid var(--portal-admin-line);
}

.portal-plan-meta dt {
    color: var(--portal-admin-muted);
    font-weight: 700;
}

.portal-plan-meta dd {
    margin: 0;
    color: var(--portal-admin-ink);
    font-weight: 800;
}

.portal-account-summary {
    display: flex;
    align-items: center;
    gap: 20px;
    padding: 24px;
    margin-bottom: 22px;
    color: var(--portal-admin-ink);
}

.portal-account-summary-avatar {
    flex: 0 0 74px;
    width: 74px;
    height: 74px;
    display: grid;
    place-items: center;
    background: rgba(var(--mirror-brand-rgb), .08);
    color: var(--portal-brand);
    border: 1px solid rgba(var(--mirror-brand-rgb), .16);
    border-radius: 16px;
    font-size: 28px;
    font-weight: 800;
}

.portal-account-summary h1 {
    margin: 2px 0 8px;
    color: var(--portal-admin-ink);
    font-family: Inter, ui-sans-serif, system-ui, sans-serif;
}

.portal-account-summary-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 10px 16px;
    color: var(--portal-admin-muted);
    font-size: 14px;
}

.portal-profile-section {
    padding: 22px 24px;
    margin-bottom: 18px;
}

.portal-profile-section legend {
    width: auto;
    padding: 0 0 10px;
    color: var(--portal-admin-ink);
    font-size: 18px;
    font-weight: 800;
}

.portal-form {
    display: grid;
    gap: 2px;
    max-width: none;
}

.portal-form fieldset.portal-profile-section,
fieldset.portal-profile-section {
    display: block;
    padding: 22px 24px;
    margin-bottom: 18px;
    border: 1px solid var(--portal-admin-line);
}

.portal-field {
    display: grid;
    gap: 6px;
    margin-bottom: 14px;
}

.portal-field label {
    color: var(--portal-admin-muted);
    font-weight: 800;
}

.portal-multi-select {
    position: relative;
    width: 100%;
}

.portal-multi-select-summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: 46px;
    padding: 10px 14px;
    cursor: pointer;
    color: var(--portal-admin-ink);
    background: #fff;
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
}

.portal-multi-select-summary::after {
    content: "v";
    color: var(--portal-admin-muted);
    font-size: 18px;
    line-height: 1;
}

.portal-multi-select[open] .portal-multi-select-summary {
    border-color: rgba(var(--mirror-brand-rgb), .44);
    box-shadow: 0 0 0 3px rgba(var(--mirror-brand-rgb), .08);
}

.portal-multi-select-panel {
    display: grid;
    gap: 6px;
    max-height: 220px;
    overflow: auto;
    margin-top: 8px;
    padding: 10px;
    background: #fff;
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    box-shadow: var(--portal-admin-shadow-card);
}

.portal-multi-select-option {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 36px;
    padding: 7px 8px;
    border-radius: 6px;
    color: var(--portal-admin-ink);
    font-weight: 700;
}

.portal-multi-select-option:hover {
    background: rgba(var(--mirror-brand-rgb), .06);
}

.portal-multi-select-option input {
    width: 16px;
    height: 16px;
    margin: 0;
    accent-color: var(--portal-brand);
}

.portal-staff-assignment-panel {
    gap: 8px;
}

.portal-staff-checkbox-option span {
    display: grid;
    gap: 2px;
    min-width: 0;
}

.portal-staff-checkbox-option strong {
    color: var(--portal-admin-ink);
    font-weight: 900;
}

.portal-staff-checkbox-option small {
    color: var(--portal-admin-muted);
    font-size: 13px;
    line-height: 1.35;
}

.portal-staff-checkbox-list {
    display: grid;
    gap: 4px;
    padding-top: 8px;
    border-top: 1px solid var(--portal-admin-line);
}

.portal-staff-all-option {
    border-bottom: 1px solid var(--portal-admin-line);
    border-radius: 0;
    padding-bottom: 10px;
}

.portal-staff-checkbox-option--disabled {
    color: var(--portal-admin-muted);
    cursor: not-allowed;
    opacity: .62;
}

.portal-staff-checkbox-option--disabled:hover {
    background: transparent;
}

.portal-next-appointment {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    gap: 18px;
    align-items: center;
    margin-bottom: 22px;
    padding: 22px 24px;
    background:
        linear-gradient(135deg, rgba(var(--mirror-brand-rgb), .10), rgba(223, 244, 232, .78)),
        #fff;
    border: 1px solid rgba(var(--mirror-brand-rgb), .24);
    border-radius: 8px;
    box-shadow: var(--portal-admin-shadow-card);
}

.portal-next-appointment h2 {
    margin: 0;
    color: var(--portal-admin-ink);
    font-size: 30px;
    font-weight: 900;
}

.portal-next-appointment-services {
    margin: 6px 0 0;
    color: var(--portal-admin-muted);
    font-weight: 700;
}

.portal-next-appointment-meta {
    display: grid;
    grid-template-columns: repeat(3, auto);
    gap: 12px;
    margin: 0;
}

.portal-next-appointment-meta div {
    min-width: 96px;
    padding: 10px 12px;
    background: rgba(255, 255, 255, .82);
    border: 1px solid rgba(var(--mirror-brand-rgb), .12);
    border-radius: 8px;
}

.portal-next-appointment-meta dt {
    margin-bottom: 3px;
    color: var(--portal-admin-muted);
    font-size: 11px;
    font-weight: 800;
    text-transform: uppercase;
}

.portal-next-appointment-meta dd {
    margin: 0;
    color: var(--portal-admin-ink);
    font-weight: 900;
}

@media (max-width: 900px) {
    .portal-next-appointment {
        grid-template-columns: 1fr;
    }

    .portal-next-appointment-meta {
        grid-template-columns: 1fr;
    }
}

.portal-booking-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
    gap: 16px;
}

.portal-booking-card {
    position: relative;
    padding: 20px;
    background: #fff;
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    box-shadow: var(--portal-admin-shadow-card);
}

.portal-booking-card--upcoming {
    border-color: rgba(var(--mirror-brand-rgb), .24);
}

.portal-booking-card--upcoming::before {
    top: 14px;
    left: 18px;
    background: var(--portal-brand);
    font-size: 11px;
    letter-spacing: 0;
}

[dir="rtl"] .portal-booking-card--upcoming::before {
    left: auto;
    right: 18px;
}

.portal-booking-card-head {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    margin-top: 18px;
}

.portal-booking-card-when strong {
    color: var(--portal-admin-ink);
    font-family: Inter, ui-sans-serif, system-ui, sans-serif;
    font-size: 18px;
    font-weight: 800;
}

.portal-booking-card-services {
    color: var(--portal-admin-muted);
}

/* Acceptance polish for operational provider surfaces: keep the
   admin-inspired frame, but make the inner booking/detail/forms
   readable and prevent mobile-only controls from leaking onto
   desktop. */
.portal-section-card,
.portal-detail-hero,
.portal-detail-card,
.portal-form-card,
.portal-table-card,
.portal-review-card {
    background: #fff;
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    box-shadow: var(--portal-admin-shadow-card);
}

.portal-section-card,
.portal-detail-hero,
.portal-form-card {
    padding: 24px 26px;
}

.portal-surface-intro {
    margin: 0 0 18px;
    color: var(--portal-admin-muted);
    font-size: 14px;
    line-height: 1.6;
    max-width: 780px;
}

.portal-table-card {
    overflow-x: auto;
    margin-top: 18px;
}

.portal-form-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 18px;
}

.portal-form-grid .portal-field--full,
.portal-form-grid .portal-actions-inline {
    grid-column: 1 / -1;
}

.portal-actions-inline {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    align-items: center;
}

.portal-checkbox-row {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    width: fit-content;
    min-height: 42px;
    margin: 18px 0 0;
    padding: 8px 12px;
    background: #fff;
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    color: var(--portal-admin-ink);
    font-weight: 700;
}

.portal-checkbox-row input[type="checkbox"] {
    width: 18px;
    height: 18px;
    min-height: 0;
    margin: 0;
    padding: 0;
    border-radius: 4px;
    box-shadow: none;
    accent-color: var(--portal-brand);
}


.portal-detail-hero {
    margin-bottom: 18px;
}

.portal-detail-hero h1 {
    margin: 4px 0 12px;
    color: var(--portal-admin-ink);
    font-family: Inter, ui-sans-serif, system-ui, sans-serif;
    font-size: clamp(28px, 3vw, 42px);
    font-weight: 800;
    letter-spacing: 0;
}

.portal-detail-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 18px;
}

.portal-detail-card {
    padding: 22px 24px;
}

.portal-detail-card h2 {
    margin: 0 0 16px;
    color: var(--portal-admin-ink);
    font-family: Inter, ui-sans-serif, system-ui, sans-serif;
    font-size: 20px;
    font-weight: 800;
}

.portal-detail-meta {
    display: grid;
    gap: 10px;
    margin: 0;
}

.portal-detail-meta div {
    display: grid;
    grid-template-columns: 150px minmax(0, 1fr);
    gap: 12px;
    align-items: start;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--portal-admin-line);
}

.portal-detail-meta dt {
    color: var(--portal-admin-muted);
    font-size: 13px;
    font-weight: 800;
}

.portal-detail-meta dd {
    margin: 0;
    color: var(--portal-admin-ink);
}

.portal-detail-card--wide {
    grid-column: 1 / -1;
}

.portal-detail-services-list {
    display: grid;
    gap: 10px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.portal-detail-services-list li {
    padding: 12px 14px;
    background: var(--portal-admin-bg-soft);
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
}

.portal-review-card {
    padding: 22px 24px;
}

.portal-review-response {
    margin-top: 14px;
    padding: 14px 16px;
    background: #f8fafc;
    border: 1px solid var(--portal-admin-line);
    border-left: 4px solid var(--portal-admin-navy);
    border-radius: 8px;
    color: var(--portal-admin-muted);
}

[dir="rtl"] .portal-review-response {
    border-left: 1px solid var(--portal-admin-line);
    border-right: 4px solid var(--portal-admin-navy);
}

.portal-plan-price-free {
    display: block;
    margin: 18px 0;
    color: var(--portal-brand);
    font-size: 30px;
    font-weight: 900;
}

.portal-plan-note,
.portal-plan-current-note {
    margin: 12px 0 18px;
    color: var(--portal-admin-muted);
    font-size: 14px;
    line-height: 1.55;
}

.portal-button-secondary[disabled] {
    cursor: default;
    opacity: .75;
}

/* Round 10.60 — Provider acceptance corrective polish
   Booking chart, non-overlapping booking cards, service units,
   staff/deal action buttons, working-hours editor, and clearer
   subscription upgrade states. */

.portal-bookings-status-chart {
    display: grid;
    gap: 14px;
    margin: 0 0 18px;
    padding: 16px 18px;
    background: #fff;
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    box-shadow: var(--portal-admin-shadow-card);
}

.portal-bookings-status-chart-header {
    display: flex;
    justify-content: space-between;
    gap: 12px;
}

.portal-bookings-status-chart-header strong {
    display: block;
    margin-top: 4px;
    color: var(--portal-admin-ink);
    font-size: 18px;
}

.portal-bookings-status-bars {
    display: grid;
    gap: 10px;
}

.portal-bookings-status-bar-row {
    display: grid;
    grid-template-columns: minmax(110px, .4fr) minmax(140px, 1fr) 42px;
    gap: 12px;
    align-items: center;
    color: var(--portal-admin-muted);
    font-size: 13px;
    font-weight: 800;
}

.portal-bookings-status-bar-track {
    height: 8px;
    overflow: hidden;
    background: var(--portal-admin-bg-soft);
    border-radius: 999px;
}

.portal-bookings-status-bar-fill {
    display: block;
    min-width: 4px;
    height: 100%;
    background: var(--portal-admin-navy);
    border-radius: inherit;
}

.portal-bookings-status-bar-fill--confirmed,
.portal-bookings-status-bar-fill--completed {
    background: var(--portal-mint-ink);
}

.portal-bookings-status-bar-fill--cancelled,
.portal-bookings-status-bar-fill--no_show {
    background: var(--portal-brand);
}

.portal-booking-row-card,
.portal-booking-row-card-head,
.portal-booking-row-card-meta,
.portal-booking-row-card-meta span {
    min-width: 0;
}

.portal-booking-row-card-head {
    flex-wrap: wrap;
}

.portal-booking-row-card .portal-status-badge {
    white-space: nowrap;
}

.portal-unit-value,
.portal-money-value {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    color: var(--portal-admin-ink);
    font-weight: 800;
}

.portal-unit-value small,
.portal-money-value small {
    color: var(--portal-admin-muted);
    font-size: 12px;
    font-weight: 800;
    text-transform: uppercase;
}

.portal-action-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 34px;
    padding: 0 12px;
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    background: #fff;
    color: var(--portal-brand);
    font-size: 13px;
    font-weight: 800;
    line-height: 1;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
}

.portal-action-button:hover {
    color: #fff;
    background: var(--portal-brand);
    border-color: var(--portal-brand);
}

.portal-action-button--view {
    color: var(--portal-brand);
}

.portal-action-button--danger {
    color: var(--mirror-error-fg);
    border-color: rgba(153, 27, 27, .28);
}

.portal-action-button--danger:hover {
    background: var(--mirror-error-fg);
    border-color: var(--mirror-error-fg);
}

.portal-action-button--success {
    color: var(--portal-mint-ink);
    border-color: rgba(17, 105, 78, .28);
}

.portal-action-button--success:hover {
    background: var(--portal-mint-ink);
    border-color: var(--portal-mint-ink);
}

.portal-actions-inline {
    align-items: center;
}

.portal-working-hours-card {
    display: grid;
    gap: 18px;
}


.portal-day-pill {
    display: inline-flex;
    min-width: 104px;
    min-height: 32px;
    align-items: center;
    padding: 0 12px;
    background: #fff;
    border: 1px solid var(--portal-admin-line);
    border-radius: 999px;
    color: var(--portal-admin-ink);
    font-weight: 800;
}

.portal-time-field {
    display: grid;
    gap: 5px;
    max-width: 180px;
}

.portal-time-field span,
.portal-field-hint {
    color: var(--portal-admin-muted);
    font-size: 12px;
    font-weight: 800;
}

.portal-time-field input[type="time"] {
    width: 100%;
    min-height: 38px;
    padding: 6px 10px;
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    background: #fff;
    color: var(--portal-admin-ink);
}

.portal-time-field input[disabled] {
    color: var(--portal-admin-muted);
    background: var(--portal-admin-bg-soft);
}

.portal-toggle-row {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--portal-admin-ink);
    font-weight: 800;
    cursor: pointer;
}

.portal-toggle-row input[type="checkbox"] {
    width: 18px;
    height: 18px;
    margin: 0;
    flex: 0 0 18px;
}

.portal-plan-card.--current:hover,
.portal-plan-card.--disabled:hover {
    transform: none;
}

.portal-plan-card.--current .portal-plan-name {
    padding-right: 130px;
}

[dir="rtl"] .portal-plan-card.--current .portal-plan-name {
    padding-right: 0;
    padding-left: 130px;
}

.portal-plan-upgrade-note {
    margin: 8px 0 0;
    color: var(--portal-mint-ink);
    font-size: 14px;
    font-weight: 800;
}

.portal-subscription-benefits {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 14px;
    margin: 18px 0;
}

.portal-subscription-benefits > div {
    padding: 18px 20px;
    background: #fff;
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    box-shadow: var(--portal-admin-shadow-card);
}

.portal-subscription-benefits h2 {
    margin: 0 0 10px;
    color: var(--portal-admin-ink);
    font-size: 18px;
    font-weight: 900;
}

.portal-subscription-benefits ul {
    display: grid;
    gap: 8px;
    margin: 0;
    padding-left: 18px;
    color: var(--portal-admin-muted);
    line-height: 1.5;
}

[dir="rtl"] .portal-subscription-benefits ul {
    padding-left: 0;
    padding-right: 18px;
}

.portal-subscription-command {
    display: grid;
    grid-template-columns: minmax(260px, .8fr) minmax(320px, 1fr) minmax(280px, .8fr);
    gap: 14px;
    align-items: stretch;
    margin: 0 0 18px;
}

.portal-current-plan-strip,
.portal-subscription-flow,
.portal-billing-cycle {
    min-height: 96px;
    padding: 16px 18px;
    background: #fff;
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    box-shadow: var(--portal-admin-shadow-card);
}

.portal-current-plan-strip {
    display: grid;
    gap: 4px;
}

.portal-current-plan-strip span,
.portal-billing-cycle span {
    color: var(--portal-admin-muted);
    font-size: 12px;
    font-weight: 900;
    text-transform: uppercase;
}

.portal-current-plan-strip strong {
    color: var(--portal-admin-ink);
    font-size: 22px;
    font-weight: 900;
}

.portal-current-plan-strip small {
    color: var(--portal-admin-muted);
    font-size: 13px;
    font-weight: 700;
}

.portal-subscription-flow {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px;
    align-content: center;
}

.portal-subscription-flow span {
    display: grid;
    min-height: 46px;
    place-items: center;
    padding: 8px 10px;
    background: var(--portal-admin-bg-soft);
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    color: var(--portal-admin-ink);
    font-size: 13px;
    font-weight: 900;
    text-align: center;
}

.portal-billing-cycle {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    align-content: center;
}

.portal-billing-cycle > span {
    grid-column: 1 / -1;
}

.portal-billing-cycle button {
    min-height: 40px;
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    background: #fff;
    color: var(--portal-admin-muted);
    font-weight: 900;
}

.portal-billing-cycle button.is-active,
.portal-billing-cycle button:hover {
    color: #fff;
    background: var(--portal-brand);
    border-color: var(--portal-brand);
}

.portal-subscription-payment-status:empty {
    display: none;
}

.portal-plan-cycle-chip {
    display: inline-flex;
    align-self: flex-start;
    min-height: 24px;
    align-items: center;
    padding: 0 10px;
    background: var(--portal-admin-bg-soft);
    border: 1px solid var(--portal-admin-line);
    border-radius: 999px;
    color: var(--portal-admin-muted);
    font-size: 11px;
    font-weight: 900;
    text-transform: uppercase;
}

.portal-subscription-guide {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 14px;
    margin: 0 0 18px;
}

.portal-subscription-guide article,
.portal-plan-empty-state {
    padding: 18px 20px;
    background: #fff;
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    box-shadow: var(--portal-admin-shadow-card);
}

.portal-subscription-guide article {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.portal-subscription-guide article > span {
    color: var(--portal-admin-muted);
    font-size: 12px;
    font-weight: 900;
    text-transform: uppercase;
}

.portal-subscription-guide strong,
.portal-plan-empty-state strong {
    color: var(--portal-admin-ink);
    font-size: 18px;
    font-weight: 900;
}

.portal-subscription-guide p,
.portal-plan-empty-state p {
    margin: 0;
    color: var(--portal-admin-muted);
    line-height: 1.55;
}

.portal-subscription-guide dl {
    display: grid;
    gap: 6px;
    margin: auto 0 0;
}

.portal-subscription-guide dl div {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding-top: 8px;
    border-top: 1px solid var(--portal-admin-line);
}

.portal-subscription-guide dt {
    color: var(--portal-admin-muted);
    font-size: 13px;
    font-weight: 800;
}

.portal-subscription-guide dd {
    margin: 0;
    color: var(--portal-admin-ink);
    font-weight: 900;
}

.portal-subscription-guide ul {
    display: grid;
    gap: 6px;
    margin: auto 0 0;
    padding-left: 18px;
    color: var(--portal-admin-muted);
    line-height: 1.45;
}

[dir="rtl"] .portal-subscription-guide ul {
    padding-left: 0;
    padding-right: 18px;
}

.portal-subscription-provider-note {
    margin-top: auto !important;
    color: var(--portal-brand) !important;
    font-weight: 900;
}

.portal-subscription-policy-notice {
    display: grid;
    gap: 8px;
    margin: 0 0 18px;
    padding: 16px 18px;
    background: rgba(var(--mirror-brand-rgb), .06);
    border: 1px solid rgba(var(--mirror-brand-rgb), .18);
    border-radius: 8px;
    box-shadow: var(--portal-admin-shadow-card);
}
.portal-subscription-policy-notice.--scheduled {
    background: rgba(44, 95, 72, .07);
    border-color: rgba(44, 95, 72, .24);
}
.portal-subscription-policy-notice.--scheduled span {
    color: var(--portal-mint-ink);
}

.portal-subscription-policy-notice span {
    color: var(--portal-brand);
    font-size: 12px;
    font-weight: 900;
    text-transform: uppercase;
}

.portal-subscription-policy-notice p {
    margin: 0;
    color: var(--portal-admin-ink);
    font-size: 13px;
    line-height: 1.55;
}

.portal-plan-cta .portal-button-secondary.--compact,
.portal-subscription-policy-notice .portal-button-secondary {
    justify-self: start;
    min-height: 38px;
    padding: 0 14px;
    font-size: 13px;
}

.portal-plan-empty-state {
    display: grid;
    justify-items: center;
    gap: 12px;
    margin-top: 12px;
    border-style: dashed;
    text-align: center;
}

.portal-plan-picker {
    display: grid;
    gap: 16px;
    padding: 18px;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .98), rgba(248, 250, 252, .92)),
        #fff;
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    box-shadow: var(--portal-admin-shadow-card);
}

.portal-plan-picker-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 18px;
    padding-bottom: 16px;
    border-bottom: 1px solid var(--portal-admin-line);
}

.portal-plan-picker-header span,
.portal-plan-empty-state > span {
    display: inline-flex;
    align-self: flex-start;
    min-height: 24px;
    align-items: center;
    padding: 0 10px;
    background: rgba(var(--mirror-brand-rgb), .08);
    border-radius: 999px;
    color: var(--portal-brand);
    font-size: 11px;
    font-weight: 900;
    text-transform: uppercase;
}

.portal-plan-picker-header h2 {
    margin: 8px 0 6px;
    color: var(--portal-admin-ink);
    font-size: 24px;
    font-weight: 900;
}

.portal-plan-picker-header p {
    max-width: 740px;
    margin: 0;
    color: var(--portal-admin-muted);
    line-height: 1.55;
}

.portal-plan-picker-deadline {
    display: grid;
    gap: 4px;
    min-width: 180px;
    padding: 14px 16px;
    background: var(--portal-admin-bg-soft);
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
}

.portal-plan-picker-deadline span {
    padding: 0;
    background: transparent;
    border-radius: 0;
    color: var(--portal-admin-muted);
}

.portal-plan-picker-deadline strong {
    color: var(--portal-admin-ink);
    font-size: 18px;
    font-weight: 900;
}

.portal-plan-empty-state ol {
    display: grid;
    gap: 8px;
    width: min(620px, 100%);
    margin: 4px 0 0;
    padding-left: 22px;
    color: var(--portal-admin-muted);
    text-align: left;
}

[dir="rtl"] .portal-plan-empty-state ol {
    padding-left: 0;
    padding-right: 22px;
    text-align: right;
}

.portal-plan-static-state {
    display: block;
    width: 100%;
    min-height: 42px;
    padding: 12px 14px;
    background: #fff;
    border: 1px solid var(--portal-admin-line);
    border-radius: 8px;
    color: var(--portal-admin-muted);
    font-weight: 900;
    text-align: center;
    cursor: default;
}

.portal-button-secondary[disabled],
.portal-button-secondary[aria-disabled="true"] {
    pointer-events: none;
    transform: none;
    box-shadow: none;
}

@media (max-width: 1180px) {
    .metrics-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .portal-admin-dashboard-row,
    .portal-subscription-overview {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 820px) {
    .portal-header {
        align-items: flex-start;
        flex-direction: column;
    }

    .portal-header-right {
        width: 100%;
        justify-content: space-between;
    }

    .page-body-wrapper {
        flex-direction: column;
    }

    .portal-sidebar {
        width: 100%;
        flex-basis: auto;
        border-right: 0;
        border-bottom: 1px solid var(--portal-admin-line);
    }

    .portal-sidebar ul {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .page-body {
        padding: 24px 16px 40px;
    }

    .portal-dashboard-header,
    .portal-admin-page-title,
    .portal-booking-pulse-section header,
    .portal-upcoming-bookings header {
        align-items: stretch;
        flex-direction: column;
    }

    .portal-dashboard-controls,
    .portal-admin-toolbar,
    .portal-bookings-toolbar,
    .portal-list-summary {
        grid-template-columns: 1fr;
    }

    .metrics-grid,
    .portal-booking-pulse {
        grid-template-columns: 1fr;
    }

    .portal-upcoming-booking-item,
    .portal-booking-row-card {
        grid-template-columns: 1fr;
    }

    .portal-bookings-table-wrapper {
        display: none;
    }

    .portal-booking-row-cards {
        display: grid;
    }

    .portal-booking-row-card-head {
        justify-content: flex-start;
    }

    .portal-booking-row-card-meta {
        grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    }

    .portal-subscription-command {
        grid-template-columns: 1fr;
    }

    .portal-subscription-flow {
        grid-template-columns: 1fr;
    }

    .portal-plan-picker-header {
        align-items: stretch;
        flex-direction: column;
    }

    .portal-subscription-guide,
    .portal-form-grid,
    .portal-detail-grid,
    .portal-subscription-benefits {
        grid-template-columns: 1fr;
    }

    .portal-detail-card--wide,
    .portal-form-grid .portal-field--full,
    .portal-form-grid .portal-actions-inline {
        grid-column: auto;
    }

    .portal-detail-meta div {
        grid-template-columns: 1fr;
        gap: 4px;
    }

    .portal-bookings-status-bar-row {
        grid-template-columns: 1fr;
        gap: 6px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .metric,
    .portal-plan-card,
    .portal-sidebar li a,
    .portal-sidebar a,
    .portal-button-primary,
    .portal-logout-button {
        transition: none !important;
    }
}

.portal-language-toggle {
    align-items: center;
    background: #fff;
    border: 1px solid rgba(var(--mirror-brand-rgb), 0.2);
    border-radius: 999px;
    color: var(--mirror-brand);
    display: inline-flex;
    font-size: 0.9rem;
    font-weight: 700;
    height: 38px;
    justify-content: center;
    min-width: 42px;
    padding: 0 12px;
    text-decoration: none;
}

.portal-language-toggle:hover,
.portal-language-toggle:focus {
    background: var(--mirror-brand);
    color: #fff;
    text-decoration: none;
}

.portal-notification-link {
    align-items: center;
    background: #fff;
    border: 1px solid rgba(var(--mirror-brand-rgb), 0.2);
    border-radius: 999px;
    color: var(--mirror-brand);
    display: inline-flex;
    font-size: 0.9rem;
    font-weight: 700;
    gap: 8px;
    min-height: 38px;
    padding: 0 12px;
    text-decoration: none;
}

.portal-notification-link:hover,
.portal-notification-link:focus {
    background: var(--mirror-brand);
    color: #fff;
    text-decoration: none;
}

.portal-notification-count {
    align-items: center;
    background: var(--mirror-brand);
    border-radius: 999px;
    color: #fff;
    display: inline-flex;
    font-size: 0.75rem;
    height: 22px;
    justify-content: center;
    min-width: 22px;
    padding: 0 6px;
}

.portal-notification-link:hover .portal-notification-count,
.portal-notification-link:focus .portal-notification-count {
    background: #fff;
    color: var(--mirror-brand);
}

/* =====================================================================
   Phase 1 screen (1) — Profile avatar. Row B (2026-08-23).
   Ports lib/app/modules/profile/views/profile_view.dart:45-66 (ImageSelector).
   Token-only: no literal colour, radius or spacing values.

   ⚠️ REGISTERED ADAPTATION (ruling B4) — NOT parity. The app's control opens a
   two-item menu, camera / gallery (image_selector.dart:54-70). A browser
   delegates that choice to the operating system, so the menu itself is not
   reproducible on the web. What IS ported: the placement (top of the form),
   the circle, tap-to-pick, and the current-photo preview. There is NO
   remove-photo affordance — the app has none either.
   ===================================================================== */
.portal-profile-avatar-field {
    display: grid;
    justify-items: center;
    gap: var(--mirror-space-2);
    margin-bottom: var(--mirror-space-6);
}

.portal-profile-avatar {
    display: grid;
    justify-items: center;
    gap: var(--mirror-space-2);
    cursor: pointer;
}

/* :50 BoxShape.circle, :48-49 sized from the app's 25%-of-screen-width. */
.portal-profile-avatar-figure {
    display: grid;
    place-items: center;
    inline-size: var(--mirror-avatar-profile);
    block-size: var(--mirror-avatar-profile);
    border-radius: var(--mirror-radius-pill);
    /* :51-55 — the empty state is a lightGrayColor circle. */
    background: var(--mirror-line-soft);
    color: var(--mirror-brand);
    font-size: var(--mirror-text-2xl);
    font-weight: var(--mirror-weight-bold);
    overflow: hidden;
}

.portal-profile-avatar-figure img {
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    display: block;
}

.portal-profile-avatar-label {
    color: var(--mirror-body);
    font-size: var(--mirror-text-sm);
    font-weight: var(--mirror-weight-bold);
}

/* The real <input type="file"> is clipped, NEVER `display: none` — it must
   stay focusable and in the tab order. The circle carries its focus ring,
   reusing the sheet's established .portal-gallery-thumb:focus-visible shape. */
.portal-profile-avatar-input {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    padding: 0;
    margin: -1px;
    border: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.portal-profile-avatar-field:focus-within .portal-profile-avatar-figure {
    outline: 3px solid var(--mirror-brand);
    outline-offset: 2px;
}

/* --mirror-body, not --mirror-hint: E7 is open and must not gain a new
   sub-4.5:1 occurrence from this row. */
.portal-profile-avatar-status {
    color: var(--mirror-body);
    font-size: var(--mirror-text-xs);
}

/* =====================================================================
   Phase 1 screen (2)/(3) — Row D (2026-08-23). ACCOUNT-OWNED booking rules.
   Ports lib/app/modules/main/tabs/bookings/view/bookings_view.dart and
   lib/app/modules/single_order/single_order_screen.dart.
   Token-only: no literal colour, radius or spacing values.

   ⛔ EVERY rule in this block is ACCOUNT-OWNED and new. The shared
   `.portal-status-badge` blocks (:1018 portal theme, :2339 admin theme) are
   BYTE-UNCHANGED — they are Step I's closed work with eight consumers across
   provider, notifications, deals and /account/reviews, and ruling D6 forbids
   touching them. `.portal-button-secondary` is likewise untouched (D5).
   ===================================================================== */

/* single_order_screen.dart:244-255 + order.dart:250-265 — the app's pill is a
   SOLID getStatusColor() fill with a WHITE label, radius 8, padding h8 v4.
   The web's shared badge is a tinted pastel; ruling D6 ports the app's. */
.portal-account-status-badge {
    /* inline-flex + explicit self-alignment: this badge sits inside a GRID
       parent on the detail header and a FLEX parent on the cards, and a grid
       item is blockified and stretched by default — which rendered the pill as
       a tall block on first paint. Hugging its own content is declared here
       rather than assumed from any parent. */
    display: inline-flex;
    align-items: center;
    align-self: start;
    justify-self: start;
    inline-size: fit-content;
    border-radius: var(--mirror-radius-md);
    padding: var(--mirror-space-1) var(--mirror-space-2);
    font-size: var(--mirror-text-xs);
    font-weight: var(--mirror-weight-bold);
    color: var(--mirror-surface);
    background: var(--mirror-app-status-unmapped);
}

/* The five getStatusColor branches, in the app's own predicate order. */
.portal-account-status-badge--completed  { background: var(--mirror-app-green); }
.portal-account-status-badge--pending    { background: var(--mirror-app-orange); }
.portal-account-status-badge--cancelled,
.portal-account-status-badge--user_cancel,
.portal-account-status-badge--provider_cancel { background: var(--mirror-app-red); }
.portal-account-status-badge--confirmed  { background: var(--mirror-app-blue); }
/* :262-264 else-branch — the app paints no_show / expired / unknown grey. */
.portal-account-status-badge--no_show,
.portal-account-status-badge--expired,
.portal-account-status-badge--unknown    { background: var(--mirror-app-status-unmapped); }

/* single_order_screen.dart:29-72 — Booking Date is its own titled section,
   Date and Time side by side, each a grey label over a bold value. */
.portal-booking-date-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: var(--mirror-space-4);
    margin: 0;
}

.portal-booking-date-grid dt {
    color: var(--mirror-hint);
    font-size: var(--mirror-text-sm);
    margin: 0 0 var(--mirror-space-1);
}

.portal-booking-date-grid dd {
    color: var(--mirror-ink);
    font-size: var(--mirror-text-sm);
    font-weight: var(--mirror-weight-bold);
    margin: 0;
}

/* single_order_screen.dart:81-104 — the chip carries an icon beside the
   label: Icons.store for a salon, Icons.person for a freelancer (:91). The
   glyphs are hand-authored in this sheet's established inline-SVG stroke
   style (provider-employees-list-component.blade.php:108-111), not imported. */
.portal-provider-chip-icon {
    inline-size: 1em;
    block-size: 1em;
    vertical-align: -0.125em;
    margin-inline-end: var(--mirror-space-1);
}

/* single_order_screen.dart:218-226 — CustomButton(cancel): transparent fill,
   RED label, 2px RED border, radius 8. Ruling D5 ports it verbatim and
   forbids touching any other button class. */
.portal-booking-cancel-button {
    display: inline-block;
    background: transparent;
    border: 2px solid var(--mirror-app-red);
    border-radius: var(--mirror-radius-md);
    color: var(--mirror-app-red);
    cursor: pointer;
    font-size: var(--mirror-text-sm);
    font-weight: var(--mirror-weight-bold);
    padding: var(--mirror-space-2) var(--mirror-space-5);
}

.portal-booking-cancel-button:focus-visible {
    outline: 3px solid var(--mirror-app-red);
    outline-offset: 2px;
}

.portal-booking-cancel-button[disabled] {
    cursor: default;
    opacity: .6;
}

/* bookings_view.dart:125-130 — the per-tab empty illustration is sized to 30%
   of the SHORTEST side. `min(30vw, 30vh)` is the CSS reading of that; the
   Step H art rule two blocks down is height-driven for its own 750x500 asset
   and is NOT edited here (Step H is closed). no_bookings.svg is square. */
.bookings-empty__art {
    inline-size: min(30vw, 30vh);
    max-inline-size: 100%;
    block-size: auto;
}

/* =====================================================================
   Phase 1 screen (2) — Bookings status tabs + card detail blocks.
   Ports lib/app/modules/main/tabs/bookings/view/bookings_view.dart.
   Token-only: no literal colour, radius or spacing values.
   ===================================================================== */

/* TabBar — bookings_view.dart:48-63: white bar, brand label + brand
   indicator on the active tab, grey when unselected. */
.portal-booking-tabs {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--mirror-space-2);
    background: var(--mirror-surface);
    border-bottom: 1px solid var(--mirror-line);
    margin-bottom: var(--mirror-space-5);
    padding: 0 0 var(--mirror-space-1) 0;
}

.portal-booking-tab {
    appearance: none;
    background: transparent;
    border: 0;
    border-bottom: 2px solid transparent;
    color: var(--mirror-hint);
    cursor: pointer;
    font-family: inherit;
    font-size: var(--mirror-text-sm);
    font-weight: var(--mirror-weight-semibold);
    padding: var(--mirror-space-3) var(--mirror-space-4);
}

.portal-booking-tab:hover:not(:disabled),
.portal-booking-tab:focus-visible {
    color: var(--mirror-brand);
}

.portal-booking-tab.is-active {
    border-bottom-color: var(--mirror-brand);
    color: var(--mirror-brand);
}

.portal-booking-tab:disabled {
    cursor: progress;
    opacity: 0.6;
}

/* Refresh — ports the app bar action at bookings_view.dart:14-18.
   Pushed to the trailing edge; direction-agnostic for RTL. */
.portal-booking-tabs-refresh {
    appearance: none;
    background: transparent;
    border: 1px solid var(--mirror-line-strong);
    border-radius: var(--mirror-radius-button-dense);
    color: var(--mirror-brand);
    cursor: pointer;
    font-family: inherit;
    font-size: var(--mirror-text-xs);
    font-weight: var(--mirror-weight-semibold);
    margin-inline-start: auto;
    padding: var(--mirror-space-2) var(--mirror-space-3);
}

.portal-booking-tabs-refresh:hover:not(:disabled),
.portal-booking-tabs-refresh:focus-visible {
    border-color: var(--mirror-brand);
}

.portal-booking-tabs-refresh:disabled {
    cursor: progress;
    opacity: 0.6;
}

/* Card header — `Order ID: #{order.id}` bold 16sp, bookings_view.dart:171-175 */
.portal-booking-card-order-id {
    color: var(--mirror-ink);
    font-size: var(--mirror-text-md);
    font-weight: var(--mirror-weight-bold);
}

/* Card payment + invoice blocks — bookings_view.dart:229-284 */
.portal-booking-card-detail {
    border-top: 1px solid var(--mirror-line-soft);
    margin: var(--mirror-space-3) 0 0 0;
    padding-top: var(--mirror-space-3);
}

.portal-booking-card-detail-title {
    color: var(--mirror-ink);
    font-size: var(--mirror-text-sm);
    font-weight: var(--mirror-weight-bold);
    margin-bottom: var(--mirror-space-1);
}

.portal-booking-card-detail dd {
    display: flex;
    flex-direction: column;
    gap: var(--mirror-space-1);
    margin: 0;
}

.portal-booking-card-detail dd span {
    color: var(--mirror-body);
    font-size: var(--mirror-text-xs);
}

/* =====================================================================
   Phase 1 screen (3) — Order Details sections.
   Ports lib/app/modules/single_order/single_order_screen.dart.
   Token-only: no literal colour, radius or spacing values.
   ===================================================================== */

/* Provider chip — single_order_screen.dart:81-104: brand tint at 10%,
   radius 6, brand label. */
.portal-provider-chip {
    background: rgba(var(--mirror-brand-rgb), 0.1);
    border-radius: var(--mirror-radius-sm);
    color: var(--mirror-brand);
    display: inline-block;
    font-size: var(--mirror-text-xs);
    font-weight: var(--mirror-weight-bold);
    margin: 0;
    padding: var(--mirror-space-1) var(--mirror-space-2);
}

/* Employee card — single_order_screen.dart:114-171: elevation 2, radius 8,
   circular 50px avatar, name bold with the job title beneath.

   Row C (2026-08-23) — these four rules are re-pointed off
   `.portal-employee-card`, which the provider staff list now owns alone (its
   block is further down this sheet). The two skins had been declared at equal
   specificity on one class name, so the provider's brand tint was winning on
   this customer surface while this block's border and shadow survived as
   orphans. Renaming the ACCOUNT side ends the collision and touches no
   provider file.

   The border is deliberately NOT carried over. The app's Card (:114-118) has
   none, so the retired `border: 1px solid var(--mirror-line-soft)` was already
   off-parity before the collision — "restore white" would not have been
   "restore parity". Every remaining value is the app's own: white surface and
   elevation 2 (:115), radius 8 (:117), padding 12 (:120), 16 between the
   avatar and the text (:144), the name bold at 14 (:151-152) and the job title
   at 12 in gray1 (:161-162). */
.portal-booking-employee-card {
    align-items: center;
    background: var(--mirror-surface);
    border-radius: var(--mirror-radius-md);
    box-shadow: var(--mirror-shadow-sm);
    display: flex;
    gap: var(--mirror-space-4);
    padding: var(--mirror-space-3);
}

.portal-booking-employee-card-avatar {
    /* 50% is the circle shape itself, not a design value: the app clips a
       50px box with BorderRadius.circular(25), which is a full circle. */
    border-radius: 50%;
    height: var(--mirror-avatar-employee);
    object-fit: cover;
    width: var(--mirror-avatar-employee);
}

.portal-booking-employee-card strong {
    color: var(--mirror-ink);
    display: block;
    font-size: var(--mirror-text-sm);
    font-weight: var(--mirror-weight-bold);
}

.portal-booking-employee-card small {
    color: var(--mirror-hint);
    display: block;
    font-size: var(--mirror-text-xs);
}

/* Detail rows — single_order_screen.dart:359-378: label left (grey),
   value right (bold), 8px vertical rhythm. Logical properties so the
   pairing mirrors correctly in RTL. */
.portal-detail-rows {
    margin: 0;
}

.portal-detail-rows > div {
    border-bottom: 1px solid var(--mirror-line-soft);
    display: flex;
    gap: var(--mirror-space-3);
    justify-content: space-between;
    padding: var(--mirror-space-2) 0;
}

.portal-detail-rows > div:last-child {
    border-bottom: 0;
}

.portal-detail-rows dt {
    color: var(--mirror-hint);
    font-size: var(--mirror-text-sm);
}

.portal-detail-rows dd {
    color: var(--mirror-ink);
    font-size: var(--mirror-text-sm);
    font-weight: var(--mirror-weight-bold);
    margin: 0;
    text-align: end;
}

/* =====================================================================
   Phase 1 screen (4) — Favorites list.
   Ports lib/app/modules/favorites/favorites_screen.dart +
   .../main/tabs/search/view/widgets/service_card.dart.
   Token-only: no literal colour, radius or spacing values.
   ===================================================================== */

/* ListView.separated, 12px gaps — favorites_screen.dart:26-34 */
.portal-favorites-list {
    display: flex;
    flex-direction: column;
    gap: var(--mirror-space-3);
    list-style: none;
    margin: 0;
    padding: 0;
}

.portal-favorite-card {
    align-items: flex-start;
    background: var(--mirror-surface);
    border: 1px solid var(--mirror-line-soft);
    border-radius: var(--mirror-radius-lg);
    display: flex;
    flex-wrap: wrap;
    gap: var(--mirror-space-4);
    justify-content: space-between;
    padding: var(--mirror-space-4);
}

.portal-favorite-card-body {
    display: flex;
    flex-direction: column;
    gap: var(--mirror-space-1);
    min-width: 0;
}

/* Title — service_card.dart:145-154: bold, 2 lines, ellipsis */
.portal-favorite-card-title {
    color: var(--mirror-ink);
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    font-size: var(--mirror-text-sm);
    font-weight: var(--mirror-weight-bold);
    overflow: hidden;
}

/* `subCategory, category` in italics — service_card.dart:269-279 */
.portal-favorite-card-taxonomy {
    color: var(--mirror-body);
    font-size: var(--mirror-text-xs);
    font-style: italic;
}

.portal-favorite-card-provider,
.portal-favorite-card-cities,
.portal-favorite-card-duration {
    color: var(--mirror-hint);
    font-size: var(--mirror-text-xs);
}

.portal-favorite-card-aside {
    align-items: flex-end;
    display: flex;
    flex-direction: column;
    gap: var(--mirror-space-2);
    margin-inline-start: auto;
}

/* Price + AED — service_card.dart:213-221: brand, bold */
.portal-favorite-card-price {
    color: var(--mirror-brand);
    font-size: var(--mirror-text-sm);
    font-weight: var(--mirror-weight-bold);
    white-space: nowrap;
}

.portal-favorite-card-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--mirror-space-2);
}

.portal-account-review-rating {
    /* ROW F (2026-08-25) — ruling F7 (OD-57). The star count used to render on
       `.portal-status-badge--completed`, which is Step-I-closed, byte-pinned at
       portal.css:1018 / :2339 and shared with provider, notifications and deals.
       A RATING IS NOT A STATUS, and the shared class must not be re-scoped, so
       the account surface owns this one instead.

       Same self-alignment reasoning as .portal-account-status-badge: this pill
       sits inside a flex card head, and it hugs its own content by declaration
       rather than by inheritance. */
    display: inline-flex;
    align-items: center;
    align-self: start;
    justify-self: start;
    inline-size: fit-content;
    border-radius: var(--mirror-radius-md);
    padding: var(--mirror-space-1) var(--mirror-space-2);
    font-size: var(--mirror-text-xs);
    font-weight: var(--mirror-weight-bold);
    color: var(--mirror-surface);
    background: var(--mirror-brand);
}

/* =====================================================================
   Phase 1 screen (5) — sidebar legal group.
   Ports lib/app/modules/main/tabs/settings/views/settings_view.dart:78-145.
   ===================================================================== */

.portal-sidebar-group-heading {
    color: var(--mirror-hint);
    font-size: var(--mirror-text-xs);
    font-weight: var(--mirror-weight-semibold);
    letter-spacing: 0.08em;
    margin: var(--mirror-space-5) 0 var(--mirror-space-2);
    text-transform: uppercase;
}

/* =====================================================================
   Phase 3 step A (2026-08-20) — provider sidebar group divider.

   The Flutter provider app splits its navigation into two tiers:
   a 4-item bottom bar (main/views/bottom_bar.dart:29-91) and a drawer
   (home/widget/home_drawer.dart:37-136). The drawer separates its items
   with `HDivider(thickness: 0.5.r)` — it has NO section headings.

   So the web reproduces the tiering with a divider, not with heading
   copy: inventing group labels would be inventing product copy the app
   does not have. Token-based, block-axis margin only, so it is
   direction-agnostic under [dir="rtl"].
   ===================================================================== */

.portal-sidebar-divider {
    border: 0;
    border-top: 1px solid var(--portal-admin-line);
    margin: var(--mirror-space-4) 0;
}

/* =====================================================================
   Phase 3 step B (2026-08-20) — app-faithful provider dashboard.

   Ports the Flutter provider app's home screen:
     · greeting          home_view.dart:31-37
     · stat cards        home_view.dart:39-80 + custom_statistics_card.dart:14-76
     · gallery section   home_view.dart:81-92 + galley_section.dart:37-113
                         + image_galley_card.dart:32-56

   Token-only; no hex literal. Logical properties throughout so the
   whole block mirrors under [dir="rtl"] without a second ruleset.
   ===================================================================== */

/* ── 1. Greeting — 18.sp, mainColor, w700 (home_view.dart:31-37) ───── */
.portal-dashboard-greeting {
    color: var(--mirror-brand);
    font-size: var(--mirror-text-lg);
    font-weight: var(--mirror-weight-bold);
    margin: 0 0 var(--mirror-space-5);
}

/* ── 2. Stat cards ────────────────────────────────────────────────────
   custom_statistics_card.dart:19-24 — RadialGradient(
     colors: mainColorGradient, center: AlignmentDirectional.centerStart,
     radius: 1.5), borderRadius 15.r.
   `circle at start center` is the logical-property equivalent of
   AlignmentDirectional.centerStart, so it flips with direction. */
.portal-stat-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--mirror-space-3);
    margin-bottom: var(--mirror-space-6);
}

.portal-stat-card {
    flex: 0 1 260px;
    position: relative;
    overflow: hidden;
    min-height: 104px;
    padding: var(--mirror-space-4) 20px;
    border-radius: 15px;
    background: radial-gradient(circle at left center,
                var(--mirror-brand) 0%,
                var(--mirror-brand-gradient-end) 150%);
    box-shadow: var(--mirror-shadow-md);
    color: var(--mirror-text-on-brand);
    text-decoration: none;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: var(--mirror-space-2);
}

[dir="rtl"] .portal-stat-card {
    background: radial-gradient(circle at right center,
                var(--mirror-brand) 0%,
                var(--mirror-brand-gradient-end) 150%);
}

.portal-stat-card:hover,
.portal-stat-card:focus-visible {
    color: var(--mirror-text-on-brand);
    text-decoration: none;
    box-shadow: var(--mirror-shadow-lg);
}

/* A1 — the app draws no focus ring; the web must. */
.portal-stat-card:focus-visible {
    outline: 3px solid var(--mirror-brand-light);
    outline-offset: 2px;
}

/* title: 16.sp, bold, letterSpacing 2 (custom_statistics_card.dart:56-62) */
.portal-stat-card-title {
    font-size: var(--mirror-text-md);
    font-weight: var(--mirror-weight-bold);
    letter-spacing: 2px;
    position: relative;
    z-index: 1;
}

/* value: 20.sp (custom_statistics_card.dart:62-67) */
.portal-stat-card-value {
    font-size: var(--mirror-text-lg);
    position: relative;
    z-index: 1;
}

/* watermark — Positioned.directional(bottom: -15.w, end: 0), rotated,
   white at 25%, width 90.w (custom_statistics_card.dart:30-36).
   Assets copied from the frozen Flutter tree (assets/svgs/*.svg). */
.portal-stat-card::after {
    content: "";
    position: absolute;
    inset-block-end: -15px;
    inset-inline-end: 0;
    width: 90px;
    height: 90px;
    opacity: .25;
    transform: rotate(11.25deg);
    background-repeat: no-repeat;
    background-size: contain;
    background-position: center;
    pointer-events: none;
}

.portal-stat-card[data-stat="services"]::after {
    -webkit-mask: url("../provider/svgs/service.svg") no-repeat center / contain;
            mask: url("../provider/svgs/service.svg") no-repeat center / contain;
    background: var(--mirror-text-on-brand);
}

.portal-stat-card[data-stat="employees"]::after {
    -webkit-mask: url("../provider/svgs/employees.svg") no-repeat center / contain;
            mask: url("../provider/svgs/employees.svg") no-repeat center / contain;
    background: var(--mirror-text-on-brand);
}

/* ── 3. Gallery section ──────────────────────────────────────────── */
.portal-dashboard-gallery {
    margin-bottom: var(--mirror-space-6);
}

.portal-dashboard-gallery-head h2 {
    color: var(--mirror-brand);
    font-size: var(--mirror-text-lg);
    font-weight: var(--mirror-weight-bold);
    margin: 0 0 var(--mirror-space-3);
}

.portal-dashboard-gallery-add {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--mirror-space-3);
    margin-bottom: var(--mirror-space-4);
}

.portal-dashboard-gallery-uploading {
    flex: 1 1 160px;
    min-width: 120px;
}

/* carousel — viewportFraction 0.8, enlargeCenterPage + zoom
   (galley_section.dart:37-47). Scroll-snap gives the paging; the
   Alpine `is-centered` class gives the centre-enlarge. */
.portal-gallery-carousel {
    display: flex;
    gap: var(--mirror-space-3);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: 10%;
    padding-block: var(--mirror-space-2);
    -webkit-overflow-scrolling: touch;
}

.portal-gallery-slide {
    position: relative;
    flex: 0 0 80%;           /* viewportFraction: 0.8 */
    max-width: 320px;
    margin: 0;
    scroll-snap-align: center;
    aspect-ratio: 3 / 4;      /* image_galley_card.dart:32 */
    border-radius: var(--mirror-radius-lg);
    overflow: hidden;
    box-shadow: var(--mirror-shadow-sm);
    transform: scale(.9);
    transition: transform .25s ease;
}

.portal-gallery-slide.is-centered {
    transform: scale(1);
    box-shadow: var(--mirror-shadow-md);
}

@media (prefers-reduced-motion: reduce) {
    .portal-gallery-slide { transition: none; }
}

.portal-gallery-slide-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* delete badge — image_galley_card.dart:39-56. The app anchors it with
   a physical `left`, which does not mirror; the web uses the logical
   property so it sits on the trailing edge in both directions. */
.portal-gallery-slide-delete {
    position: absolute;
    inset-block-start: var(--mirror-space-4);
    inset-inline-end: var(--mirror-space-4);
    border: 0;
    border-radius: var(--mirror-radius-pill);
    padding: var(--mirror-space-1) var(--mirror-space-3);
    font-size: var(--mirror-text-xs);
    font-weight: var(--mirror-weight-semibold);
    color: var(--mirror-error-fg);
    background: var(--mirror-error-bg);
    cursor: pointer;
}

.portal-gallery-slide-delete:focus-visible {
    outline: 3px solid var(--mirror-brand);
    outline-offset: 2px;
}

/* filmstrip — galley_section.dart:75-113, 50.r thumbnails */
.portal-gallery-filmstrip {
    display: flex;
    gap: var(--mirror-space-2);
    overflow-x: auto;
    margin-top: var(--mirror-space-3);
}

.portal-gallery-thumb {
    flex: 0 0 auto;
    width: 50px;
    height: 50px;
    padding: 0;
    border: 2px solid transparent;
    border-radius: var(--mirror-radius-md);
    overflow: hidden;
    background: none;
    cursor: pointer;
    opacity: .6;
    transition: opacity .2s ease, border-color .2s ease;
}

.portal-gallery-thumb.is-active {
    opacity: 1;
    border-color: var(--mirror-brand);
}

.portal-gallery-thumb:focus-visible {
    outline: 3px solid var(--mirror-brand);
    outline-offset: 2px;
}

.portal-gallery-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* =====================================================================
   Phase 3 step C (2026-08-20) — salon create + edit form fields.

   The salon form moved from 5 paired <fieldset>/<legend> blocks to a
   FLAT list of 9 labelled controls, matching the app's own structure
   (createsalon_view.dart:23-153 / update_salon_view.dart:26-176 are a
   single Column of 9 CustomTextFormFields). Only the coordinate pair
   stays a fieldset, because it is one logical control until the map
   picker replaces it in step D.

   Sizing/fill/radius are inherited from the existing .portal-salon-form
   rules above, so nothing here restates them.
   ===================================================================== */

.portal-salon-form .salon-field {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    border: none;
    padding: 0;
    margin: 0;
}

.portal-salon-form .salon-field > label {
    font-weight: 700;
    color: var(--portal-ink);
    font-size: 13px;
    letter-spacing: .15px;
}

/* A3 — the app never renders its own required marker even though 8 of
   its 9 salon controls are mandatory.

   G8: --mirror-error (#F44336) measures 3.68:1 on the form card, below
   AA body text. --mirror-error-fg (#991B1B) is the same semantic family,
   is already what the adjacent validation message uses, and measures
   8.31:1. Choosing the compliant token for a NEW element — no token
   value is altered, and E12 stays open and untouched. */
.salon-required {
    color: var(--mirror-error-fg);
    margin-inline-start: 2px;
}

/* A4 — <bdi> isolates the Latin coordinate digits from surrounding RTL
   text. It is inline by default, so it must fill the field row. */
.portal-salon-form bdi {
    display: block;
}

/* =====================================================================
   PHASE 3 STEP D (2026-08-20) — map location picker.  Gap G10.

   Ports lib/app/modules/map/views/map_view.dart:1-64 and its cubit.
   The rendering engine is Leaflet + CartoDB rather than the Maps SDK
   (adaptation A8 / owner decision E4 — no maps key exists and .env is
   frozen); the interaction is the app's, exactly.

   The step-C coordinate-pair rules that used to sit here are gone with
   the control they styled: two typeable inputs were a stand-in for the
   app's single read-only field, and the field now exists.
   ===================================================================== */

/* Alpine hides x-show elements only after it boots. Without this the
   confirm action and the A7 notice flash visible on first paint. */
[x-cloak] {
    display: none !important;
}

/* Present for the accessible name only. The app's map screen has no
   title at all — CustomAppBar receives showBackButton and actions and
   nothing else (map_view.dart:14-17) — so this must not be seen. */
.mirror-visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* The read-only display field. Fill, radius and rhythm are inherited
   from the .portal-salon-form input rules that already dress its eight
   siblings; only the affordance differs.

   No ::placeholder rule is set. --mirror-hint is the app's own field-hint
   colour (constants.dart:13 gray1Color) but measures 2.92:1 on white,
   which is open escalation E7 — and the eight sibling fields Step C
   shipped carry no placeholder rule either. Introducing one here would
   both break with them and quietly add a new sub-AA surface while E7 is
   still undecided. */
.mirror-map-picker__display {
    cursor: pointer;
}

/* G5. The field is direction-pinned to ltr so the coordinate pair cannot be
   reordered by the bidi algorithm under Arabic (§4.4 / A4) — but that pinning
   also drags the Arabic PLACEHOLDER to the leading edge, where it would sit
   out of line with the eight fields above it. While the placeholder is the
   only thing showing there is no coordinate to protect, so the empty state
   aligns with the document and the filled state keeps the pin. */
[dir="rtl"] .mirror-map-picker__display:placeholder-shown {
    text-align: right;
}

/* The app pushes a whole route for the map, so the web equivalent is a
   full-bleed surface rather than a small inline canvas. <dialog> gives
   focus trap, Escape and background inertness from the platform — the
   same mechanism the x-mirror.modal primitive uses. */
.mirror-map-picker__dialog {
    width: min(96vw, 1100px);
    height: min(90vh, 760px);
    max-width: none;
    max-height: none;
    padding: 0;
    border: none;
    border-radius: var(--mirror-radius-lg);
    background: var(--mirror-surface);
    color: var(--mirror-body);
    box-shadow: var(--mirror-shadow-lg);
    overflow: hidden;
}

.mirror-map-picker__dialog::backdrop {
    background: rgba(var(--mirror-brand-rgb), .35);
}

.mirror-map-picker__dialog[open] {
    display: grid;
    grid-template-rows: auto auto 1fr;
}

/* map_view.dart:14-17 — a back arrow leading, the confirm action
   trailing, nothing between them. Logical properties carry the flip. */
.mirror-map-picker__bar {
    display: flex;
    align-items: center;
    gap: var(--mirror-space-2);
    padding: var(--mirror-space-3) var(--mirror-space-4);
    border-block-end: 1px solid var(--mirror-line-soft);
    background: var(--mirror-surface);
}

.mirror-map-picker__spacer {
    flex: 1 1 auto;
}

.mirror-map-picker__back {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 36px;
    block-size: 36px;
    padding: 0;
    border: none;
    border-radius: var(--mirror-radius-pill);
    background: transparent;
    color: var(--mirror-ink);
    cursor: pointer;
}

.mirror-map-picker__back:hover {
    background: var(--mirror-field-fill);
}

/* G5 — the glyph is directional, so it mirrors with the document. */
[dir="rtl"] .mirror-map-picker__back svg {
    transform: scaleX(-1);
}

/* map_view.dart:34-38 — CustomButton(color: Colors.transparent,
   textColor: mainColor, hoveColor: mainColor). */
.mirror-map-picker__confirm {
    border: none;
    background: transparent;
    color: var(--mirror-brand);
    font-weight: var(--mirror-weight-bold);
    font-size: var(--mirror-text-sm);
    padding: var(--mirror-space-2) var(--mirror-space-3);
    border-radius: var(--mirror-radius-button);
    cursor: pointer;
}

.mirror-map-picker__confirm:hover,
.mirror-map-picker__confirm:focus-visible {
    background: var(--mirror-field-fill);
}

/* A7 — the notice sits above the map and the map keeps working. */
.mirror-map-picker__notice {
    display: flex;
    align-items: flex-start;
    gap: var(--mirror-space-2);
    margin: 0;
    border-radius: 0;
}

.mirror-map-picker__notice-dismiss {
    margin-inline-start: auto;
    border: none;
    background: transparent;
    color: inherit;
    font-size: var(--mirror-text-md);
    line-height: 1;
    padding: 0 var(--mirror-space-1);
    cursor: pointer;
}

/* Full-bleed map (map_view.dart:50 fills the Scaffold body). */
.mirror-map-picker__canvas {
    inline-size: 100%;
    block-size: 100%;
    min-block-size: 320px;
    background: var(--mirror-field-fill);
}

.mirror-map-picker__canvas:focus-visible {
    outline: 2px solid var(--mirror-brand);
    outline-offset: -2px;
}

/* myLocationButtonEnabled: true (map_view.dart:57). Google draws it at
   the trailing edge over the map; so does this. */
.mirror-map-picker__locate {
    position: absolute;
    inset-block-end: var(--mirror-space-5);
    inset-inline-end: var(--mirror-space-4);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 40px;
    block-size: 40px;
    padding: 0;
    border: 1px solid var(--mirror-line-soft);
    border-radius: var(--mirror-radius-pill);
    background: var(--mirror-surface);
    color: var(--mirror-ink);
    box-shadow: var(--mirror-shadow-sm);
    cursor: pointer;
    z-index: 500; /* above Leaflet's own panes and controls */
}

.mirror-map-picker__locate[disabled] {
    cursor: progress;
    color: var(--mirror-hint);
}

.mirror-map-picker__locate[aria-busy="true"] svg {
    animation: mirror-map-locate-spin 1s linear infinite;
}

@keyframes mirror-map-locate-spin {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .mirror-map-picker__locate[aria-busy="true"] svg {
        animation: none;
    }
}

/* The pin is a plain image and must never look interactive: the app's
   marker is not draggable (map_cubit.dart:55-59). */
.mirror-map-picker__pin {
    cursor: default;
}

/* =====================================================================
   PHASE 3 STEP E (2026-08-20) — the working-hours VERTICAL STEPPER.

   Ports lib/app/modules/working_hours/widgets/vertical_stepper.dart.
   The flat 7-row table and its comma-separated holidays field are gone;
   the rules that dressed them went with them.

   The stepper stays TOP-TO-BOTTOM under Arabic — this is the app's best
   RTL surface and the web matches it. Only the horizontal alignment
   flips, and it does so through logical properties.
   ===================================================================== */

.portal-working-hours-stepper {
    list-style: none;
    margin: 0;
    padding: 0;
    display: block;
}

.portal-step {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: var(--mirror-space-3);
}

/* The rail: a state dot with a connector running to the next step. */
.portal-step-rail {
    display: flex;
    flex-direction: column;
    align-items: center;
    /* Block axis, so the rail never flips side under RTL — the grid
       column order does that on its own. */
    padding-block-start: var(--mirror-space-2);
}

.portal-step-dot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 26px;
    block-size: 26px;
    border-radius: var(--mirror-radius-pill);
    font-size: var(--mirror-text-xs);
    font-weight: var(--mirror-weight-bold);
    line-height: 1;
    border: 1px solid var(--mirror-line);
    background: var(--mirror-surface);
    color: var(--mirror-body);
}

.portal-step-connector {
    flex: 1 1 auto;
    inline-size: 2px;
    min-block-size: 12px;
    background: var(--mirror-line-soft);
    margin-block: var(--mirror-space-1);
}

/* vertical_stepper.dart:493-516 — the step state drives the dot AND the
   label colour: green when complete, black when current, grey when not
   yet reached.

   The "not yet reached" grey is the ONE colour not reproduced. The app
   uses Colors.grey (#9E9E9E), which measures ~2.85:1 on white — the same
   sub-AA territory as open escalation E7, and step D established that a
   new sub-AA text surface is not introduced while E7 is open. The step
   state is still fully conveyed, by the dot, the connector and
   aria-current. No token value was changed and E7 stays open. */
.portal-step.is-complete .portal-step-dot {
    background: var(--mirror-success-fg);
    border-color: var(--mirror-success-fg);
    color: var(--mirror-text-on-brand);
}

.portal-step.is-complete .portal-step-header {
    color: var(--mirror-success-fg);
}

.portal-step.is-complete .portal-step-connector {
    background: var(--mirror-success-fg);
}

.portal-step.is-current .portal-step-dot {
    background: var(--mirror-brand);
    border-color: var(--mirror-brand);
    color: var(--mirror-text-on-brand);
}

.portal-step.is-current .portal-step-header {
    color: var(--mirror-ink);
    font-weight: var(--mirror-weight-bold);
}

.portal-step.is-upcoming .portal-step-header {
    color: var(--mirror-body);
    font-weight: var(--mirror-weight-regular);
}

.portal-step-body {
    padding-block-end: var(--mirror-space-2);
    min-inline-size: 0;
}

/* :449 — the whole header is the tap target that jumps to that day. */
.portal-step-header {
    display: block;
    inline-size: 100%;
    text-align: start;
    padding: var(--mirror-space-2) 0;
    border: none;
    background: transparent;
    font-size: var(--mirror-text-md);
    cursor: pointer;
}

.portal-step-header:focus-visible {
    outline: 2px solid var(--mirror-brand);
    outline-offset: 2px;
    border-radius: var(--mirror-radius-sm);
}

/* Only the active step's content is expanded (:506-510). */
.portal-step-panel {
    display: grid;
    gap: var(--mirror-space-2);
    padding-block: var(--mirror-space-2) var(--mirror-space-4);
}

.portal-step-question {
    margin: 0;
    color: var(--mirror-ink);
    font-size: var(--mirror-text-sm);
}

/* :546-558 — MainAxisAlignment.spaceBetween: label at the leading edge,
   switch at the trailing edge. */
.portal-step-toggle-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--mirror-space-3);
}

.portal-step-toggle-row > label {
    font-size: var(--mirror-text-sm);
    color: var(--mirror-body);
}

/* custom_switch.dart:16-27 — a CupertinoSwitch, brand when on. Its
   inactive track is #D5D5D5, which has no token; --mirror-disabled
   (#D9D9D9) is the same role and within 2% of it, so no second
   near-identical token is minted. */
.portal-switch {
    appearance: none;
    -webkit-appearance: none;
    flex: 0 0 auto;
    inline-size: 46px;
    block-size: 28px;
    margin: 0;
    border: none;
    border-radius: var(--mirror-radius-pill);
    background: var(--mirror-disabled);
    position: relative;
    cursor: pointer;
    transition: background-color .15s ease-in-out;
}

.portal-switch::after {
    content: "";
    position: absolute;
    inset-block-start: 2px;
    inset-inline-start: 2px;
    inline-size: 24px;
    block-size: 24px;
    border-radius: var(--mirror-radius-pill);
    background: var(--mirror-surface);
    box-shadow: var(--mirror-shadow-sm);
    transition: inset-inline-start .15s ease-in-out;
}

.portal-switch:checked {
    background: var(--mirror-brand);
}

.portal-switch:checked::after {
    inset-inline-start: 20px;
}

.portal-switch:focus-visible {
    outline: 2px solid var(--mirror-brand);
    outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
    .portal-switch,
    .portal-switch::after {
        transition: none;
    }
}

/* :563-600 — both labels on one row above both fields, equal widths,
   16px between the columns. */
.portal-step-times {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: var(--mirror-space-4);
    row-gap: var(--mirror-space-1);
    align-items: center;
}

.portal-step-times > label {
    font-size: var(--mirror-text-sm);
    color: var(--mirror-body);
}

/* :643-658 — height 50, Colors.blueGrey border, radius 8, centred. This
   is the app's actual appearance and is ported as-is, even though it is
   off-system for the rest of the product. */
.portal-time-box {
    block-size: 50px;
    padding: var(--mirror-space-2) var(--mirror-space-3);
    border: 1px solid var(--mirror-blue-grey);
    border-radius: var(--mirror-radius-md);
    background: var(--mirror-surface);
    color: var(--mirror-ink);
    font-size: var(--mirror-text-md);
    text-align: center;
    inline-size: 100%;
}

.portal-time-box:focus-visible {
    outline: 2px solid var(--mirror-brand);
    outline-offset: 1px;
}

/* :601-619 — inline, red, directly under the two controls, aligned to
   the reading edge. */
.portal-step-error {
    margin: 0;
    color: var(--mirror-error-fg);
    font-size: var(--mirror-text-sm);
    text-align: start;
}

/* :700-722 — Continue leading, Cancel after it. */
.portal-step-controls {
    display: flex;
    flex-wrap: wrap;
    gap: var(--mirror-space-2);
    padding-block-start: var(--mirror-space-2);
}

.portal-step-continue,
.portal-step-cancel {
    padding: var(--mirror-space-3) var(--mirror-space-4);
    border-radius: var(--mirror-radius-button-dense);
    font-size: var(--mirror-text-sm);
    font-weight: var(--mirror-weight-semibold);
    cursor: pointer;
}

.portal-step-continue {
    border: 1px solid var(--mirror-brand);
    background: var(--mirror-brand);
    color: var(--mirror-text-on-brand);
}

.portal-step-cancel {
    border: 1px solid var(--mirror-brand);
    background: transparent;
    color: var(--mirror-brand);
}

.portal-step-continue[disabled],
.portal-step-cancel[disabled] {
    opacity: .6;
    cursor: progress;
}

/* working_hours_screen.dart:29 — the submit lives below the stepper, not
   inside it, and is absent unless there are unsaved, valid changes. */
.portal-working-hours-submit {
    margin-block-start: var(--mirror-space-4);
}

.portal-working-hours-submit .portal-flash {
    margin: 0;
}

/* =====================================================================
   PHASE 3 STEP F (2026-08-20) — blocked times.  Gap G11.

   Ports lib/app/modules/service_form_view/widgets/tab_bar_widget.dart
   and .../block_times_tab.dart. Every colour resolves through a token;
   where the app uses an off-system Material shade the nearest existing
   semantic token is used and the substitution is noted inline.
   ===================================================================== */

/* tab_bar_widget.dart:15-25 — indicator and label in the brand colour,
   unselected labels grey. */
.portal-tablist {
    display: flex;
    gap: var(--mirror-space-5);
    border-block-end: 1px solid var(--mirror-line-soft);
    margin-block-end: var(--mirror-space-4);
}

.portal-tab {
    position: relative;
    padding: var(--mirror-space-3) var(--mirror-space-1);
    border: none;
    background: transparent;
    font-size: var(--mirror-text-sm);
    font-weight: var(--mirror-weight-semibold);
    cursor: pointer;
    /* The app's unselected label is Colors.grey (~2.85:1 on white). That is
       open escalation E7's territory, and step D established that no new
       sub-AA text surface is introduced while E7 is open, so the recessive
       state is carried by weight and by the missing indicator instead. */
    color: var(--mirror-body);
}

.portal-tab.is-active {
    color: var(--mirror-brand);
    font-weight: var(--mirror-weight-bold);
}

/* indicatorColor: Constants.mainColor */
.portal-tab.is-active::after {
    content: "";
    position: absolute;
    inset-inline: 0;
    inset-block-end: -1px;
    block-size: 2px;
    background: var(--mirror-brand);
}

.portal-tab:focus-visible {
    outline: 2px solid var(--mirror-brand);
    outline-offset: 2px;
    border-radius: var(--mirror-radius-sm);
}

/* block_times_tab.dart:34-55 — heading leading, Add New trailing. */
.block-times__bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--mirror-space-3);
    flex-wrap: wrap;
    padding-block: var(--mirror-space-3);
}

.block-times__heading {
    margin: 0;
    color: var(--mirror-brand);
    font-size: var(--mirror-text-lg);
    font-weight: var(--mirror-weight-bold);
}

/* :49-51 — height 42, radius 8. */
.block-times__add {
    min-block-size: 42px;
    border-radius: var(--mirror-radius-md);
    padding-inline: var(--mirror-space-4);
}

/* :70-75 — a calendar glyph at 100x100, tinted grey. The asset is the
   app's OWN assets/svgs/calender.svg, copied read-only; the mask lets a
   token colour it, which is what SvgWidget(color:) does in the app. */
.block-times__glyph {
    display: block;
    inline-size: 100px;
    block-size: 100px;
    background: var(--mirror-line);
    -webkit-mask: url("../provider/svgs/calender.svg") no-repeat center / contain;
            mask: url("../provider/svgs/calender.svg") no-repeat center / contain;
}

/* :77-93 — a heading and a hint, both centred, the hint smaller. */
.block-times__empty-title,
.block-times__empty-hint {
    display: block;
    text-align: center;
}

.block-times__empty-title {
    font-size: var(--mirror-text-md);
    color: var(--mirror-body);
}

.block-times__empty-hint {
    margin-block-start: var(--mirror-space-2);
    font-size: var(--mirror-text-sm);
    color: var(--mirror-body);
}

.block-times__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: var(--mirror-space-2);
}

/* :115-124 — radius 12, elevation 2, tinted by state. The app's
   green.shade50 / red.shade50 are the same role as the semantic
   background tokens, which is what they resolve to here. */
.block-time {
    display: flex;
    align-items: center;
    gap: var(--mirror-space-3);
    padding: var(--mirror-space-2) var(--mirror-space-4);
    border-radius: var(--mirror-radius-lg);
    box-shadow: var(--mirror-shadow-sm);
    background: var(--mirror-surface);
}

.block-time.is-new {
    background: var(--mirror-success-bg);
}

.block-time.is-marked {
    background: var(--mirror-error-bg);
}

/* :126-140 — a tinted circle carrying the state icon. */
.block-time__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    inline-size: 40px;
    block-size: 40px;
    border-radius: var(--mirror-radius-pill);
    background: rgba(var(--mirror-brand-rgb), .1);
    color: var(--mirror-brand);
}

.block-time.is-new .block-time__icon {
    background: var(--mirror-success-bg);
    color: var(--mirror-success-fg);
}

.block-time.is-marked .block-time__icon {
    background: var(--mirror-error-bg);
    color: var(--mirror-error-fg);
}

.block-time__body {
    flex: 1 1 auto;
    min-inline-size: 0;
}

/* :143-151 — the date, bold, 15sp. */
.block-time__date {
    display: flex;
    align-items: center;
    gap: var(--mirror-space-2);
    margin: 0;
    font-size: 15px;
    font-weight: var(--mirror-weight-bold);
    color: var(--mirror-ink);
}

/* :187-193 — the time, brand coloured, 14sp. */
.block-time__time {
    margin: 0;
    font-size: var(--mirror-text-sm);
    color: var(--mirror-brand);
}

/* :149, :192 — a slot queued for removal is struck through, date and
   time alike. A NEW slot never is. */
.block-time.is-marked .block-time__date > bdi,
.block-time.is-marked .block-time__time > bdi {
    text-decoration: line-through;
}

/* :154-184 — a filled pill. The app fills with Colors.green / Colors.red
   and writes white on top; --mirror-success (#14D176) would measure about
   1.9:1 that way, so the -fg tokens of the same families carry the fill.
   No token value is altered. */
.block-time__badge {
    flex: 0 0 auto;
    padding: 2px var(--mirror-space-2);
    border-radius: var(--mirror-radius-pill);
    font-size: var(--mirror-text-xs);
    font-weight: var(--mirror-weight-bold);
    line-height: 1.4;
    color: var(--mirror-text-on-brand);
}

.block-time__badge.is-new {
    background: var(--mirror-success-fg);
}

.block-time__badge.is-remove {
    background: var(--mirror-error-fg);
}

/* :195-201 — the trailing control: delete, or restore once queued. */
.block-time__action {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 40px;
    block-size: 40px;
    border: none;
    border-radius: var(--mirror-radius-pill);
    background: transparent;
    color: var(--mirror-error-fg);
    cursor: pointer;
}

.block-time.is-marked .block-time__action {
    color: var(--mirror-success-fg);
}

.block-time__action:hover {
    background: rgba(var(--mirror-brand-rgb), .06);
}

.block-time__action:focus-visible {
    outline: 2px solid var(--mirror-brand);
    outline-offset: 2px;
}

.block-time__action[disabled] {
    cursor: progress;
    opacity: .6;
}

/* date_time_picker.dart:6-59 — the two-stage picker. Same platform
   mechanism as the map picker: a native <dialog>. */
.mirror-slot-picker {
    inline-size: min(92vw, 420px);
    max-width: none;
    padding: var(--mirror-space-5);
    border: none;
    border-radius: var(--mirror-radius-lg);
    background: var(--mirror-surface);
    color: var(--mirror-body);
    box-shadow: var(--mirror-shadow-lg);
}

.mirror-slot-picker::backdrop {
    background: rgba(var(--mirror-brand-rgb), .35);
}

.mirror-slot-picker__title {
    margin: 0 0 var(--mirror-space-4);
    font-size: var(--mirror-text-md);
    font-weight: var(--mirror-weight-bold);
    color: var(--mirror-ink);
}

.mirror-slot-picker__body {
    display: grid;
    gap: var(--mirror-space-3);
}

.mirror-slot-picker__field {
    display: block;
}

.mirror-slot-picker__actions {
    display: flex;
    gap: var(--mirror-space-2);
    justify-content: flex-end;
    padding-block-start: var(--mirror-space-4);
}

.mirror-slot-picker__confirm,
.mirror-slot-picker__cancel {
    padding: var(--mirror-space-3) var(--mirror-space-4);
    border-radius: var(--mirror-radius-button-dense);
    font-size: var(--mirror-text-sm);
    font-weight: var(--mirror-weight-semibold);
    cursor: pointer;
}

.mirror-slot-picker__confirm {
    border: 1px solid var(--mirror-brand);
    background: var(--mirror-brand);
    color: var(--mirror-text-on-brand);
}

.mirror-slot-picker__confirm[disabled] {
    opacity: .5;
    cursor: not-allowed;
}

.mirror-slot-picker__cancel {
    border: 1px solid var(--mirror-brand);
    background: transparent;
    color: var(--mirror-brand);
}

.portal-service-save {
    margin-block-start: var(--mirror-space-5);
}

/* =====================================================================
   PHASE 3 STEP G (2026-08-20) — the services CARD GRID.  Gap G15.

   Ports lib/app/modules/services/view/services_view.dart:34-160. The
   5-column table is gone. Every colour resolves through a token.
   ===================================================================== */

/* :36-43 — crossAxisCount 2, childAspectRatio 3/4, 8px spacing. The web
   widens past two columns where the viewport allows it, because a
   desktop document is not a phone screen; the CARD is what the parity
   ruling is about, and it keeps the app's 3:4 proportion exactly. */
.portal-service-grid {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--mirror-space-2);
}

@media (min-width: 900px) {
    .portal-service-grid {
        grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    }
}

/* :64-78 — white, radius 8, a soft shadow offset (0,2), clipped. */
.portal-service-card {
    position: relative;
    display: flex;
    flex-direction: column;
    aspect-ratio: 3 / 4;
    overflow: hidden;
    border-radius: var(--mirror-radius-md);
    background: var(--mirror-surface);
    box-shadow: var(--mirror-shadow-sm);
}

/* :83-91 — Expanded: the image takes every pixel the text does not. */
.portal-service-card__media {
    position: relative;
    flex: 1 1 auto;
    min-block-size: 0;
    background: var(--mirror-field-fill);
}

.portal-service-card__image {
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    display: block;
}

/* :93-121 — Positioned.directional(top: 5, end: 5): a circular plate at
   half opacity carrying the delete icon. `end` is the trailing edge, so
   it flips with the document — inset-inline-end does exactly that. */
.portal-service-card__delete {
    position: absolute;
    inset-block-start: 5px;
    inset-inline-end: 5px;
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 36px;
    block-size: 36px;
    padding: 0;
    border: none;
    border-radius: var(--mirror-radius-pill);
    /* Colors.white.withOpacity(0.5) — expressed through the surface token
       rather than a literal, so nothing new is minted. */
    background: color-mix(in srgb, var(--mirror-surface) 50%, transparent);
    /* :115 passes `color: null`, i.e. the ambient icon theme — NOT red. The
       blocked-times row control in step F sets Colors.red explicitly; this one
       deliberately does not, so it stays ink. */
    color: var(--mirror-ink);
    cursor: pointer;
}

.portal-service-card__delete:hover {
    background: var(--mirror-surface);
}

.portal-service-card__delete:focus-visible {
    outline: 2px solid var(--mirror-brand);
    outline-offset: 2px;
}

/* :126-127 — 8px of padding around the text column. */
.portal-service-card__body {
    flex: 0 0 auto;
    padding: var(--mirror-space-2);
    display: grid;
    gap: var(--mirror-space-1);
}

/* :132-135 — titleMedium. */
.portal-service-card__title {
    margin: 0;
    font-size: var(--mirror-text-md);
    font-weight: var(--mirror-weight-medium);
    color: var(--mirror-ink);
}

/* :62 — the whole card opens the service form. A stretched link keeps
   that true without nesting the delete control inside an anchor, which
   would be invalid markup and would swallow its clicks. */
.portal-service-card__link {
    color: inherit;
    text-decoration: none;
}

.portal-service-card__link::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
}

.portal-service-card__link:focus-visible::after {
    outline: 2px solid var(--mirror-brand);
    outline-offset: -2px;
    border-radius: var(--mirror-radius-md);
}

/* :137-151 — bodySmall for the description and the two meta lines. */
.portal-service-card__description,
.portal-service-card__meta {
    margin: 0;
    font-size: var(--mirror-text-xs);
    color: var(--mirror-body);
}

.portal-service-card__description {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* :163-181 — EmptyDataWidget: the illustration at 30% of screen height,
   then the caption. The asset keeps its own palette (the app passes
   color: null at :172), so it is a plain image and not a mask. */
.services-empty__art {
    inline-size: auto;
    max-inline-size: 100%;
    block-size: clamp(160px, 30vh, 300px);
}

.services-pagination.is-busy {
    opacity: .6;
    cursor: progress;
}

/* =====================================================================
   PHASE 3 STEP H (2026-08-21) — staff CARD LIST + gallery states.

   Staff ports lib/app/modules/employee/view/widgets/single_employee_list.dart
   :12-75 and employees_view.dart:40-51. The 4-column table is gone, under the
   owner's 2026-08-21 scope correction (see the blade header).

   Every colour resolves through a token. Two token-scale roundings are
   recorded once here rather than minting one-off values: the app's card radius
   is 10 and its row separator is 10, and the design scale steps 8 / 12 either
   side of both. The nearer sibling value is used so the two provider card
   surfaces share a corner.
   ===================================================================== */

/* :40-44 — ListView.separated, 10 between rows, 12/4 page padding. */
.portal-employee-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--mirror-space-3);
}

/* :13-19 — mainColor at 10% opacity, radius 10, padding h12 v8. The tint is
   expressed with the channel-form brand token, so no literal is introduced. */
.portal-employee-card {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--mirror-space-3);
    padding: var(--mirror-space-2) var(--mirror-space-3);
    border-radius: var(--mirror-radius-md);
    background: rgba(var(--mirror-brand-rgb), .1);
}

/* :21-33 — Container(shape: circle, color: white) clipping the photo at
   15% of the screen width. --mirror-avatar-employee is the design system's
   existing app-derived avatar box. */
.portal-employee-card__avatar {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    inline-size: var(--mirror-avatar-employee);
    block-size: var(--mirror-avatar-employee);
    border-radius: var(--mirror-radius-pill);
    background: var(--mirror-surface);
    overflow: hidden;
}

.portal-employee-card__avatar img {
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    display: block;
}

/* :35-56 — Expanded > Column. The Column passes no crossAxisAlignment, so
   Flutter centres both lines; reproduced rather than corrected. */
.portal-employee-card__body {
    flex: 1 1 auto;
    min-inline-size: 0;
    display: grid;
    gap: var(--mirror-space-1);
    justify-items: center;
    text-align: center;
}

/* :38-42 — 16.sp. The app paints this Colors.black; the design system has no
   black token and --mirror-ink is the ported heading colour used by every
   other card title, so it is used here too. */
.portal-employee-card__link {
    margin: 0;
    font-size: var(--mirror-text-md);
    color: var(--mirror-ink);
    text-decoration: none;
    max-inline-size: 100%;
    overflow-wrap: anywhere;
}

/* :45-49 — the whole row opens the employee form. A stretched link keeps that
   true without nesting the delete control inside an anchor. */
.portal-employee-card__link::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
}

.portal-employee-card__link:focus-visible::after {
    outline: 2px solid var(--mirror-brand);
    outline-offset: -2px;
    border-radius: var(--mirror-radius-md);
}

/* :44-53 — the locale-resolved job title: mainColor, bold, 12.sp. */
.portal-employee-card__job {
    font-size: var(--mirror-text-xs);
    font-weight: var(--mirror-weight-bold);
    color: var(--mirror-brand);
    max-inline-size: 100%;
    overflow-wrap: anywhere;
}

/* :58-71 — the trailing IconButton. The app passes no colour, i.e. the ambient
   icon theme, so this is ink and NOT red — same finding as step G's card
   overlay; step F's red control sets Colors.red explicitly. */
.portal-employee-card__delete {
    position: relative;
    z-index: 2;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 36px;
    block-size: 36px;
    padding: 0;
    border: none;
    border-radius: var(--mirror-radius-pill);
    background: transparent;
    color: var(--mirror-ink);
    cursor: pointer;
}

.portal-employee-card__delete:hover {
    background: var(--mirror-surface);
}

.portal-employee-card__delete:focus-visible {
    outline: 2px solid var(--mirror-brand);
    outline-offset: 2px;
}

.employees-pagination.is-busy {
    opacity: .6;
    cursor: progress;
}

/* employees_placeholder.dart:11-23 — the illustration at 30% of screen height.
   no_employees.svg is the only 750x500 asset of the three; the square ones are
   500x500. Height-driven sizing keeps both honest. */
.employees-empty__art,
.gallery-empty__art {
    inline-size: auto;
    max-inline-size: 100%;
    block-size: clamp(160px, 30vh, 300px);
}

/* Phase 3 step H — the two live upload paths finally show their transfer.
   Mirrors .portal-dashboard-gallery-uploading, shipped in step B. */
.portal-gallery-uploading,
.portal-employee-uploading {
    margin-block-start: var(--mirror-space-2);
    max-inline-size: 320px;
}

/* ⚠️ Collision repair. `.portal-gallery-thumb` is declared twice at equal
   specificity: portal.css:735 (this page's <img>) and portal.css:4455 (step
   B's dashboard filmstrip <button>). The later rule won, so since step B every
   image on /provider/gallery rendered at 50x50, opacity .6, with a 2px
   transparent border. The standalone page's image now carries its own class;
   the body is the pre-step-B one, unchanged. */
.portal-gallery-image {
    max-inline-size: 100%;
    block-size: auto;
    border-radius: var(--radius-soft);
    display: block;
    margin-inline: auto;
}

.portal-gallery-item__delete {
    margin-block-start: var(--mirror-space-2);
}

/* ============================================================
   PHASE 3 STEP I — provider bookings list states.
   Class names grepped against this whole sheet before adding
   (Step B/H .portal-gallery-thumb collision): both were absent.
   ============================================================ */

/* The app's two empty states differ only in illustration size:
   the global one is 0.5 of the shortest side (bookings_screen.dart:96-98),
   the per-tab one is 0.3 (`:139-141`). Same copy on both. */
.portal-bookings-empty .mirror-empty__media { width: 50%; max-width: 260px; }
.portal-bookings-empty--tab .mirror-empty__media { width: 30%; max-width: 160px; }

/* Scoped loading placeholder for filter / tab round-trips. */
.portal-bookings-loading {
    display: none;
    flex-direction: column;
    gap: var(--mirror-space-3, 12px);
    padding: var(--mirror-space-4, 16px) 0;
}

/* ═══════════════════════════════════════════════════════════════════
   PHASE 3 STEP J — provider profile (/provider/profile) · G14
   Ports profile/views/profile_view.dart (:14-245) and the drawer's
   header user card (home_drawer.dart:182-250).

   ⚠️ Every class here is namespaced `portal-provider-profile-*`.
   `.portal-profile-*` was ALREADY TAKEN by the account surface and is
   itself declared twice (:1481 and :2673) — the same duplicate shape
   as the §6.11 .portal-gallery-thumb trap. Grepped clean before use.

   G2: no new hex literals. The app paints the delete control with
   `Colors.red` (profile_view.dart:143-149). Reproduced as
   --mirror-error for the 2px BORDER (non-text, needs 3:1) and
   --mirror-error-fg for the LABEL — the same standing mitigation the
   phase applies to the app's recessive greys: never reproduce a
   sub-AA colour for text.
   ═══════════════════════════════════════════════════════════════════ */

.portal-provider-profile-form {
    display: flex;
    flex-direction: column;
    gap: var(--mirror-space-3, 12px);
    max-width: 640px;
}

/* 1. Avatar picker — circular, 25% of the container width
      (profile_view.dart:51-53). */
.portal-provider-profile-avatar {
    display: flex;
    align-items: center;
    gap: var(--mirror-space-4, 16px);
    margin-bottom: var(--mirror-space-4, 16px);
}

.portal-provider-profile-avatar-frame {
    flex: 0 0 auto;
    width: 25%;
    min-width: 88px;
    max-width: 120px;
    aspect-ratio: 1 / 1;
    border-radius: var(--mirror-radius-pill, 999px);
    background: var(--mirror-field-fill);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.portal-provider-profile-avatar-image {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* The app centres images.svg at 10% of screen width inside a 25% circle
   — i.e. 40% of the avatar (profile_view.dart:60-64). Masked rather than
   <img> because the asset carries its own #141B34/#000000 fills and the
   app recolours it; same technique as the dashboard stat cards (:4374). */
.portal-provider-profile-avatar-placeholder {
    width: 40%;
    height: 40%;
    -webkit-mask: url("../provider/svgs/images.svg") no-repeat center / contain;
            mask: url("../provider/svgs/images.svg") no-repeat center / contain;
    /* G8: --mirror-hint on --mirror-field-fill measures 2.68:1, BELOW the
       3:1 non-text floor — it would have been a NEW sub-AA occurrence, and
       Step I's discipline is not to introduce one. --mirror-body is 10.27:1 on the field fill (and higher on white)
       and is ALSO closer to the app, which renders images.svg in its own
       near-black with no colour override (profile_view.dart:60-64). */
    background: var(--mirror-body);
}

.portal-provider-profile-photo-field {
    flex: 1 1 auto;
    min-width: 0;
}

.portal-provider-profile-uploading {
    margin-top: var(--mirror-space-2, 8px);
}

/* Delete THEN update — the app's own order (profile_view.dart:129-181). */
.portal-provider-profile-actions {
    display: flex;
    flex-direction: column;
    gap: var(--mirror-space-3, 12px);
    margin-top: var(--mirror-space-5, 24px);
}

.portal-provider-profile-delete,
.portal-provider-profile-submit {
    min-height: 48px;
    border-radius: var(--mirror-radius-button, 999px);
    font-size: var(--mirror-text-sm, 14px);
    font-weight: 600;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--mirror-space-2, 8px);
    width: 100%;
}

.portal-provider-profile-delete {
    background: transparent;
    border: 2px solid var(--mirror-error);
    color: var(--mirror-error-fg);
}

.portal-provider-profile-delete-icon {
    width: 24px;
    height: 24px;
    flex: 0 0 auto;
    -webkit-mask: url("../provider/svgs/trash.svg") no-repeat center / contain;
            mask: url("../provider/svgs/trash.svg") no-repeat center / contain;
    background: var(--mirror-error-fg);
}

.portal-provider-profile-submit {
    background: var(--mirror-brand);
    border: 2px solid var(--mirror-brand);
    color: var(--mirror-text-on-brand);
}

.portal-provider-profile-submit[disabled] {
    opacity: .6;
    cursor: default;
}

/* The reason field inside the delete dialog. */
.portal-provider-profile-reason {
    margin-block: var(--mirror-space-3, 12px);
    text-align: start;
}

.portal-provider-profile-reason textarea {
    width: 100%;
    border-radius: var(--mirror-radius-input, 12px);
    background: var(--mirror-field-fill);
    border: 1px solid var(--mirror-field-fill);
    padding: var(--mirror-space-3, 12px);
    font: inherit;
    resize: vertical;
}

/* ⚠️ REVERSE-PARITY — the app has no password/2FA/sessions screen.
   Owner ruling OD-1(a): link out to the pre-existing Jetstream surface
   instead of redirecting it away. Appended after the app's own IA. */
.portal-provider-profile-security {
    margin-top: var(--mirror-space-6, 32px);
    padding-top: var(--mirror-space-4, 16px);
    border-top: 1px solid var(--mirror-field-fill);
    max-width: 640px;
}

.portal-provider-profile-security h2 {
    font-size: var(--mirror-text-md, 16px);
    margin: 0 0 var(--mirror-space-2, 8px);
}

.portal-provider-profile-security p {
    margin: 0 0 var(--mirror-space-2, 8px);
}

/* ── The sidebar user card — the app's drawer header
      (home_drawer.dart:182-250), NOT a nav row. ────────────────────── */
/* ⚠️ Scoped to `.portal-sidebar a` on purpose. The card IS an <a> inside
   the sidebar, so without this it inherits `.portal-sidebar a` (:1916) and,
   on /provider/profile itself, `.portal-sidebar a.is-active` (:1939) —
   which paints a brand pill and white text. That turned the brand-coloured
   name into brand-on-brand and made it INVISIBLE; caught in the first
   runtime capture, not shipped. The app's card sits on white with a
   brand-coloured name and a brand badge (home_drawer.dart:206-228), and the
   app has no active state for it at all. These selectors match the
   specificity of the sidebar rules (0,2,1) and win on order. */
.portal-sidebar a.portal-provider-profile-card,
.portal-sidebar a.portal-provider-profile-card.is-active,
.portal-sidebar a.portal-provider-profile-card[aria-current="page"] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--mirror-space-2, 8px);
    padding: var(--mirror-space-4, 16px) var(--mirror-space-3, 12px);
    margin-bottom: var(--mirror-space-5, 24px);
    text-decoration: none;
    text-align: center;
    background: transparent;
    color: inherit;
    box-shadow: none;
    border-radius: 0;
}

.portal-provider-profile-card-avatar {
    width: 72px;
    height: 72px;
    border-radius: var(--mirror-radius-pill, 999px);
    background: var(--mirror-surface);
    box-shadow: 0 0 8px rgba(var(--mirror-brand-rgb), .25);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.portal-provider-profile-card-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.portal-provider-profile-card-placeholder {
    width: 40%;
    height: 40%;
    -webkit-mask: url("../provider/svgs/images.svg") no-repeat center / contain;
            mask: url("../provider/svgs/images.svg") no-repeat center / contain;
    /* G8: --mirror-hint on --mirror-field-fill measures 2.68:1, BELOW the
       3:1 non-text floor — it would have been a NEW sub-AA occurrence, and
       Step I's discipline is not to introduce one. --mirror-body is 10.27:1 on the field fill (and higher on white)
       and is ALSO closer to the app, which renders images.svg in its own
       near-black with no colour override (profile_view.dart:60-64). */
    background: var(--mirror-body);
}

.portal-provider-profile-card-name {
    font-size: var(--mirror-text-md, 16px);
    font-weight: 500;
    color: var(--mirror-brand);
    overflow-wrap: anywhere;
}

.portal-provider-profile-card-type {
    font-size: var(--mirror-text-xs, 12px);
    background: var(--mirror-brand);
    color: var(--mirror-text-on-brand);
    border-radius: var(--mirror-radius-md, 8px);
    padding: 4px 6px;
}

.portal-sidebar a.portal-provider-profile-card.is-active .portal-provider-profile-card-name,
.portal-sidebar a.portal-provider-profile-card[aria-current="page"] .portal-provider-profile-card-name {
    text-decoration: underline;
}
