:root {
    --ink: #071b20;
    --ink-2: #102d34;
    --glass: rgba(255, 255, 255, 0.12);
    --glass-strong: rgba(255, 255, 255, 0.18);
    --line: rgba(255, 255, 255, 0.18);
    --white-soft: rgba(255, 255, 255, 0.74);
    --white-muted: rgba(255, 255, 255, 0.56);
    --amber: #ff9f2e;
    --gold: #ffd188;
    --sky: #86d7ff;
    --danger: #ff6b3a;
    --good: #a6e9c0;
    --ease: cubic-bezier(0.2, 0.8, 0.2, 1);

    /* Semantic aliases — property-detail.css and walkthrough-enhancements.css
       are written against these names (accent/success/warning/info/white)
       rather than the concrete color tokens above, so both resolve here
       instead of duplicating color values at every call site. */
    --accent: var(--amber);
    --success: var(--good);
    --warning: var(--gold);
    --info: var(--sky);
    --white: #ffffff;

    /* Type scale for the dashboard redesign (mockups/assets/dashboard-pilot.css)
       — only the page h1 uses --fs-xl; everything else in a card tops out at
       --fs-lg, so nothing inside a panel can out-rank the page title. */
    --fs-2xs: 11px;
    --fs-xs: 12px;
    --fs-sm: 13px;
    --fs-md: 14px;
    --fs-base: 15px;
    --fs-lg: 18px;
    --fs-xl: 24px;

    --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
}

* {
    box-sizing: border-box;
}

html {
    scroll-behavior: smooth;
}

body {
    min-height: 100vh;
    margin: 0;
    background:
        radial-gradient(circle at 78% 10%, rgba(255, 209, 136, 0.18), transparent 28rem),
        linear-gradient(135deg, #071b20 0%, #173840 48%, #647776 100%);
    color: white;
    font-family: Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    letter-spacing: 0;
}

a {
    color: inherit;
}

.skip-link {
    position: absolute;
    left: 1rem;
    top: -4rem;
    z-index: 50;
    padding: 0.75rem 1rem;
    border-radius: 0.75rem;
    background: white;
    color: var(--ink);
    font-weight: 800;
}

.skip-link:focus {
    top: 1rem;
}

.app-shell {
    min-height: 100vh;
    padding: 18px;
}

body:not(.full-bleed) .app-shell {
    display: grid;
    grid-template-columns: 17rem minmax(0, 1fr);
    gap: 20px;
}

.app-frame {
    min-width: 0;
}

.main-content {
    display: grid;
    gap: 24px;
}

.landing-hero {
    display: grid;
    grid-template-rows: auto 1fr;
    min-height: calc(100vh - 36px);
    overflow: hidden;
    padding: clamp(24px, 5vw, 64px);
    border-radius: 34px;
    background:
        linear-gradient(90deg, rgba(7, 27, 32, 0.9), rgba(7, 27, 32, 0.38)),
        linear-gradient(0deg, rgba(7, 27, 32, 0.66), rgba(7, 27, 32, 0.12)),
        url("https://images.unsplash.com/photo-1600607688969-a5bfcd646154?auto=format&fit=crop&w=2200&q=84") center/cover;
    box-shadow: 0 34px 90px rgba(0, 0, 0, 0.34);
}

.landing-nav,
.landing-nav div,
.landing-hero-grid,
.landing-feature-grid,
.workflow-showcase,
.landing-proof,
.pricing-grid,
.why-list {
    display: grid;
    gap: 18px;
}

.pricing-grid {
    margin-top: 32px;
}

.landing-nav {
    grid-template-columns: auto 1fr;
    align-items: center;
}

.landing-nav div {
    grid-template-columns: repeat(6, max-content);
    justify-content: end;
    align-items: center;
}

.landing-nav a {
    color: white;
    font-weight: 850;
    text-decoration: none;
}

.landing-nav-toggle {
    display: none;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.08);
    color: white;
    cursor: pointer;
}

.landing-nav-toggle i { width: 20px; height: 20px; }

.landing-hero-grid {
    grid-template-columns: minmax(0, 1fr) minmax(320px, 420px);
    align-items: center;
    gap: clamp(28px, 6vw, 84px);
}

.landing-hero-copy {
    max-width: 820px;
}

.landing-hero-copy h1 {
    margin: 0;
    font-size: clamp(4.4rem, 11vw, 8.8rem);
    font-weight: 520;
    line-height: 0.9;
}

.landing-hero-copy p:not(.eyebrow) {
    max-width: 46rem;
    margin: 24px 0;
    color: rgba(255, 255, 255, 0.78);
    font-size: 1.1rem;
    font-weight: 650;
}

.conversion-proof {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 22px;
}

.conversion-proof span {
    display: inline-flex;
    gap: 8px;
    align-items: center;
    min-height: 36px;
    padding: 0 12px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.22);
    color: rgba(255, 255, 255, 0.78);
    font-size: 0.84rem;
    font-weight: 800;
}

.login-panel,
.landing-feature-grid article,
.why-list article,
.pricing-grid article {
    border: 1px solid var(--line);
    background:
        linear-gradient(145deg, rgba(255, 255, 255, 0.13), rgba(255, 255, 255, 0.05)),
        rgba(7, 27, 32, 0.68);
    box-shadow: 0 24px 70px rgba(0, 0, 0, 0.22);
    backdrop-filter: blur(20px);
}

.login-panel {
    display: grid;
    gap: 14px;
    padding: 24px;
    border-radius: 18px;
}

.login-panel h2 {
    margin: 0;
    font-size: 1.55rem;
}

.login-panel label {
    display: grid;
    gap: 8px;
    color: white;
    font-weight: 850;
}

.login-panel input,
.repair-form input:not([type="checkbox"]):not([type="radio"]),
.repair-form select,
.repair-form textarea,
.form-control,
.form-select,
.app-frame input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]),
.app-frame select,
.app-frame textarea {
    width: 100%;
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.12);
    color: white;
    padding: 12px 14px;
    font: inherit;
}

/* Placeholder text — the browser default (Bootstrap's --bs-secondary-color,
   a dark charcoal meant for light inputs) is nearly unreadable against
   these dark translucent-white inputs; nothing had a real placeholder
   until the repairs.php search field. */
.form-control::placeholder,
.app-frame input::placeholder,
.app-frame textarea::placeholder {
    color: rgba(255, 255, 255, 0.48);
    opacity: 1;
}

.repair-form select,
.form-select,
.app-frame select {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    padding-right: 40px;
    background-image:
        linear-gradient(45deg, transparent 50%, rgba(255, 255, 255, 0.88) 50%),
        linear-gradient(135deg, rgba(255, 255, 255, 0.88) 50%, transparent 50%);
    background-position:
        calc(100% - 18px) calc(50% - 1px),
        calc(100% - 12px) calc(50% - 1px);
    background-size: 6px 6px, 6px 6px;
    background-repeat: no-repeat;
}

.login-panel input:focus,
.repair-form input:focus,
.repair-form select:focus,
.repair-form textarea:focus,
.form-control:focus,
.form-select:focus,
.app-frame input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]):focus,
.app-frame select:focus,
.app-frame textarea:focus {
    border-color: rgba(255, 255, 255, 0.3);
    outline: 0;
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.08);
}

.landing-band,
.workflow-showcase,
.landing-proof,
.pricing-band {
    width: min(1240px, calc(100% - 36px));
    margin: 0 auto;
    padding: 74px 0;
}

.landing-feature-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

.landing-feature-grid article,
.why-list article,
.pricing-grid article {
    min-height: 210px;
    padding: 24px;
    border-radius: 16px;
    display: flex;
    flex-direction: column;
}

.pricing-grid article ul {
    flex-grow: 1;
}

.pricing-grid article > a {
    margin-top: auto;
}

.landing-feature-grid h3,
.why-list strong,
.pricing-grid strong {
    display: block;
    margin: 14px 0 8px;
    color: white;
}

.landing-feature-grid p,
.why-list span,
.pricing-grid p {
    color: var(--white-soft);
}

.workflow-showcase {
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    align-items: start;
}

.workflow-showcase h2 {
    margin: 0;
    font-size: clamp(2.4rem, 5vw, 4.4rem);
    font-weight: 430;
    line-height: 0.98;
}

.why-list article {
    min-height: auto;
}

.landing-proof {
    grid-template-columns: minmax(0, 0.9fr) minmax(320px, 0.7fr);
    align-items: stretch;
}

.landing-proof .property-showcase,
.landing-proof .metric-glass {
    min-height: 390px;
}

.landing-proof .reserve-btn {
    margin-top: 22px;
}

.pricing-grid {
    grid-template-columns: minmax(0, 0.92fr) minmax(380px, 1.28fr) minmax(0, 0.92fr);
    align-items: stretch;
}

.billing-toggle {
    display: inline-grid;
    grid-template-columns: repeat(2, minmax(0, auto));
    gap: 4px;
    margin-bottom: 22px;
    padding: 4px;
    border: 1px solid var(--line);
    border-radius: 14px;
    background: rgba(0, 0, 0, 0.24);
}

.billing-toggle button {
    min-height: 42px;
    border: 0;
    border-radius: 10px;
    background: transparent;
    color: var(--white-soft);
    padding: 0 16px;
    font-weight: 850;
}

.billing-toggle button.active {
    background: white;
    color: var(--ink);
}

.billing-toggle span {
    margin-left: 6px;
    color: var(--amber);
    font-size: 0.76rem;
}

.pricing-grid article {
    gap: 14px;
}

.pricing-grid span {
    color: var(--gold);
    font-weight: 900;
    text-transform: uppercase;
}

.pricing-grid strong {
    margin: 0;
    font-size: 2.6rem;
    font-weight: 520;
}

.pricing-grid small {
    color: var(--white-muted);
    font-weight: 850;
}

.pricing-grid ul {
    display: grid;
    gap: 10px;
    margin: 4px 0;
    padding: 0;
    list-style: none;
}

.pricing-grid li {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    color: var(--white-soft);
}

.pricing-grid li svg {
    flex: 0 0 auto;
    margin-top: 2px;
    color: var(--gold);
}

.price-card {
    position: relative;
}

.pricing-grid .featured-price {
    border-color: rgba(255, 209, 136, 0.48);
    box-shadow:
        0 34px 100px rgba(0, 0, 0, 0.38),
        0 16px 60px rgba(255, 159, 46, 0.5),
        0 4px 20px rgba(255, 209, 136, 0.4),
        inset 0 0 0 1px rgba(255, 209, 136, 0.32);
    transform: translateY(-24px);
}

.best-choice {
    position: absolute;
    top: 18px;
    right: 18px;
    min-height: 30px;
    display: inline-flex;
    align-items: center;
    padding: 0 10px;
    border-radius: 999px;
    background: rgba(255, 209, 136, 0.18);
    color: var(--gold);
    font-size: 0.76rem;
    font-weight: 900;
    text-transform: uppercase;
}

.auth-page {
    display: grid;
    align-content: center;
    gap: 24px;
    width: min(760px, calc(100% - 36px));
    min-height: calc(100vh - 36px);
    margin: 0 auto;
}

.auth-brand {
    justify-self: start;
    color: white;
    text-decoration: none;
}

.auth-panel {
    display: grid;
    gap: 16px;
    padding: clamp(24px, 5vw, 42px);
    border: 1px solid var(--line);
    border-radius: 24px;
    background:
        linear-gradient(145deg, rgba(255, 255, 255, 0.13), rgba(255, 255, 255, 0.05)),
        rgba(7, 27, 32, 0.72);
    box-shadow: 0 34px 90px rgba(0, 0, 0, 0.28);
    backdrop-filter: blur(22px);
}

.auth-panel h1 {
    margin: 0;
    font-size: clamp(2.5rem, 6vw, 4.4rem);
    font-weight: 460;
    line-height: 0.96;
}

.auth-panel p {
    color: var(--white-soft);
}

.public-detail-list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

.support-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    margin: 6px 0;
}

.support-grid article {
    min-height: 150px;
}

.app-sidebar,
.topbar,
.panel,
.stat-card,
.phone-frame,
.booking-card,
.metric-glass,
.repair-panel,
.binder-card,
.property-card,
.msg-shell {
    border: 1px solid var(--line);
    background:
        linear-gradient(145deg, rgba(255, 255, 255, 0.13), rgba(255, 255, 255, 0.05)),
        rgba(7, 27, 32, 0.58);
    box-shadow: 0 34px 90px rgba(0, 0, 0, 0.24);
    backdrop-filter: blur(22px);
}

/* Real Bootstrap offcanvas (.offcanvas-lg on the element in sidebar.php)
   drives the mobile drawer instead of the old hand-rolled body.sidebar-open
   toggle. Positioning below 992px is entirely Bootstrap's; above 992px we
   reinstate the static/sticky panel look in the media query further down. */
.app-sidebar {
    border-radius: 26px;
    --bs-offcanvas-width: 272px;
    --bs-offcanvas-bg: rgba(5, 18, 23, 0.92);
    --bs-offcanvas-color: white;
    --bs-offcanvas-border-color: var(--line);
}

.app-sidebar .offcanvas-header {
    border-bottom: 1px solid var(--line);
    color: white;
}

.app-sidebar .offcanvas-body {
    display: flex;
    flex-direction: column;
    gap: 24px;
    padding: 16px;
}

@media (min-width: 992px) {
    .app-sidebar {
        position: sticky;
        top: 18px;
        height: calc(100vh - 36px);
        /* Bootstrap's own .offcanvas-lg rule sets background-color: transparent
           !important at this breakpoint; match !important to reinstate the
           shared glass-panel background from the combined selector above. */
        background:
            linear-gradient(145deg, rgba(255, 255, 255, 0.13), rgba(255, 255, 255, 0.05)),
            rgba(7, 27, 32, 0.58) !important;
    }

    .app-sidebar .offcanvas-body {
        background: transparent !important;
        height: 100%;
    }
}

.brand-mark {
    display: flex;
    gap: 12px;
    align-items: center;
    padding: 8px;
    text-decoration: none;
}

.brand-icon,
.stat-icon {
    display: grid;
    place-items: center;
    width: 42px;
    height: 42px;
    border-radius: 14px;
    background: rgba(255, 159, 46, 0.22);
    color: var(--amber);
}

.brand-mark strong,
.brand-mark small {
    display: block;
}

.brand-mark small {
    color: var(--white-muted);
    font-size: 0.78rem;
}

.sidebar-nav {
    display: grid;
    gap: 6px;
    margin-top: 28px;
}

.sidebar-link {
    display: flex;
    gap: 12px;
    align-items: center;
    min-height: 46px;
    padding: 0 12px;
    border-radius: 14px;
    color: var(--white-soft);
    font-weight: 750;
    text-decoration: none;
    transition: transform 180ms var(--ease), background 180ms var(--ease), color 180ms var(--ease);
}

/* Unread-count pill on a nav item (currently just the tenant portal's
   Message Center link) -- same red-pill treatment as .notification-bell-badge,
   but inline/margin-left:auto instead of absolutely positioned, since this
   sits at the end of a flex row rather than pinned to a small icon button. */
.sidebar-badge {
    margin-left: auto;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: 999px;
    background: var(--danger);
    color: #fff;
    font-size: 0.72rem;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
}

.sidebar-link:hover,
.sidebar-link.active {
    transform: translateX(4px);
    background: rgba(255, 255, 255, 0.14);
    color: white;
}

.sidebar-callout {
    margin-top: auto;
    padding: 18px;
    border-radius: 22px;
    background: rgba(0, 0, 0, 0.26);
}

.sidebar-callout p {
    margin: 8px 0 0;
    color: var(--white-muted);
    font-size: 0.86rem;
}

.topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    min-height: 76px;
    margin-bottom: 22px;
    padding: 16px 18px;
    border-radius: 26px;
}

.topbar h1 {
    margin: 0;
    font-size: 24px;
    font-weight: 700;
    line-height: 1.2;
}

.topbar-actions,
.hero-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-items: center;
}

.icon-button,
.glass-icon {
    display: inline-grid;
    place-items: center;
    width: 44px;
    height: 44px;
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.12);
    color: white;
    text-decoration: none;
    transition: transform 180ms var(--ease), background 180ms var(--ease);
}

.icon-button:hover,
.glass-icon:hover {
    transform: translateY(-2px);
    background: rgba(255, 255, 255, 0.18);
}

.menu-button {
    display: none;
}

.btn,
.reserve-btn,
.nav-cta,
.ghost-btn {
    display: inline-flex;
    gap: 8px;
    align-items: center;
    justify-content: center;
    text-decoration: none;
    transition: transform 200ms var(--ease), background 200ms var(--ease), box-shadow 200ms var(--ease);
}

/* .reserve-btn/.nav-cta/.ghost-btn are landing.php-only (the marketing hero
   page) — kept at their original size/weight, since STYLE_GUIDE.md reserves
   the heavier "Modern Frame Treatment" for marketing surfaces specifically.
   Only .btn (every operational page's buttons) moves to the mockup's
   compact sizing below. */
.reserve-btn,
.nav-cta,
.ghost-btn {
    min-height: 46px;
    padding: 0 20px;
    border-radius: 14px;
    font-weight: 850;
}

.btn {
    min-height: 40px;
    padding: 0 16px;
    border-radius: 16px;
    font-weight: 600;
}

.reserve-btn,
.btn-light {
    border: 0;
    background: white;
    color: #071b20;
}

.nav-cta {
    border: 0;
    background: linear-gradient(135deg, var(--amber), #ffb84d);
    color: var(--ink);
    box-shadow:
        0 8px 24px rgba(255, 159, 46, 0.35),
        0 2px 8px rgba(0, 0, 0, 0.15);
}

.reserve-btn:hover,
.btn-light:hover {
    transform: translateY(-3px);
    box-shadow: 0 18px 42px rgba(0, 0, 0, 0.2);
}

.nav-cta:hover {
    transform: translateY(-3px);
    box-shadow:
        0 12px 32px rgba(255, 159, 46, 0.45),
        0 4px 12px rgba(0, 0, 0, 0.2);
}

.ghost-btn,
.btn-outline-dark,
.btn-dark {
    border: 1px solid var(--line);
    background: rgba(255, 255, 255, 0.1);
    color: white;
}

.btn-dark:hover,
.btn-outline-dark:hover,
.ghost-btn:hover {
    background: rgba(255, 255, 255, 0.16);
    color: white;
}

.btn-danger { background: var(--danger); border-color: var(--danger); color: #2a0a02; }
.btn-danger:hover { background: #ff8259; border-color: #ff8259; }

.btn-text-danger { border: none; background: none; color: var(--danger); font-size: var(--fs-sm); font-weight: 650; cursor: pointer; padding: 9px 4px; }
.btn-text-danger:hover { text-decoration: underline; }
.btn-text-danger[hidden] { display: none; }

.btn-ghost { background: #123039; color: var(--white); border: 1px solid rgba(255,255,255,.24); }
.btn-ghost:hover { border-color: var(--gold); }

.btn-sm { min-height: 0; padding: 7px 13px; font-size: .8rem; }
.btn-block { width: 100%; justify-content: center; margin-top: 6px; }

.hero-world {
    min-height: clamp(720px, 92vh, 900px);
    padding: 10px;
}

.hero-frame {
    position: relative;
    display: grid;
    grid-template-rows: auto 1fr auto;
    width: min(100%, 1500px);
    min-height: clamp(680px, calc(100vh - 38px), 860px);
    margin: 0 auto;
    overflow: hidden;
    padding: clamp(26px, 4vw, 64px);
    border-radius: 56px;
    background:
        linear-gradient(90deg, rgba(7, 27, 32, 0.86), rgba(7, 27, 32, 0.42)),
        linear-gradient(0deg, rgba(7, 27, 32, 0.56), rgba(7, 27, 32, 0.1)),
        url("https://images.unsplash.com/photo-1500534314209-a25ddb2bd429?auto=format&fit=crop&w=2200&q=84") center/cover;
    box-shadow:
        0 34px 90px rgba(0, 0, 0, 0.42),
        inset 0 0 0 6px rgba(255, 255, 255, 0.24),
        inset 0 1px 0 rgba(255, 255, 255, 0.18);
}

.hero-frame::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: radial-gradient(circle at 52% 76%, rgba(255, 159, 46, 0.22), transparent 18rem);
}

.hero-frame > * {
    position: relative;
    z-index: 1;
}

.hero-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 22px;
}

.hero-nav div {
    display: flex;
    flex-wrap: wrap;
    gap: clamp(16px, 3vw, 38px);
}

.hero-nav a {
    color: white;
    font-weight: 850;
    text-decoration: none;
}

.brand {
    display: inline-flex;
    gap: 14px;
    align-items: center;
}

.brand-mark-dot {
    width: 32px;
    height: 16px;
    border-radius: 999px;
    background: var(--amber);
    box-shadow: 0 0 18px rgba(255, 159, 46, 0.48);
}

.hero-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(320px, 460px);
    gap: clamp(24px, 5vw, 72px);
    align-items: center;
}

.hero-copy h2 {
    margin: 0;
    max-width: 740px;
    font-size: clamp(4.6rem, 10vw, 9.4rem);
    font-weight: 400;
    line-height: 0.84;
    letter-spacing: 0;
}

.hero-copy span {
    color: rgba(255, 255, 255, 0.42);
}

.booking-card {
    padding: clamp(24px, 3vw, 34px);
    border-radius: 32px;
    background:
        linear-gradient(145deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.05)),
        rgba(7, 27, 32, 0.72);
}

.card-title-row,
.hero-footer,
.property-footer,
.panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
}

.card-title-row h3 {
    margin: 0;
    font-size: clamp(2rem, 4vw, 3.1rem);
    font-weight: 460;
    line-height: 0.95;
}

.panel-actions {
    display: inline-flex;
    align-items: center;
    gap: 10px;
}

.checkbox-row {
    display: inline-flex;
    align-items: center;
    gap: 10px;
}

.checkbox-row input[type="checkbox"] {
    width: 16px;
    height: 16px;
    margin: 0;
}

.guided-next {
    margin: 10px 0 16px;
    padding: 12px 14px;
    border: 1px solid rgba(134, 215, 255, 0.35);
    border-radius: 12px;
    background: rgba(134, 215, 255, 0.12);
}

.guided-next strong {
    display: block;
    margin-bottom: 4px;
}

.guided-next p {
    margin: 0 0 8px;
    color: rgba(255, 255, 255, 0.86);
}

.pending-requests-section {
    margin: 10px 0 20px;
    padding: 14px 16px;
    border: 1px solid rgba(255, 209, 136, 0.35);
    border-radius: 12px;
    background: rgba(255, 209, 136, 0.08);
}

.pending-requests-header h3 {
    margin: 0 0 2px;
    font-size: 1rem;
}

.pending-requests-header p {
    margin: 0 0 10px;
    color: rgba(255, 255, 255, 0.68);
    font-size: 0.86rem;
}

.pending-request-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.pending-request-actions .form-select {
    width: auto;
    min-width: 200px;
}

html[data-theme="light"] .pending-requests-section {
    border-color: rgba(160, 120, 30, 0.35);
    background: rgba(160, 120, 30, 0.08);
}

html[data-theme="light"] .pending-requests-header p {
    color: rgba(30, 24, 15, 0.68);
}

.repair-row-shell {
    display: grid;
    gap: 8px;
}

.repair-row-actions,
.row-inline-actions {
    display: inline-flex;
    gap: 8px;
    align-items: center;
}

.repair-row-actions {
    justify-content: flex-end;
    padding-right: 6px;
}

.data-row-shell {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 10px;
}

.data-row-main {
    display: grid;
    grid-template-columns: 1.2fr 1fr 0.9fr 0.8fr 0.7fr;
    gap: 12px;
    align-items: center;
    text-decoration: none;
    color: inherit;
}

.date-grid,
.detail-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
    margin-top: 28px;
}

.date-grid span,
.detail-grid span {
    display: flex;
    gap: 10px;
    align-items: center;
    min-height: 58px;
    padding: 0 14px;
    border-radius: 12px;
    background: rgba(0, 0, 0, 0.28);
    color: var(--white-soft);
    font-weight: 850;
}

.detail-grid small {
    display: block;
    color: rgba(255, 255, 255, 0.42);
    font-weight: 800;
}

.price-row {
    display: flex;
    gap: 14px;
    align-items: baseline;
    margin: 32px 0 24px;
}

.price-row strong {
    font-size: 3rem;
    font-weight: 460;
}

.price-row span,
.hero-footer p,
.rating span {
    color: var(--white-soft);
}

.hero-footer {
    align-items: flex-end;
}

.hero-footer p {
    max-width: 420px;
    margin: 0;
    font-size: 1.06rem;
    font-weight: 650;
}

.rating {
    display: flex;
    gap: 12px;
    align-items: center;
}

.rating i {
    color: white;
}

.rating strong {
    font-size: 2.2rem;
    font-weight: 500;
}

.glass-band,
.binder-section,
.repair-world {
    width: min(1240px, calc(100% - 36px));
    margin: 0 auto;
    padding: 70px 0;
}

.section-heading {
    max-width: 760px;
    margin-bottom: 28px;
}

.eyebrow {
    margin: 0 0 8px;
    color: var(--gold);
    font-size: 0.72rem;
    font-weight: 900;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.section-heading h2,
.binder-card h2 {
    margin: 0;
    font-size: clamp(2.4rem, 5vw, 4.7rem);
    font-weight: 430;
    line-height: 0.98;
}

.portfolio-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 22px;
}

.property-showcase,
.metric-glass {
    min-height: 460px;
    border-radius: 30px;
}

.property-showcase {
    position: relative;
    overflow: hidden;
}

.property-showcase img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 420ms var(--ease);
}

.property-showcase:hover img {
    transform: scale(1.04);
}

.property-showcase::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(0deg, rgba(7, 27, 32, 0.82), transparent 62%);
}

.property-showcase div {
    position: absolute;
    left: 28px;
    right: 28px;
    bottom: 28px;
    z-index: 1;
}

.property-showcase span {
    color: var(--gold);
    font-weight: 850;
}

.property-showcase h3 {
    margin: 12px 0 8px;
    font-size: 2.45rem;
    font-weight: 460;
    line-height: 0.98;
}

.property-showcase p,
.metric-glass span,
.repair-row p,
.binder-card p {
    color: var(--white-soft);
}

.metric-glass {
    padding: 26px;
}

.chart-title {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    min-height: 28px;
}

.chart-title i {
    width: 20px;
    height: 20px;
    color: var(--amber);
}

.metric-glass small {
    color: var(--white-muted);
    font-weight: 850;
}

.metric-glass strong {
    display: block;
    margin: 8px 0;
    font-size: clamp(2.7rem, 4vw, 3.45rem);
    font-weight: 460;
    line-height: 0.96;
}

.chart-card-head {
    display: grid;
    gap: 10px;
}

.rent-ledger,
.repair-cost-card {
    display: grid;
    gap: 8px;
    margin-top: 22px;
    padding: 12px;
    border-radius: 20px;
    background:
        linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.03)),
        rgba(0, 0, 0, 0.2);
}

.ledger-row {
    position: relative;
    display: grid;
    grid-template-columns: 42px minmax(80px, 1fr) minmax(82px, auto) 12px;
    gap: 10px;
    align-items: center;
    min-height: 38px;
    padding: 0 12px;
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 14px;
    background: rgba(255, 255, 255, 0.06);
    color: var(--white-soft);
    text-decoration: none;
    transition: transform 180ms var(--ease), background 180ms var(--ease), border-color 180ms var(--ease);
}

.ledger-row:hover {
    transform: translateX(4px);
    border-color: rgba(255, 255, 255, 0.18);
    background: rgba(255, 255, 255, 0.11);
}

.ledger-row span {
    color: var(--white-muted);
    font-size: 0.78rem;
    font-weight: 850;
}

.ledger-row strong {
    margin: 0;
    font-size: 1rem;
    font-weight: 850;
}

.ledger-row em {
    color: rgba(255, 255, 255, 0.66);
    font-size: 0.76rem;
    font-style: normal;
    font-weight: 800;
    text-align: right;
}

.ledger-row i,
.repair-stage::before,
.repair-status i,
.chart-legend span {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--sky);
    box-shadow: 0 0 16px rgba(134, 215, 255, 0.42);
}

.ledger-row.late i,
.repair-stage.attention::before,
.repair-status.attention i,
.chart-legend .late {
    background: var(--gold);
    box-shadow: 0 0 16px rgba(255, 209, 136, 0.42);
}

.ledger-row.processing i,
.chart-legend .processing {
    background: rgba(255, 255, 255, 0.54);
    box-shadow: 0 0 16px rgba(255, 255, 255, 0.18);
}

.ledger-row::after,
.repair-stage::after,
.cost-rowline::after {
    content: attr(data-tip);
    position: absolute;
    left: 50%;
    bottom: calc(100% + 12px);
    z-index: 10;
    width: max-content;
    max-width: 230px;
    padding: 10px 12px;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: rgba(4, 15, 19, 0.94);
    color: white;
    font-size: 0.78rem;
    font-weight: 750;
    opacity: 0;
    pointer-events: none;
    transform: translate(-50%, 6px);
    transition: opacity 160ms var(--ease), transform 160ms var(--ease);
}

.ledger-row:hover::after,
.repair-stage:hover::after,
.cost-rowline:hover::after {
    opacity: 1;
    transform: translate(-50%, 0);
}

.chart-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    align-items: center;
    margin-top: 16px;
    color: rgba(255, 255, 255, 0.68);
    font-size: var(--fs-xs);
}

.chart-legend .on-time {
    background: var(--sky);
}

.chart-legend .urgent-dot {
    background: var(--danger);
    box-shadow: 0 0 16px rgba(255, 107, 58, 0.48);
}

.repair-snapshot {
    display: grid;
    gap: 16px;
    margin-top: 22px;
}

.repair-stage-map {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px;
    margin-top: 22px;
}

/* Grid, not the flex-column + inner .stage-top wrapper the mockup uses —
   the dot is generated content (::before), shared with .ledger-row/
   .repair-status/.chart-legend's dot rule below, so it can't be wrapped in
   a real element without duplicating that markup pattern in both this file
   and open-repairs-card.php. A 2-column/2-row grid gets the same visual
   result (dot beside the number on row 1, label spanning both columns on
   row 2) without touching the dot's shared sizing/color rules. */
.repair-stage {
    position: relative;
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: 8px;
    row-gap: 4px;
    align-items: center;
    min-width: 0;
    min-height: 92px;
    padding: 12px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 16px;
    background: rgba(0, 0, 0, 0.2);
    color: white;
    text-decoration: none;
    transition: transform 190ms var(--ease), background 190ms var(--ease), border-color 190ms var(--ease);
}

.repair-stage:hover {
    transform: translateY(-3px);
    border-color: rgba(255, 255, 255, 0.2);
    background: rgba(255, 255, 255, 0.1);
}

.repair-stage::before {
    content: "";
    display: block;
    grid-column: 1;
    grid-row: 1;
}

.repair-stage.urgent::before,
.repair-status.urgent i {
    background: var(--danger);
    box-shadow: 0 0 18px rgba(255, 107, 58, 0.48);
}

.repair-stage.info::before,
.repair-status.info i {
    background: var(--sky);
    box-shadow: 0 0 18px rgba(134, 215, 255, 0.38);
}

.repair-stage span {
    grid-column: 2;
    grid-row: 1;
    color: white;
    font-size: var(--fs-lg);
    font-weight: 700;
    line-height: 1.2;
}

.repair-stage em {
    grid-column: 1 / -1;
    grid-row: 2;
    min-width: 0;
    overflow: hidden;
    color: rgba(255, 255, 255, 0.68);
    font-size: var(--fs-sm);
    font-style: normal;
    font-weight: 600;
    line-height: 1.15;
    text-overflow: ellipsis;
}

/* Tone-colored border + number, matching the approved repairs-pilot mockup
   (mockups/repairs-pilot.html's .repair-stage.urgent/.attention/.info) —
   the dot-only treatment above predates that pilot and read as too subtle
   once repairs.php started using these cards as active filter toggles, not
   just a static summary. Shared with the Dashboard's Open Repairs card
   (open-repairs-card.php), which gets the same upgrade for free. */
.repair-stage.urgent {
    border-color: rgba(255, 107, 58, 0.4);
}

.repair-stage.urgent span {
    color: var(--danger);
}

.repair-stage.attention {
    border-color: rgba(255, 209, 136, 0.4);
}

.repair-stage.attention span {
    color: var(--gold);
}

.repair-stage.info {
    border-color: rgba(134, 215, 255, 0.4);
}

.repair-stage.info span {
    color: var(--sky);
}

/* Active-filter state — only meaningful on repairs.php, where these cards
   double as links that toggle the workflow filter (aria-current="true"
   when selected). Harmless no-op on the Dashboard card, which never sets
   aria-current. */
.repair-stage.active {
    background: rgba(255, 255, 255, 0.16);
    border-width: 2px;
}

.repair-cost-card {
    margin-top: 0;
}

.cost-rowline {
    position: relative;
    display: grid;
    grid-template-columns: minmax(96px, 1fr) 74px;
    gap: 12px;
    align-items: center;
    color: rgba(255, 255, 255, 0.68);
    font-size: 0.78rem;
    font-weight: 800;
}

.cost-rowline strong {
    color: white;
    font-size: 0.92rem;
    text-align: right;
}

.cost-rowline i {
    grid-column: 1 / -1;
    display: block;
    height: 9px;
    overflow: hidden;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.13);
}

.cost-rowline b {
    display: block;
    height: 100%;
    border-radius: inherit;
}

.cost-rowline.exposure b {
    background: linear-gradient(90deg, var(--gold), var(--danger));
}

.cost-rowline.approved b {
    background: var(--sky);
}

.cost-rowline.invoiced b {
    background: rgba(255, 255, 255, 0.52);
}

.repair-world {
    width: 100%;
    padding-inline: max(18px, calc((100vw - 1240px) / 2));
    background:
        linear-gradient(120deg, rgba(7, 27, 32, 0.94), rgba(29, 88, 96, 0.54)),
        url("https://images.unsplash.com/photo-1560185127-6ed189bf02f4?auto=format&fit=crop&w=1800&q=82") center/cover;
}

.repair-panel,
.binder-card {
    padding: clamp(24px, 4vw, 46px);
    border-radius: 34px;
}

.repair-stack,
.repair-list {
    display: grid;
    gap: 14px;
    margin-top: 28px;
}

.repair-row {
    display: grid;
    grid-template-columns: 110px minmax(0, 1fr) minmax(190px, 0.7fr) minmax(120px, auto);
    gap: 18px;
    align-items: center;
    min-height: 82px;
    padding: 18px;
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 16px;
    background: rgba(255, 255, 255, 0.1);
    transition: transform 220ms var(--ease), background 220ms var(--ease);
}

.repair-row:hover {
    transform: translateX(6px);
    background: rgba(255, 255, 255, 0.15);
}

.repair-status {
    display: inline-flex;
    gap: 10px;
    align-items: center;
    color: var(--gold);
    font-weight: 850;
}

.repair-main strong,
.repair-meta span {
    display: block;
    color: white;
}

.repair-main span,
.repair-meta small,
.repair-eta,
.muted-copy {
    color: var(--white-soft);
}

/* ============================================================
   Repairs page work-order rows (2026 redesign) — replaces repair-row.php's
   always-visible Review/Schedule/Close trio with one status-driven next
   action per row (repair-item.php). Grid, not flex: with the action button
   sized to its own label ("View" vs "Review & approve"), a flex row let
   leftover space get split unevenly between the title and status columns,
   so their left edges drifted per row depending on that row's label length.
   Fixed/matched tracks keep every row's columns aligned regardless of
   content length.
   ============================================================ */
.repair-item-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-top: 20px;
}

.repair-item {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) minmax(0, 1fr) 190px;
    align-items: center;
    gap: 16px;
    padding: 12px 16px;
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 16px;
    background: rgba(255, 255, 255, 0.1);
}

.repair-item-flag {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--line);
}

.repair-item.urgent .repair-item-flag { background: var(--danger); box-shadow: 0 0 12px rgba(255, 107, 58, 0.5); }
.repair-item.attention .repair-item-flag { background: var(--gold); box-shadow: 0 0 12px rgba(255, 209, 136, 0.5); }
.repair-item.info .repair-item-flag { background: var(--sky); box-shadow: 0 0 12px rgba(134, 215, 255, 0.5); }
.repair-item.done .repair-item-flag { background: rgba(255, 255, 255, 0.5); }

.repair-item-main {
    min-width: 0;
    text-decoration: none;
    color: inherit;
}

.repair-item-main strong {
    display: block;
    font-size: var(--fs-md);
    color: white;
}

.repair-item-main span {
    display: block;
    font-size: var(--fs-sm);
    color: var(--white-soft);
    margin-top: 2px;
}

.repair-item-main:hover strong {
    text-decoration: underline;
}

.repair-item-meta {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: var(--fs-xs);
    color: var(--white-soft);
}

.repair-item-meta strong {
    font-size: var(--fs-sm);
    font-weight: 600;
    color: white;
}

.repair-item-action {
    display: flex;
    justify-content: flex-end;
}

/* The shared .btn now already matches the mockup's compact sizing site-wide
   (see the "site-wide mockup parity pass" further down), so only font-size
   still needs setting here — .btn itself doesn't declare one, it inherits
   from context, which isn't 14px by default inside a .repair-item. */
.repair-item-action .btn {
    font-size: var(--fs-md);
}

@media (max-width: 767px) {
    .repair-item {
        grid-template-columns: auto 1fr;
    }

    .repair-item-meta,
    .repair-item-action {
        grid-column: 1 / -1;
    }

    .repair-item-action .btn {
        width: 100%;
    }
}

/* Quick vendor-contact trigger — a labeled text button, not an icon-only
   circle, so it doesn't repeat the sub-40px icon-button issue flagged in
   docs/UX_REVIEW.md. Opens a Bootstrap popover (phone/email + a link back
   to this work order); see repairs.php's inline script for the JS init
   Bootstrap requires for popovers (unlike modal/offcanvas, not automatic). */
.vendor-contact-btn {
    display: inline-flex;
    align-items: center;
    align-self: flex-start;
    gap: 3px;
    min-height: 22px;
    padding: 0 6px;
    margin-top: 2px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, 0.16);
    background: rgba(255, 255, 255, 0.08);
    color: var(--sky);
    font-size: var(--fs-2xs);
    font-weight: 600;
    cursor: pointer;
}

.vendor-contact-btn:hover {
    background: rgba(255, 255, 255, 0.16);
}

.vendor-contact-btn svg {
    width: 11px;
    height: 11px;
}

/* Bootstrap's popover pulls border/background/arrow-fill from its own
   --bs-popover-* custom properties — a plain .popover-body background rule
   would leave the arrow triangle unstyled against a colored body. */
.popover {
    --bs-popover-max-width: 240px;
    --bs-popover-bg: rgba(15, 32, 38, 0.98);
    --bs-popover-border-color: var(--line);
    --bs-popover-header-bg: rgba(255, 255, 255, 0.1);
    --bs-popover-header-color: white;
    --bs-popover-body-color: white;
    --bs-popover-body-padding-x: 14px;
    --bs-popover-body-padding-y: 14px;
}

.vendor-popover-name {
    display: block;
    font-weight: 700;
    margin-bottom: 4px;
}

.vendor-popover-detail {
    display: block;
    color: var(--white-soft);
    font-size: var(--fs-xs);
}

.vendor-popover-link {
    display: inline-block;
    margin-top: 8px;
    color: var(--amber);
    font-weight: 600;
    text-decoration: underline;
    font-size: var(--fs-xs);
}

/* Filter bar above the work-order list — inputs/selects reuse the app-wide
   .form-control/.form-select treatment defined earlier in this file; this
   only adds the row layout and each field's relative width. */
.filter-bar {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    align-items: center;
    margin: 20px 0;
}

.filter-search {
    flex: 1 1 220px;
}

.filter-location,
.filter-workflow {
    flex: 0 1 190px;
}

/* Compact field sizing, scoped to the filter bar and the New Repair modal
   only — matches the approved mockup's 40px/16px-radius/13px-font controls
   exactly (mockups/repairs-pilot.html) without touching the shared
   site-wide .form-control/.form-select (50px/12px-radius/16px-font),
   which every other form on the app still uses unchanged. #repairSearch is
   named explicitly because its <input> also matches the much higher-
   specificity `.app-frame input:not([type=...]):not(...):not(...):not(...)`
   rule above (four :not() clauses inflate that selector's specificity well
   past a two-class selector) — an ID is the simplest way to still win. */
.filter-bar .form-control,
.filter-bar .form-select,
.modal-body .form-control,
.modal-body .form-select,
#repairSearch {
    height: 40px;
    padding: 6px 12px;
    border-radius: 16px;
    font-size: var(--fs-sm);
}

.filter-bar .form-select,
.modal-body .form-select {
    padding-right: 32px;
}

.filter-button {
    flex: none;
    font-size: var(--fs-sm);
    white-space: nowrap;
}

/* .btn-light's shared background matches the panel surface by design (see
   its rule above) so it reads as a quiet secondary action elsewhere on the
   site — against this specific button bar it left Filter blending into the
   panel with no visible affordance, so it gets its own tinted surface. */
.filter-button {
    background: rgba(255, 255, 255, 0.08);
}

.repair-list-footer {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 20px;
}

/* Pagination — Bootstrap's own .pagination/.page-link, retinted. Only
   rendered by the view once the filtered result count exceeds one page. */
.pagination {
    margin: 0;
}

.page-link {
    border: 1px solid var(--line);
    color: white;
    background-color: rgba(255, 255, 255, 0.08);
}

.page-link:hover {
    background-color: rgba(255, 255, 255, 0.16);
    color: white;
}

.page-item.active .page-link {
    background-color: var(--amber);
    border-color: var(--amber);
    color: #0a171a;
}

.page-item.disabled .page-link {
    color: var(--white-muted);
    background-color: rgba(255, 255, 255, 0.06);
}

/* Warranty watch — a compact list, not the full data-table + disposition
   form the old page had; the actual disposition action lives on the
   repair's own detail page now. */
.warranty-watch-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 4px;
}

.warranty-watch-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 14px;
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 16px;
    text-decoration: none;
    color: white;
    font-size: var(--fs-sm);
}

.warranty-watch-row:hover {
    background: rgba(255, 255, 255, 0.08);
}

.warranty-watch-row span {
    display: block;
    color: var(--white-soft);
    font-size: var(--fs-xs);
}

/* Success banner after logging a repair via the New Repair Request modal. */
.repair-confirm-banner {
    display: none;
    align-items: center;
    gap: 12px;
    padding: 16px;
    border: 1px solid var(--sky);
    border-radius: 16px;
    background: rgba(134, 215, 255, 0.12);
    color: white;
    font-size: var(--fs-sm);
    margin-bottom: 20px;
}

.repair-confirm-banner.show {
    display: flex;
}

.repair-confirm-banner strong {
    display: block;
}

/* Event rows in the work calendar's day agenda are real links to the
   matching repair — restores normal link semantics on top of .event-row
   (a plain, non-interactive div where the dashboard's Schedule card uses it). */
a.event-row {
    text-decoration: none;
    color: inherit;
    cursor: pointer;
}

a.event-row:hover {
    background: rgba(255, 255, 255, 0.11);
}

/* Bootstrap modal — retint from its white-only default. Only used by the
   New Repair Request modal today; the app's other modal-like surfaces
   (repair-detail.php's photo lightbox) use a bespoke .rp-modal instead. */
.modal-content {
    background: linear-gradient(135deg, #0d2b31 0%, #1b3f45 100%);
    color: white;
    border: 1px solid var(--line);
    border-radius: 20px;
}

.modal-header,
.modal-footer {
    border-color: var(--line);
}

.modal-title {
    font-weight: 700;
}

.modal-body .form-label {
    display: block;
    font-size: var(--fs-sm);
    font-weight: 600;
    margin-bottom: 4px;
}

.modal-body textarea.form-control {
    min-height: 88px;
}

.modal-field {
    margin-bottom: 16px;
}

.modal-field:last-child {
    margin-bottom: 0;
}

.binder-card {
    min-height: 460px;
    display: grid;
    align-content: end;
    background:
        linear-gradient(120deg, rgba(7, 27, 32, 0.76), rgba(29, 88, 96, 0.42)),
        url("https://images.unsplash.com/photo-1494526585095-c41746248156?auto=format&fit=crop&w=1800&q=84") center/cover;
}

.binder-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1px;
    margin-top: 28px;
}

.binder-grid span {
    display: inline-flex;
    gap: 10px;
    align-items: center;
    min-height: 64px;
    padding: 0 16px;
    border-radius: 12px;
    background: rgba(0, 0, 0, 0.28);
}

.panel {
    padding: 24px;
    border-radius: 16px;
}

.panel h2 {
    margin: 0;
    font-size: clamp(1.6rem, 3vw, 2.4rem);
    font-weight: 520;
}

/* The vendor's own estimate/accepted-quote panel on the work order page --
   a slim accent rule across the top plus a document-like header row (title
   left, amount/status right) is what actually reads as "a quote" rather
   than just another form panel. */
.quote-panel {
    border-top: 3px solid var(--amber);
}

.quote-panel-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 16px;
}

.quote-panel-header h3 {
    margin: 4px 0 0;
}

.quote-panel-header > strong {
    font-size: var(--fs-lg);
    white-space: nowrap;
}

/* Vendor dashboard's summary tiles -- reuses the real .stat-card/.stat-icon
   primitives (app.css already defines the glass background + icon badge
   for both) rather than a one-off card, but neither one ever shipped with
   an actual icon+text layout of its own (unit-detail.php's own
   ".unit-key-stats .stat-card" override is a different, icon-less shape),
   so that layout is completed here, scoped the same way that one is. */
.vendor-stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 16px;
}

.vendor-stat-grid .stat-card {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 20px;
    text-decoration: none;
    color: inherit;
}

.vendor-stat-grid a.stat-card {
    transition: transform 180ms var(--ease), border-color 180ms var(--ease);
}

.vendor-stat-grid a.stat-card:hover {
    transform: translateY(-2px);
    border-color: var(--amber);
}

/* Vendor settings' Profile tab, restyled as a LinkedIn-style masthead:
   a small round avatar with a corner edit badge sitting beside the
   vendor's name/trade, instead of the photo living in its own
   full-width card (that card's "Photo" heading + a 64px-tall dashed
   drop-zone button for a single avatar was most of the tab's height
   for very little actual content). */
.vendor-profile-header {
    display: flex;
    align-items: center;
    gap: 20px;
    flex-wrap: wrap;
}

.vendor-avatar-wrap {
    position: relative;
    width: 96px;
    height: 96px;
    flex-shrink: 0;
}

.vendor-avatar-placeholder {
    position: absolute;
    inset: 0;
    border-radius: 999px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 209, 136, 0.16);
    border: 1px solid var(--line);
    color: var(--gold);
    font-size: 2.1rem;
    font-weight: 700;
}

/* Reuses the shared photo-upload-field component's own classes
   (.wt-photo-grid/-thumb/-upload-btn), just re-sized, rounded, and
   pinned to a 96px badge within this one field instead of changing
   the component's default look everywhere else it's used (galleries,
   walkthrough photos, Document Items). */
.vendor-avatar-field [data-photo-row] {
    position: absolute;
    inset: 0;
    padding: 0;
}

.vendor-avatar-field .wt-condition-label {
    display: none;
}

.vendor-avatar-field .wt-photo-grid {
    grid-template-columns: 96px;
    margin: 0;
}

.vendor-avatar-field .wt-photo-thumb {
    width: 96px;
    height: 96px;
    border-radius: 999px;
}

.vendor-avatar-field .wt-photo-upload-btn {
    position: absolute;
    right: -3px;
    bottom: -3px;
    z-index: 1;
    width: 34px;
    height: 34px;
    min-height: 0;
    padding: 0;
    border-radius: 999px;
    border: 2px solid var(--ink-2);
    background: var(--gold);
    color: var(--ink);
    /* No gap -- the button's visible label sits in .wt-photo-upload-btn-label
       below, taken out of flow (visually-hidden, but still in the
       accessible name) so the base component's `gap: 10px` between icon
       and label can't shove the icon off-center inside this tiny circle. */
    gap: 0;
}

.vendor-avatar-field .wt-photo-upload-btn:focus-visible {
    outline: 2px solid var(--sky);
    outline-offset: 2px;
}

.vendor-avatar-field .wt-photo-upload-btn svg {
    width: 16px;
    height: 16px;
}

/* Visually-hidden but still announced by screen readers -- keeps the
   button's real accessible name ("Change photo") without the base
   component's visible text competing for space in a 34px circle. */
.vendor-avatar-field .wt-photo-upload-btn-label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.vendor-avatar-photo-error {
    margin: 6px 0 0;
    color: var(--danger);
    font-size: var(--fs-xs);
}

.vendor-profile-identity {
    min-width: 0;
}

.vendor-profile-name {
    margin: 2px 0 4px;
    font-size: var(--fs-xl);
    font-weight: 650;
}

.vendor-profile-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 0 0 4px;
    color: var(--white-soft);
    font-size: var(--fs-sm);
}

.vendor-profile-tagline {
    margin: 0;
    color: var(--white-muted);
    font-size: var(--fs-xs);
}

.vendor-profile-divider {
    border: none;
    border-top: 1px solid var(--line);
    margin: 22px 0;
}

.vendor-stat-grid .stat-card p {
    margin: 0;
    font-size: 26px;
    font-weight: 750;
    line-height: 1.1;
}

.vendor-stat-grid .stat-card span {
    font-size: 0.78rem;
    color: var(--white-soft);
}

/* A simple, honest two-row bar comparison (total invoiced vs. average job)
   -- real numbers only, no fabricated trend line, since that's all
   RepairInvoiceRepository::summaryForVendor() actually has to show. */
.bar-compare {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.bar-compare-row {
    display: grid;
    grid-template-columns: 110px 1fr 100px;
    align-items: center;
    gap: 12px;
}

.bar-compare-label {
    font-size: 0.82rem;
    color: var(--white-soft);
}

.bar-compare-track {
    height: 10px;
    border-radius: 6px;
    background: rgba(255, 255, 255, 0.08);
    overflow: hidden;
}

.bar-compare-fill {
    height: 100%;
    border-radius: 6px;
    background: var(--amber);
}

.bar-compare-fill.muted {
    background: var(--info);
}

.bar-compare-value {
    font-size: 0.85rem;
    font-weight: 700;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* .hero-title never had a rule at all — every h2.hero-title (Work calendar,
   All repairs, Warranty watch, Repair triage) was silently falling through
   to .panel h2's giant clamp() size above. .panel-heading-row .hero-title
   (two classes) is needed, not a bare .hero-title, specifically to outrank
   .panel h2 (one class + one type = the same specificity tier a bare class
   selector loses to). */
.panel-heading-row .hero-title {
    margin: 0;
    font-size: var(--fs-lg);
    font-weight: 500;
    color: white;
}

.content-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.2fr) minmax(280px, 0.8fr);
    gap: 22px;
}

.workflow-strip {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 12px;
    margin-top: 22px;
}

.workflow-strip a,
.workflow-strip span {
    min-height: 54px;
    display: grid;
    place-items: center;
    border: 1px solid var(--line);
    border-radius: 16px;
    background: rgba(255, 255, 255, 0.1);
    color: var(--white-muted);
    font-weight: 850;
    text-decoration: none;
    transition: transform 180ms var(--ease), background 180ms var(--ease), border-color 180ms var(--ease), color 180ms var(--ease);
}

.workflow-strip a:hover {
    transform: translateY(-2px);
    border-color: rgba(255, 255, 255, 0.28);
    background: rgba(255, 255, 255, 0.16);
    color: white;
}

.workflow-strip a.active {
    transform: translateY(-2px);
    border-color: rgba(255, 255, 255, 0.32);
    background: rgba(255, 255, 255, 0.2);
    color: white;
}

.check-list {
    display: grid;
    gap: 12px;
    margin: 18px 0 0;
    padding: 0;
    list-style: none;
}

.check-list li {
    display: flex;
    gap: 10px;
    align-items: center;
    color: var(--white-soft);
}

.score-badge {
    display: grid;
    place-items: center;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.12);
    color: white;
    font-weight: 850;
}

.text-link {
    color: var(--gold);
    font-weight: 850;
    text-decoration: none;
}

/* Standard "view everything" secondary link — a condensed panel pointing
   to its own full view (a modal, usually). Deliberately lighter-weight
   than .text-link: sky-blue instead of the accent gold, small, no bold,
   so it reads as a quiet way out of a summary rather than a call to
   action competing with real buttons. */
.view-all-link {
    color: var(--sky);
    font-size: var(--fs-xs);
    font-weight: 600;
    text-decoration: none;
}

.view-all-link:hover {
    text-decoration: underline;
}

.property-grid,
.stats-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px;
    margin-top: 18px;
}

.property-grid-wide {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

.property-card,
.stat-card {
    overflow: hidden;
    border-radius: 24px;
}

.property-card img {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
}

.property-card-image-empty {
    display: grid;
    place-items: center;
    width: 100%;
    aspect-ratio: 16 / 9;
    background: rgba(255, 255, 255, 0.08);
    color: var(--white-soft);
}

.property-image-field {
    display: grid;
    gap: 10px;
}

.property-image-field > span {
    color: white;
    font-weight: 850;
}

.property-image-preview {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    border-radius: 12px;
    border: 1px solid rgba(255, 255, 255, 0.16);
    object-fit: cover;
    background: rgba(255, 255, 255, 0.08);
}

.property-image-dropzone {
    position: relative;
    display: grid;
    gap: 10px;
    padding: 12px;
    border: 1px dashed rgba(255, 255, 255, 0.3);
    border-radius: 14px;
    background: rgba(255, 255, 255, 0.06);
    cursor: pointer;
    transition: border-color 180ms var(--ease), background 180ms var(--ease), transform 180ms var(--ease);
}

.property-image-dropzone strong {
    color: white;
    font-size: 0.95rem;
}

.property-image-dropzone small {
    color: var(--white-soft);
}

.property-image-dropzone.is-drag-over {
    border-color: rgba(255, 255, 255, 0.52);
    background: rgba(255, 255, 255, 0.12);
    transform: translateY(-1px);
}

.property-image-input {
    display: none;
}

.image-delete-btn {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 2;
    min-height: 28px;
    padding: 0 8px;
}

.property-image-empty {
    display: grid;
    place-items: center;
    color: var(--white-soft);
}

.property-image-remove {
    display: inline-flex;
    gap: 8px;
    align-items: center;
    color: var(--white-soft);
}

.property-image-remove input {
    width: auto;
}

.property-editor {
    display: grid;
    grid-template-columns: minmax(280px, 0.9fr) minmax(0, 1.1fr);
    gap: 20px;
    align-items: start;
}

.property-editor-media,
.property-editor-form {
    padding: 20px;
    border: 1px solid var(--line);
    border-radius: 16px;
    background: rgba(255, 255, 255, 0.08);
}

/* Single outer surface (was two nested glass panels — .property-workbench-main
   plus .property-workbench-media — inside the page's own .panel wrapper).
   Removing a level of glass-on-glass nesting per user feedback: this is now
   the outermost surface for the form view, .panel is only used for the grid/
   empty-state view. */
.property-workbench {
    display: flex;
    flex-direction: column;
    gap: 20px;
    padding: 22px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 14px;
    background: rgba(255, 255, 255, 0.05);
}

/* Image sits beside name/address/off-market instead of on its own row —
   recovers the vertical space that band was wasting. Full size preserved
   (the original 480px cap, not shrunk to make room) — the fields column
   next to it is a single stack (name, then address, then a compact
   off-market row) rather than a 2-up grid, so it doesn't need much width.
   The image shrinks on its own at narrower viewports via the media query
   below. */
.property-workbench-header {
    display: flex;
    gap: 20px;
    align-items: flex-start;
}

.property-workbench-image {
    flex: 0 0 480px;
    max-width: 480px;
}

.property-workbench-top {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

/* Just a checkbox + label — sized to its content instead of stretching to
   the full column width like the text-input rows above it. */
.property-workbench-top .choice-row {
    align-self: flex-start;
}

.form-error-banner {
    margin-bottom: 14px;
    padding: 10px 12px;
    border: 1px solid rgba(255, 125, 125, 0.55);
    border-radius: 12px;
    background: rgba(255, 82, 82, 0.14);
    color: #ffd1d1;
    font-weight: 650;
}

.form-error-banner p {
    margin: 0;
}

.form-error-banner p + p {
    margin-top: 4px;
}

.form-success-banner {
    margin-bottom: 14px;
    padding: 10px 12px;
    border: 1px solid rgba(134, 215, 255, 0.4);
    border-radius: 12px;
    background: rgba(134, 215, 255, 0.14);
    color: var(--sky);
    font-weight: 650;
}

.form-success-banner p {
    margin: 0;
}

/* Neutral, not error-red/success-green — this marks a permanent page
   state (a plan-tier restriction), not the result of a form submission. */
.plan-gate-banner {
    margin-bottom: 14px;
    padding: 10px 12px;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.08);
    color: var(--white-soft);
    font-weight: 650;
}

.plan-gate-banner p {
    margin: 0;
}

.plan-gate-banner a {
    color: var(--sky);
}

/* ---------- Tabs — two named styles, both real and kept, not one
   replacing the other. Plain "tabs" (bare .nav-tabs, Bootstrap's own
   underlined-strip look, lightly retinted) is style 2; "pill tabs"
   (.nav-tabs.pill-tabs, add class="pill-tabs" alongside nav-tabs to opt
   in) is style 1. Both keep Bootstrap's real tab JS (data-bs-toggle="tab")
   untouched either way. Promoted here from property-detail.php's own
   page-scoped <style> block — that page's own comment named the exact
   condition for the move ("scoped to this page... until a second page
   needs them too"), and Settings now does. Light-theme overrides live in
   the html[data-theme="light"] section further down. ---------- */
.nav-tabs {
    border-bottom-color: var(--line);
    margin-bottom: 16px;
    gap: 4px;
}
.nav-tabs .nav-link {
    border: none;
    border-radius: 8px 8px 0 0;
    color: var(--white-muted);
    font-size: var(--fs-sm);
    font-weight: 650;
    padding: 8px 14px;
}
.nav-tabs .nav-link:hover { color: var(--white-soft); border-color: transparent; }
.nav-tabs .nav-link.active { color: var(--amber); background: rgba(255, 159, 46, 0.1); border-color: transparent; }

.nav-tabs.pill-tabs {
    border-bottom: none;
    gap: 6px;
    padding: 3px;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.05);
}
.nav-tabs.pill-tabs .nav-item { flex: 1; }
.nav-tabs.pill-tabs .nav-link {
    display: block;
    width: 100%;
    border-radius: 8px;
    background: none;
    color: var(--white-soft);
    font-size: var(--fs-xs);
    font-weight: 700;
    padding: 8px 6px;
    text-align: center;
}
.nav-tabs.pill-tabs .nav-link:hover { color: var(--white-soft); background: none; }
.nav-tabs.pill-tabs .nav-link.active { color: #1a1206; background: var(--amber); }

/* ---------- Settings > Templates: the "Insert variable" lookup, and the
   Settings > Workflows stub tab. ---------- */
.note { margin: 0 0 4px; font-size: var(--fs-xs); color: var(--white-muted); line-height: 1.5; }

.field-label-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.var-picker { position: relative; }
.var-menu {
    position: absolute; right: 0; top: calc(100% + 6px); z-index: 5; width: 300px; max-height: 320px; overflow-y: auto;
    padding: 10px; border-radius: 14px; border: 1px solid var(--line); background: var(--ink-2);
    box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4);
}
.var-group { margin-bottom: 10px; }
.var-group:last-child { margin-bottom: 0; }
.var-group-title { margin: 2px 6px 6px; font-size: var(--fs-2xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--white-muted); }
.var-chip { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; width: 100%; text-align: left; border: none; background: none; color: #fff; padding: 7px 8px; border-radius: 8px; cursor: pointer; font: inherit; }
.var-chip:hover { background: rgba(255, 255, 255, 0.08); }
.var-chip code { font-size: var(--fs-xs); font-weight: 700; color: var(--gold); }
.var-chip small { font-size: var(--fs-2xs); color: var(--white-muted); }

.stub-badge { display: inline-block; vertical-align: middle; margin-left: 8px; padding: 3px 9px; border-radius: 999px; background: rgba(255, 209, 136, 0.18); color: var(--gold); font-size: var(--fs-2xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; }
.plan-picker {
    display: grid;
    gap: 10px;
    margin: 0;
    padding: 0;
    border: 0;
}

.plan-picker legend {
    padding: 0;
    margin-bottom: 4px;
    color: white;
    font-weight: 850;
}

.plan-picker-option {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.06);
    cursor: pointer;
}

.starter-pick-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 10px;
    margin-bottom: 8px;
    cursor: pointer;
}

.starter-pick-row span {
    display: flex;
    flex-direction: column;
    flex: 1;
}

.starter-pick-row small {
    color: rgba(255, 255, 255, 0.6);
}

.starter-pick-row:has(input:disabled) {
    opacity: 0.6;
    cursor: default;
}

.plan-picker-option:has(input:checked) {
    border-color: var(--sky);
    background: rgba(134, 215, 255, 0.14);
}

.plan-picker-option input {
    width: auto;
}

.plan-picker-option span {
    display: grid;
    gap: 2px;
}

.plan-picker-option small {
    color: var(--white-muted);
}

.billing-placeholder-notice {
    margin: 0;
    color: var(--white-muted);
    font-size: 0.9rem;
}

.signature-pad-wrap {
    display: flex;
    flex-direction: column;
    gap: 8px;
    max-width: 420px;
}

.signature-pad {
    width: 100%;
    height: 160px;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: #fff;
    touch-action: none;
    cursor: crosshair;
}

.signature-pad-actions {
    display: flex;
    justify-content: flex-end;
}

.inline-adjustment-form {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 6px;
}

.inline-amount-input {
    width: 90px;
    height: 32px;
    padding: 4px 8px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: rgba(255, 255, 255, 0.06);
    color: inherit;
    font-size: 0.85rem;
}

.condition-tag-list {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 10px;
    margin-top: 8px;
}

.condition-tag-choice {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.78rem;
    color: var(--white-muted);
    cursor: pointer;
}

.condition-tag-choice input {
    accent-color: var(--gold);
}

.form-error-text {
    margin-top: 4px;
    color: #ffbaba;
    font-size: 0.78rem;
    font-weight: 650;
}

.is-invalid {
    border-color: rgba(255, 125, 125, 0.65) !important;
    box-shadow: 0 0 0 2px rgba(255, 125, 125, 0.14);
}

.property-units-error {
    grid-column: 1 / -1;
}

.property-card-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.walkthrough-address {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.walkthrough-unit-list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 10px;
    margin: 14px 0;
}

.walkthrough-unit-card {
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.05);
    color: white;
    text-decoration: none;
    padding: 10px 12px;
    display: grid;
    gap: 3px;
}

.walkthrough-unit-card.active {
    border-color: rgba(134, 215, 255, 0.62);
    box-shadow: inset 0 0 0 1px rgba(134, 215, 255, 0.34), 0 0 18px rgba(134, 215, 255, 0.24);
}

.walkthrough-unit-card small,
.walkthrough-unit-card span {
    color: var(--white-muted);
    font-size: 0.75rem;
}

.walkthrough-kpis {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 10px;
    margin: 14px 0;
}

.walkthrough-kpis article {
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.04);
    padding: 10px 12px;
    display: grid;
    gap: 2px;
}

.walkthrough-kpis span {
    font-size: 0.75rem;
    color: var(--white-muted);
}

.walkthrough-kpis strong {
    font-size: 1.12rem;
}

.walkthrough-section {
    margin-top: 12px;
}

.walkthrough-form .data-header,
.walkthrough-form .data-row {
    grid-template-columns: minmax(0, 1fr) 170px minmax(0, 1fr) minmax(190px, 0.9fr);
    align-items: start;
}

.proof-cell {
    display: grid;
    gap: 8px;
    justify-items: start;
    align-content: start;
    width: 100%;
    grid-column: 1 / -1;
}

.proof-action-cell {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: flex-start;
}

.proof-input {
    display: none;
}

.proof-count {
    color: var(--white-muted);
    font-size: 0.74rem;
}

.proof-thumbs {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(52px, 52px));
    gap: 6px;
    justify-content: start;
    align-content: start;
    width: 100%;
}

.proof-thumbs a {
    display: inline-flex;
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid rgba(255, 255, 255, 0.2);
}

.proof-thumb-wrap {
    display: grid;
    gap: 4px;
    justify-items: start;
}

.proof-thumb {
    border: 0;
    padding: 0;
    background: none;
    border-radius: 8px;
    overflow: hidden;
    cursor: pointer;
}

.proof-remove-btn {
    min-height: 28px;
    min-width: 28px;
    padding: 0;
}

.proof-thumbs img {
    width: 52px;
    height: 52px;
    object-fit: cover;
    display: block;
}

.calendar-controls {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 14px;
}

.month-controls,
.view-toggle,
.time-slot-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.month-controls button,
.view-toggle button,
.time-slot-grid button {
    min-height: 38px;
    padding: 0 12px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.08);
    color: rgba(255, 255, 255, 0.82);
    font-weight: 800;
}

.view-toggle .active-view,
.time-slot-grid .selected {
    background: white;
    color: #0a171a;
}

.calendar-grid {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 8px;
}

.calendar-grid > span {
    color: rgba(255, 255, 255, 0.46);
    font-size: 0.75rem;
    font-weight: 800;
    text-align: center;
    text-transform: uppercase;
}

.calendar-grid button,
.calendar-day {
    position: relative;
    display: grid;
    place-items: center;
    min-height: 58px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 14px;
    background: rgba(255, 255, 255, 0.08);
    color: rgba(255, 255, 255, 0.86);
    font-weight: 800;
    text-decoration: none;
}

.calendar-grid button:hover,
.calendar-day:hover,
.calendar-grid .active-day {
    background: rgba(255, 255, 255, 0.16);
}

.calendar-day small {
    position: absolute;
    left: 7px;
    right: 7px;
    bottom: 5px;
    overflow: hidden;
    color: rgba(255, 255, 255, 0.64);
    font-size: 0.58rem;
    text-overflow: ellipsis;
    white-space: nowrap;
    opacity: 0;
    transform: translateY(4px);
    transition: opacity 160ms var(--ease), transform 160ms var(--ease);
}

.calendar-day:hover small,
.calendar-grid .active-day small {
    opacity: 1;
    transform: translateY(0);
}

.calendar-grid .mini-dot {
    position: absolute;
    right: 8px;
    top: 8px;
    width: 8px;
    height: 8px;
    border-radius: 999px;
}

.mini-dot.urgent {
    background: #ff8f8f;
    box-shadow: 0 0 18px rgba(255, 143, 143, 0.42);
}

.mini-dot.attention {
    background: #ffd188;
    box-shadow: 0 0 18px rgba(255, 209, 136, 0.42);
}

.mini-dot.info {
    background: #86d7ff;
    box-shadow: 0 0 18px rgba(134, 215, 255, 0.38);
}

.time-slot-grid {
    margin-top: 14px;
}

.time-slot-grid button:disabled {
    cursor: not-allowed;
    opacity: 0.38;
}

@media (max-width: 900px) {
    .calendar-grid {
        gap: 6px;
    }

    .calendar-grid button,
    .calendar-day {
        min-height: 48px;
    }
}

.rp-modal[hidden] {
    display: none;
}

.rp-modal {
    position: fixed;
    inset: 0;
    z-index: 1200;
    padding: 8px;
    display: grid;
    place-items: center;
    box-sizing: border-box;
}

.rp-modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.6);
}

.rp-modal-sheet {
    position: relative;
    margin: 0;
    width: min(760px, 100%);
    max-width: 100%;
    max-height: calc(100vh - 16px);
    overflow: auto;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 14px;
    background: rgba(19, 43, 50, 0.98);
    padding: 14px;
    display: grid;
    gap: 12px;
}

.lightbox-sheet img,
.lightbox-sheet video {
    width: 100%;
    max-height: calc(100vh - 120px);
    object-fit: contain;
    border-radius: 10px;
}

.lightbox-sheet {
    position: relative;
    padding-top: 44px;
}

.lightbox-close {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 2;
}

.lightbox-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    width: 40px;
    height: 40px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, 0.16);
    background: rgba(0, 0, 0, 0.55);
    color: var(--white);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}

.lightbox-nav:hover {
    background: rgba(0, 0, 0, 0.75);
}

.lightbox-nav[hidden] {
    display: none;
}

.lightbox-prev {
    left: 10px;
}

.lightbox-next {
    right: 10px;
}

.lightbox-counter {
    position: absolute;
    bottom: 10px;
    left: 50%;
    transform: translateX(-50%);
    padding: 4px 12px;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.6);
    color: var(--white);
    font-size: 0.78rem;
    font-weight: 700;
}

.lightbox-counter[hidden] {
    display: none;
}

/* Photo gallery (shared) — hero image + optional thumbnail strip + Gallery
   button, paired with components/photo-gallery.php. The parent grid column
   (e.g. unit-detail.php's 320px .unit-hero-section column) sets the width;
   .unit-hero-image stretches to fill it via the flex column's default
   align-items: stretch, so no separate width rule/media override is needed
   here for narrower or full-width callers. */
.unit-hero-photos {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.unit-thumbnail-strip {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    padding-bottom: 2px;
}

.unit-thumbnail-strip[hidden] {
    display: none;
}

.unit-thumbnail {
    flex: 0 0 56px;
    width: 56px;
    height: 56px;
    padding: 0;
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid rgba(255, 255, 255, 0.14);
    background: rgba(255, 255, 255, 0.04);
    cursor: pointer;
}

.unit-thumbnail:hover {
    border-color: var(--accent);
}

.unit-thumbnail img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.unit-hero-image {
    position: relative;
    height: 220px;
    border-radius: 14px;
    overflow: hidden;
    background: rgba(0, 0, 0, 0.4);
}

.unit-hero-image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.unit-hero-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    color: rgba(255, 255, 255, 0.4);
}

.unit-hero-placeholder i {
    width: 48px;
    height: 48px;
    margin-bottom: 0.5rem;
}

.unit-hero-fallback-badge {
    position: absolute;
    top: 12px;
    left: 12px;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 8px;
    color: var(--white);
    font-size: 0.78rem;
    font-weight: 700;
}

.unit-hero-fallback-badge i {
    width: 14px;
    height: 14px;
}

.gallery-btn {
    position: absolute;
    bottom: 12px;
    right: 12px;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 8px;
    color: var(--white);
    font-size: 0.82rem;
    font-weight: 700;
    cursor: pointer;
    transition: all 180ms ease;
}

.gallery-btn:hover {
    background: rgba(0, 0, 0, 0.85);
    border-color: var(--accent);
}

.gallery-btn i {
    width: 16px;
    height: 16px;
}

@media (max-width: 1024px) {
    .unit-hero-image {
        height: 200px;
    }
}

.upload-sheet-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.upload-dropzone {
    min-height: 140px;
}

.upload-dropzone .property-image-preview {
    min-height: 120px;
}

.upload-preview-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
    gap: 8px;
    width: 100%;
}

.upload-preview-thumb {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    border-radius: 8px;
    border: 1px solid rgba(255, 255, 255, 0.22);
    background: rgba(0, 0, 0, 0.28);
}

.upload-sheet-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.camera-preview {
    width: 100%;
    max-width: 100%;
    max-height: min(62vh, 480px);
    object-fit: contain;
    border-radius: 12px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    background: rgba(0, 0, 0, 0.42);
}

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

    .walkthrough-form .data-header {
        display: none;
    }

    .walkthrough-form .data-row.walkthrough-grid {
        grid-template-columns: 1fr;
        gap: 8px;
    }

    .rp-modal {
        padding: 6px;
    }

    .rp-modal-sheet {
        width: 100%;
        max-height: calc(100vh - 12px);
        border-radius: 12px;
        padding: 12px;
    }

    .camera-preview {
        max-height: 52vh;
    }
}

.property-workbench-top label:not(.choice-row) {
    display: grid;
    gap: 6px;
    color: white;
    font-weight: 750;
    align-content: start;
    min-height: 78px;
}

.property-workbench-top label span {
    font-size: 0.82rem;
    color: var(--white-soft);
}

.property-workbench-top .choice-row span,
.property-workbench-top .switch-row span {
    font-size: inherit;
    color: inherit;
}

.property-workbench-body {
    display: grid;
    grid-template-columns: minmax(220px, 0.35fr) minmax(0, 0.65fr);
    gap: 18px;
}

.unit-nav {
    padding: 16px;
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.035);
}

.unit-nav-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 10px;
}

.unit-tabs-stack {
    display: grid;
    gap: 8px;
}

.unit-tab-row {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
}

.unit-tab-btn {
    justify-content: flex-start;
    min-height: 44px;
    padding: 8px 12px;
    border-radius: 10px;
    border-color: rgba(134, 215, 255, 0.62);
    background: rgba(134, 215, 255, 0.14);
    color: white;
    width: 100%;
    text-align: left;
    align-items: flex-start;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    flex: 1 1 auto;
}

.unit-tab-btn:hover,
.unit-tab-btn:focus-visible {
    transform: none;
    background: rgba(134, 215, 255, 0.2);
    color: white;
    box-shadow: inset 0 0 0 1px rgba(134, 215, 255, 0.32);
}

.unit-tab-btn strong {
    font-size: 0.95rem;
    line-height: 1.2;
}

.unit-tab-btn small {
    color: var(--white-muted);
    font-weight: 650;
    font-size: 0.72rem;
    line-height: 1.2;
    white-space: normal;
    overflow-wrap: anywhere;
}

.unit-tab-remove {
    min-height: 32px;
    min-width: 32px;
    padding: 0;
    display: inline-grid;
    place-items: center;
}

.unit-detail {
    min-width: 0;
}

.property-primary-cta {
    min-height: 40px;
    padding: 0 16px;
}

.checklist-editor {
    display: grid;
    gap: 10px;
}

.chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.item-list {
    display: grid;
    gap: 8px;
}

.item-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 180px minmax(0, 1fr) auto;
    gap: 10px;
    align-items: center;
}

[data-room-list],
[data-amenity-list] {
    display: grid;
    gap: 10px;
}

.item-row-2 {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto;
    align-items: start;
}

.item-row-2 .form-control {
    min-height: 40px;
}

.item-row-spacer {
    width: 32px;
}

.unit-list {
    display: grid;
    gap: 12px;
}

.unit-card {
    display: none;
    gap: 16px;
    padding: 16px;
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.03);
}

.unit-card.active {
    display: grid;
}

/* Details/Gallery split within one unit card — distinct from .unit-tabs
   (which switches between whole units), this switches views within the
   currently-selected unit. */
.unit-subtabs {
    display: flex;
    gap: 8px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
    padding-bottom: 12px;
}

.unit-subtab {
    padding: 6px 14px;
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.04);
    color: rgba(255, 255, 255, 0.7);
    font-size: var(--fs-sm);
    font-weight: 700;
    cursor: pointer;
}

.unit-subtab:hover {
    background: rgba(255, 255, 255, 0.09);
    color: white;
}

.unit-subtab.active {
    background: rgba(76, 149, 190, 0.34);
    border-color: rgba(134, 215, 255, 0.34);
    color: white;
}

.unit-subpanel {
    display: none;
    gap: 16px;
}

.unit-subpanel.active {
    display: grid;
}

.unit-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.unit-tabs .btn.active {
    border-color: rgba(255, 255, 255, 0.36);
    background: rgb(88 88 88 / 14%);
    color: white;
}

.unit-tab-btn.active {
    background: rgba(76, 149, 190, 0.34);
    box-shadow:
        inset 0 0 0 1px rgba(134, 215, 255, 0.34),
        0 0 18px rgba(134, 215, 255, 0.24);
}

/* Global form primitives for non-text controls (aligned to component library) */
.choice-row,
.switch-row {
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: 44px;
    padding: 0 12px;
    border-radius: 14px;
    background: rgba(255, 255, 255, 0.08);
    color: rgba(255, 255, 255, 0.82);
    font-weight: 750;
}

.choice-row input {
    width: 18px;
    height: 18px;
    margin: 0;
    accent-color: var(--amber);
}

.choice-row:has(input:disabled) {
    opacity: 0.46;
}

.switch-row input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.switch-row span {
    position: relative;
    width: 44px;
    height: 24px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.16);
    transition: background 180ms var(--ease);
}

.switch-row span::after {
    content: "";
    position: absolute;
    left: 4px;
    top: 4px;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: white;
    transition: transform 180ms var(--ease);
}

.switch-row input:checked + span {
    background: rgba(255, 159, 46, 0.5);
}

.switch-row input:checked + span::after {
    transform: translateX(20px);
}

.app-frame input[type="checkbox"],
.app-frame input[type="radio"] {
    cursor: pointer;
}

.unit-card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.sub-list {
    display: grid;
    gap: 12px;
    padding-top: 8px;
}

.sub-list > .btn,
.unit-nav-header > .btn {
    justify-self: start;
    width: auto;
}

.sub-list > label span {
    font-size: 0.8rem;
    color: var(--white-soft);
}

.property-workbench .btn.btn-light.btn-sm[data-remove-row],
.property-workbench .btn.btn-light.btn-sm[data-remove-unit],
.property-workbench .image-delete-btn {
    min-height: 32px;
    min-width: 32px;
    padding: 0;
    display: inline-grid;
    place-items: center;
}


.property-body {
    padding: 18px;
}

.property-body h3 {
    margin: 10px 0 8px;
    font-size: 1.25rem;
}

.property-body p {
    color: var(--white-soft);
}

.property-meta-list {
    display: grid;
    gap: 4px;
    margin-top: 10px;
}

.property-meta-list small {
    color: var(--white-soft);
}

.status-pill {
    display: inline-flex;
    min-height: 28px;
    align-items: center;
    padding: 0 10px;
    border-radius: 999px;
    background: rgba(255, 209, 136, 0.16);
    color: var(--gold);
    font-size: 0.78rem;
    font-weight: 850;
}

.renter-portal {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(280px, 390px);
    gap: 32px;
    align-items: center;
    min-height: calc(100vh - 120px);
    padding: clamp(24px, 5vw, 56px);
    border-radius: 40px;
    background:
        linear-gradient(110deg, rgba(7, 27, 32, 0.92), rgba(40, 95, 87, 0.55)),
        url("https://images.unsplash.com/photo-1560448204-e02f11c3d0e2?auto=format&fit=crop&w=1600&q=80") center/cover;
}

.renter-hero h2 {
    margin: 0;
    font-size: clamp(3rem, 7vw, 6rem);
    font-weight: 430;
    line-height: 0.96;
}

.renter-hero p:not(.eyebrow) {
    max-width: 35rem;
    color: var(--white-soft);
}

.phone-frame,
.balance-card,
.mobile-card {
    border-radius: 28px;
}

.phone-frame {
    min-height: 560px;
    padding: 18px;
}

.phone-top {
    display: flex;
    justify-content: space-between;
    padding: 10px 8px 18px;
}

.balance-card,
.mobile-card {
    padding: 18px;
    background: rgba(255, 255, 255, 0.12);
}

.balance-card span,
.balance-card p,
.mobile-card span {
    color: var(--white-soft);
}

.balance-card strong {
    display: block;
    margin: 6px 0;
    font-size: 2.8rem;
    font-weight: 460;
}

.mobile-action-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
    margin: 18px 0;
}

.mobile-action-grid button {
    display: grid;
    gap: 8px;
    place-items: center;
    min-height: 100px;
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 18px;
    background: rgba(255, 255, 255, 0.1);
    color: white;
    font-weight: 850;
}

.mobile-action-grid a {
    display: grid;
    gap: 8px;
    place-items: center;
    min-height: 100px;
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 18px;
    background: rgba(255, 255, 255, 0.1);
    color: white;
    font-weight: 850;
    text-decoration: none;
}

.repair-main a {
    color: white;
    text-decoration: none;
}

.repair-main a:hover {
    color: var(--gold);
}

.ledger-summary-grid,
.binder-tool,
.support-signal-grid,
.detail-list {
    display: grid;
    gap: 16px;
    margin-top: 22px;
}

.ledger-summary-grid,
.binder-tool {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

.screening-summary-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 16px;
    margin-top: 22px;
}

.screening-summary-grid button {
    display: grid;
    gap: 10px;
    width: 100%;
    min-height: 150px;
    align-content: start;
    border: 1px solid var(--line);
    border-radius: 16px;
    padding: 18px;
    background: rgba(255, 255, 255, 0.1);
    color: inherit;
    text-align: left;
    transition: transform 180ms var(--ease), background 180ms var(--ease), border-color 180ms var(--ease);
}

.screening-summary-grid button:hover,
.screening-summary-grid button.active {
    transform: translateY(-2px);
    border-color: rgba(255, 255, 255, 0.28);
    background: rgba(255, 255, 255, 0.16);
}

.screening-summary-grid i {
    display: grid;
    place-items: center;
    width: 42px;
    height: 42px;
    border-radius: 14px;
    background: rgba(255, 209, 136, 0.16);
    color: var(--gold);
}

.screening-summary-grid span {
    color: var(--white-muted);
    font-size: 0.82rem;
    font-weight: 850;
}

.screening-summary-grid strong {
    color: white;
    font-size: 2.2rem;
    font-weight: 520;
    line-height: 1;
}

.support-signal-grid,
.detail-list {
    grid-template-columns: repeat(4, minmax(0, 1fr));
}

.ledger-summary-grid article,
.binder-tool article,
.support-signal-grid article,
.detail-list div,
.vendor-profile {
    border: 1px solid var(--line);
    border-radius: 16px;
    padding: 18px;
    background: rgba(255, 255, 255, 0.1);
}

.ledger-summary-grid span,
.binder-tool span,
.support-signal-grid span,
.detail-list span,
.timeline-list time {
    color: var(--white-muted);
    font-size: 0.82rem;
    font-weight: 850;
}

.ledger-summary-grid strong,
.support-signal-grid strong {
    display: block;
    margin-top: 6px;
    color: white;
    font-size: 2rem;
    font-weight: 520;
}

.detail-list strong {
    display: block;
    margin-top: 6px;
    color: white;
    font-size: 1.06rem;
    font-weight: 760;
    overflow-wrap: anywhere;
    word-break: break-word;
}

.repair-detail-list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

.repair-request-gallery {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 10px;
    margin-top: 16px;
}

.repair-request-photo {
    padding: 0;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 12px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.08);
    cursor: pointer;
}

.repair-request-photo img {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    display: block;
}

/* Three classes deep (.record-status-table .data-row.vendor-job-row), not
   just .vendor-job-row -- the job board wraps this row in
   .record-status-table, whose own ".record-status-table .data-row" rule
   (below) is a two-class descendant selector at EQUAL specificity to a
   bare ".record-status-table .vendor-job-row", so it was still winning on
   source order alone. Naming .data-row explicitly here too (it's already
   on the element) breaks that tie for real, rather than depending on
   which rule happens to sit later in the file. This silently discarded
   the 4-column layout entirely (the 4th column, Action, had nowhere to
   go and wrapped onto its own row) until caught by visually checking the
   rendered page rather than just the source. */
.record-status-table .data-row.vendor-job-row {
    grid-template-columns: minmax(180px, 1fr) minmax(120px, 0.6fr) minmax(110px, 0.5fr) minmax(96px, 0.4fr);
}

.vendor-job-row > :last-child {
    justify-self: end;
    text-align: right;
}

/* The work order title link inherited the browser's default blue/
   underline instead of the row's own white text -- every other data-row
   link in the app (.screening-table a, .workflow-name-link) already
   overrides this the same way. */
.vendor-job-row a {
    color: inherit;
    text-decoration: none;
}

.vendor-job-row a:hover {
    text-decoration: underline;
}

.vendor-inline-form {
    justify-self: end;
}

/* Kind/Description/Qty/Unit cost entry grid shared by the bid, change
   order, and invoice line-item forms -- record-status-table's default
   3-column widths were built for name/status/date rows, not a select +
   a free-text description + two narrow numeric fields, so Kind and Qty
   both inherited far more width than their content needs while
   Description (the field that actually needs room) inherited less.
   Scoped through .record-status-table too (3 classes total), not just
   .line-item-entry-row.data-row -- otherwise it ties on specificity with
   ".record-status-table .data-row" below and loses on source order,
   the exact bug this rule exists to fix in the first place. */
.record-status-table .data-row.line-item-entry-row {
    grid-template-columns: 132px minmax(160px, 1fr) 64px 100px;
}

.record-status-table .data-row.line-item-entry-row select {
    width: 100%;
    text-overflow: ellipsis;
}

.record-status-table .data-row.line-item-entry-row input[type="number"] {
    text-align: right;
}

.data-table,
.timeline-list {
    display: grid;
    gap: 8px;
    margin-top: 22px;
}

.data-row {
    display: grid;
    grid-template-columns: 0.7fr minmax(0, 1.5fr) 0.8fr 0.9fr;
    gap: 12px;
    align-items: center;
    min-height: 56px;
    padding: 12px 14px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.08);
    color: white;
    text-decoration: none;
}

.screening-table .data-row {
    grid-template-columns: minmax(130px, 1fr) minmax(160px, 1.15fr) 0.7fr minmax(130px, 0.9fr) 0.6fr 0.7fr;
}

.screening-table a {
    color: white;
    text-decoration: none;
}

.screening-table a:hover {
    text-decoration: underline;
}

.record-status-table .data-row {
    grid-template-columns: minmax(180px, 1fr) minmax(120px, 0.45fr) minmax(130px, 0.55fr);
}

/* Repair Detail's "Compare vendor bids" table (Vendor/Score/Bid/
   Availability/Award) has 5 real columns, not the 3 .record-status-table
   .data-row assumes -- same "silently discarded" class of bug the
   .vendor-job-row comment above already warns about, just not yet fixed
   here (the Award column had nowhere to go and wrapped onto its own row
   even before the Score column was added). Scoped 3 classes deep, same
   specificity-tie reasoning as .vendor-job-row and .line-item-entry-row. */
.record-status-table .data-row.bid-compare-row {
    grid-template-columns: minmax(160px, 1fr) minmax(64px, 0.4fr) minmax(110px, 0.6fr) minmax(110px, 0.55fr) minmax(90px, 0.4fr);
}

.warranty-table .data-row {
    grid-template-columns: minmax(100px, 0.55fr) minmax(160px, 1fr) minmax(105px, 0.55fr) minmax(100px, 0.45fr);
}

.workflows-table .data-row {
    grid-template-columns: minmax(150px, 1.6fr) minmax(70px, 0.5fr) minmax(140px, 1fr) minmax(50px, 0.35fr) minmax(110px, 0.8fr) minmax(130px, 0.9fr) 44px;
}

.workflow-name-link {
    color: white;
    text-decoration: none;
}

.workflow-name-link:hover strong {
    text-decoration: underline;
}

.workflow-row-menu .icon-button {
    width: 36px;
    height: 36px;
    background: rgba(255, 255, 255, 0.08);
    border-color: var(--line);
}

.workflow-activity-table .data-row {
    grid-template-columns: minmax(120px, 1fr) minmax(80px, 0.6fr) minmax(80px, 0.6fr) minmax(140px, 1fr);
}

.templates-table .data-row {
    grid-template-columns: minmax(150px, 1fr) minmax(90px, 0.5fr) minmax(200px, 1.5fr) minmax(120px, 0.6fr);
}

.automation-table .data-row {
    grid-template-columns: minmax(140px, 1fr) minmax(100px, 0.5fr) minmax(130px, 0.7fr);
}

.automation-table label {
    cursor: pointer;
}

.automation-table input {
    margin-right: 8px;
    accent-color: var(--gold);
}

.upload-action {
    position: relative;
    overflow: hidden;
}

.upload-action input {
    position: absolute;
    inset: 0;
    opacity: 0;
    cursor: pointer;
}

.record-status-table .status-pill {
    justify-self: start;
}

.condition-changed {
    color: var(--danger);
    font-weight: 850;
}

/* Tenants list: a checkbox column + reserved action-button column layered
   on top of the shared record-status-table row shape. record-status-table
   is used by several other pages too, so this is scoped to
   .tenant-row-shell rather than touching the shared .data-row-shell rule. */
.record-status-table .tenant-row-shell {
    grid-template-columns: 28px minmax(0, 1fr) 112px;
}

.tenant-row-select {
    display: flex;
    align-items: center;
    justify-content: center;
}

.tenant-row-select input[type="checkbox"] {
    width: 16px;
    height: 16px;
    accent-color: var(--gold);
    cursor: pointer;
}

.data-head-sort {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: inherit;
    text-decoration: none;
}

.data-head-sort:hover,
.data-head-sort.active {
    color: white;
}

.data-head-sort svg {
    width: 14px;
    height: 14px;
}

.urgency-badge {
    display: inline-flex;
    align-items: center;
    padding: 0 8px;
    margin-left: 6px;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 850;
    background: rgba(255, 255, 255, 0.12);
    color: var(--white-muted);
}

.urgency-badge.soon {
    background: rgba(255, 209, 136, 0.16);
    color: var(--gold);
}

.urgency-badge.urgent {
    background: rgba(255, 107, 58, 0.16);
    color: var(--danger);
}

.attention-strip {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 18px;
}

.attention-chip {
    display: inline-flex;
    align-items: center;
    padding: 8px 14px;
    border-radius: 999px;
    border: 1px solid var(--line);
    background: rgba(255, 209, 136, 0.12);
    color: var(--gold);
    font-size: var(--fs-sm);
    font-weight: 800;
    text-decoration: none;
    transition: transform 180ms var(--ease), background 180ms var(--ease);
}

.attention-chip:hover {
    transform: translateY(-1px);
    background: rgba(255, 209, 136, 0.2);
}

.attention-chip.active {
    background: rgba(255, 209, 136, 0.28);
    border-color: rgba(255, 209, 136, 0.5);
}

.property-attention-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 8px 0;
}

.attention-chip-mini {
    padding: 3px 10px;
    font-size: 11px;
    font-weight: 700;
    cursor: default;
}

.attention-chip-mini:hover {
    transform: none;
}

.bulk-action-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 14px;
    padding: 12px 16px;
    border: 1px solid var(--line);
    border-radius: 14px;
    background: rgba(255, 255, 255, 0.08);
    color: var(--white-muted);
    font-size: var(--fs-sm);
    font-weight: 750;
}

.bulk-action-bar[hidden] {
    display: none;
}

.screening-filter-empty {
    margin: 18px 0 0;
    color: var(--white-soft);
    font-weight: 750;
}

.data-head {
    min-height: 42px;
    background: rgba(0, 0, 0, 0.22);
    color: var(--white-muted);
    font-size: 0.8rem;
    font-weight: 850;
    text-transform: uppercase;
}

.data-row em {
    justify-self: start;
    font-style: normal;
}

.timeline-list article {
    display: grid;
    grid-template-columns: 90px minmax(0, 1fr);
    gap: 16px;
    padding: 16px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 14px;
    background: rgba(255, 255, 255, 0.08);
}

.timeline {
    display: grid;
    gap: 0;
    margin: 0;
    padding: 0;
    list-style: none;
    margin-top: 18px;
}

.timeline li {
    position: relative;
    display: grid;
    grid-template-columns: 28px minmax(0, 1fr) 180px;
    gap: 14px;
    padding: 0 0 16px;
}

.timeline li:not(:last-child)::before {
    content: "";
    position: absolute;
    left: 5px;
    top: 18px;
    bottom: 4px;
    width: 1px;
    background: rgba(255, 255, 255, 0.16);
}

.timeline strong {
    color: white;
}

.timeline p {
    margin: 4px 0 0;
    color: rgba(255, 255, 255, 0.68);
}

.timeline time {
    color: rgba(255, 255, 255, 0.5);
    font-weight: 800;
    white-space: nowrap;
    justify-self: end;
    text-align: right;
}

.timeline-dot {
    margin-top: 5px;
    width: 10px;
    height: 10px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.34);
}

.timeline-dot.urgent {
    background: #ff8f8f;
    box-shadow: 0 0 18px rgba(255, 143, 143, 0.42);
}

.timeline-dot.attention {
    background: #ffd188;
    box-shadow: 0 0 18px rgba(255, 209, 136, 0.42);
}

.timeline-dot.info {
    background: #86d7ff;
    box-shadow: 0 0 18px rgba(134, 215, 255, 0.38);
}

.timeline-list p,
.vendor-profile p {
    margin: 4px 0 0;
    color: var(--white-soft);
}

.decision-factor-list {
    display: grid;
    gap: 12px;
    margin-top: 18px;
}

.decision-factor-list article {
    display: grid;
    grid-template-columns: 12px minmax(0, 1fr);
    gap: 14px;
    align-items: start;
    padding: 16px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 14px;
    background: rgba(255, 255, 255, 0.08);
}

.decision-factor-list article > span {
    width: 10px;
    height: 10px;
    margin-top: 6px;
    border-radius: 50%;
    background: var(--sky);
    box-shadow: 0 0 16px rgba(134, 215, 255, 0.36);
}

.decision-factor-list article.complete > span {
    background: var(--gold);
    box-shadow: 0 0 16px rgba(255, 209, 136, 0.36);
}

.decision-factor-list article.attention > span {
    background: var(--danger);
    box-shadow: 0 0 16px rgba(255, 107, 58, 0.36);
}

.decision-factor-list strong {
    display: block;
    color: white;
}

.decision-factor-list p {
    margin: 4px 0 0;
    color: var(--white-soft);
}

.repair-form {
    display: grid;
    gap: 14px;
}

.repair-form label {
    display: grid;
    gap: 8px;
    color: white;
    font-weight: 850;
}

.repair-form option,
.form-select option,
.app-frame select option,
.repair-form optgroup,
.form-select optgroup,
.app-frame select optgroup {
    color: var(--ink);
    background: #fff;
}

/* The rule above sets an explicit color on every <option>, which beats
   the browser's own native dimming for a disabled one (e.g. an already-
   booked time slot in .time-select) — without this, a disabled option
   reads identically to an available one. */
.repair-form option:disabled,
.form-select option:disabled,
.app-frame select option:disabled {
    color: rgba(7, 27, 32, 0.35);
}

.empty-state {
    display: grid;
    place-items: center;
    align-content: center;
    gap: 12px;
    min-height: 50vh;
    text-align: center;
}

.empty-state > svg {
    box-sizing: content-box;
    width: 30px;
    height: 30px;
    padding: 17px;
    margin-bottom: 4px;
    border: 1px solid var(--line);
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.08);
    color: var(--white-soft);
    stroke-width: 1.5;
}

.empty-state h2 {
    margin: 0;
}

.empty-state p {
    margin: 0 0 8px;
    max-width: 420px;
    color: var(--white-soft);
}

/* .empty-state's 50vh height and default h2/svg sizing only ever look
   right filling a whole page (properties/repairs/tenants list with
   nothing in it). Dropped into a compact card (a panel section, a modal
   body) it reads as broken instead of empty — this variant is for those
   embedded spots. */
.empty-state-compact {
    min-height: auto;
    padding: 32px 20px;
    gap: 8px;
}

.empty-state-compact svg {
    width: 28px;
    height: 28px;
    padding: 0;
    margin: 0;
    border: 0;
    background: none;
    stroke-width: 1.5;
    color: var(--white-muted);
}

.empty-state-compact h2 {
    margin: 0;
    font-size: var(--fs-base);
    font-weight: 650;
}

.empty-state-compact p {
    margin: 0;
    font-size: var(--fs-sm);
    color: var(--white-muted);
    max-width: 320px;
}

svg {
    width: 1.1rem;
    height: 1.1rem;
    stroke-width: 2;
}

/* Bootstrap's .btn-close is a black X by default (its own dark-background
   variant is a separate .btn-close-white class nobody here opts into) —
   invisible against every modal in this dark-first app. Inverted globally
   since every modal uses the same dark surface; light mode gets it back
   below since a light modal needs the original dark X again. */
.btn-close {
    filter: invert(1) grayscale(100%) brightness(200%);
}

/* Must match Bootstrap's own lg breakpoint (992px) exactly — that's where
   .offcanvas-lg switches the sidebar between a fixed off-screen drawer and
   a static in-flow column. A mismatched breakpoint here left a dead zone
   (formerly up to 1100px) where the sidebar was already static/sticky but
   the grid hadn't yet given it its own column, so it rendered full-width
   and full-height over the page. */
@media (max-width: 991.98px) {
    body:not(.full-bleed) .app-shell {
        grid-template-columns: 1fr;
    }

    .menu-button {
        display: inline-grid;
    }
}

@media (max-width: 1100px) {
    .hero-grid,
    .content-grid,
    .renter-portal,
    .portfolio-grid,
    .landing-hero-grid,
    .workflow-showcase,
    .landing-proof {
        grid-template-columns: 1fr;
    }

    .stats-grid,
    .property-grid-wide,
    .property-editor,
    .property-workbench,
    .property-workbench-top,
    .property-workbench-body,
    .landing-feature-grid,
    .pricing-grid,
    .ledger-summary-grid,
    .screening-summary-grid,
    .binder-tool,
    .support-signal-grid,
    .detail-list {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 720px) {
    .app-shell {
        padding: 10px;
    }

    .hero-world {
        padding: 0;
    }

    .hero-frame {
        min-height: auto;
        border-radius: 34px;
        padding: 24px;
    }

    .hero-nav,
    .hero-footer,
    .topbar {
        align-items: flex-start;
        flex-direction: column;
    }

    .hero-nav div {
        gap: 14px;
    }

    .hero-copy h2 {
        font-size: clamp(4rem, 22vw, 6rem);
    }

    .property-workbench-header {
        flex-direction: column;
    }

    .property-workbench-image {
        flex-basis: auto;
        max-width: 100%;
    }

    .date-grid,
    .detail-grid,
    .portfolio-grid,
    .binder-grid,
    .property-grid,
    .property-grid-wide,
    .workflow-strip,
    .stats-grid,
    .landing-nav,
    .landing-nav div,
    .landing-feature-grid,
    .pricing-grid,
    .ledger-summary-grid,
    .screening-summary-grid,
    .binder-tool,
    .support-signal-grid,
    .detail-list,
    .data-row {
        grid-template-columns: 1fr;
    }

    .screening-table .data-row,
    .record-status-table .data-row,
    .record-status-table .data-row.bid-compare-row,
    .warranty-table .data-row,
    .automation-table .data-row,
    .workflows-table .data-row,
    .templates-table .data-row {
        grid-template-columns: 1fr;
    }

    .landing-hero {
        min-height: auto;
        border-radius: 24px;
        padding: 24px;
    }

    .landing-hero-copy h1 {
        /* The old clamp's 22vw preferred term already exceeded its own
           5.4rem cap above ~392px wide — meaning it rendered at a flat
           86.4px on every real phone in this breakpoint (checked against
           320-720px), long enough as one unbreakable word to overflow the
           viewport outright rather than ever actually scaling with it. */
        font-size: clamp(2.6rem, 13vw, 4.6rem);
    }

    .landing-nav {
        grid-template-columns: auto auto;
        position: relative;
    }

    .landing-nav-toggle {
        display: inline-flex;
    }

    .landing-nav div {
        display: none;
        grid-template-columns: 1fr;
        justify-content: stretch;
        gap: 4px;
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        margin-top: 12px;
        padding: 14px;
        border-radius: 16px;
        background: rgba(7, 27, 32, 0.96);
        border: 1px solid rgba(255, 255, 255, 0.14);
        box-shadow: 0 20px 50px rgba(0, 0, 0, 0.4);
        z-index: 20;
    }

    .landing-nav div.is-open {
        display: grid;
    }

    .landing-nav div a {
        padding: 10px 8px;
        border-radius: 8px;
    }

    .pricing-grid .featured-price {
        transform: translateY(-12px);
    }

    .repair-row {
        grid-template-columns: 1fr;
    }

    .topbar-actions .icon-button {
        display: none;
    }
}

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

/* ============================================================
   DASHBOARD REDESIGN
   Schedule card (calendar + day agenda), the content-columns
   masonry fix, and the panel-icon/stat-hero treatment used by the
   dashboard's own cards. Added additively — nothing above this
   point was removed, so every other page keeps rendering exactly
   as it did before.
   ============================================================ */

/* Independent per-column flex stacks instead of row-paired grid cells,
   so a taller card in one column (rent ledger) never pushes dead space
   beneath a shorter card in the other (open repairs) before the next
   card starts. */
.content-columns {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 22px;
    align-items: start;
}

.content-column {
    display: flex;
    flex-direction: column;
    gap: 22px;
}

/* Icon badge + eyebrow/title sit side by side (dashboard card headers:
   Schedule, Open Repairs, Properties, Rent Ledger, Records) — missing from
   the initial port, so the icon fell to its own line above the text. */
.panel-heading-row {
    display: flex;
    align-items: center;
    gap: 12px;
}

.panel-heading-row.standalone {
    margin-bottom: 16px;
}

/* Overrides the shared .eyebrow rule (900 weight, 0.72rem) scoped to this
   dashboard-only context to match mockups/assets/dashboard-pilot.css exactly
   — the site-wide .eyebrow used by the other 24 pages is untouched. line-height:1
   tightens the text's own box so flexbox's align-items:center on
   .panel-heading-row visually (not just geometrically) lines it up with the
   icon and .panel-stat, which have very different natural line-heights. */
.panel-heading-row .eyebrow {
    margin: 0;
    line-height: 1;
    font-size: var(--fs-xs);
    font-weight: 600;
}

/* Compact inline stat next to an eyebrow label (Open Repairs' count,
   Properties' active count) — replaces stat-hero/h2 used as a pseudo card
   title, which rendered bigger than the page's own h1 and read as a second
   competing header rather than a number attached to its label. */
.panel-stat {
    font-size: var(--fs-xs);
    font-weight: 700;
    line-height: 1;
    color: white;
}

/* Optional shaded header band (panel-card.php: $card['headerShaded']) — pulls
   the header out to the panel's own edges via negative margin (panel padding
   is a fixed 24px) so the tint reads as a distinct zone above a divider,
   rather than just a color change inline with the body. */
.panel-header-shaded {
    margin: -24px -24px 0;
    padding: 16px 24px;
    border-radius: 30px 30px 0 0;
    background: rgba(255, 255, 255, 0.04);
}

/* Optional rule under the header (panel-card.php: $card['divider']). */
.panel-divider {
    border: none;
    border-top: 1px solid var(--line);
    margin: 16px 0;
}

/* Locked bottom button bar (panel-card.php: $card['footer']). The panel
   becomes a column flexbox so the footer is a normal flex sibling after
   .panel-body, not something re-positioned with position:sticky — it can
   never scroll away because it was never inside the scrolling area. Pair
   with $card['scroll'] to bound .panel-body's height and prove the footer
   stays put while the body scrolls under it. */
.panel-has-footer {
    display: flex;
    flex-direction: column;
}

.panel-has-footer .panel-body {
    flex: 1 1 auto;
    min-height: 0;
}

.panel-scroll .panel-body {
    max-height: 320px;
    overflow-y: auto;
}

.panel-footer {
    display: flex;
    flex: none;
    justify-content: flex-end;
    gap: 10px;
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid var(--line);
}

/* /dev/card-lab only — groups a caption with the panel-card variant it
   describes, so the between-group rhythm (.content-column's own gap) stays
   visibly bigger than the caption-to-card rhythm within a group. */
.card-lab-item {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.card-lab-section {
    margin-bottom: 36px;
}

.card-lab-section-title {
    margin: 0 0 16px 4px;
    font-size: var(--fs-lg);
    font-weight: 700;
}

.card-lab-section > .card-lab-item {
    margin-bottom: 22px;
}

.card-lab-caption {
    margin: 0 0 0 4px;
}

.card-lab-placeholder {
    margin: 0;
    color: var(--white-muted);
    font-size: var(--fs-sm);
}

/* .chart-legend's own selector (.ledger-row i, .repair-stage::before,
   .repair-status i, .chart-legend span { width:10px; height:10px; ... })
   was written for an empty dot element — it wasn't previously consumed
   anywhere, so nothing caught that a <span> holding label text collapses
   into an unreadable 10px swatch. These higher-specificity overrides move
   the dot to ::before and let the span render as normal label text. */
.chart-legend span.on-time,
.chart-legend span.late,
.chart-legend span.processing {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    width: auto;
    height: auto;
    background: none;
    box-shadow: none;
    color: var(--white-soft);
    font-size: 0.84rem;
}

.chart-legend span.on-time::before,
.chart-legend span.late::before,
.chart-legend span.processing::before {
    content: "";
    display: inline-block;
    flex: none;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--sky);
    box-shadow: 0 0 16px rgba(134, 215, 255, 0.42);
}

.chart-legend span.late::before {
    background: var(--gold);
    box-shadow: 0 0 16px rgba(255, 209, 136, 0.42);
}

.chart-legend span.processing::before {
    background: rgba(255, 255, 255, 0.54);
    box-shadow: 0 0 16px rgba(255, 255, 255, 0.18);
}

.panel-icon {
    display: grid;
    flex: none;
    place-items: center;
    width: 32px;
    height: 32px;
    padding: 7px;
    border-radius: 16px;
    background: rgba(255, 159, 46, 0.16);
    color: var(--amber);
}

/* lucide.createIcons() replaces the <i data-lucide class="panel-icon">
   element with an <svg> that carries the same class directly (there's no
   wrapper), so .panel-icon's own width/height apply to the icon glyph
   itself, not a container around it — the padding above is what actually
   keeps the drawn icon smaller than its circular background. This rule
   still helps the rare case where a real <svg> sits nested inside a
   .panel-icon wrapper instead. */
.panel-icon svg {
    width: 18px;
    height: 18px;
}

.panel-icon.blue { background: rgba(134, 215, 255, 0.16); color: var(--sky); }
.panel-icon.green { background: rgba(255, 255, 255, 0.14); color: var(--white-soft); }

/* Schedule card: a month calendar plus a day agenda, instead of a
   per-property list, so it scales to any portfolio size (events are
   keyed by day, not by property). Selecting a day is a plain link to
   ?day=N — the agenda re-renders server-side, no client JS involved. */
.schedule-layout {
    display: grid;
    grid-template-columns: minmax(280px, 340px) 1fr;
    gap: 32px;
    align-items: start;
}

.calendar-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;
}

.calendar-nav strong {
    font-size: 15px;
}

.calendar-weekdays {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 4px;
    margin-bottom: 8px;
}

.calendar-weekdays span {
    text-align: center;
    font-size: 11px;
    color: var(--white-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.calendar-daygrid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 4px;
}

.calendar-cell {
    position: relative;
    aspect-ratio: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 14px;
    border: 1px solid transparent;
    background: none;
    font-size: 13px;
    color: white;
    text-decoration: none;
}

span.calendar-cell.muted {
    color: var(--white-muted);
}

a.calendar-cell:hover:not(.selected) {
    background: rgba(255, 255, 255, 0.08);
}

.cell-dot {
    position: absolute;
    bottom: 5px;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: currentColor;
}

.calendar-cell.has-events.urgent { color: var(--danger); }
.calendar-cell.has-events.attention { color: var(--gold); }
.calendar-cell.has-events.info { color: var(--sky); }

.calendar-cell.selected {
    background: var(--amber);
    border-color: var(--amber);
    color: #0a171a !important;
}

.calendar-cell.selected .cell-dot {
    background: #0a171a;
}

.day-events-heading {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 0 0 16px;
    font-size: 16px;
    font-weight: 700;
}

.event-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.event-row {
    display: flex;
    gap: 12px;
    padding: 12px;
    border-radius: 14px;
    background: rgba(255, 255, 255, 0.06);
}

.event-title {
    display: flex;
    align-items: center;
    margin: 0 0 2px;
    font-size: 14px;
    font-weight: 600;
}

.event-dot {
    display: inline-block;
    flex: none;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    margin-right: 8px;
    background: var(--line);
}

.event-row.urgent .event-dot { background: var(--danger); box-shadow: 0 0 10px rgba(255, 107, 58, 0.5); }
.event-row.attention .event-dot { background: var(--gold); box-shadow: 0 0 10px rgba(255, 209, 136, 0.5); }
.event-row.info .event-dot { background: var(--sky); box-shadow: 0 0 10px rgba(134, 215, 255, 0.5); }

.event-thumb,
.event-icon {
    flex: none;
    width: 44px;
    height: 44px;
    border-radius: 14px;
    overflow: hidden;
}

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

.event-icon {
    display: grid;
    place-items: center;
    background: rgba(255, 159, 46, 0.16);
    color: var(--amber);
}

.event-icon svg {
    width: 18px;
    height: 18px;
}

.event-meta {
    margin: 0;
    font-size: 13px;
    color: var(--white-muted);
}

.event-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 32px 16px;
    color: var(--white-muted);
    text-align: center;
}

.event-empty svg {
    width: 28px;
    height: 28px;
    color: var(--line);
}

.event-empty p {
    margin: 0;
    font-size: 13px;
}

@media (max-width: 767px) {
    .schedule-layout {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 1100px) {
    .content-columns {
        grid-template-columns: 1fr;
    }
}

/* ============================================================
   REPAIR DETAIL — work order card, activity/tasks, composer, feed
   Ported from mockups/repair-detail-pilot.html + assets/repair-detail-pilot.css.
   Structural rules are theme-neutral; colors below are this file's
   dark (default) palette. Light equivalents are appended at the end
   of this file under html[data-theme="light"], per this file's own
   convention (default = dark, light = override).
   ============================================================ */
.fact-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 16px 24px;
    margin-top: 16px;
}

.fact span {
    display: block;
    font-size: var(--fs-xs);
    color: var(--white-muted);
    margin-bottom: 2px;
}

.fact strong {
    font-size: var(--fs-sm);
    font-weight: 600;
    color: white;
}

.fact-link {
    font: inherit;
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--amber);
    background: none;
    border: none;
    padding: 0;
    text-align: left;
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
}

.fact-link:hover {
    color: white;
}

.action-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 24px;
}

.dropdown-menu {
    --bs-dropdown-bg: rgba(15, 32, 38, 0.98);
    --bs-dropdown-border-color: var(--line);
    --bs-dropdown-link-color: white;
    --bs-dropdown-link-hover-bg: rgba(255, 255, 255, 0.08);
    --bs-dropdown-link-hover-color: white;
    --bs-dropdown-box-shadow: 0 20px 45px rgba(0, 0, 0, 0.4);
    --bs-dropdown-padding-y: 8px;
    --bs-dropdown-font-size: var(--fs-sm);
    border-radius: 16px;
}

.dropdown-item.text-danger {
    --bs-dropdown-link-color: var(--danger);
}

.dropdown-item.text-danger:hover,
.dropdown-item.text-danger:focus {
    color: var(--danger);
    background: rgba(255, 107, 58, 0.14);
}

.field-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 16px;
    margin-top: 16px;
}

.field-grid label {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: var(--fs-sm);
    font-weight: 600;
    color: white;
}

.field-grid label.span-2 {
    grid-column: 1 / -1;
}

/* Sectioned create/edit forms: a <fieldset class="form-section"> per group,
   eyebrow legend, .field-grid inside, one .form-actions bar at the end. */
.form-section {
    min-width: 0;
    margin: 0;
    padding: 0 0 24px;
    border: 0;
}

.form-section + .form-section {
    padding-top: 24px;
    border-top: 1px solid var(--line);
}

.form-section > legend {
    float: left;
    width: 100%;
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 4px;
    padding: 0;
}

.form-section > legend + * {
    clear: both;
}

.optional-tag {
    padding: 2px 8px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.08);
    color: var(--white-soft);
    font-size: var(--fs-2xs);
    letter-spacing: 0.04em;
}

.required-mark {
    color: var(--gold);
}

.field-grid .form-control::placeholder {
    color: var(--white-muted);
    font-weight: 500;
}

.field-help {
    margin: 0;
    color: var(--white-soft);
    font-size: var(--fs-xs);
    font-weight: 500;
}

.form-section > .field-help {
    margin-top: 12px;
}

.choice-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 10px;
    margin-top: 12px;
}

.choice-list .choice-row {
    min-height: 56px;
    border: 1px solid transparent;
    cursor: pointer;
}

.choice-list .choice-row:hover {
    border-color: var(--line);
}

.choice-list .choice-row:has(input:checked) {
    border-color: rgba(255, 159, 46, 0.6);
    background: rgba(255, 159, 46, 0.1);
}

.choice-list .choice-row:has(input:focus-visible) {
    outline: 2px solid white;
    outline-offset: 2px;
}

.choice-text {
    display: grid;
    min-width: 0;
}

.choice-text strong {
    color: white;
}

.choice-text small {
    overflow: hidden;
    color: var(--white-soft);
    font-weight: 500;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.form-actions {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    padding-top: 20px;
    border-top: 1px solid var(--line);
}

.platform-config-tabs {
    margin-bottom: 20px;
}

.platform-config-tabs .btn.active,
.tenancy-status-tabs .btn.active {
    border-color: rgba(255, 255, 255, 0.36);
    background: rgba(255, 255, 255, 0.14);
    color: white;
}

/* Long-form template editor: body textarea beside a sticky variable list */
.template-editor {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 260px;
    gap: 20px;
    margin-top: 16px;
}

.template-editor .template-body {
    min-height: 480px;
    font-family: var(--font-mono);
    font-size: var(--fs-sm);
    line-height: 1.6;
}

.lease-variables {
    position: sticky;
    top: 16px;
    align-self: start;
    max-height: calc(100vh - 32px);
    overflow-y: auto;
    padding: 14px;
    border: 1px solid var(--line);
    border-radius: 16px;
    background: rgba(255, 255, 255, 0.04);
}

.lease-variables .eyebrow {
    margin: 0;
}

.lease-variables .var-group {
    margin-top: 12px;
}

.template-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

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

    .lease-variables {
        position: static;
        max-height: none;
    }
}

html[data-theme="light"] .field-help,
html[data-theme="light"] .choice-text small,
html[data-theme="light"] .optional-tag {
    color: var(--rp-muted);
}

html[data-theme="light"] .choice-text strong {
    color: var(--rp-text);
}

.field-grid .form-control,
.field-grid .form-select {
    border: 1px solid var(--line);
    background: rgba(255, 255, 255, 0.08);
    color: white;
    border-radius: 16px;
    min-height: 40px;
}

.field-grid .form-control:focus,
.field-grid .form-select:focus {
    border-color: rgba(255, 255, 255, 0.3);
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.08);
}

.field-grid textarea.form-control {
    min-height: 80px;
}

/* .form-select's caret ships as part of Bootstrap's own `background`
   shorthand — the background-color-only override above would otherwise
   silently strip it, same gap already fixed once for .filter-bar/
   .modal-body in mockups/assets/repairs-pilot.css. Redrawn explicitly. */
.field-grid .form-select {
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%23b9c4c2' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round' d='M2.5 4.5l3.5 3.5 3.5-3.5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 12px;
    padding-right: 32px;
}

.field-grid .form-select option {
    background: var(--ink-2);
    color: white;
}

.field-grid .form-control::placeholder {
    color: var(--white-soft);
    opacity: 1;
}

input[type="date"]::-webkit-calendar-picker-indicator,
input[type="datetime-local"]::-webkit-calendar-picker-indicator {
    filter: invert(1);
}

/* No border/background/padding of its own -- .property-tenant-card's own
   .panel already frames this content. A second border+background here
   (this used to have one) just double-framed the exact same box: an
   outer .panel card with an inner "card" drawn immediately inside it,
   both the same radius, one pixel apart. */
.property-strip {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 16px;
    margin-top: 0;
}

.property-strip-info {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.property-strip-info strong {
    font-size: var(--fs-sm);
    color: white;
}

.property-strip-info span {
    font-size: var(--fs-xs);
    color: var(--white-soft);
}

/* Sits below the property/unit line inside the same info stack -- its
   own row (not another .property-strip-info span) since it needs its
   own top gap and full-width wrapping regardless of the icon/unit/
   location line above it. */
.property-strip-requested-by {
    margin-top: 4px;
    font-size: var(--fs-xs);
    color: var(--white-muted);
}

.property-strip-requested-by strong {
    color: var(--white-soft);
    font-weight: 600;
}

.property-strip-tenant {
    font-size: var(--fs-xs);
    color: var(--white-soft);
}

.property-strip-link {
    margin-left: auto;
}

.property-thumb {
    width: 72px;
    height: 72px;
    flex: none;
    border-radius: 16px;
    border: 1px solid var(--line);
    object-fit: cover;
}

/* Primary CTA — solid fill, one level up from .btn-light, for the page's
   single most important action. Same values as the established (mockup-
   only until now) convention in repairs-pilot.css. */
.btn-primary {
    background: var(--amber);
    border-color: var(--amber);
    color: #0a171a;
}

.btn-primary:hover {
    background: #ffb655;
    border-color: #ffb655;
}

.status-pill.urgent,
.status-pill.failed {
    background: rgba(255, 107, 58, 0.16);
    color: var(--danger);
}

.status-pill.scheduled,
.status-pill.processing {
    background: rgba(255, 209, 136, 0.16);
    color: var(--gold);
}

.status-pill.complete {
    background: rgba(134, 215, 255, 0.16);
    color: var(--sky);
}

.status-pill.draft {
    background: rgba(255, 255, 255, 0.1);
    color: var(--white-soft);
}

/* Work order command card -------------------------------------------------
   A decision-oriented summary: identity and state first, then stage,
   property context, operational facts, and finally the pending decisions. */
.work-order-card {
    position: relative;
    overflow: visible;
}

.work-order-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
}

.work-order-heading h2 {
    margin: 2px 0 0;
    color: white;
    font-size: clamp(1.5rem, 2vw, 2rem);
    letter-spacing: -0.035em;
}

.work-order-kicker {
    display: flex;
    align-items: center;
    gap: 8px;
}

.work-order-kicker .eyebrow {
    margin: 0;
}

.work-order-kicker > span {
    padding-left: 8px;
    border-left: 1px solid var(--line);
    color: var(--white-muted);
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: 0.04em;
}

.work-order-description {
    margin: 4px 0 0;
    color: var(--white-soft);
    font-size: var(--fs-sm);
}

.work-order-header-tools {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: none;
}

.work-order-menu .icon-button {
    width: 40px;
    height: 40px;
    background: rgba(255, 255, 255, 0.08);
    border-color: var(--line);
}

/* The stepper and the facts row used to be two visually disconnected
   pieces (an unboxed <ol> followed by its own separately-bordered grid)
   sitting one after another in the card, reading as "slapped together."
   .status-card gives both one shared frame with a single divider between
   them -- .work-order-progress and .work-order-snapshot are unchanged in
   every other way, just no longer drawing their own outer border/margin. */
.status-card {
    margin-top: 22px;
    border: 1px solid var(--line);
    border-radius: 16px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.03);
}

.status-card-progress {
    padding: 20px 22px 18px;
}

.status-card-divider {
    height: 1px;
    background: var(--line);
}

.work-order-progress {
    display: grid;
    /* Sized to however many <li> steps actually render (5 for a
       landlord-serviced repair, 6 once a vendor is on the job — see
       RepairService::progressSteps()) instead of a fixed 5 columns,
       which squeezed a 6th step onto its own wrapped row. */
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    margin: 0;
    padding: 0;
    list-style: none;
}

.work-order-progress li {
    position: relative;
    display: grid;
    justify-items: center;
    gap: 8px;
    min-width: 0;
    color: var(--white-soft);
    font-size: var(--fs-xs);
    text-align: center;
}

.work-order-progress li::before {
    content: "";
    position: absolute;
    z-index: 0;
    top: 14px;
    right: 50%;
    width: 100%;
    height: 2px;
    background: var(--line);
}

.work-order-progress li:first-child::before {
    display: none;
}

/* .step-circle-outer specifically -- NOT the generic "li > span" this
   used to be, which was also matching .frac and .step-tip (every other
   direct-child span this stepper now has) and turning them into stray
   30x30 circular badges too. */
.work-order-progress li > .step-circle-outer {
    position: relative;
    z-index: 1;
    display: grid;
    width: 30px;
    height: 30px;
    place-items: center;
    border: 2px solid var(--line);
    border-radius: 999px;
    background: var(--ink-2);
    color: var(--white-soft);
    font-size: 11px;
    font-weight: 700;
}

.work-order-progress li > .step-circle-outer svg {
    width: 14px;
    height: 14px;
    stroke-width: 3;
}

.work-order-progress li.complete::before,
.work-order-progress li.current::before {
    background: var(--amber);
}

.work-order-progress li.complete > .step-circle-outer {
    border-color: var(--amber);
    background: var(--amber);
    color: #0a171a;
}

.work-order-progress li.current {
    color: white;
}

.work-order-progress li.current > .step-circle-outer {
    border-color: var(--amber);
    color: white;
    box-shadow: 0 0 0 4px rgba(255, 159, 46, 0.22);
}

.work-order-progress li strong {
    overflow: hidden;
    max-width: 100%;
    font-weight: 600;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The tenant Service Request drawer (my-unit-repair.php) reuses this same
   stepper at a fixed 560px width -- narrower than the owner/vendor
   status-card it was designed against -- so "Vendor sourcing" clips to
   "Vendor so..." at the base font-size. Smaller text (not the mobile
   breakpoint's label-hiding trick; the drawer is wider than a phone and
   all six labels still fit) is enough to stop the clipping. */
.drawer .work-order-progress li strong {
    font-size: 11px;
}

/* The tenant drawer's .status-card wraps only the progress row itself (no
   divider/snapshot section below it, unlike the owner page's version), so
   the card's own box is barely taller than the circles -- short enough
   that .status-card's overflow:hidden (kept globally for its rounded
   corners) clips the downward-opening .step-tip tooltip completely, the
   same class of bug already fixed once this session for the owner page's
   upward-opening version. Restoring visibility here is safe: this simpler
   card has no rounded-corner-bleeding children to clip in the first place. */
.drawer .status-card {
    overflow: visible;
}

/* Liquid-fill circles (mockups/work-order-step-fill.html, approved design)
   -- every step, even the single-action ones, renders through this same
   component instead of a plain dot, with the fill height driven by
   RepairService::progressSteps()'s fillPercent. */
.work-order-progress .step-circle-outer {
    position: relative;
    overflow: hidden;
}

.work-order-progress .step-circle-fill {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 0%;
    background: var(--amber);
    transition: height .6s cubic-bezier(.2, .8, .2, 1);
}

.work-order-progress .step-circle-icon {
    position: relative;
    z-index: 1;
}

.work-order-progress .step-circle-icon {
    width: 14px;
    height: 14px;
    stroke-width: 3;
    color: #0a171a;
}

.work-order-progress li:not(.complete) .step-circle-icon {
    display: none;
}

.work-order-progress li .frac {
    font-size: 10px;
    color: var(--white-muted);
    font-variant-numeric: tabular-nums;
}

/* Tooltip -- mirrors .field-tip/.tip-bubble exactly (bubble size, colors,
   arrow), triggered by the whole <li> rather than a separate "?" icon;
   this stepper has no room to spare per step, and every step is already
   a natural hover/focus target. */
.work-order-progress li {
    cursor: help;
    outline: none;
}

.work-order-progress li .step-tip {
    /* Opens DOWNWARD, not upward like .field-tip/.tip-bubble normally
       does -- the circles sit right at the top of .status-card, which has
       its own overflow:hidden for its rounded corners, so a tooltip
       popping up gets silently clipped by that ancestor with no visible
       cascade conflict to explain why (confirmed live: opacity/visibility
       were correctly toggling, the box was just rendering off-clip).
       There's real room below, inside the same card, so this direction
       has nothing to collide with. */
    position: absolute;
    top: calc(100% + 12px);
    left: 50%;
    transform: translateX(-50%);
    width: 200px;
    padding: 10px 12px;
    border-radius: 10px;
    border: 1px solid var(--line);
    background: var(--ink-2);
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.35);
    color: var(--white-soft);
    font-size: var(--fs-xs);
    font-weight: 400;
    line-height: 1.5;
    text-align: left;
    opacity: 0;
    visibility: hidden;
    transition: opacity 120ms ease;
    pointer-events: none;
    z-index: 6;
}

.work-order-progress li .step-tip::after {
    content: "";
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 6px solid transparent;
    border-bottom-color: var(--ink-2);
}

.work-order-progress li:hover .step-tip,
.work-order-progress li:focus-visible .step-tip {
    opacity: 1;
    visibility: visible;
}

.work-order-progress .step-tip-heading { margin-bottom: 8px; }
.work-order-progress .step-tip-heading strong {
    color: var(--amber);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: .04em;
}
.work-order-progress .step-tip-list { display: flex; flex-direction: column; gap: 6px; }
.work-order-progress .step-tip-row { display: flex; align-items: center; gap: 7px; }
.work-order-progress .step-tip-row-icon { display: inline-flex; flex: none; }
.work-order-progress .step-tip-row-icon svg { width: 13px; height: 13px; display: block; }
.work-order-progress .step-tip-row-icon.is-done { color: var(--amber); }
.work-order-progress .step-tip-row-icon.is-pending { color: var(--white-muted); }
.work-order-progress .step-tip-row.is-pending span:last-child { color: var(--white-muted); }

/* Keep edge steps' bubbles from forcing horizontal scroll on narrow
   viewports -- center-anchored is fine for every step in between. */
.work-order-progress li:first-child .step-tip { left: 0; transform: translateX(0); }
.work-order-progress li:first-child .step-tip::after { left: 14px; transform: translateX(0); }
.work-order-progress li:last-child .step-tip { left: auto; right: 0; transform: translateX(0); }
.work-order-progress li:last-child .step-tip::after { left: auto; right: 14px; transform: translateX(0); }

/* property-strip has exactly one real caller (the property/tenant
   snapshot atop repair-detail.php) -- unscoped from .work-order-card
   here (it used to inherit that class's spacing/sizing rules purely
   because its own <section> was mislabeled with the wrong shared class,
   not because the card itself needed them), so a caller no longer has
   to opt into a whole other component's class just to get these. */
.property-strip {
    flex-wrap: nowrap;
}

.property-thumb {
    width: 64px;
    height: 64px;
}

.context-label,
.snapshot-label {
    display: flex;
    align-items: center;
    gap: 4px;
    color: var(--white-muted);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.055em;
    line-height: 1.2;
    text-transform: uppercase;
}

.context-label svg {
    width: 12px;
    height: 12px;
}

.property-strip-tenant {
    display: flex;
    min-width: 190px;
    flex-direction: column;
    gap: 2px;
    padding-left: 16px;
    border-left: 1px solid var(--line);
}

.property-strip-tenant small,
.snapshot-item small {
    color: var(--white-muted);
    font-size: 11px;
}

.property-strip-link {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: var(--amber);
    font-size: var(--fs-xs);
    font-weight: 700;
    text-decoration: none;
}

.property-strip-link:hover {
    text-decoration: underline;
    text-underline-offset: 3px;
}

.property-strip-link svg {
    width: 14px;
    height: 14px;
}

.work-order-snapshot {
    display: grid;
    /* --snapshot-cols is set inline per render, from how many facts
       actually apply to the current viewer role (repair-detail.php) --
       equal-width columns so a value like "View photos (3)" clips with
       an ellipsis instead of wrapping or leaving mismatched widths. */
    grid-template-columns: repeat(var(--snapshot-cols, 3), 1fr);
    gap: 1px;
    background: var(--line);
}

.snapshot-item {
    display: flex;
    min-width: 0;
    gap: 12px;
    padding: 16px;
    background: var(--ink-2);
}

.snapshot-icon {
    display: grid;
    width: 36px;
    height: 36px;
    flex: none;
    place-items: center;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.08);
    color: var(--amber);
}

.snapshot-avatar {
    object-fit: cover;
    border-radius: 999px;
}

.vendor-picker-preview {
    display: block;
    margin-top: 8px;
}

.sourcing-control .vendor-picker-preview {
    margin-top: 0;
}

.vendor-picker-preview img {
    width: 36px;
    height: 36px;
    border-radius: 999px;
    object-fit: cover;
    border: 1px solid var(--line);
}

.bid-vendor-name {
    display: flex;
    align-items: center;
    gap: 8px;
}

.bid-vendor-avatar {
    width: 24px;
    height: 24px;
    border-radius: 999px;
    object-fit: cover;
    border: 1px solid var(--line);
    flex-shrink: 0;
}

.msg-avatar {
    width: 22px;
    height: 22px;
    border-radius: 999px;
    object-fit: cover;
    border: 1px solid var(--line);
}

.snapshot-icon svg {
    width: 17px;
    height: 17px;
}

.snapshot-item > div:not(.snapshot-heading-row) {
    min-width: 0;
}

.snapshot-value {
    display: block;
    max-width: 100%;
    margin-top: 3px;
    overflow: hidden;
    color: white;
    font-size: var(--fs-sm);
    font-style: normal;
    font-weight: 700;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.snapshot-value em {
    color: var(--white-muted);
    font-size: 11px;
    font-style: normal;
    font-weight: 500;
}

.mini-state {
    display: inline-block;
    width: 7px;
    height: 7px;
    margin-right: 3px;
    border-radius: 999px;
    background: var(--amber);
}

.snapshot-heading-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 8px;
}

.cap-remaining {
    flex: none;
    color: var(--white-muted);
    font-size: 11px;
    font-weight: 600;
}

.cost-meter {
    display: block;
    width: 100%;
    height: 6px;
    margin-top: 12px;
    overflow: hidden;
    appearance: none;
    border: 0;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.1);
}

.cost-meter::-webkit-progress-bar {
    border-radius: inherit;
    background: rgba(255, 255, 255, 0.1);
}

.cost-meter::-webkit-progress-value {
    border-radius: inherit;
    background: var(--amber);
}

.cost-meter::-moz-progress-bar {
    border-radius: inherit;
    background: var(--amber);
}

.work-order-meta {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-top: 12px;
    color: var(--white-muted);
    font-size: var(--fs-xs);
}

.work-order-meta span {
    display: inline-flex;
    align-items: center;
    gap: 5px;
}

.work-order-meta svg {
    width: 13px;
    height: 13px;
}

.work-order-modal-copy {
    margin: 0;
    color: var(--white-soft);
    font-size: var(--fs-sm);
}

.work-order-modal-fields {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

.work-order-modal-fields label small {
    color: var(--white-muted);
    font-size: 11px;
    font-weight: 400;
}

/* ---- Vendor sourcing: three fields side by side instead of three
   stacked full-width forms, each with a small control floating in a lot
   of otherwise-empty horizontal space. ---- */
.sourcing-card {
    margin-top: 22px;
    border: 1px solid var(--line);
    border-radius: 16px;
    background: rgba(255, 255, 255, 0.03);
}

.sourcing-head {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 20px;
    border-bottom: 1px solid var(--line);
    border-radius: 16px 16px 0 0;
}

.sourcing-head .icon {
    display: grid;
    width: 34px;
    height: 34px;
    flex: none;
    place-items: center;
    border-radius: 10px;
    background: rgba(134, 215, 255, 0.14);
    color: var(--sky);
}

.sourcing-head strong {
    display: block;
    font-size: var(--fs-sm);
    color: #fff;
}

.draft-badge {
    margin-left: auto;
    flex: none;
    padding: 4px 11px;
    border-radius: 999px;
    border: 1px solid rgba(255, 159, 46, 0.5);
    background: rgba(255, 159, 46, 0.12);
    color: var(--amber);
    font-size: var(--fs-2xs);
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.draft-badge.is-live {
    border-color: rgba(166, 233, 192, 0.5);
    background: rgba(166, 233, 192, 0.14);
    color: var(--good);
}

.sourcing-fields {
    display: flex;
    flex-wrap: wrap;
    border-bottom: 1px solid var(--line);
}

.sourcing-field {
    flex: 0 0 25%;
    min-width: 0;
    padding: 15px 20px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    border-right: 1px solid var(--line);
}

.sourcing-field:last-child {
    border-right: none;
}

.sourcing-field.is-wide {
    flex: 0 0 50%;
}

.sourcing-field-label {
    display: flex;
    align-items: center;
    gap: 6px;
}

.sourcing-field-label strong {
    font-size: var(--fs-sm);
    color: #fff;
    font-weight: 650;
}

/* (?) tooltip -- replaces the paragraph of helper copy that used to sit
   under every field. Same information, shown only when asked for. */
.field-tip {
    position: relative;
    display: inline-flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 15px;
    height: 15px;
    border-radius: 999px;
    border: 1px solid var(--white-muted);
    color: var(--white-muted);
    font-size: 10px;
    font-weight: 700;
    line-height: 1;
    cursor: help;
}

.field-tip:hover,
.field-tip:focus-visible {
    border-color: var(--sky);
    color: var(--sky);
    outline: none;
}

.field-tip .tip-bubble {
    position: absolute;
    bottom: calc(100% + 9px);
    left: 50%;
    transform: translateX(-50%);
    width: 216px;
    padding: 10px 12px;
    border-radius: 10px;
    border: 1px solid var(--line);
    background: var(--ink-2);
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.35);
    color: var(--white-soft);
    font-size: var(--fs-xs);
    font-weight: 400;
    line-height: 1.5;
    text-align: left;
    opacity: 0;
    visibility: hidden;
    transition: opacity 120ms ease;
    pointer-events: none;
    z-index: 6;
}

.field-tip:hover .tip-bubble,
.field-tip:focus-visible .tip-bubble {
    opacity: 1;
    visibility: visible;
}

.field-tip .tip-bubble::after {
    content: "";
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 6px solid transparent;
    border-top-color: var(--ink-2);
}

/* Content-sized, not stretched to fill the field -- a date and a percent
   don't need to be as wide as a vendor-name select. nowrap so the %
   suffix and Save button never drop to their own line under the input. */
.sourcing-control {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: nowrap;
}

/* !important throughout this block (and its light-theme counterpart
   below) fights one specific rule: the global .app-frame
   input:not(...) form reset, which sets width/padding/border/
   background/color with four :not() clauses in its selector --
   (0,5,1) specificity, beating this rule's (0,2,1) outright regardless
   of source order. These compact fields are a deliberate, narrow
   exception to that reset (a date/percent value sized to its content,
   not stretched to fill a 25%-wide column), so !important reinstates
   that intent everywhere the reset would otherwise win -- width alone
   isn't enough, since the reset's own 14px/side padding left almost no
   room inside a content-sized box.  */
.sourcing-control input,
.sourcing-control select {
    flex: none;
    padding: 7px 10px !important;
    border-radius: 8px !important;
    border: 1px solid var(--line) !important;
    background: rgba(255, 255, 255, 0.06) !important;
    color: #fff !important;
    font: inherit;
    font-size: var(--fs-sm) !important;
    color-scheme: dark;
}

.sourcing-field.is-wide .sourcing-control select {
    flex: 1 1 auto;
    min-width: 0;
}

.sourcing-control input[type="date"] {
    width: 14ch !important;
}

/* Native Chromium calendar-picker glyph ignores color-scheme in some
   builds and renders black regardless of the input's own dark styling --
   inverted explicitly here rather than relying on color-scheme alone. */
.sourcing-control input[type="date"]::-webkit-calendar-picker-indicator {
    filter: invert(1);
    cursor: pointer;
}

.sourcing-control input[type="number"] {
    /* border-box width has to budget for the field's own h-padding and
       the native spinner buttons, not just the digits themselves (max
       value is 100, 3 digits) -- a bare "3ch" left almost nothing once
       that chrome was subtracted. Sized for 4 digits' worth of room so
       "100" still has visible breathing space, not a hairline fit. */
    width: 58px !important;
    padding-left: 8px !important;
    padding-right: 2px !important;
    text-align: right;
}

.sourcing-control input.is-invalid {
    border-color: var(--danger);
    background: rgba(255, 107, 58, 0.1);
}

.field-error {
    display: block;
    margin-top: 7px;
    color: var(--danger);
    font-size: var(--fs-xs);
}

.sourcing-suffix {
    color: var(--white-soft);
    font-size: var(--fs-sm);
    font-weight: 600;
    margin-left: -2px;
}

.sourcing-save,
.sourcing-invite-btn {
    flex: none;
    padding: 7px 14px;
    border-radius: 8px;
    font-weight: 650;
    font-size: var(--fs-sm);
    cursor: pointer;
}

.sourcing-save {
    border: 1px solid var(--line);
    background: rgba(255, 255, 255, 0.08);
    color: #fff;
}

.sourcing-save:hover {
    background: rgba(255, 255, 255, 0.14);
}

.sourcing-save:disabled {
    opacity: 0.4;
    cursor: not-allowed;
    background: rgba(255, 255, 255, 0.04);
    color: var(--white-muted);
}

.sourcing-save:disabled:hover {
    background: rgba(255, 255, 255, 0.04);
}

.sourcing-invite-btn {
    border: 1px dashed rgba(255, 159, 46, 0.5);
    background: rgba(255, 159, 46, 0.08);
    color: var(--amber);
}

.sourcing-invite-btn:hover {
    background: rgba(255, 159, 46, 0.14);
}

/* ---- Open for bids / Withdraw work order: the one action that actually
   publishes the draft, and its reverse. ---- */
.open-bids-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    padding: 20px 24px;
    background: rgba(255, 159, 46, 0.05);
    border-radius: 0 0 16px 16px;
}

.open-bids-row > div {
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 1;
    min-width: 0;
}

.open-bids-row strong {
    display: block;
    font-size: var(--fs-md);
    color: #fff;
}

.open-bids-row small {
    display: block;
    color: var(--white-muted);
    font-size: var(--fs-sm);
    line-height: 1.6;
}

.open-bids-btn {
    flex: none;
    padding: 10px 20px;
    border-radius: 10px;
    border: none;
    background: var(--amber);
    color: var(--ink);
    font-weight: 700;
    font-size: var(--fs-sm);
    cursor: pointer;
}

.open-bids-btn:hover {
    background: #ffb655;
}

.open-bids-btn.is-withdraw {
    background: var(--danger);
    color: #fff;
}

.open-bids-btn.is-withdraw:hover {
    background: #ff8257;
}

/* ---- vendor pills (already-invited vendors) + the multi-select invite
   modal that replaces the old single-vendor dropdown ---- */
.vendor-pills {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}

.vendor-pill {
    flex: none;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 6px 4px 4px;
    border-radius: 999px;
    border: 1px solid var(--line);
    background: rgba(255, 255, 255, 0.05);
}

.vendor-pill img {
    width: 22px;
    height: 22px;
    border-radius: 999px;
    object-fit: cover;
}

.vendor-pill span {
    font-size: var(--fs-xs);
    color: var(--white-soft);
    font-weight: 600;
    white-space: nowrap;
}

.vendor-pill form {
    display: contents;
}

.vendor-pill button {
    display: grid;
    place-items: center;
    width: 16px;
    height: 16px;
    border-radius: 999px;
    border: none;
    background: rgba(255, 255, 255, 0.12);
    color: var(--white-soft);
    font-size: 11px;
    line-height: 1;
    cursor: pointer;
    padding: 0;
}

.vendor-pill button:hover {
    background: rgba(255, 107, 58, 0.4);
    color: #fff;
}

.invite-vendor-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.invite-vendor-card {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    border-radius: 12px;
    border: 1px solid var(--line);
    cursor: pointer;
    transition: background 120ms ease, border-color 120ms ease;
}

.invite-vendor-card:hover {
    background: rgba(255, 255, 255, 0.04);
}

.invite-vendor-card:has(input:checked) {
    border-color: var(--amber);
    background: rgba(255, 159, 46, 0.08);
}

.invite-vendor-card input {
    flex: none;
    width: 16px;
    height: 16px;
    accent-color: var(--amber);
}

.invite-vendor-card img,
.invite-vendor-card-avatar {
    width: 34px;
    height: 34px;
    border-radius: 999px;
    object-fit: cover;
    flex: none;
}

.invite-vendor-card-avatar {
    display: grid;
    place-items: center;
    background: rgba(255, 159, 46, 0.14);
    color: var(--amber);
}

.invite-vendor-card strong {
    font-size: var(--fs-sm);
    color: #fff;
}

@media (max-width: 900px) {
    .work-order-snapshot {
        grid-template-columns: 1fr;
    }

    .property-strip {
        flex-wrap: wrap;
    }

    .property-strip-tenant {
        margin-left: auto;
    }

    .sourcing-field {
        border-right: none;
        border-bottom: 1px solid var(--line);
    }

    .sourcing-field:last-child {
        border-bottom: none;
    }
}

@media (max-width: 600px) {
    .work-order-header {
        flex-wrap: wrap;
    }

    .work-order-header-tools {
        margin-left: auto;
    }

    .work-order-progress li strong {
        font-size: 10px;
    }

    .work-order-progress li:nth-last-child(-n + 2) strong {
        display: none;
    }

    .property-strip {
        align-items: flex-start;
    }

    .property-strip-info {
        width: calc(100% - 84px);
    }

    .property-strip-tenant {
        width: 100%;
        margin-left: 0;
        padding: 12px 0 0;
        border-top: 1px solid var(--line);
        border-left: none;
    }

    .property-strip-link {
        margin-left: 0;
    }

    .work-order-modal-fields {
        grid-template-columns: 1fr;
    }

    .work-order-modal-fields label.span-2 {
        grid-column: auto;
    }
}

/* Activity card: open tasks + composer + feed ----------------------------- */
.activity-card-heading {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
}

.open-task-count {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 6px 10px;
    border: 1px solid rgba(255, 159, 46, 0.55);
    border-radius: 999px;
    background: rgba(255, 159, 46, 0.1);
    color: var(--amber);
    font-size: var(--fs-xs);
    font-weight: 600;
    white-space: nowrap;
}

.open-task-count strong {
    font-size: var(--fs-sm);
}

.task-section {
    margin-top: 16px;
}

.task-section-heading,
.history-heading {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 12px;
}

.task-section-heading h3,
.history-heading h3 {
    margin: 0;
    color: white;
    font-size: var(--fs-md);
    letter-spacing: -0.015em;
}

.task-section-heading p,
.history-heading > span {
    margin: 2px 0 0;
    color: var(--white-soft);
    font-size: var(--fs-xs);
}

.task-stack {
    display: grid;
    gap: 12px;
    margin-top: 12px;
}

.task-card {
    display: grid;
    grid-template-columns: 40px minmax(0, 1fr);
    gap: 12px;
    padding: 16px;
    border: 1px solid var(--line);
    border-radius: 16px;
    background: rgba(255, 255, 255, 0.045);
}

.task-card.owner-task {
    border-color: rgba(255, 159, 46, 0.55);
    background: rgba(255, 159, 46, 0.08);
}

.task-icon {
    display: grid;
    width: 40px;
    height: 40px;
    place-items: center;
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.06);
    color: white;
}

.owner-task .task-icon {
    color: var(--amber);
}

.task-icon svg {
    width: 18px;
    height: 18px;
}

.task-body {
    min-width: 0;
}

.task-topline {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px 16px;
    flex-wrap: wrap;
}

.task-type {
    color: var(--amber);
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.055em;
    text-transform: uppercase;
}

.tenant-task .task-type {
    color: white;
}

.task-assignee {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    color: var(--white-soft);
    font-size: var(--fs-xs);
}

.task-assignee svg {
    width: 14px;
    height: 14px;
}

.task-assignee em {
    padding: 2px 6px;
    border-radius: 999px;
    background: var(--amber);
    color: #0a171a;
    font-size: 10px;
    font-style: normal;
    font-weight: 700;
    text-transform: uppercase;
}

.task-card h4 {
    margin: 8px 0 0;
    color: white;
    font-size: var(--fs-md);
    letter-spacing: -0.015em;
}

.task-card p {
    max-width: 800px;
    margin: 4px 0 0;
    color: var(--white-soft);
    font-size: var(--fs-sm);
}

.task-context {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 12px;
}

.task-context span {
    padding: 5px 9px;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.045);
    color: var(--white-soft);
    font-size: 11px;
}

.task-context strong {
    color: white;
}

.task-deadline {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 12px;
    color: var(--white-soft);
    font-size: var(--fs-xs);
    font-weight: 600;
}

.task-deadline svg {
    width: 14px;
    height: 14px;
}

.task-deadline.overdue {
    color: var(--danger);
}

.task-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 12px;
}

.task-actions .btn svg {
    width: 15px;
    height: 15px;
}

.composer-disclosure {
    margin-top: 16px;
}

.composer-disclosure > summary {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    border: 1px solid var(--line);
    border-radius: 16px;
    background: rgba(255, 255, 255, 0.06);
    cursor: pointer;
    list-style: none;
}

.composer-disclosure > summary::-webkit-details-marker {
    display: none;
}

.composer-disclosure > summary > span:nth-child(2) {
    display: flex;
    min-width: 0;
    flex: 1;
    flex-direction: column;
}

.composer-disclosure > summary strong {
    color: white;
    font-size: var(--fs-sm);
}

.composer-disclosure > summary small {
    color: var(--white-soft);
    font-size: var(--fs-xs);
}

.composer-summary-icon {
    display: grid;
    width: 32px;
    height: 32px;
    flex: none;
    place-items: center;
    border-radius: 999px;
    background: var(--amber);
    color: #0a171a;
}

.composer-summary-icon svg,
.composer-summary-chevron {
    width: 16px;
    height: 16px;
}

.composer-summary-chevron {
    flex: none;
    color: var(--white-soft);
    transition: transform 150ms ease;
}

.composer-disclosure[open] .composer-summary-chevron {
    transform: rotate(180deg);
}

/* The timeline used to always render its full feed inline (every note,
   visit, and status change since the work order opened) right below
   the open-tasks/composer section -- collapsed by default now, behind
   the same disclosure pattern as "Add an update" above it, so a long
   history doesn't push everything else down the page by default. */
.timeline-disclosure {
    margin-top: 24px;
    padding-top: 24px;
    border-top: 1px solid var(--line);
}

.timeline-disclosure > summary {
    margin-top: 0;
}

.timeline-disclosure-body {
    margin-top: 16px;
}

.composer {
    margin-top: 8px;
    padding: 16px;
    border: 1px solid var(--line);
    border-radius: 16px;
    background: rgba(255, 255, 255, 0.06);
}

.composer-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 12px;
}

.composer-tab {
    border: 1px solid var(--line);
    background: rgba(255, 255, 255, 0.06);
    color: var(--white-soft);
    font-size: var(--fs-xs);
    font-weight: 600;
    padding: 6px 14px;
    border-radius: 999px;
    cursor: pointer;
}

.composer-tab.active {
    background: var(--amber);
    border-color: var(--amber);
    color: #0a171a;
}

.composer-pane {
    display: none;
}

.composer-pane.active {
    display: block;
}

.feed {
    list-style: none;
    margin: 12px 0 0;
    padding: 0;
    display: grid;
    gap: 16px;
}

.feed-item {
    display: grid;
    grid-template-columns: 36px minmax(0, 1fr);
    gap: 12px;
    padding-bottom: 16px;
    border-bottom: 1px solid var(--line);
}

.feed-item:last-child {
    border-bottom: 0;
    padding-bottom: 0;
}

.feed-avatar {
    width: 36px;
    height: 36px;
}

.feed-body {
    min-width: 0;
}

.feed-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}

.feed-author {
    font-size: var(--fs-sm);
    font-weight: 600;
    color: white;
}

.feed-time {
    font-size: var(--fs-xs);
    color: var(--white-soft);
    white-space: nowrap;
}

.feed-text {
    margin: 4px 0 0;
    font-size: var(--fs-sm);
    color: white;
}

.feed-decline {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    font-weight: 600;
    color: var(--danger);
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 2px;
}

.feed-photos {
    display: flex;
    gap: 8px;
    margin-top: 12px;
}

.feed-photo {
    width: 64px;
    height: 64px;
    flex: none;
    padding: 0;
    border: 1px solid var(--line);
    border-radius: 16px;
    overflow: hidden;
    cursor: pointer;
    background: none;
}

.feed-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

@media (max-width: 600px) {
    .activity-card-heading {
        align-items: flex-start;
    }

    .task-card {
        grid-template-columns: 1fr;
    }

    .task-actions .btn {
        width: 100%;
        justify-content: center;
    }

    .task-actions .feed-decline {
        margin: 0 auto;
    }
}

/* ============================================================
   DASHBOARD LIGHT THEME
   Scoped entirely under html[data-theme="light"]. That attribute is
   only ever set by the inline script in app.php, which only ships
   when the controller passes themeToggle=true — currently index(),
   the two /dev lab pages (cardLab, propertyCardLab), properties(),
   propertyWalkthrough(), and repairs(). Still never on any of the
   other real pages, regardless of the visitor's saved preference.
   ============================================================ */
html[data-theme="light"] {
    --rp-bg: #f7f4ef;
    --rp-surface: #fffdf8;
    --rp-surface-muted: #eef3ef;
    --rp-text: #18221f;
    --rp-muted: #66736d;
    --rp-border: #e2ded5;
    --rp-teal: #285f57;
    --rp-teal-dark: #123833;
    --rp-amber: #d9aa49;
    /* Current-step ring/glow/label accent for .work-order-progress --
       distinct from --rp-amber (used elsewhere for lighter accents/
       badges) because --rp-amber alone is only ~2.1:1 against
       --rp-surface, short of the ~4.5:1 floor needed once it's a current-
       step label color, not just a light border. #946a0a clears ~5:1.
       Verified in mockups/work-order-step-fill.html's :root comment. */
    --rp-amber-current: #946a0a;
    --rp-clay: #d95032;
    --rp-blue: #6f9cad;
}

html[data-theme="light"] body {
    background: var(--rp-bg);
    color: var(--rp-text);
}

html[data-theme="light"] .app-sidebar,
html[data-theme="light"] .topbar,
html[data-theme="light"] .panel,
html[data-theme="light"] .property-card {
    border: 1px solid var(--rp-border);
    background: var(--rp-surface);
    box-shadow: 0 12px 30px rgba(24, 34, 31, 0.07);
    backdrop-filter: none;
}

html[data-theme="light"] .app-sidebar {
    --bs-offcanvas-bg: var(--rp-surface);
    --bs-offcanvas-color: var(--rp-text);
    --bs-offcanvas-border-color: var(--rp-border);
}

html[data-theme="light"] .app-sidebar .offcanvas-header {
    border-bottom-color: var(--rp-border);
    color: var(--rp-text);
}

@media (min-width: 992px) {
    html[data-theme="light"] .app-sidebar {
        background: var(--rp-surface) !important;
    }
}

html[data-theme="light"] .brand-mark strong,
html[data-theme="light"] .topbar h1,
html[data-theme="light"] .panel h2,
html[data-theme="light"] .panel-header h2,
html[data-theme="light"] .panel-heading-row .hero-title,
html[data-theme="light"] .panel-stat,
html[data-theme="light"] .day-events-heading,
html[data-theme="light"] .repair-stage span,
html[data-theme="light"] .event-title,
html[data-theme="light"] .calendar-nav strong,
html[data-theme="light"] .calendar-cell {
    color: var(--rp-text);
}

html[data-theme="light"] .brand-mark small,
html[data-theme="light"] .eyebrow,
html[data-theme="light"] .sidebar-callout,
html[data-theme="light"] .sidebar-callout p,
html[data-theme="light"] .calendar-weekdays span,
html[data-theme="light"] .event-meta,
html[data-theme="light"] .event-empty,
html[data-theme="light"] .ledger-row span,
html[data-theme="light"] .repair-stage em,
html[data-theme="light"] .property-body p,
html[data-theme="light"] .property-meta-list small,
html[data-theme="light"] .muted-copy,
html[data-theme="light"] .walkthrough-unit-card small,
html[data-theme="light"] .walkthrough-unit-card span,
html[data-theme="light"] .walkthrough-kpis span {
    color: var(--rp-muted);
}

/* .property-card-image-empty had no light variant — translucent white on
   translucent white in dark, invisible on cream in light. Same class of gap
   as .btn-dark: never rendered in light mode until this page turned the
   toggle on for a page other than the dashboard. */
html[data-theme="light"] .property-card-image-empty {
    background: var(--rp-surface-muted);
    color: var(--rp-muted);
}

html[data-theme="light"] .sidebar-link {
    color: var(--rp-text);
}

html[data-theme="light"] .sidebar-link svg {
    color: var(--rp-muted);
}

html[data-theme="light"] .sidebar-link:hover,
html[data-theme="light"] .sidebar-link.active {
    transform: none;
    background: var(--rp-surface-muted);
    color: var(--rp-text);
}

html[data-theme="light"] .sidebar-link.active {
    background: var(--rp-teal);
    color: #fff;
}

html[data-theme="light"] .sidebar-link.active svg {
    color: #fff;
}

html[data-theme="light"] .sidebar-callout {
    background: var(--rp-surface-muted);
}

html[data-theme="light"] .icon-button {
    border-color: var(--rp-border);
    background: var(--rp-surface);
    color: var(--rp-text);
}

html[data-theme="light"] .icon-button:hover {
    background: var(--rp-surface-muted);
}

html[data-theme="light"] .btn-light {
    border: 1px solid var(--rp-border);
    background: var(--rp-surface);
    color: var(--rp-text);
}

html[data-theme="light"] .btn-light:hover {
    background: var(--rp-surface-muted);
}

/* .btn-dark had no light variant at all — it inherited the dark theme's
   white-text-on-translucent-white styling verbatim, which is white-on-cream
   in light mode. Latent since before this pass (empty-state.php's CTA is a
   btn-dark, reachable today any time a dashboard card has zero rows) but
   only actually rendered on the dashboard by panel-card.php's new footer
   buttons, which is what surfaced it. */
html[data-theme="light"] .btn-dark {
    border: 1px solid var(--rp-teal-dark);
    background: var(--rp-teal-dark);
    color: #fff;
}

html[data-theme="light"] .btn-dark:hover {
    background: var(--rp-teal);
    border-color: var(--rp-teal);
}

html[data-theme="light"] .btn-danger { background: var(--rp-clay); border-color: var(--rp-clay); color: white; }
html[data-theme="light"] .btn-danger:hover { background: #c04227; border-color: #c04227; }
html[data-theme="light"] .btn-text-danger { color: var(--rp-clay); }

html[data-theme="light"] .btn-ghost {
    border: 1px solid var(--rp-teal-dark);
    background: var(--rp-teal-dark);
    color: #fff;
}

html[data-theme="light"] .btn-ghost:hover {
    background: var(--rp-teal);
    border-color: var(--rp-teal);
}

html[data-theme="light"] .nav-tabs { border-color: var(--rp-border); }
html[data-theme="light"] .nav-tabs .nav-link.active { color: #9a7523; background: rgba(217, 170, 73, 0.16); }
html[data-theme="light"] .nav-tabs.pill-tabs { background: var(--rp-surface-muted); border-color: transparent; }
html[data-theme="light"] .nav-tabs.pill-tabs .nav-link:hover { color: var(--rp-text); }
html[data-theme="light"] .nav-tabs.pill-tabs .nav-link.active { color: #1a1206; background: var(--amber); }

html[data-theme="light"] .panel-icon {
    background: rgba(217, 170, 73, 0.16);
    color: #9a7523;
}

html[data-theme="light"] .panel-icon.blue { background: rgba(111, 156, 173, 0.18); color: var(--rp-teal-dark); }
html[data-theme="light"] .panel-icon.green { background: rgba(113, 156, 114, 0.18); color: #3f5f40; }

html[data-theme="light"] .panel-header-shaded {
    background: var(--rp-surface-muted);
}

html[data-theme="light"] .panel-divider,
html[data-theme="light"] .panel-footer {
    border-color: var(--rp-border);
}

html[data-theme="light"] .card-lab-placeholder {
    color: var(--rp-muted);
}

html[data-theme="light"] .status-pill {
    background: rgba(217, 170, 73, 0.16);
    color: #9a7523;
}

html[data-theme="light"] .data-row {
    border-color: var(--rp-border);
    background: var(--rp-surface-muted);
    color: var(--rp-text);
}

html[data-theme="light"] .workflow-name-link {
    color: var(--rp-text);
}

html[data-theme="light"] .workflow-strip a,
html[data-theme="light"] .workflow-strip span {
    border-color: var(--rp-border);
    background: var(--rp-surface-muted);
    color: var(--rp-muted);
}

html[data-theme="light"] .workflow-strip a:hover {
    background: var(--rp-surface);
    color: var(--rp-text);
}

html[data-theme="light"] .workflow-strip a.active {
    border-color: var(--rp-teal-dark);
    background: var(--rp-surface);
    color: var(--rp-text);
}

html[data-theme="light"] .data-head {
    background: var(--rp-surface-muted);
    color: var(--rp-muted);
}

/* var(--sky) is tuned for this app's dark surfaces (#86d7ff) — nearly
   unreadable as text on the light theme's cream background. A darker,
   more saturated blue instead, same choice the light-mode mockup this
   pattern is copied from made for its own equivalent link. */
html[data-theme="light"] .view-all-link {
    color: #1595c9;
}

html[data-theme="light"] .empty-state-compact svg,
html[data-theme="light"] .empty-state-compact p,
html[data-theme="light"] .empty-state p {
    color: var(--rp-muted);
}

html[data-theme="light"] .empty-state:not(.empty-state-compact) > svg {
    border-color: var(--rp-border);
    background: var(--rp-surface-muted);
    color: var(--rp-teal);
}

html[data-theme="light"] .data-head-sort:hover,
html[data-theme="light"] .data-head-sort.active {
    color: var(--rp-text);
}

html[data-theme="light"] .urgency-badge {
    background: var(--rp-surface-muted);
    color: var(--rp-muted);
}

html[data-theme="light"] .condition-changed {
    color: var(--rp-clay);
}

html[data-theme="light"] .urgency-badge.soon {
    background: rgba(217, 170, 73, 0.16);
    color: #9a7523;
}

html[data-theme="light"] .urgency-badge.urgent {
    background: rgba(217, 80, 50, 0.12);
    color: var(--rp-clay);
}

html[data-theme="light"] .attention-chip {
    border-color: var(--rp-border);
    background: rgba(217, 170, 73, 0.16);
    color: #9a7523;
}

html[data-theme="light"] .attention-chip:hover {
    background: rgba(217, 170, 73, 0.26);
}

html[data-theme="light"] .attention-chip.active {
    border-color: var(--rp-amber);
    background: rgba(217, 170, 73, 0.32);
}

html[data-theme="light"] .bulk-action-bar {
    border-color: var(--rp-border);
    background: var(--rp-surface-muted);
    color: var(--rp-text);
}

html[data-theme="light"] .timeline strong,
html[data-theme="light"] .timeline p {
    color: var(--rp-text);
}

html[data-theme="light"] .timeline time,
html[data-theme="light"] .detail-list span {
    color: var(--rp-muted);
}

html[data-theme="light"] .repair-form label,
html[data-theme="light"] .repair-form select,
html[data-theme="light"] .repair-form option,
html[data-theme="light"] .repair-form optgroup {
    color: var(--rp-text);
}

html[data-theme="light"] .repair-stage {
    border-color: var(--rp-border);
    background: var(--rp-surface-muted);
    color: var(--rp-text);
}

html[data-theme="light"] .repair-cost-card,
html[data-theme="light"] .rent-ledger {
    background: var(--rp-surface-muted);
}

html[data-theme="light"] .cost-rowline {
    color: var(--rp-muted);
}

html[data-theme="light"] .cost-rowline strong {
    color: var(--rp-text);
}

html[data-theme="light"] .cost-rowline i,
html[data-theme="light"] .ledger-row {
    background: rgba(24, 34, 31, 0.05);
}

html[data-theme="light"] .ledger-row {
    border: 1px solid var(--rp-border);
    color: var(--rp-text);
}

html[data-theme="light"] .ledger-row i,
html[data-theme="light"] .repair-stage::before {
    background: var(--rp-blue);
    box-shadow: none;
}

html[data-theme="light"] .ledger-row.late i,
html[data-theme="light"] .repair-stage.attention::before {
    background: var(--rp-amber);
}

html[data-theme="light"] .ledger-row.processing i {
    background: var(--rp-muted);
}

html[data-theme="light"] .chart-legend span.on-time,
html[data-theme="light"] .chart-legend span.late,
html[data-theme="light"] .chart-legend span.processing {
    color: var(--rp-muted);
}

html[data-theme="light"] .chart-legend span.on-time::before {
    background: var(--rp-blue);
    box-shadow: none;
}

html[data-theme="light"] .chart-legend span.late::before {
    background: var(--rp-amber);
    box-shadow: none;
}

html[data-theme="light"] .chart-legend span.processing::before {
    background: var(--rp-muted);
    box-shadow: none;
}

html[data-theme="light"] .repair-stage.urgent::before {
    background: var(--rp-clay);
}

html[data-theme="light"] .repair-stage.info::before {
    background: var(--rp-blue);
}

html[data-theme="light"] .repair-stage.urgent {
    border-color: var(--rp-clay);
}

html[data-theme="light"] .repair-stage.urgent span {
    color: var(--rp-clay);
}

html[data-theme="light"] .repair-stage.attention {
    border-color: var(--rp-amber);
}

html[data-theme="light"] .repair-stage.attention span {
    color: #9a7523;
}

html[data-theme="light"] .repair-stage.info {
    border-color: var(--rp-blue);
}

html[data-theme="light"] .repair-stage.info span {
    color: var(--rp-teal-dark);
}

html[data-theme="light"] .repair-stage.active {
    background: var(--rp-surface);
}

html[data-theme="light"] .calendar-cell:not(.selected):not(.muted) {
    color: var(--rp-text);
}

html[data-theme="light"] span.calendar-cell.muted {
    color: var(--rp-border);
}

html[data-theme="light"] a.calendar-cell:hover:not(.selected) {
    background: var(--rp-surface-muted);
}

html[data-theme="light"] .calendar-cell.has-events.urgent { color: var(--rp-clay); }
html[data-theme="light"] .calendar-cell.has-events.attention { color: #9a7523; }
html[data-theme="light"] .calendar-cell.has-events.info { color: var(--rp-teal-dark); }

html[data-theme="light"] .calendar-cell.selected {
    background: var(--rp-teal);
    border-color: var(--rp-teal);
    color: #fff !important;
}

html[data-theme="light"] .calendar-cell.selected .cell-dot {
    background: #fff;
}

html[data-theme="light"] .event-row {
    border: 1px solid var(--rp-border);
    background: var(--rp-surface);
}

html[data-theme="light"] .event-dot {
    background: var(--rp-border);
}

html[data-theme="light"] .event-row.urgent .event-dot { background: var(--rp-clay); box-shadow: none; }
html[data-theme="light"] .event-row.attention .event-dot { background: var(--rp-amber); box-shadow: none; }
html[data-theme="light"] .event-row.info .event-dot { background: var(--rp-blue); box-shadow: none; }

html[data-theme="light"] .event-icon {
    background: var(--rp-surface-muted);
    color: var(--rp-teal);
}

html[data-theme="light"] .event-empty svg {
    color: var(--rp-border);
}

/* ============================================================
   PROPERTIES FORM LIGHT THEME
   Same html[data-theme="light"] scoping as the dashboard block above —
   only ever active on pages that ship themeToggle (now also
   DashboardController::properties()). .form-control/.form-select are
   shared with other pages (login, repair-form, app-frame) that never
   set data-theme, so this is inert there regardless of scope.
   ============================================================ */
html[data-theme="light"] .form-control,
html[data-theme="light"] .form-select,
html[data-theme="light"] .app-frame input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]),
html[data-theme="light"] .app-frame select,
html[data-theme="light"] .app-frame textarea {
    border-color: var(--rp-border);
    background: var(--rp-surface);
    color: var(--rp-text);
}

html[data-theme="light"] .form-control::placeholder,
html[data-theme="light"] .app-frame input::placeholder,
html[data-theme="light"] .app-frame textarea::placeholder {
    color: var(--rp-muted);
    opacity: 1;
}

html[data-theme="light"] .form-select {
    background-image:
        linear-gradient(45deg, transparent 50%, rgba(24, 34, 31, 0.6) 50%),
        linear-gradient(135deg, rgba(24, 34, 31, 0.6) 50%, transparent 50%);
}

html[data-theme="light"] .form-control:focus,
html[data-theme="light"] .form-select:focus,
html[data-theme="light"] .app-frame input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]):focus,
html[data-theme="light"] .app-frame select:focus {
    border-color: var(--rp-teal);
    box-shadow: 0 0 0 2px rgba(40, 95, 87, 0.14);
}

html[data-theme="light"] .property-workbench,
html[data-theme="light"] .unit-card {
    border-color: var(--rp-border);
    background: var(--rp-surface);
}

html[data-theme="light"] .unit-nav {
    border-color: var(--rp-border);
    background: var(--rp-surface-muted);
}

html[data-theme="light"] .property-workbench-top label:not(.choice-row),
html[data-theme="light"] .property-image-field > span,
html[data-theme="light"] .property-image-dropzone strong {
    color: var(--rp-text);
}

html[data-theme="light"] .property-workbench-top label span,
html[data-theme="light"] .sub-list > label span,
html[data-theme="light"] .property-image-dropzone small,
html[data-theme="light"] .property-image-empty,
html[data-theme="light"] .property-image-remove,
html[data-theme="light"] .unit-tab-btn small {
    color: var(--rp-muted);
}

html[data-theme="light"] .choice-row,
html[data-theme="light"] .switch-row {
    background: var(--rp-surface-muted);
    color: var(--rp-text);
}

html[data-theme="light"] .property-image-preview {
    border-color: var(--rp-border);
    background: var(--rp-surface-muted);
}

html[data-theme="light"] .property-image-dropzone {
    border-color: var(--rp-border);
    background: var(--rp-surface-muted);
}

html[data-theme="light"] .property-image-dropzone.is-drag-over {
    border-color: var(--rp-teal);
    background: rgba(40, 95, 87, 0.08);
}

html[data-theme="light"] .unit-tab-btn {
    border-color: rgba(111, 156, 173, 0.5);
    background: rgba(111, 156, 173, 0.14);
    color: var(--rp-text);
}

html[data-theme="light"] .unit-tab-btn:hover,
html[data-theme="light"] .unit-tab-btn:focus-visible {
    background: rgba(111, 156, 173, 0.22);
    color: var(--rp-text);
    box-shadow: inset 0 0 0 1px rgba(111, 156, 173, 0.4);
}

html[data-theme="light"] .unit-tab-btn.active {
    background: rgba(111, 156, 173, 0.3);
    color: var(--rp-text);
    box-shadow:
        inset 0 0 0 1px rgba(111, 156, 173, 0.5),
        0 0 12px rgba(111, 156, 173, 0.18);
}

html[data-theme="light"] .unit-subtabs {
    border-color: var(--rp-border);
}

html[data-theme="light"] .unit-subtab {
    border-color: var(--rp-border);
    background: var(--rp-surface);
    color: var(--rp-muted);
}

html[data-theme="light"] .unit-subtab:hover {
    background: var(--rp-surface-muted);
    color: var(--rp-text);
}

html[data-theme="light"] .unit-subtab.active {
    background: rgba(111, 156, 173, 0.3);
    border-color: rgba(111, 156, 173, 0.5);
    color: var(--rp-text);
}

html[data-theme="light"] .form-error-banner {
    border-color: rgba(217, 80, 50, 0.4);
    background: rgba(217, 80, 50, 0.1);
    color: #a3341c;
}

html[data-theme="light"] .form-error-text {
    color: #a3341c;
}

html[data-theme="light"] .plan-gate-banner {
    border-color: var(--rp-border);
    background: var(--rp-surface-muted);
    color: var(--rp-muted);
}

/* ============================================================
   WALKTHROUGH LIGHT THEME
   Same html[data-theme="light"] scoping — only active on pages
   that ship themeToggle (now also propertyWalkthrough()).
   ============================================================ */
html[data-theme="light"] .walkthrough-unit-card {
    border-color: var(--rp-border);
    background: var(--rp-surface);
    color: var(--rp-text);
}

html[data-theme="light"] .walkthrough-unit-card.active {
    border-color: rgba(111, 156, 173, 0.6);
    box-shadow:
        inset 0 0 0 1px rgba(111, 156, 173, 0.4),
        0 0 12px rgba(111, 156, 173, 0.18);
}

html[data-theme="light"] .walkthrough-kpis article {
    border-color: var(--rp-border);
    background: var(--rp-surface);
}

/* ============================================================
   REPAIRS LIGHT THEME
   Same html[data-theme="light"] scoping — only active on pages that ship
   themeToggle (now also DashboardController::repairs()).
   ============================================================ */
html[data-theme="light"] .repair-item {
    border-color: var(--rp-border);
    background: var(--rp-surface);
}

html[data-theme="light"] .filter-button {
    background: var(--rp-surface-muted);
}

html[data-theme="light"] .repair-item-flag {
    background: var(--rp-border);
}

html[data-theme="light"] .repair-item.urgent .repair-item-flag { background: var(--rp-clay); box-shadow: 0 0 0 4px rgba(217, 80, 50, 0.14); }
html[data-theme="light"] .repair-item.attention .repair-item-flag { background: var(--rp-amber); box-shadow: 0 0 0 4px rgba(217, 170, 73, 0.16); }
html[data-theme="light"] .repair-item.info .repair-item-flag { background: var(--rp-blue); box-shadow: 0 0 0 4px rgba(111, 156, 173, 0.16); }
html[data-theme="light"] .repair-item.done .repair-item-flag { background: var(--rp-teal); }

html[data-theme="light"] .repair-item-main strong,
html[data-theme="light"] .repair-item-meta strong {
    color: var(--rp-text);
}

html[data-theme="light"] .repair-item-main span,
html[data-theme="light"] .repair-item-meta {
    color: var(--rp-muted);
}

html[data-theme="light"] .vendor-contact-btn {
    border-color: var(--rp-border);
    background: var(--rp-surface-muted);
    color: var(--rp-teal-dark);
}

html[data-theme="light"] .vendor-contact-btn:hover {
    background: var(--rp-border);
}

html[data-theme="light"] .popover {
    --bs-popover-bg: var(--rp-surface);
    --bs-popover-border-color: var(--rp-border);
    --bs-popover-header-bg: var(--rp-surface-muted);
    --bs-popover-header-color: var(--rp-text);
    --bs-popover-body-color: var(--rp-text);
}

html[data-theme="light"] .vendor-popover-detail {
    color: var(--rp-muted);
}

html[data-theme="light"] .vendor-popover-link {
    color: var(--rp-teal);
}

html[data-theme="light"] .page-link {
    border-color: var(--rp-border);
    color: var(--rp-text);
    background-color: var(--rp-surface);
}

html[data-theme="light"] .page-link:hover {
    background-color: var(--rp-surface-muted);
}

html[data-theme="light"] .page-item.active .page-link {
    background-color: var(--rp-teal);
    border-color: var(--rp-teal);
    color: #fff;
}

html[data-theme="light"] .page-item.disabled .page-link {
    color: var(--rp-muted);
    background-color: var(--rp-surface);
}

html[data-theme="light"] .warranty-watch-row {
    border-color: var(--rp-border);
    color: var(--rp-text);
}

html[data-theme="light"] .warranty-watch-row:hover {
    background: var(--rp-surface-muted);
}

html[data-theme="light"] .warranty-watch-row span {
    color: var(--rp-muted);
}

html[data-theme="light"] .repair-confirm-banner {
    border-color: var(--rp-teal);
    background: rgba(40, 95, 87, 0.1);
    color: var(--rp-text);
}

html[data-theme="light"] .repair-confirm-banner strong {
    color: var(--rp-text);
}

html[data-theme="light"] a.event-row:hover {
    background: var(--rp-surface-muted);
}

html[data-theme="light"] .modal-content {
    background: var(--rp-surface);
    color: var(--rp-text);
    border-color: var(--rp-border);
}

html[data-theme="light"] .btn-close {
    filter: none;
}

html[data-theme="light"] .modal-header,
html[data-theme="light"] .modal-footer {
    border-color: var(--rp-border);
}

/* ============================================================
   REPAIR DETAIL — light theme overrides
   Companion to the dark (default) rules ported earlier in this file;
   mirrors mockups/assets/repair-detail-pilot.css's own light-mode
   values 1:1 since the --rp-* tokens already match by name.
   ============================================================ */
html[data-theme="light"] .fact span {
    color: var(--rp-muted);
}

html[data-theme="light"] .fact strong {
    color: var(--rp-text);
}

html[data-theme="light"] .fact-link {
    color: var(--rp-teal-dark);
}

html[data-theme="light"] .fact-link:hover {
    color: var(--rp-teal);
}

html[data-theme="light"] .dropdown-menu {
    --bs-dropdown-bg: var(--rp-surface);
    --bs-dropdown-border-color: var(--rp-border);
    --bs-dropdown-link-color: var(--rp-text);
    --bs-dropdown-link-hover-bg: var(--rp-surface-muted);
    --bs-dropdown-link-hover-color: var(--rp-text);
    --bs-dropdown-box-shadow: 0 12px 30px rgba(24, 34, 31, 0.07);
}

html[data-theme="light"] .dropdown-item.text-danger {
    --bs-dropdown-link-color: var(--rp-clay);
}

html[data-theme="light"] .dropdown-item.text-danger:hover,
html[data-theme="light"] .dropdown-item.text-danger:focus {
    color: var(--rp-clay);
    background: rgba(217, 80, 50, 0.1);
}

html[data-theme="light"] .field-grid label {
    color: var(--rp-text);
}

html[data-theme="light"] .field-grid .form-control,
html[data-theme="light"] .field-grid .form-select {
    border: 1px solid var(--rp-border);
    background: var(--rp-surface);
    color: var(--rp-text);
}

html[data-theme="light"] .field-grid .form-control:focus,
html[data-theme="light"] .field-grid .form-select:focus {
    border-color: var(--rp-teal);
    box-shadow: 0 0 0 2px rgba(40, 95, 87, 0.14);
}

html[data-theme="light"] .field-grid .form-select {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%2366736d' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round' d='M2.5 4.5l3.5 3.5 3.5-3.5'/%3E%3C/svg%3E");
}

html[data-theme="light"] .field-grid .form-select option {
    background: var(--rp-surface);
    color: var(--rp-text);
}

html[data-theme="light"] .field-grid .form-control::placeholder {
    color: var(--rp-muted);
    opacity: 1;
}

html[data-theme="light"] input[type="date"]::-webkit-calendar-picker-indicator,
html[data-theme="light"] input[type="datetime-local"]::-webkit-calendar-picker-indicator {
    filter: none;
}

html[data-theme="light"] .property-strip-info strong {
    color: var(--rp-text);
}

html[data-theme="light"] .property-strip-info span,
html[data-theme="light"] .property-strip-tenant {
    color: var(--rp-muted);
}

html[data-theme="light"] .property-thumb {
    border-color: var(--rp-border);
}

html[data-theme="light"] .btn-primary {
    background: var(--rp-teal);
    border-color: var(--rp-teal);
    color: white;
}

html[data-theme="light"] .btn-primary:hover {
    background: var(--rp-teal-dark);
    border-color: var(--rp-teal-dark);
}

html[data-theme="light"] .status-pill.urgent,
html[data-theme="light"] .status-pill.failed {
    background: rgba(217, 80, 50, 0.12);
    color: var(--rp-clay);
}

html[data-theme="light"] .status-pill.scheduled,
html[data-theme="light"] .status-pill.processing {
    background: rgba(217, 170, 73, 0.16);
    color: #9a7523;
}

html[data-theme="light"] .status-pill.complete {
    background: rgba(111, 156, 173, 0.18);
    color: var(--rp-teal-dark);
}

html[data-theme="light"] .status-pill.draft {
    background: var(--rp-surface-muted);
    color: var(--rp-muted);
}

html[data-theme="light"] .work-order-heading h2 {
    color: var(--rp-text);
}

html[data-theme="light"] .work-order-kicker > span {
    border-left-color: var(--rp-border);
    color: var(--rp-muted);
}

html[data-theme="light"] .work-order-description,
html[data-theme="light"] .work-order-modal-copy,
html[data-theme="light"] .work-order-modal-fields label small,
html[data-theme="light"] .context-label,
html[data-theme="light"] .snapshot-label,
html[data-theme="light"] .snapshot-item small,
html[data-theme="light"] .property-strip-tenant small,
html[data-theme="light"] .snapshot-value em,
html[data-theme="light"] .cap-remaining,
html[data-theme="light"] .work-order-meta {
    color: var(--rp-muted);
}

html[data-theme="light"] .work-order-menu .icon-button {
    background: var(--rp-surface-muted);
    border-color: var(--rp-border);
}

html[data-theme="light"] .property-strip-tenant {
    border-left-color: var(--rp-border);
}

html[data-theme="light"] .property-strip-requested-by {
    color: var(--rp-muted);
}

html[data-theme="light"] .property-strip-requested-by strong {
    color: var(--rp-text);
}

html[data-theme="light"] .work-order-progress li {
    color: var(--rp-muted);
}

html[data-theme="light"] .work-order-progress li::before {
    background: var(--rp-border);
}

html[data-theme="light"] .work-order-progress li > .step-circle-outer {
    border-color: var(--rp-border);
    background: var(--rp-surface);
    color: var(--rp-muted);
}

html[data-theme="light"] .work-order-progress li.complete::before,
html[data-theme="light"] .work-order-progress li.current::before {
    background: var(--rp-teal);
}

html[data-theme="light"] .work-order-progress li.complete > .step-circle-outer {
    border-color: var(--rp-teal);
    background: var(--rp-teal);
    color: white;
}

html[data-theme="light"] .work-order-progress li.current {
    color: var(--rp-text);
}

html[data-theme="light"] .work-order-progress li.current > .step-circle-outer {
    border-color: var(--rp-amber-current);
    background: var(--rp-surface);
    color: var(--rp-text);
    box-shadow: 0 0 0 4px rgba(148, 106, 10, 0.25);
}

html[data-theme="light"] .work-order-progress li.current strong {
    color: var(--rp-amber-current);
}

/* Teal reads clearly against the circle's own unfilled background at any
   fill height, so the liquid fill itself stays teal whether a step is
   current or complete -- only the ring/glow/label (above) switch to the
   warm current-accent. A lighter gold fill would barely stand out against
   the light unfilled portion of the same circle, undermining the whole
   point of a liquid gauge (verified in the mockup this was designed in). */
html[data-theme="light"] .work-order-progress .step-circle-fill {
    background: var(--rp-teal);
}

html[data-theme="light"] .work-order-progress .step-circle-icon {
    color: #fffdf8;
}

html[data-theme="light"] .work-order-progress li .step-tip {
    background: var(--rp-surface);
    border-color: var(--rp-border);
    color: var(--rp-muted);
    box-shadow: 0 18px 32px rgba(24, 34, 31, 0.12);
}

html[data-theme="light"] .work-order-progress li .step-tip::after {
    border-bottom-color: var(--rp-surface);
}

html[data-theme="light"] .work-order-progress .step-tip-heading strong {
    color: var(--rp-teal);
}

html[data-theme="light"] .work-order-progress .step-tip-row-icon.is-done {
    color: var(--rp-teal);
}

html[data-theme="light"] .work-order-progress .step-tip-row-icon.is-pending {
    color: var(--rp-muted);
}

html[data-theme="light"] .work-order-progress .step-tip-row.is-pending span:last-child {
    color: var(--rp-muted);
}

html[data-theme="light"] .property-strip-link,
html[data-theme="light"] .snapshot-icon {
    color: #9a7523;
}

html[data-theme="light"] .snapshot-icon {
    background: rgba(217, 170, 73, 0.16);
}

html[data-theme="light"] .status-card {
    border-color: var(--rp-border);
    background: var(--rp-surface);
}

html[data-theme="light"] .status-card-divider,
html[data-theme="light"] .work-order-snapshot {
    background: var(--rp-border);
}

html[data-theme="light"] .snapshot-item {
    background: var(--rp-surface);
}

html[data-theme="light"] .snapshot-value {
    color: var(--rp-text);
}

html[data-theme="light"] .sourcing-card,
html[data-theme="light"] .sourcing-head,
html[data-theme="light"] .sourcing-fields,
html[data-theme="light"] .sourcing-field {
    border-color: var(--rp-border);
}

html[data-theme="light"] .sourcing-head strong,
html[data-theme="light"] .sourcing-field-label strong {
    color: var(--rp-text);
}

html[data-theme="light"] .field-tip {
    border-color: var(--rp-muted);
    color: var(--rp-muted);
}

html[data-theme="light"] .field-tip .tip-bubble {
    background: var(--rp-surface);
    border-color: var(--rp-border);
    color: var(--rp-muted);
}

html[data-theme="light"] .field-tip .tip-bubble::after {
    border-top-color: var(--rp-surface);
}

html[data-theme="light"] .sourcing-control input,
html[data-theme="light"] .sourcing-control select {
    border-color: var(--rp-border) !important;
    background: var(--rp-surface-muted) !important;
    color: var(--rp-text) !important;
    color-scheme: light;
}

html[data-theme="light"] .sourcing-control input[type="date"]::-webkit-calendar-picker-indicator {
    filter: none;
}

html[data-theme="light"] .sourcing-save {
    border-color: var(--rp-border);
    background: var(--rp-surface-muted);
    color: var(--rp-text);
}

html[data-theme="light"] .vendor-pill,
html[data-theme="light"] .invite-vendor-card {
    border-color: var(--rp-border);
}

html[data-theme="light"] .vendor-pill span,
html[data-theme="light"] .invite-vendor-card strong {
    color: var(--rp-text);
}

html[data-theme="light"] .cost-meter {
    background: var(--rp-surface-muted);
    border: 1px solid var(--rp-border);
}

html[data-theme="light"] .cost-meter::-webkit-progress-bar {
    background: var(--rp-surface-muted);
}

html[data-theme="light"] .cost-meter::-webkit-progress-value {
    background: var(--rp-amber);
}

html[data-theme="light"] .cost-meter::-moz-progress-bar {
    background: var(--rp-amber);
}

html[data-theme="light"] .open-task-count {
    border-color: rgba(217, 170, 73, 0.55);
    background: rgba(217, 170, 73, 0.12);
    color: #815f16;
}

html[data-theme="light"] .task-section-heading h3,
html[data-theme="light"] .history-heading h3,
html[data-theme="light"] .task-card h4,
html[data-theme="light"] .task-context strong,
html[data-theme="light"] .composer-disclosure > summary strong {
    color: var(--rp-text);
}

html[data-theme="light"] .task-section-heading p,
html[data-theme="light"] .history-heading > span,
html[data-theme="light"] .task-assignee,
html[data-theme="light"] .task-card p,
html[data-theme="light"] .task-deadline,
html[data-theme="light"] .task-context span,
html[data-theme="light"] .composer-disclosure > summary small {
    color: var(--rp-muted);
}

html[data-theme="light"] .task-assignee em {
    background: var(--rp-teal-dark);
    color: white;
}

html[data-theme="light"] .task-deadline.overdue {
    color: var(--rp-clay);
}

html[data-theme="light"] .task-card,
html[data-theme="light"] .task-context span {
    border-color: var(--rp-border);
    background: var(--rp-surface);
}

html[data-theme="light"] .task-card.owner-task {
    border-color: rgba(217, 170, 73, 0.55);
    background: rgba(217, 170, 73, 0.08);
}

html[data-theme="light"] .task-type,
html[data-theme="light"] .owner-task .task-icon {
    color: #815f16;
}

html[data-theme="light"] .tenant-task .task-type,
html[data-theme="light"] .task-icon {
    color: var(--rp-teal-dark);
}

html[data-theme="light"] .task-icon,
html[data-theme="light"] .composer-disclosure > summary {
    border-color: var(--rp-border);
    background: var(--rp-surface-muted);
}

html[data-theme="light"] .composer-summary-icon {
    background: var(--rp-teal-dark);
    color: white;
}

html[data-theme="light"] .timeline-disclosure {
    border-color: var(--rp-border);
}

html[data-theme="light"] .composer {
    border-color: var(--rp-border);
    background: var(--rp-surface-muted);
}

html[data-theme="light"] .composer-tab {
    border-color: var(--rp-border);
    background: var(--rp-surface);
    color: var(--rp-muted);
}

html[data-theme="light"] .composer-tab.active {
    background: var(--rp-teal-dark);
    border-color: var(--rp-teal-dark);
    color: white;
}

html[data-theme="light"] .feed-item {
    border-color: var(--rp-border);
}

html[data-theme="light"] .feed-author,
html[data-theme="light"] .feed-text {
    color: var(--rp-text);
}

html[data-theme="light"] .feed-time {
    color: var(--rp-muted);
}

html[data-theme="light"] .feed-decline {
    color: var(--rp-clay);
}

html[data-theme="light"] .feed-photo {
    border-color: var(--rp-border);
}

/* Shared save-confirmation toasts (window.RP.showToast — layouts/app.php).
   Fixed dark chrome regardless of page theme, same precedent as the
   Bootstrap dropdown/popover overrides above never following
   [data-theme="light"] either. */
.toast-stack {
    position: fixed;
    right: 20px;
    bottom: 20px;
    z-index: 1080;
    display: flex;
    flex-direction: column-reverse;
    gap: 10px;
    max-width: min(360px, calc(100vw - 40px));
    pointer-events: none;
}

.toast {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 14px 16px 14px 18px;
    border-radius: 14px;
    background: rgba(10, 23, 26, 0.96);
    border: 1px solid var(--line);
    box-shadow: 0 20px 45px rgba(0, 0, 0, 0.4);
    color: var(--white);
    font-size: var(--fs-sm);
    line-height: 1.4;
    overflow: hidden;
    pointer-events: auto;
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 200ms var(--ease), transform 200ms var(--ease);
}

.toast.is-visible {
    opacity: 1;
    transform: translateY(0);
}

.toast::before {
    content: "";
    position: absolute;
    inset: 0 auto 0 0;
    width: 4px;
    background: var(--info);
}

.toast-success::before { background: var(--success); }
.toast-error::before { background: var(--danger); }
.toast-info::before { background: var(--info); }

.toast-message {
    flex: 1;
    padding-top: 1px;
}

.toast-close {
    flex-shrink: 0;
    width: 20px;
    height: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 0;
    background: transparent;
    color: var(--white-muted);
    cursor: pointer;
    border-radius: 6px;
}

.toast-close:hover {
    background: rgba(255, 255, 255, 0.1);
    color: var(--white);
}

.toast-close i {
    width: 14px;
    height: 14px;
}

@media (prefers-reduced-motion: reduce) {
    .toast {
        transition: opacity 1ms linear;
        transform: none;
    }
}

/* photo-upload-field.php / window.RP.wirePhotoField shared styling,
   mirroring walkthrough-inspection.css's versions of the same selectors
   (identical values — that stylesheet still wins on walkthrough pages
   since it loads after this one there) for pages using the component
   outside the walkthrough flow, which don't load that stylesheet at all:
   the property/unit editors' marketing-gallery panels. */
.wt-condition-label {
    display: block;
    margin-bottom: 10px;
    color: rgba(255, 255, 255, 0.74);
    font-size: 0.86rem;
    font-weight: 700;
}

.wt-photo-row { padding: 16px 0 0; }

.wt-photo-row.is-drag-over {
    outline: 2px dashed var(--info);
    outline-offset: 6px;
    border-radius: 12px;
    background: rgba(134, 215, 255, 0.06);
}

.wt-photo-upload-btn {
    width: 100%;
    min-height: 64px;
    border: 1.5px dashed rgba(134, 215, 255, 0.28);
    border-radius: 12px;
    background: rgba(134, 215, 255, 0.06);
    color: var(--info);
    font-weight: 750;
    cursor: pointer;
    transition: all 180ms var(--ease);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
}

.wt-photo-upload-btn:hover {
    background: rgba(134, 215, 255, 0.12);
    border-color: rgba(134, 215, 255, 0.42);
}

.wt-photo-upload-btn svg { width: 24px; height: 24px; }

/* Opt-in fuller dropzone treatment (photo-upload-field.php's $dropzone) —
   a bordered drop target with an icon badge, drag-here copy, and a hint
   line, matching the approved Request Desk artifact's own .dropzone. */
.dropzone {
    border: 1.5px dashed rgba(255,255,255,.24); border-radius: 14px; padding: 24px;
    text-align: center; margin-top: 8px; background: #0c262c;
    transition: border-color .15s ease, background-color .15s ease;
}
.dropzone.is-drag-over { border-color: var(--gold); background: rgba(255,159,46,.08); }
.dz-icon {
    width: 44px; height: 44px; border-radius: 50%; background: rgba(255,159,46,.15);
    display: flex; align-items: center; justify-content: center; margin: 0 auto 12px;
}
.dz-icon svg { width: 20px; height: 20px; color: var(--gold); }
.dropzone p { font-size: .84rem; color: var(--white-soft); margin-bottom: 2px; }
.dz-hint { font-size: .74rem; color: var(--white-muted); margin-bottom: 14px !important; }
.dz-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }

.wt-photo-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
    gap: 10px;
    margin-top: 12px;
}

.wt-photo-thumb {
    position: relative;
    aspect-ratio: 1;
    border-radius: 10px;
    overflow: hidden;
    background: rgba(0, 0, 0, 0.32);
}

.wt-photo-thumb img,
.wt-photo-thumb video { width: 100%; height: 100%; object-fit: cover; }

.wt-photo-video-badge {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.28);
    color: #fff;
    pointer-events: none;
}

.wt-photo-video-badge svg { width: 22px; height: 22px; }

/* ---------- Shared schedule calendar (schedule-calendar.php) ----------
   Class names and rules match the approved Request Desk artifact
   precisely (--panel-2/--panel-3/--border/--border-strong/--r-md/--r-sm
   are the artifact's own literal values, hardcoded here since this app
   has no matching named tokens — every color that DOES have a real
   sitewide token, e.g. --accent → --amber, uses that token instead of a
   second literal). Monospace stays a system stack (no new webfont load)
   rather than the artifact's own IBM Plex Mono. */
.rp-calendar { background: #0c262c; border: 1px solid rgba(255,255,255,.24); border-radius: 14px; padding: 16px; }
.cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.cal-head strong { font-size: .86rem; font-weight: 650; }
.cal-nav { display: flex; gap: 4px; }

.cal-nav button {
    width: 26px; height: 26px; border-radius: 7px; border: 1px solid rgba(255,255,255,.24);
    background: transparent; color: var(--white-soft); cursor: pointer;
    display: flex; align-items: center; justify-content: center;
}
.cal-nav button:hover:not(:disabled) { border-color: var(--gold); color: var(--gold); }
.cal-nav button:disabled { opacity: .3; cursor: not-allowed; }
.cal-nav svg { width: 15px; height: 15px; }

.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }

.cal-dow { font-size: .66rem; text-align: center; color: var(--white-muted); font-weight: 600; padding-bottom: 4px; }

.cal-day {
    position: relative; aspect-ratio: 1; border-radius: 8px;
    display: flex; align-items: center; justify-content: center;
    font-family: ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace;
    font-size: .78rem; color: var(--white-soft); cursor: pointer; border: 1px solid transparent;
}
.cal-day.muted { color: var(--white-muted); opacity: .3; cursor: default; }
.cal-day.past { color: var(--white-muted); opacity: .28; cursor: not-allowed; }
.cal-day:not(.muted):not(.past):hover { background: #123039; border: 1px dashed var(--amber); }
.cal-day.today { border-color: rgba(255,255,255,.24); font-weight: 700; color: var(--white); }
.cal-day.selected { background: var(--amber); color: var(--ink); font-weight: 700; }
.cal-day.selected:hover { color: var(--white); }
.cal-day.proposed::after { content: ''; position: absolute; bottom: 4px; width: 5px; height: 5px; border-radius: 50%; background: var(--sky); }
.cal-day.proposed { border-color: var(--sky); color: var(--white); }
.cal-day.booked::before {
    content: ''; position: absolute; top: 5px; right: 5px; width: 6px; height: 6px; border-radius: 50%;
    background: var(--ink); box-shadow: 0 0 0 1.5px rgba(255,255,255,.85);
}

.booked-note { display: flex; align-items: flex-start; gap: 6px; font-size: .78rem; color: var(--gold); margin-top: 10px; line-height: 1.4; }
.booked-note[hidden] { display: none; }
.booked-note svg { width: 14px; height: 14px; flex: none; margin-top: 1px; }

.time-row { display: grid; grid-template-columns: 1fr auto 1fr; gap: 8px; align-items: center; margin-top: 14px; }
.time-row span { color: var(--white-muted); font-size: .78rem; text-align: center; }

/* .app-frame select (a global chevron rule matching every <select> in the
   app-frame) ties .time-select on specificity (0,1,1 vs 0,1,0) and would
   otherwise win on border/background/padding — qualified under .app-frame
   here so this always wins outright, not by source-order luck. */
.app-frame .time-select {
    appearance: none; -webkit-appearance: none; color-scheme: dark;
    background-color: #0c262c;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffd188' stroke-width='2.4'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 10px center; background-size: 14px;
    border: 1px solid rgba(255,255,255,.24); border-radius: 9px; color: var(--white);
    font-family: ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace;
    font-size: .84rem; padding: 9px 30px 9px 12px; width: 100%; cursor: pointer;
}
.app-frame .time-select:hover { border-color: var(--gold); background-color: #123039; }
.app-frame .time-select:focus-visible {
    outline: none; border-color: var(--gold);
    box-shadow: 0 0 0 3px rgba(255,209,136,.32);
}

.window-chips { display: flex; flex-direction: column; gap: 6px; margin-top: 14px; }
.window-chip {
    display: flex; align-items: center; justify-content: space-between; background: #123039;
    border: 1px solid rgba(255,255,255,.24); border-radius: 9px; padding: 8px 11px; font-size: .82rem;
    font-family: ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace;
}
.window-chip button { background: none; border: none; color: var(--white-muted); cursor: pointer; font-size: .95rem; line-height: 1; padding: 2px 4px; }
.window-chip button:hover { color: var(--danger); }

/* ---------- Shared message thread (my-unit-messages.php + repair
   comments) — promoted here once a second page needed the identical
   bubble pattern, same precedent as .btn-danger/.btn-text-danger. ---------- */
.empty-note { margin-top: 14px; padding: 20px 16px; text-align: center; border-radius: 12px; border: 1px dashed var(--line); color: var(--white-muted); font-size: var(--fs-sm); }
.empty-note i { width: 26px; height: 26px; margin-bottom: 8px; display: block; margin-left: auto; margin-right: auto; }

.thread { display: flex; flex-direction: column; gap: 14px; margin: 4px 0 16px; max-height: 420px; overflow-y: auto; padding-right: 4px; }
.msg-day-divider {
    align-self: center; font-size: var(--fs-2xs); color: var(--white-muted); text-transform: uppercase;
    letter-spacing: 0.05em; font-weight: 700; padding: 4px 12px; border-radius: 999px; background: rgba(255,255,255,0.06);
}
.msg { display: flex; flex-direction: column; max-width: 76%; gap: 4px; }
.msg.landlord { align-self: flex-start; align-items: flex-start; }
.msg.tenant { align-self: flex-end; align-items: flex-end; }
.msg-bubble { padding: 10px 14px; border-radius: 14px; font-size: var(--fs-sm); line-height: 1.45; }
.msg.landlord .msg-bubble { background: rgba(255,255,255,0.08); border: 1px solid var(--line); border-bottom-left-radius: 4px; }
.msg.tenant .msg-bubble { background: rgba(255,159,46,0.22); border: 1px solid rgba(255,159,46,0.32); border-bottom-right-radius: 4px; }
.msg-meta { font-size: var(--fs-2xs); color: var(--white-muted); padding: 0 4px; }

/* .msg.mine/.msg.theirs are the landlord-side equivalent of
   .msg.tenant/.msg.landlord above -- the tenant portal names bubbles from
   the tenant's own point of view ("tenant" = mine, right/amber), which
   would be backwards on the Communications page, where the landlord's own
   message is "mine". Same visual rules, viewer-neutral names, so a single
   .msg-bubble/.msg-meta/.msg-day-divider vocabulary still covers both
   sides of the same conversation. */
.msg.mine { align-self: flex-end; align-items: flex-end; }
.msg.theirs { align-self: flex-start; align-items: flex-start; }
.msg.mine .msg-bubble { background: rgba(255,159,46,0.22); border: 1px solid rgba(255,159,46,0.32); border-bottom-right-radius: 4px; }
.msg.theirs .msg-bubble { background: rgba(255,255,255,0.08); border: 1px solid var(--line); border-bottom-left-radius: 4px; }
.msg-bubble.system { background: none; border: 1px dashed var(--line); color: var(--white-muted); font-size: var(--fs-xs); }

.form-field textarea { display: block; width: 100%; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--line); background: rgba(255,255,255,0.05); color: #fff; font-size: var(--fs-sm); font-family: inherit; min-height: 52px; resize: vertical; }

.compose-box { display: flex; gap: 10px; align-items: flex-end; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); }
.compose-box .form-field { flex: 1; }

/* ---------- Message Center (communications.php): a contact list + a
   single focused thread, replacing the old tenant-tab-strip + stacked
   forms layout. .msg-shell joins the shared glass-panel selector list
   below purely for its border/background; its own layout rules (grid,
   height, radius) live here since none of the other members of that list
   are a fixed-height two-pane shell. ---------- */
.msg-shell { display: grid; grid-template-columns: 320px minmax(0, 1fr); border-radius: 16px; overflow: hidden; height: min(680px, calc(100vh - 200px)); }

.contacts { border-right: 1px solid var(--line); display: flex; flex-direction: column; min-height: 0; }
.contacts-head { padding: 16px 16px 12px; border-bottom: 1px solid var(--line); }
.contacts-head h2 { margin: 0 0 10px; font-size: var(--fs-base); font-weight: 700; }
.contact-search { position: relative; }
.contact-search input { width: 100%; padding: 9px 12px 9px 34px; border-radius: 10px; border: 1px solid var(--line); background: rgba(255,255,255,0.05); color: #fff; font: inherit; font-size: var(--fs-sm); }
.contact-search i { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); width: 15px; height: 15px; color: var(--white-muted); }

.contact-list { flex: 1; overflow-y: auto; padding: 6px; }
.contact { display: flex; gap: 10px; align-items: flex-start; width: 100%; padding: 10px; border-radius: 11px; text-decoration: none; color: inherit; }
.contact:hover { background: rgba(255,255,255,0.06); }
.contact.active { background: rgba(255,159,46,0.16); }
.contact-avatar { flex: none; width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center; font-size: var(--fs-xs); font-weight: 700; color: #1a1206; background: var(--gold); }
.thread-avatar { width: 36px; height: 36px; }
.contact-body { min-width: 0; flex: 1; }
.contact-top { display: flex; justify-content: space-between; gap: 8px; align-items: baseline; }
.contact-name { font-weight: 600; font-size: var(--fs-sm); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.contact-time { flex: none; font-size: var(--fs-2xs); color: var(--white-muted); }
.contact-unit { display: block; font-size: var(--fs-2xs); color: var(--white-muted); margin: 1px 0 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.contact-preview { display: flex; justify-content: space-between; gap: 8px; align-items: center; }
.contact-snippet { font-size: var(--fs-xs); color: var(--white-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.contact.unread .contact-snippet { color: var(--white-soft); font-weight: 500; }
.contact.unread .contact-name { color: #fff; }
.unread-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--amber); }

.thread-pane { display: flex; flex-direction: column; min-height: 0; }
.thread-empty { flex: 1; display: flex; align-items: center; justify-content: center; }
.thread-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 20px; border-bottom: 1px solid var(--line); }
.thread-who { display: flex; align-items: center; gap: 12px; }
.thread-name { font-weight: 700; font-size: var(--fs-md); }
.thread-sub { font-size: var(--fs-xs); color: var(--white-muted); }
.thread-actions a { font-size: var(--fs-xs); font-weight: 600; color: var(--sky); text-decoration: none; }
.thread-actions a:hover { text-decoration: underline; }
.thread-scroll { flex: 1; overflow-y: auto; padding: 18px 22px; display: flex; flex-direction: column; gap: 10px; }
.thread-scroll .msg { max-width: 62%; }
.thread-pane .compose-box { padding: 14px 20px; margin-top: 0; }

.wt-photo-remove {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 24px;
    height: 24px;
    border: 0;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.84);
    color: var(--danger);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.wt-photo-remove svg { width: 14px; height: 14px; }

/* Reorderable gallery grids only (options.reorderable in wirePhotoField). */
.wt-photo-thumb[draggable="true"] { cursor: grab; }
.wt-photo-thumb.is-dragging { opacity: 0.4; }

/* Visual drop-target indicator while dragging to reorder — a bar on
   whichever edge of the hovered thumb the dragged photo would land next
   to, computed live in wireDrag()'s dragover handler. */
.wt-photo-thumb.drop-before,
.wt-photo-thumb.drop-after {
    position: relative;
}
.wt-photo-thumb.drop-before::before,
.wt-photo-thumb.drop-after::after {
    content: '';
    position: absolute;
    top: 4px;
    bottom: 4px;
    width: 3px;
    border-radius: 2px;
    background: var(--amber);
    z-index: 2;
}
.wt-photo-thumb.drop-before::before { left: -6px; }
.wt-photo-thumb.drop-after::after { right: -6px; }

/* Gallery mode only (options.gallery in wirePhotoField — property/unit
   marketing galleries, never walkthrough/Document Items/addendum photos).
   A hover-revealed control overlay replaces the always-visible remove-X,
   plus a cover badge on the first non-hidden photo and a dimmed treatment
   for hidden ones (still visible to the owner, excluded from the cover/
   any future public listing feed). */
.wt-photo-thumb-gallery[data-hidden="1"] img { opacity: 0.4; }

.wt-photo-cover-badge,
.wt-photo-hidden-badge {
    position: absolute;
    top: 6px;
    left: 6px;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 10px;
    font-weight: 750;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    z-index: 1;
}
.wt-photo-cover-badge { background: var(--amber); color: #1a1206; }
.wt-photo-hidden-badge { background: rgba(0, 0, 0, 0.75); color: var(--white-soft); }

.wt-photo-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    gap: 6px;
    padding: 8px;
    background: linear-gradient(to top, rgba(0, 0, 0, 0.7), transparent 60%);
    opacity: 0;
    transition: opacity 120ms ease;
}
.wt-photo-thumb-gallery:hover .wt-photo-overlay,
.wt-photo-thumb-gallery:focus-within .wt-photo-overlay {
    opacity: 1;
}

.wt-photo-action {
    width: 26px;
    height: 26px;
    border: 0;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.84);
    color: white;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}
.wt-photo-action svg { width: 13px; height: 13px; }
.wt-photo-action-danger { color: var(--danger); }

.wt-photo-alt-editor {
    position: absolute;
    left: 6px;
    right: 6px;
    bottom: 6px;
    z-index: 2;
}
.wt-photo-alt-input {
    width: 100%;
    padding: 5px 8px;
    border: 1px solid var(--line);
    border-radius: 6px;
    background: rgba(0, 0, 0, 0.88);
    color: white;
    font-size: 11px;
}

/* Shared "marketing gallery" panel wrapper — unit-detail-edit.php's Photo
   Gallery panel and properties.php's Property Gallery panel. */
.rp-gallery-panel {
    padding: 1.25rem;
    margin-bottom: 1.75rem;
    border-radius: 14px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.08);
    transition: background 150ms ease, border-color 150ms ease;
}

.rp-gallery-panel.is-drag-over {
    border-color: var(--info);
    background: rgba(134, 215, 255, 0.08);
}

.rp-gallery-hint {
    margin: -0.5rem 0 0.5rem;
    color: rgba(255, 255, 255, 0.56);
    font-size: 0.84rem;
}

/* Lease clause library (lease-clauses.php) and the lease draft's clause
   picker (lease-edit.php) — plain reorderable rows, wired by
   window.RP.wireSortableList rather than wirePhotoField's photo-specific
   drag handling. */
.clause-list {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.clause-row {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 1rem 1.1rem;
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.08);
}

.clause-row[draggable="true"] { cursor: grab; }
.clause-row.is-dragging { opacity: 0.4; }

.clause-row-default {
    background: rgba(255, 255, 255, 0.02);
    border-style: dashed;
}

.clause-drag-handle {
    color: rgba(255, 255, 255, 0.35);
    flex-shrink: 0;
    margin-top: 0.15rem;
}

.clause-row-body { flex: 1; min-width: 0; }

.clause-row-header {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
}

.clause-row-header h3 { margin: 0; font-size: 1rem; }

.clause-badge {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.08);
    color: rgba(255, 255, 255, 0.6);
}

.clause-row-text {
    margin: 0.4rem 0 0;
    color: rgba(255, 255, 255, 0.72);
    font-size: 0.88rem;
    white-space: pre-line;
}

.clause-row-actions {
    display: flex;
    gap: 0.5rem;
    flex-shrink: 0;
}

/* Batch-upload progress queue (wirePhotoField's autoUploadUrl mode). */
.wt-upload-queue {
    display: grid;
    gap: 8px;
    margin-top: 12px;
}

.wt-upload-queue-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.08);
}

.wt-upload-queue-thumb {
    width: 36px;
    height: 36px;
    border-radius: 6px;
    object-fit: cover;
    flex-shrink: 0;
    background: rgba(0, 0, 0, 0.3);
}

.wt-upload-queue-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--white-soft);
    font-size: var(--fs-sm);
}

.wt-upload-queue-status {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: var(--fs-xs);
    font-weight: 700;
    white-space: nowrap;
}

.wt-upload-queue-status[data-status="uploading"] { color: var(--info); }
.wt-upload-queue-status[data-status="done"] { color: var(--success); }
.wt-upload-queue-status[data-status="error"] { color: var(--danger); }

.wt-upload-queue-status i { width: 14px; height: 14px; }

.wt-upload-queue-spinner {
    width: 13px;
    height: 13px;
    border-radius: 50%;
    border: 2px solid rgba(134, 215, 255, 0.3);
    border-top-color: var(--info);
    animation: wt-upload-spin 700ms linear infinite;
}

@keyframes wt-upload-spin {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .wt-upload-queue-spinner { animation: none; }
}

/* ---------- Platform admin: impersonation banner + role switcher ---------- */

.impersonation-banner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 24px;
    background: var(--amber);
    color: var(--ink);
    font-size: 0.88rem;
    font-weight: 700;
}

.maintenance-banner {
    padding: 10px 24px;
    background: var(--amber);
    color: var(--ink);
    font-size: 0.88rem;
    font-weight: 700;
    text-align: center;
}

.billing-banner {
    margin: 0;
}

.billing-banner button {
    margin-left: 8px;
    padding: 0;
    border: 0;
    background: none;
    color: var(--ink);
    font: inherit;
    text-decoration: underline;
    cursor: pointer;
}

.impersonation-banner form { margin: 0; }

.role-switcher-form { margin: 0; }

.role-switcher-form select {
    background: rgba(255, 255, 255, 0.1);
    color: inherit;
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 6px 10px;
    font: inherit;
    font-size: 0.85rem;
}

.inline-replace-form {
    display: flex;
    align-items: center;
    gap: 8px;
}

.inline-replace-form input[type="password"] {
    max-width: 220px;
}

.channel-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
}

.channel-badge i {
    width: 14px;
    height: 14px;
}

/* Notification bell + inbox ------------------------------------------------
   The in-app fallback path: always populated regardless of whether email/
   SMS delivery succeeds (see NotificationService). */
.notification-bell-wrap {
    position: relative;
}

.notification-bell-badge {
    position: absolute;
    top: -2px;
    right: -2px;
    min-width: 18px;
    height: 18px;
    padding: 0 4px;
    border-radius: 999px;
    background: var(--danger);
    color: #fff;
    font-size: 0.7rem;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
}

.notification-panel {
    /* Fixed, not absolute, positioned in JS from the bell button's rect --
       needed once the real culprit below was found: EVERY .panel card
       throughout this app (dashboard cards, schedule, etc.) sets
       backdrop-filter: blur(22px), which promotes each into its own GPU
       compositing layer. Chromium has a long-standing bug where such
       backdrop-filter layers can paint above other fixed/absolute content
       regardless of z-index, since layer compositing order isn't always
       reconciled correctly against the normal stacking-context rules.
       will-change: transform below forces this dropdown onto its own
       dedicated compositing layer too, which reliably resolves the
       mis-ordering in testing -- confirmed via a real backdrop-filter
       .panel card visibly painting over this dropdown without it. */
    position: fixed;
    width: min(360px, 90vw);
    max-height: 420px;
    display: flex;
    flex-direction: column;
    background: var(--panel-bg, #1c2430);
    border: 1px solid var(--line);
    border-radius: 12px;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
    z-index: 1300;
    overflow: hidden;
    will-change: transform;
    transform: translateZ(0);
}

.notification-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 12px;
    border-bottom: 1px solid var(--line);
}

.notification-panel-list {
    overflow-y: auto;
}

.notification-row {
    display: flex;
    flex-direction: column;
    gap: 2px;
    width: 100%;
    text-align: left;
    padding: 10px 12px;
    background: none;
    border: none;
    border-bottom: 1px solid var(--line);
    color: inherit;
    cursor: pointer;
}

.notification-row:hover {
    background: rgba(255, 255, 255, 0.06);
}

.notification-row.is-unread .notification-row-title::before {
    content: '';
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--gold);
    margin-right: 6px;
}

.notification-row-title {
    font-weight: 600;
    font-size: 0.85rem;
}

.notification-row-body {
    font-size: 0.78rem;
    color: var(--white-muted);
}

.btn-link-sm {
    background: none;
    border: none;
    color: var(--gold);
    font-size: 0.78rem;
    cursor: pointer;
    padding: 0;
}

html[data-theme="light"] .notification-panel {
    background: var(--rp-surface);
    border-color: var(--rp-border);
    color: var(--rp-text);
}

html[data-theme="light"] .notification-panel-header,
html[data-theme="light"] .notification-row {
    border-color: var(--rp-border);
}

html[data-theme="light"] .notification-row:hover {
    background: var(--rp-surface-muted);
}

html[data-theme="light"] .notification-row-body {
    color: var(--rp-muted);
}

/* Onboarding Float Widget */
.onboarding-floating {
    position: fixed;
    bottom: 24px;
    right: 24px;
    z-index: 1000;
}

.onboarding-icon {
    width: 56px;
    height: 56px;
    border: 0;
    border-radius: 50%;
    background: var(--amber);
    color: var(--ink);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
    transition: transform 0.2s var(--ease);
    position: relative;
}

.onboarding-icon:hover {
    transform: scale(1.05);
}

.onboarding-icon,
.onboarding-header {
    cursor: grab;
    touch-action: none;
    user-select: none;
}

.onboarding-floating.is-dragging .onboarding-icon,
.onboarding-floating.is-dragging .onboarding-header {
    cursor: grabbing;
}

.onboarding-floating.is-dragging .onboarding-icon {
    transform: scale(1.08);
    box-shadow: 0 14px 36px rgba(0, 0, 0, 0.4);
}

.onboarding-icon:focus-visible,
.onboarding-floating .btn-icon:focus-visible {
    outline: 2px solid white;
    outline-offset: 2px;
}

.progress-badge {
    position: absolute;
    top: -4px;
    right: -4px;
    background: var(--ink);
    color: white;
    font-size: 11px;
    font-weight: 700;
    padding: 2px 6px;
    border-radius: 999px;
    border: 2px solid var(--amber);
}

.onboarding-panel-compact {
    width: 320px;
    background: rgba(7, 27, 32, 0.95);
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 16px;
    padding: 20px;
    box-shadow: 0 12px 48px rgba(0, 0, 0, 0.4);
    backdrop-filter: blur(20px);
}

.onboarding-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;
    color: white;
    font-size: 15px;
    font-weight: 700;
}

.btn-icon {
    width: 28px;
    height: 28px;
    border: 0;
    background: rgba(255, 255, 255, 0.08);
    color: rgba(255, 255, 255, 0.74);
    border-radius: 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 0.2s;
    margin-left: 6px;
}

.btn-icon:hover {
    background: rgba(255, 255, 255, 0.12);
    color: white;
}

.progress-compact {
    height: 6px;
    background: rgba(255, 255, 255, 0.1);
    border-radius: 999px;
    overflow: hidden;
    margin-bottom: 8px;
}

.progress-compact .progress-bar {
    height: 100%;
    background: var(--amber);
    transition: width 0.3s var(--ease);
}

.progress-text {
    font-size: 13px;
    color: rgba(255, 255, 255, 0.74);
    margin: 0 0 16px 0;
}

.onboarding-steps {
    list-style: none;
    padding: 0;
    margin: 0;
}

.onboarding-step {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px;
    background: rgba(255, 255, 255, 0.05);
    border-radius: 8px;
    margin-bottom: 8px;
    font-size: 14px;
    color: white;
}

.onboarding-step.done {
    opacity: 0.5;
}

.step-check {
    width: 20px;
    height: 20px;
    border: 2px solid rgba(255, 255, 255, 0.3);
    border-radius: 4px;
    flex-shrink: 0;
}

.onboarding-step.done .step-check {
    background: var(--good);
    border-color: var(--good);
    display: flex;
    align-items: center;
    justify-content: center;
}

.step-label {
    flex: 1;
}

.onboarding-celebration {
    display: grid;
    justify-items: center;
    gap: 10px;
    padding: 8px 4px 4px;
    text-align: center;
    color: white;
}

.onboarding-celebration strong {
    font-size: var(--fs-lg);
}

.onboarding-celebration p {
    margin: 0 0 6px;
    font-size: var(--fs-sm);
    color: var(--white-soft);
    line-height: 1.5;
}

.celebration-icon {
    width: 52px;
    height: 52px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: var(--amber);
    color: var(--ink);
    animation: celebration-pop 500ms var(--ease);
}

.celebration-icon svg {
    width: 26px;
    height: 26px;
}

@keyframes celebration-pop {
    0% { transform: scale(0.4); opacity: 0; }
    70% { transform: scale(1.12); opacity: 1; }
    100% { transform: scale(1); }
}

.onboarding-confetti {
    position: fixed;
    inset: 0;
    width: 100vw;
    height: 100vh;
    pointer-events: none;
    z-index: 999;
}

@media (prefers-reduced-motion: reduce) {
    .celebration-icon {
        animation: none;
    }
}

/* Late fee terms (components/late-fee-fields.php) */
.late-fee-fields {
    display: grid;
    gap: 12px;
}

.late-fee-toggle {
    min-height: 60px;
}

.late-fee-toggle > span {
    flex: none;
}

.late-fee-toggle > div {
    display: grid;
    gap: 2px;
}

.late-fee-toggle small {
    color: var(--white-soft);
    font-weight: 500;
}

.late-fee-fields .field-grid {
    margin-top: 0;
}

.compliance-note {
    display: flex;
    gap: 6px;
    align-items: flex-start;
    margin: 6px 0 0 4px;
}

.compliance-note i {
    width: 14px;
    height: 14px;
    flex: none;
    margin-top: 2px;
}

.late-fee-override .choice-row > span {
    display: grid;
    gap: 2px;
}

.late-fee-override .choice-row small {
    color: var(--white-soft);
}

.late-fee-override .choice-row input {
    width: 18px !important;
    height: 18px !important;
    padding: 0 !important;
    flex: none;
}

.late-fee-custom {
    margin-top: 12px;
}

/* Standard-content updates (components/template-updates-banner.php) */
.updates-banner {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 0 0 16px;
    padding: 12px 14px;
    border: 1px solid rgba(134, 215, 255, 0.4);
    border-radius: 12px;
    background: rgba(134, 215, 255, 0.08);
}

.updates-banner > i {
    width: 20px;
    height: 20px;
    flex: none;
    color: var(--sky);
}

.updates-banner p {
    flex: 1;
    margin: 0;
    color: var(--white-soft);
    font-size: var(--fs-sm);
}

.updates-banner p strong {
    color: white;
}

.updates-banner .btn {
    flex: none;
}

.update-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 999px;
    background: rgba(134, 215, 255, 0.16);
    color: var(--sky);
    font-size: var(--fs-2xs, 0.72rem);
    font-weight: 700;
    text-decoration: none;
    white-space: nowrap;
}

.update-badge:hover {
    background: rgba(134, 215, 255, 0.26);
    color: white;
}

.update-badge i {
    width: 12px;
    height: 12px;
}
