﻿/* PMS — global app CSS.
   ADR-0064: colours ALWAYS through var(--mud-palette-*) generated by MudBlazor from
   PmsTheme.cs — never a literal hex. Dark mode is automatic (PaletteDark), no overrides.
   Documented exceptions: .pms-splash and #blazor-error-ui render BEFORE the Blazor boot
   (the theme vars do not exist yet) -> literal hex with a conscious fallback.
   Shadows use a literal rgba per level (doc 03 §1.4) — they are not palette tokens. */

html, body {
    margin: 0;
    padding: 0;
    font-family: 'Alexandria', 'Segoe UI', Roboto, Arial, sans-serif;
    background: var(--mud-palette-background, #F6F8FB);
    color: var(--mud-palette-text-primary, #1F2933);
}

a { text-decoration: none; }

/* Boot splash — PRE-BOOT (vars unavailable) + brand territory (ADR-0064 decision 3):
   the gradient and LEMON MILK are identity, not UI. Hex allowed here by exception. */
.pms-splash {
    position: fixed;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 16px;
    background: linear-gradient(135deg, #1C355E 0%, #236092 55%, #4197CB 100%);
    color: white;
    font-family: 'LEMON MILK', 'Archivo Black', 'Alexandria', sans-serif;
    letter-spacing: 0.08em;
    z-index: 9999;
}
.pms-splash img { width: 96px; height: 96px; }
.pms-splash .spinner {
    width: 28px; height: 28px;
    border: 3px solid rgba(255,255,255,0.35);
    border-top-color: #FFFFFF;
    border-radius: 50%;
    animation: pms-spin 0.9s linear infinite;
}
@keyframes pms-spin { to { transform: rotate(360deg); } }

/* Error UI override (Blazor default) — it can render with a broken runtime (vars
   unavailable) -> literal hex by exception; the tone matches the theme Error. */
#blazor-error-ui {
    background: #B3261E;
    color: #fff;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0,0,0,0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}
#blazor-error-ui .dismiss { cursor: pointer; position: absolute; right: 0.75rem; top: 0.5rem; }

/* Login card — LEMON MILK in the h1 is brand territory (login/splash, ADR-0064);
   colours come from the theme (the page renders with the MudThemeProvider active). */
.login-card {
    width: 100%;
    max-width: 420px;
    padding: 40px 36px 32px 36px;
    border-radius: 16px;
    background: var(--mud-palette-surface);
    box-shadow: 0 20px 40px rgba(28, 53, 94, 0.25);
}
.login-card .login-logo {
    width: 96px; height: 96px;
    display: block;
    margin: 0 auto 16px auto;
}
.login-card h1 {
    font-family: 'LEMON MILK', 'Archivo Black', 'Alexandria', sans-serif;
    font-size: 1.35rem;
    color: var(--mud-palette-tertiary);
    text-align: center;
    letter-spacing: 0.08em;
    margin: 0 0 6px 0;
}
.login-card .subtitle {
    font-family: 'Alexandria', sans-serif;
    font-size: 0.9rem;
    color: var(--mud-palette-text-secondary);
    text-align: center;
    margin: 0 0 24px 0;
}
.login-hint {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
    text-align: center;
    margin-top: 16px;
}
.login-footer {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 4px;
    margin-top: 8px;
    color: var(--mud-palette-text-secondary);
}

/* ---------------------------------------------------------------------
   Chrome (redesign phase 2 — ADR-0064 d.5/6): a single 56px topbar at the page
   background with a 1px border ("invisible" chrome), branding only here. The brand
   block measures 224px (+16px of AppBar padding = 240px) so the hamburger marks
   the exact drawer edge; collapsed, the wordmark disappears and the hamburger aligns to the rail.
   LEMON MILK in the wordmark = brand territory (logo), allowed by the ADR.
   --------------------------------------------------------------------- */
.pms-topbar {
    border-bottom: 1px solid var(--mud-palette-lines-default);
}
.pms-topbar-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 224px;
    flex: 0 0 auto;
    transition: width 200ms ease-out;
}
.pms-topbar-brand-collapsed {
    width: 48px;
}
.pms-topbar-logo {
    width: 36px;
    height: 36px;
    flex: 0 0 36px;
}
.pms-topbar-wordmark {
    font-family: 'LEMON MILK', 'Archivo Black', 'Alexandria', sans-serif;
    line-height: 1.05;
    white-space: nowrap;
}
.pms-topbar-wordmark .line1 {
    font-size: 0.95rem;
    letter-spacing: 0.08em;
    color: var(--mud-palette-secondary);
}
.pms-topbar-wordmark .line2 {
    font-size: 0.58rem;
    letter-spacing: 0.06em;
    color: var(--mud-palette-tertiary);
}
.pms-drawer {
    border-right: 1px solid var(--mud-palette-lines-default);
}

/* ---------------------------------------------------------------------
   Fidelity to the mockup — side navigation:
   - sub-items with NO icon (indentation only, as in the proposal);
   - nav typography: .9rem/500, tracking 0;
   - a real pill badge on groups with pending items (overlay — MudNavGroup has
     no badge slot; the .pms-nav-group-wrap wrapper positions it).
   --------------------------------------------------------------------- */
/* Geraldo's decision (2026-06-10): NO menu item without an icon — the children got
   glyphs in the same theme as the proposal (PmsNavIcons), slightly smaller. */
.pms-navmenu .mud-collapse-container .mud-nav-link .mud-icon-root {
    font-size: 14px;
    width: 18px;
    height: 18px;
}
.pms-navmenu .mud-nav-link-text {
    font-size: 0.845rem; /* 13.5px do mockup */
    font-weight: 500;
    letter-spacing: 0;
}
.pms-navmenu .mud-collapse-container .mud-nav-link-text {
    font-size: 0.8125rem; /* filhos: 13px */
}
/* INLINE count pill on the child items (mockup .count): red = overdue;
   .warn = commercial pending. */
.pms-nav-count {
    margin-left: auto;
    background: color-mix(in srgb, var(--mud-palette-error) 12%, transparent);
    color: var(--mud-palette-error);
    font-size: 0.6875rem;
    font-weight: 600;
    border-radius: 10px;
    padding: 1px 7px;
    line-height: 1.4;
}
.pms-nav-count.warn {
    background: color-mix(in srgb, var(--mud-palette-warning) 14%, transparent);
    color: var(--mud-palette-warning);
}
.pms-nav-group-wrap {
    position: relative;
}
.pms-nav-badge {
    position: absolute;
    top: 11px;
    right: 38px; /* antes do caret do grupo */
    z-index: 1;
    pointer-events: none;
    background: color-mix(in srgb, var(--mud-palette-error) 12%, transparent);
    color: var(--mud-palette-error);
    border-radius: 10px;
    padding: 1px 8px;
    font-size: 0.72rem;
    font-weight: 600;
    line-height: 1.4;
}

/* Ctrl+K global search (F-01b): a discreet topbar button with the key taught in the label
   (Stripe/Linear pattern); hits with tonal hover and visible focus. */
.pms-search-btn {
    text-transform: none;
    margin-left: 16px;
    color: var(--mud-palette-text-secondary);
    border: 1px solid var(--mud-palette-lines-default);
    background: var(--mud-palette-surface);
    border-radius: 8px;
    width: min(480px, 40vw);
    padding: 5px 12px;
    justify-content: flex-start;
}
.pms-search-btn .mud-button-label {
    width: 100%;
    display: flex;
    align-items: center;
    font-weight: 400;
}
.pms-search-ph {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.pms-search-btn .pms-search-kbd {
    margin-left: auto;
}
.pms-search-kbd {
    font-size: 0.7rem;
    padding: 1px 6px;
    border-radius: 4px;
    border: 1px solid var(--mud-palette-lines-default);
    color: var(--mud-palette-text-secondary);
}
.pms-search-results {
    max-height: 420px;
    overflow-y: auto;
}
.pms-search-hit {
    display: flex;
    align-items: center;
    padding: 8px 12px;
    border-radius: 8px;
    cursor: pointer;
    transition: background 120ms ease-out;
}
.pms-search-hit:hover, .pms-search-hit:focus-visible {
    background: color-mix(in srgb, var(--mud-palette-primary) 8%, transparent);
    outline: none;
}
/* M-02 — the item highlighted by the keyboard arrows. Stronger than :hover (12% vs 8%) plus a side bar,
   because the keyboard selection has to be distinguishable from the item under the mouse cursor. */
.pms-search-hit-selected {
    background: color-mix(in srgb, var(--mud-palette-primary) 12%, transparent);
    box-shadow: inset 3px 0 0 0 var(--mud-palette-primary);
}
.pms-search-hit-label {
    font-weight: 500;
}
.pms-search-hit-sub {
    font-size: 0.78rem;
}

/* Entity detail (DetailDialog): modal CENTERED vertically + horizontally (Geraldo's decision
   2026-06-11 — it used to be the mockup's right side panel, but it overlapped the menu). A 560px card,
   height up to 90vh with inner scroll; the overlay (in the .razor) already centers it with flex. */
.pms-detail-panel {
    width: 560px;
    max-width: 92vw;
    display: flex;
    animation: pms-panel-pop 160ms ease-out both;
}
@keyframes pms-panel-pop {
    from { transform: scale(.97); opacity: 0; }
    to   { transform: scale(1); opacity: 1; }
}

/* Modals (MudDialog) centered vertically + horizontally in the VIEWPORT, above the redesign chrome
   (topbar/drawer). It fixes the regression where the modal drifted off-center and overlapped the menu. It does
   NOT affect the DetailDialog (its own .pms-detail-panel overlay) nor the global search (DialogPosition.TopCenter). */
.mud-dialog-container:not(.mud-dialog-top-center):not(.mud-dialog-bottom-center) {
    align-items: center;
    justify-content: center;
}
/* It guarantees the overlay + dialog stay above the topbar/drawer of the new chrome. */
.mud-overlay-dialog { z-index: 1401; }
.mud-dialog-container { z-index: 1402; }

/* Pricing Calculator (Geraldo 2026-06-23): with no prospect/customer attached the inputs are locked —
   pointer-events:none blocks a click on any control (including MudSelect, which is a div) and opacity gives
   the disabled look. The real backstop (not calculating) lives in CalculateAsync/CalculateMultiAsync. The gate
   and "Go to Prospects" stay OUTSIDE this block (clickable). */
.pms-inputs-locked {
    pointer-events: none;
    opacity: 0.55;
    user-select: none;
}

/* ---------------------------------------------------------------------
   GLOBAL position of the toasts (Snackbar) — center-right (Geraldo's decision 2026-06-23).
   The config uses the DEFAULT BottomRight position (which already renders in the right corner); here we
   only swap that class's VERTICAL ANCHOR (from `bottom` to the middle of the screen), keeping the
   `right` (horizontal, right side) intact. `!important` to beat the MudBlazor `bottom:24px` rule.
   Reusing the position that works avoids hiding or displacing the toast.
   Result: vertically centered, flush right — valid for ALL toasts in the system.
   --------------------------------------------------------------------- */
.mud-snackbar-location-bottom-right {
    bottom: auto !important;
    top: 50% !important;
    transform: translateY(-50%) !important;
}

/* "Today's operation" timeline (F-02a): one row per visit — status, tabular time, customer, technician. */
.pms-today-visit {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 0;
    border-bottom: 1px solid var(--mud-palette-divider-light, var(--mud-palette-lines-default));
}
.pms-today-visit:last-child { border-bottom: none; }

/* M-09 (2026-07 UX analysis): the "Today" row became an anchor to /operations/today. An anchor instead of
   a div with onclick, so it inherits keyboard/focus; these rules give back the row appearance (the browser
   would paint it blue and underline it) and provide the clickable affordance. */
.pms-today-visit--link {
    color: inherit;
    text-decoration: none;
    cursor: pointer;
    border-radius: 4px;
}
.pms-today-visit--link:hover { background: var(--mud-palette-action-default-hover); }
.pms-today-visit--link:focus-visible { outline: 2px solid var(--mud-palette-primary); outline-offset: -2px; }

/* Completed/in-progress visit row: ONE line on desktop — the customer name shrinks with
   ellipsis (.pms-today-label already has min-width:0 + ellipsis) instead of pushing the trailing
   chips/cost/magnifier to a second line. Without nowrap, flex-wrap wraps BEFORE shrinking the
   label (flex lines are laid out at base size) — seen on macOS, where emoji glyphs render wider
   (per-OS render trade-off, journal 2026-06-10). Mobile (<600px) keeps the old wrap. */
.pms-today-visit--oneline {
    flex-wrap: nowrap;
    gap: 4px; /* tighter than the base 8px — every pixel counts on the lg=4 card */
}
.pms-today-visit--oneline .pms-today-label {
    min-width: 48px; /* the name never collapses to nothing */
}
/* Compact the fixed-width tail (chips / separators / magnifier) so the whole row FITS the card
   instead of overflowing it: chips lose the outer margins and half the inner padding, separators
   tighten, the icon-button loses its halo padding. Scoped to the one-line row only. */
.pms-today-visit--oneline .mud-chip {
    margin-left: 0;
    margin-right: 0;
    padding: 0 6px;
}
.pms-today-visit--oneline .mx-1 {
    margin-left: 2px !important;
    margin-right: 2px !important;
}
.pms-today-visit--oneline .mud-icon-button {
    padding: 4px;
}
@media (max-width: 599.98px) {
    .pms-today-visit--oneline {
        flex-wrap: wrap;
    }
}

/* Door-to-door workday rows on the tech card (ADR-0100 P4; timeline rows since 2026-07-14):
   clock-in/clock-out are regular timeline rows with a subtle panel tint so a punch reads apart
   from a visit at a glance. Inherits .pms-today-visit metrics (mobile-safe, no fixed px). */
.pms-today-visit.pms-today-shift-row {
    padding-left: 6px;
    padding-right: 6px;
    border-radius: 6px;
    background: var(--mud-palette-background-gray, rgba(0, 0, 0, 0.04));
    border-bottom: none;
}
.pms-today-time {
    font-variant-numeric: tabular-nums;
    font-size: 0.8rem;
    color: var(--mud-palette-text-secondary);
    flex: 0 0 auto;
}
.pms-today-label {
    font-size: 0.85rem;
    font-weight: 500;
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.pms-today-collab {
    font-size: 0.75rem;
    flex: 0 0 auto;
}

/* Alert bell popover (phase 2b — ADR-0062 N3): fixed width so long titles do
   not stretch the menu; the body truncates at 2 lines. */
.pms-alerts-popover {
    width: 360px;
    max-width: 90vw;
}
/* The badge (unread count) anchors on the corner of the MudIconButton; the default
   12px padding pushed the number away from the bell. Shrinking the padding brings the corner —
   and the badge — next to the glyph. */
.pms-alerts-menu .mud-badge-root .mud-icon-button {
    padding: 4px;
}
.pms-alert-item-body {
    min-width: 0;
}
.pms-alert-item-title {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    line-height: 1.3;
}

/* KPI card — doc 03: valor em fonte de UI (tabular) 1.75rem/700; label Sentence case
   (sem uppercase), 0.75rem/500. Cor de destaque = Tertiary (navy no light, #E8ECF2 no dark). */
.pms-kpi .mud-typography-subtitle2 {
    letter-spacing: 0;
    color: var(--mud-palette-text-secondary);
    font-size: 0.75rem;
    font-weight: 500;
}
.pms-kpi .pms-kpi-value {
    font-size: 1.625rem; /* 26px do mockup */
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-tertiary);
    line-height: 1.1;
}
.pms-kpi .pms-kpi-delta-up   { color: var(--mud-palette-success); font-weight: 600; }
.pms-kpi .pms-kpi-delta-down { color: var(--mud-palette-error);   font-weight: 600; }

/* Clickable KPI (phase 3a — solves UX-03): a border instead of a shadow (level 0 of doc 03 §1.4),
   hover with a primary border + the chevron appears. Visible focus for the keyboard (role=link). */
.pms-kpi-link {
    cursor: pointer;
    border: 1px solid var(--mud-palette-lines-default);
    transition: border-color 140ms ease-out, box-shadow 140ms ease-out;
}
.pms-kpi-link:hover, .pms-kpi-link:focus-visible {
    border-color: var(--mud-palette-primary);
    box-shadow: 0 1px 2px rgba(28, 53, 94, 0.06);
    outline: none;
}
.pms-kpi-chevron {
    opacity: 0;
    transition: opacity 140ms ease-out;
    color: var(--mud-palette-primary);
}
.pms-kpi-link:hover .pms-kpi-chevron, .pms-kpi-link:focus-visible .pms-kpi-chevron {
    opacity: 1;
}

/* Section cards (level 0): 1px border, no shadow — hierarchy through tone (doc 03 §1.4). */
.pms-section-card {
    border: 1px solid var(--mud-palette-lines-default);
}

/* Attention banners (mockup .alert): individual, square tinted icon, actions on the right. */
.pms-alert {
    display: flex;
    align-items: center;
    gap: 12px;
    border: 1px solid color-mix(in srgb, var(--mud-palette-error) 30%, transparent);
    background: var(--mud-palette-surface);
    border-radius: 10px;
    padding: 9px 14px;
}
.pms-alert.warn {
    border-color: color-mix(in srgb, var(--mud-palette-warning) 35%, transparent);
}
.pms-alert-ico {
    width: 30px;
    height: 30px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 30px;
    font-style: normal;
    font-weight: 700;
    background: color-mix(in srgb, var(--mud-palette-error) 12%, transparent);
    color: var(--mud-palette-error);
}
.pms-alert.warn .pms-alert-ico {
    background: color-mix(in srgb, var(--mud-palette-warning) 14%, transparent);
    color: var(--mud-palette-warning);
}
.pms-alert-text {
    flex: 1 1 auto;
}

/* Greeting (mockup .greet 15px/600) and period chip (mockup .period). */
.pms-greet {
    font-size: 0.94rem;
    font-weight: 600;
}
.pms-period {
    display: flex;
    align-items: center;
    gap: 8px;
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    padding: 7px 12px;
    font-size: 0.8125rem;
    font-weight: 500;
}

/* Section/chart card title — fonte de UI, Sentence case (doc 03 §1.3) */
.pms-section-title {
    font-size: 0.91rem; /* 14.5px do mockup */
    font-weight: 600;
    letter-spacing: 0;
    color: var(--mud-palette-tertiary);
    margin-bottom: 12px;
}

/* ---------------------------------------------------------------------
   Session-expired toast (bottom-right).
   Owns its animation timing via --pms-toast-duration (set inline by the
   component). Countdown bar scales from 100% to 0 over that duration so
   the user has a visual cue of how long until the redirect.
   Colours through the theme -> automatic dark mode (no .pms-dark block).
   --------------------------------------------------------------------- */
.pms-toast {
    position: fixed;
    right: 24px;
    bottom: 24px;
    z-index: 2000;
    min-width: 320px;
    max-width: 380px;
    display: grid;
    grid-template-columns: 40px 1fr;
    gap: 12px;
    padding: 16px 16px 0 16px;
    border-radius: 12px;
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    box-shadow: 0 16px 40px rgba(28, 53, 94, 0.28);
    overflow: hidden;
    animation: pms-toast-slide-in 220ms ease-out both;
    font-family: 'Alexandria', 'Segoe UI', Roboto, Arial, sans-serif;
}
.pms-toast-icon {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    color: var(--mud-palette-info);
    padding-top: 2px;
}
.pms-toast-body { padding-bottom: 16px; }
.pms-toast-title {
    font-weight: 700;
    font-size: 0.95rem;
    color: var(--mud-palette-tertiary);
    margin-bottom: 4px;
    letter-spacing: 0.01em;
}
.pms-toast-text {
    font-size: 0.85rem;
    line-height: 1.35;
    color: var(--mud-palette-text-primary);
}
.pms-toast-footer {
    margin-top: 10px;
    font-size: 0.72rem;
    letter-spacing: 0.02em;
    color: var(--mud-palette-text-secondary);
}
.pms-toast-progress {
    grid-column: 1 / -1;
    height: 4px;
    background: color-mix(in srgb, var(--mud-palette-tertiary) 12%, transparent);
    overflow: hidden;
}
.pms-toast-progress > span {
    display: block;
    height: 100%;
    background: linear-gradient(90deg, var(--mud-palette-primary), var(--mud-palette-secondary));
    transform-origin: left center;
    animation: pms-toast-countdown var(--pms-toast-duration, 5000ms) linear forwards;
}

/* Info variant — keep in sync with pms-toast-info in markup */
.pms-toast.pms-toast-info .pms-toast-icon { color: var(--mud-palette-info); }

@keyframes pms-toast-countdown {
    from { transform: scaleX(1); }
    to   { transform: scaleX(0); }
}
@keyframes pms-toast-slide-in {
    from { opacity: 0; transform: translateY(16px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* ---------------------------------------------------------------------
   Phase 6 — microinteractions (doc 03 §1.4): all CSS, all through tokens,
   120-160ms ease-out on frequent interactions. Nothing above 300ms.
   --------------------------------------------------------------------- */

/* Consistent visible focus (O3 — keyboard navigation): a tonal Primary ring
   on any interactive element, without depending on the browser default outline. */
:where(a, button, [role="button"], [role="link"], [tabindex="0"]):focus-visible {
    outline: 2px solid color-mix(in srgb, var(--mud-palette-primary) 70%, transparent);
    outline-offset: 2px;
    border-radius: 6px;
}

/* Table rows: hover with a short transition (the tone comes from the TableHover theme). */
.mud-table-row {
    transition: background-color 120ms ease-out;
}

/* Page content: a subtle fade-in on navigation (no displacement — cheap and calm). */
.mud-main-content > .mud-container {
    animation: pms-page-fade 160ms ease-out both;
}
@keyframes pms-page-fade {
    from { opacity: 0.6; }
    to   { opacity: 1; }
}

/* Buttons and chips: colour/elevation transition consistent with the rest. */
.mud-button-root, .mud-chip {
    transition: background-color 140ms ease-out, box-shadow 140ms ease-out, border-color 140ms ease-out;
}

/* doc 03 §1.3 "drop ALL-CAPS": the button uppercase comes from the MudBlazor CSS (not from the
   theme Typography) — cancelled globally. It is the biggest cause of the "old font" look. */
.mud-button-root {
    text-transform: none;
}

/* Topbar (mockup .icon-btn): action icons in text-2, not in primary text. */
.pms-topbar .mud-icon-button {
    color: var(--mud-palette-text-secondary);
}

/* Accessibility: GLOBAL motion kill-switch (doc 03 §1.4) — it covers every animation
   and transition of the app, not only the named ones. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

/* ================================================================
   Mobile responsive layer — Phase A foundation (2026-07-06).
   See docs/roadmap/mobile-responsividade-plano.md.
   Everything here is scoped inside width media queries (phones,
   <= 599.98px) or @supports, so the desktop layout (>= 600px) is
   byte-for-byte unchanged. Mobile-first additive: we only ADD
   narrow-screen overrides, never touch the desktop path.
   ================================================================ */
@media (max-width: 599.98px) {
    /* No accidental sideways scroll of the whole app on a phone. */
    html, body { overflow-x: hidden; }

    /* Reclaim width: the desktop pa-6 (48px) is far too much at 320px.
       Two-class selector outranks .pa-6 without needing !important. */
    .mud-container.pms-main-container { padding: 12px; }

    /* Chrome/top bar: drop the wordmark, collapse the brand to the logo,
       and let the search fill the remaining space so the 56px app bar
       does not overflow on narrow screens. */
    .pms-topbar-wordmark { display: none; }
    .pms-topbar-brand { width: 48px; }
    .pms-search-btn { width: auto; min-width: 0; flex: 1 1 auto; margin-left: 8px; }

    /* Long content must shrink, never widen the page. */
    .mud-main-content img,
    .mud-main-content .mud-table,
    .mud-main-content .mud-paper { max-width: 100%; }

    /* Tables are the main offender: scroll the table sideways inside its
       own card instead of pushing the whole viewport wide. */
    .mud-main-content .mud-table-container {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    /* Dense data reads better a touch smaller on phones, and long identifiers
       (e.g. invoice numbers "DP-2026...-45") wrap less. Kept at 13px — the same
       size as the nav's dense text — for legibility. Form inputs stay >= 16px
       (below) to avoid iOS zoom-on-focus, so this only affects display cells. */
    .mud-main-content .mud-table-cell { font-size: 13px; }

    /* iOS zooms the page when focusing an input whose font-size < 16px.
       Now that pinch-zoom is re-enabled, keep inputs at >= 16px on phones. */
    .mud-input-slot input,
    .mud-input-slot textarea,
    .mud-input-control input { font-size: 16px; }

    /* MudSimpleTable has no card breakpoint like MudTable. Opt a raw table into
       the same card-per-row behaviour with Class="pms-stack-table": the header is
       visually hidden (still read by screen readers via data-label) and each cell
       shows its column label inline. Add data-label="..." to every <td>. */
    .pms-stack-table thead {
        position: absolute;
        width: 1px; height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
        white-space: nowrap;
    }
    .pms-stack-table tr {
        display: block;
        border: 1px solid var(--mud-palette-lines-default);
        border-radius: 8px;
        margin-bottom: 8px;
        padding: 4px 10px;
    }
    .pms-stack-table td {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: 12px;
        border: none;
        padding: 5px 0;
        text-align: left !important;
    }
    .pms-stack-table td::before {
        content: attr(data-label);
        font-weight: 600;
        color: var(--mud-palette-text-secondary);
        flex: 0 0 auto;
    }

    /* Editable MudTable grids on phones. MudBlazor's native stacked cell puts the
       DataLabel on the left and the value on the right, which squeezes an input into
       ~half the row. For edit grids we opt in with Class="pms-stack-edit" to stack the
       column label ABOVE a full-width field instead — a proper mobile edit form per row. */
    .pms-stack-edit .mud-table-cell,
    .pms-stack-edit td {
        flex-direction: column;
        align-items: stretch;
    }
    .pms-stack-edit .mud-table-cell::before,
    .pms-stack-edit td::before {
        margin-bottom: 4px;
    }
    .pms-stack-edit .mud-table-cell .mud-input-control,
    .pms-stack-edit .mud-table-cell .mud-input-root,
    .pms-stack-edit td .mud-input-control,
    .pms-stack-edit td .mud-input-root { width: 100%; }
}

/* Safe-area (notch / rounded corners on iOS), phones only. max() keeps the
   normal 12px on non-notch devices and extends it under the notch. Requires
   viewport-fit=cover in index.html. Scoped inside the mobile media query, so
   the desktop layout is untouched. */
@supports (padding: max(0px, env(safe-area-inset-left))) {
    @media (max-width: 599.98px) {
        .mud-container.pms-main-container {
            padding-left: max(12px, env(safe-area-inset-left));
            padding-right: max(12px, env(safe-area-inset-right));
        }
    }
}

/* ── Shared fullscreen photo lightbox (PmsPhotoLightboxDialog) ────────────────────────────────────
   Opened as a FullScreen dialog so it covers the WHOLE viewport. A position:fixed overlay placed
   inside a MudDialog is trapped by the dialog's transform (it only covers the modal) — rendering the
   viewer as its own top-level FullScreen dialog escapes that containing block. */
.pms-lightbox-dialog {
    background: rgba(0, 0, 0, 0.92);
    box-shadow: none;
}
.pms-lightbox-dialog .mud-dialog-content {
    padding: 0;
    height: 100%;
    display: flex;
    overflow: hidden;
}
.pms-lightbox {
    flex: 1 1 auto;
    position: relative;   /* anchors the absolute toolbar to this centered box */
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: zoom-out;
    overflow: hidden;
}
.pms-lightbox__bar {
    position: absolute;
    top: 12px;
    right: 12px;
    display: flex;
    gap: 8px;
    z-index: 1;
}

/* -- Share per customer: 2 pies in the technician card (Today board) ---------------------------
   Mobile-first and ADDITIVE (hard responsiveness rule): the base is ONE column — which is the phone
   state — and desktop gains the two columns through min-width. The existing desktop path is not
   touched. `minmax(0, 1fr)` on purpose: `1fr` has min-width auto, and the chart SVG would push the
   column outside the card. */
.pms-share-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 12px;
}

@media (min-width: 600px) {
    .pms-share-grid {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    }
}

/* Card with a single pie (dispatcher/technician — the cost is role-gated and disappears): it makes no
   sense to leave the time one squeezed into half the width. */
.pms-share-grid > div:only-child {
    grid-column: 1 / -1;
}

.pms-share-legend {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-top: 4px;
}

.pms-share-legend-row {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 11.5px;
    line-height: 1.6;
}

.pms-share-swatch {
    width: 8px;
    height: 8px;
    border-radius: 2px;
    flex: 0 0 auto;
}

/* The customer name gives up space before the value — "Residencia Angelica" must not push the "$97.48"
   outside the card. min-width:0 is what allows the ellipsis inside the flex. */
.pms-share-label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--mud-palette-text-secondary);
}

.pms-share-value {
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-primary);
}

/* -- Visit photos grouped by body of water x stage (VisitDetailDialog) -------------------------
   One card per body of water, one row per stage. The SAME structure on desktop and phone (Claudinei's
   decision 2026-07-15): stacked everywhere — there is no breakpoint here on purpose, the layout is
   already vertical by nature and does not need to become something else at 320px. */
.pms-visit-photo-groups {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.pms-visit-photo-group {
    background: var(--mud-palette-background-grey);
    border-radius: 8px;
    padding: 8px 10px;
}

.pms-visit-photo-group__name {
    font-size: 13px;
    font-weight: 500;
    color: var(--mud-palette-text-primary);
    margin-bottom: 4px;
}

/* Label on top, thumbnails below: the translated stage name varies a lot in length
   ("Chemistry adjustment" vs "Ajuste") and side by side it would push the photos out in pt/es. */
.pms-visit-photo-step {
    padding: 3px 0;
}

.pms-visit-photo-step__label {
    display: block;
    font-size: 11px;
    color: var(--mud-palette-text-secondary);
    margin-bottom: 3px;
}

.pms-visit-photo-step__shots {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
}

/* A body of water with no photo: discreet but PRESENT — the absence is compliance evidence, and it
   disappears if the row does not exist. Italic and secondary so it does not compete with the ones that have photos. */
.pms-visit-photo-step__empty {
    font-size: 11px;
    font-style: italic;
    color: var(--mud-palette-text-disabled);
    padding: 2px 0;
}

/* ADR-0104 (wrap-up) — Dispatch Schedule: board + tray ALWAYS side by side on desktop.
   The previous layout (flex-wrap + a fixed 640px min-width on the grid) overflowed the row at 100% zoom
   and pushed the tray down; now the grid shrinks (min-width:0 — the MudTable scrolls horizontally
   on its own) and only the media query decides to stack (screens < 960px). */
.opsschedule-layout { display: flex; gap: 12px; align-items: flex-start; }
.opsschedule-layout__grid { flex: 1 1 auto; min-width: 0; }
.opsschedule-layout__tray { flex: 0 0 280px; }
@media (max-width: 959.98px) {
    .opsschedule-layout { flex-direction: column; }
    .opsschedule-layout__tray { flex: 1 1 auto; width: 100%; align-self: stretch; }
}

/* ADR-0104 (F6) — Dispatch Schedule month grid: aggregate day cells (server-side aggregates only —
   no per-item rendering in the month, WASM payload discipline). Overdue day = red outline. */
.opsschedule-month { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; padding: 8px; }
.opsschedule-month__dow { text-align: center; font-weight: 600; padding: 4px 0; }
.opsschedule-month__day { min-height: 84px; border: 1px solid var(--mud-palette-lines-default); border-radius: 4px; padding: 4px; cursor: pointer; }
.opsschedule-month__day--blank { border: none; cursor: default; }
.opsschedule-month__day--overdue { border: 2px solid var(--mud-palette-error); }
.opsschedule-month__day--today { box-shadow: inset 0 0 0 2px var(--mud-palette-primary); }
@media (max-width: 599.98px) { .opsschedule-month__day { min-height: 64px; } }

/* "Look here" flash — a reusable effect (see js/ui-effects.js). Fired e.g. after Calculate on a quote. */
.pms-flash {
    border-radius: 8px;
    animation: pms-flash-pulse 1.7s ease-out;
}
@keyframes pms-flash-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(24, 95, 165, 0); }
    12%  { box-shadow: 0 0 0 4px rgba(24, 95, 165, 0.9), 0 0 26px 6px rgba(24, 95, 165, 0.45); }
    100% { box-shadow: 0 0 0 0 rgba(24, 95, 165, 0); }
}

/* Environment badge (rendered by EnvironmentBadge.razor in Development only).
   pointer-events:none — the pill must never steal a tap from real UI. */
/* Completion card of the guided trail (F2). A light overlay — NOT a blocking modal: the visitor
   can ignore it and go on exploring, which is literally one of the offered options. */
.pms-demo-finish {
    position: fixed;
    inset: 0;
    z-index: 2100;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(10, 16, 28, .45);
    padding: 16px;
}

.pms-demo-finish__card {
    background: #fff;
    border-radius: 16px;
    max-width: 520px;
    padding: 28px 30px;
    box-shadow: 0 18px 48px rgba(10, 16, 28, .28);
}

.pms-demo-finish__title {
    margin: 0 0 10px;
    font-size: 22px;
    font-weight: 700;
    color: #171c28;
}

.pms-demo-finish__body {
    margin: 0 0 22px;
    font-size: 15px;
    line-height: 1.55;
    color: #48525f;
}

.pms-demo-finish__actions {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
}

.pms-demo-finish__primary,
.pms-demo-finish__secondary {
    font: inherit;
    font-weight: 600;
    padding: 9px 18px;
    border-radius: 10px;
    cursor: pointer;
}

.pms-demo-finish__primary {
    border: 0;
    background: #4197cb;
    color: #fff;
}

.pms-demo-finish__secondary {
    border: 1px solid #c9d4e0;
    background: transparent;
    color: #48525f;
}

.pms-demo-finish__primary:hover,
.pms-demo-finish__secondary:hover {
    filter: brightness(.96);
}

/* O primario virou <a> (leva ao site publico) e o secundario continua <button>: sem isto os dois
   ficam com metricas de caixa diferentes e o par sai desalinhado. */
a.pms-demo-finish__primary {
    display: inline-flex;
    align-items: center;
    text-decoration: none;
    line-height: 1.2;
}

/* Terceiro nivel: "ver de novo" e recuperacao, nao decisao. Peso de link para nao competir com as
   duas acoes acima — tres botoes com o mesmo peso e o mesmo que nenhum. */
.pms-demo-finish__tertiary {
    display: block;
    margin: 14px auto 0;
    padding: 4px 2px;
    font: inherit;
    font-size: .9rem;
    border: 0;
    background: none;
    color: #6b7684;
    text-decoration: underline;
    cursor: pointer;
}

.pms-demo-finish__tertiary:hover {
    color: #48525f;
}

/* Guided demo trail (demo-sandbox-publico plan, F2). The OPPOSITE corner to the DEV pill
   on purpose: both are fixed and in the same corner they would stack. Unlike
   .pms-env-badge, pointer-events stays ACTIVE here — there is an exit button. */
.pms-demo-trail {
    position: fixed;
    bottom: 12px;
    right: 12px;
    z-index: 2000;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 10px 6px 14px;
    border-radius: 16px;
    background: #0e1526;
    color: #fff;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .04em;
    box-shadow: 0 4px 14px rgba(10, 16, 28, .35);
    user-select: none;
}

.pms-demo-trail__next,
.pms-demo-trail__exit {
    border: 1px solid rgba(255, 255, 255, .45);
    background: transparent;
    color: inherit;
    font: inherit;
    padding: 2px 10px;
    border-radius: 10px;
    cursor: pointer;
}

.pms-demo-trail__next:hover,
.pms-demo-trail__next:focus-visible,
.pms-demo-trail__exit:hover,
.pms-demo-trail__exit:focus-visible {
    background: rgba(255, 255, 255, .14);
}

.pms-env-badge {
    position: fixed;
    bottom: 12px;
    left: 12px;
    z-index: 2000;
    padding: 2px 10px;
    border-radius: 12px;
    background: #d32f2f;
    color: #fff;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .08em;
    pointer-events: none;
    user-select: none;
    opacity: .92;
}

/* ===== ADR-0114 — navigation trimming of the public demo =====
   It lives HERE, and not in the NavMenu <style>, because the rules cite ROUTES: inside the component
   they entered the rendered markup and broke the tests asserting "this nav does not contain
   /invoices" (FieldOnlyLockoutTests, NavMenuTests). Route CSS is not markup. */
    /* ADR-0114 — trimming of the public demo. Anchored on the HREF, which is the identity of the
       destination, and not on the item's appearance: a selector by style (filled/primary) gets it
       wrong in both directions. A MudNavGroup header has no href and therefore is NOT hit — opening
       the groups and reading what exists is exactly the point. This is a UX curtain; the boundary is
       the MainLayout (route) + the server (writes). */
    .pms-demo-nav .mud-nav-link[href] {
        pointer-events: none;
        opacity: .42;
    }
    .pms-demo-nav .mud-nav-link[href="/"],
    .pms-demo-nav .mud-nav-link[href^="/customers"],
    .pms-demo-nav .mud-nav-link[href^="/operations/today"],
    .pms-demo-nav .mud-nav-link[href^="/visit-reports"],
    .pms-demo-nav .mud-nav-link[href^="/profitability"],
    .pms-demo-nav .mud-nav-link[href^="/invoices"] {
        pointer-events: auto;
        opacity: 1;
    }
    .pms-demo-nav-note {
        padding: 8px 16px 12px;
        opacity: .75;
    }
