/* ============================================================
   PID ERP — Custom Overrides
   Edit this file to modify styles across the entire system.
   ============================================================ */

/* ── Scrollbar styling (Webkit browsers) ─────────────────── */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: rgba(255,255,255,.05); }
::-webkit-scrollbar-thumb { background: rgba(255,255,255,.2); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,.35); }

/* ── Mobile: tables scroll sideways instead of being cut ── */
@media (max-width: 768px) {
    .main table, .page-wrap table {
        display: block;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
    .main table td, .main table th,
    .page-wrap table td, .page-wrap table th {
        white-space: nowrap;
    }
}

/* ============================================================
   MOBILE UX IMPROVEMENTS
   Targets phones / small tablets (≤ 768px)
   ============================================================ */
@media (max-width: 768px) {

    /* ── 1. Touch targets — minimum 44×44px recommended by Apple/Google ── */
    .btn { min-height: 44px !important; padding: 0 16px !important; font-size: 14px !important; touch-action: manipulation; }
    .btn-sm { min-height: 38px !important; padding: 0 14px !important; font-size: 13px !important; }
    .btn-xs { min-height: 34px !important; padding: 0 10px !important; }

    /* ── 2. Inputs: 16px min prevents iOS auto-zoom on focus ── */
    input:not([type="checkbox"]):not([type="radio"]):not([type="color"]):not([type="range"]),
    select,
    textarea {
        font-size: 16px !important;
        min-height: 44px !important;
    }
    textarea { min-height: auto !important; }
    select { min-height: 44px !important; }

    /* ── 3. Page title & top bar ── */
    .page-title { font-size: 18px !important; }
    .top-bar { flex-wrap: wrap; gap: 10px; padding-bottom: 6px; }

    /* ── 4. Main content padding ── */
    .main, .page-wrap { padding: 14px !important; }

    /* ── 5. Summary / stat cards: 2-column grid ── */
    .summary { grid-template-columns: repeat(2, 1fr) !important; gap: 10px !important; }
    .summary-card, .stat-card { padding: 14px !important; }
    .summary-card .sc-val, .stat-val { font-size: 20px !important; }

    /* ── 6. Kanban board: horizontal scroll with proper sizing ── */
    .board {
        overflow-x: auto !important;
        -webkit-overflow-scrolling: touch !important;
        padding-bottom: 20px !important;
        scroll-snap-type: x proximity;
    }
    .board-col {
        min-width: 260px !important;
        max-width: 290px !important;
        scroll-snap-align: start;
    }
    .board-card { padding: 12px 14px !important; }
    .c-name { font-size: 14px !important; line-height: 1.4 !important; }

    /* ── 7. Deal preview panel: vertical stack ── */
    .dp-body { flex-direction: column !important; max-height: none !important; }
    .dp-section {
        width: 100% !important;
        border-right: none !important;
        border-bottom: 1px solid rgba(255,255,255,.07);
        overflow-y: visible !important;
        max-height: none !important;
    }
    .dp-panel { border-radius: 10px !important; }

    /* ── 8. Modals / dialogs: bottom-sheet style ── */
    #modal {
        align-items: flex-end !important;
        padding: 0 !important;
    }
    .modal-box, .modal-card, .modal-inner {
        width: 100% !important;
        max-width: 100% !important;
        max-height: 88vh !important;
        border-radius: 18px 18px 0 0 !important;
        margin: 0 !important;
        overflow-y: auto !important;
    }

    /* ── 9. Slide-in panels: full width ── */
    .panel {
        width: 100% !important;
        border-radius: 18px 18px 0 0 !important;
        top: auto !important;
        right: 0 !important;
        left: 0 !important;
        transform: translateY(100%) !important;
    }
    .panel.open { transform: translateY(0) !important; }

    /* ── 10. Tabs: horizontal scroll ── */
    .tabs, .nav-tabs {
        overflow-x: auto !important;
        -webkit-overflow-scrolling: touch !important;
        flex-wrap: nowrap !important;
        padding-bottom: 2px;
        gap: 2px;
    }
    .tab-btn, .nav-tab { white-space: nowrap !important; flex-shrink: 0 !important; }

    /* ── 11. 2-column grids → single column ── */
    [style*="grid-template-columns:1fr 1fr"],
    [style*="grid-template-columns: 1fr 1fr"] {
        grid-template-columns: 1fr !important;
    }

    /* ── 12. Form grids → single column ── */
    .form-grid, .form-row, .grid-2, .grid-3 {
        grid-template-columns: 1fr !important;
    }

    /* ── 13. Deal view (deal_view.php): stack columns ── */
    .dv-body { flex-direction: column !important; }
    .dv-col {
        width: 100% !important;
        border-right: none !important;
        border-bottom: 1px solid rgba(255,255,255,.07);
    }

    /* ── 14. Clock page: bigger clock-in button ── */
    #clockBtn, .clock-btn {
        min-height: 64px !important;
        font-size: 18px !important;
        border-radius: 14px !important;
        width: 100% !important;
    }

    /* ── 15. Tbl-card actions: stack vertically ── */
    .tbl-actions, .row-actions { display: flex; flex-wrap: wrap; gap: 6px; }

    /* ── 16. Print template 2-col → 1-col ── */
    #tab-print [style*="grid-template-columns:1fr 1fr"] {
        grid-template-columns: 1fr !important;
    }
    #tab-calendar [style*="grid-template-columns:1fr 1fr"] {
        grid-template-columns: 1fr !important;
    }

    /* ── 17. cPanel-style table: allow wrapping ── */
    .tbl-card table td, .tbl-card table th { white-space: normal !important; }

    /* ── 18. Better spacing for table action buttons ── */
    table td .btn, table td .btn-sm { margin: 2px 0; }

    /* ── 19. Sidebar nav link tap size ── */
    .sb-nav a { padding: 13px 14px !important; font-size: 14px !important; min-height: 48px; }
    .sb-foot { padding: 14px !important; }
}

/* ── Very small screens (< 380px) ────────────────────────── */
@media (max-width: 380px) {
    .btn { padding: 0 12px !important; }
    .summary { grid-template-columns: 1fr !important; }
    .board-col { min-width: 240px !important; }
}

/* ============================================================
   COLOR THEME — 5 switchable themes (Dark/Day/Pink/Green/Blue), restored
   2026-07-19 per Mr T (was simplified to just Dark/Day on 2026-07-11, and
   before that was a different 4-theme set — Dark/Light/Ocean/Sunset — see
   git history). Applied via a `theme-<name>` class on <html> (no class =
   Dark, the default) set server-side in _sidebar.php from users.theme.
   Dark's base palette still follows Linear's "Midnight" theme (bg #0f0f10,
   text #eeeff1), but its ACCENT is now Discord's Blurple (#5865F2) per
   Mr T's request — buttons should look distinct from Day mode, which
   didn't used to be true when both shared the same purple accent. Day
   mode's accent is Google Blue (#4285F4), with Google's full red/green/
   yellow also mapped onto the new .btn-danger/.btn-success/.btn-warning
   classes below. Pink/Green/Blue are new full themes with their own
   tinted-near-black backgrounds (see their blocks further down) — because
   they stay dark like the base theme (not white like Day), they don't need
   the large "hardcoded dark background / white text" override lists Day
   mode required below; only Day's white background broke those assumptions.
   This file is linked AFTER every page's own inline <style> block, so on
   tied specificity it wins the cascade — that's what lets one shared file
   reskin every page without editing each one. !important is used on the
   handful of color/background/border-color properties below specifically
   so this always wins regardless of a given page's exact selector
   specificity, without needing to audit every page individually.
   ============================================================ */
:root {
  --bg:#0f0f10; --surface:#18181b; --surface-2:#1e1e22;
  --border:rgba(255,255,255,.07); --border-strong:rgba(255,255,255,.13);
  --text:#eeeff1; --text-dim:rgba(238,239,241,.68); --text-faint:rgba(238,239,241,.42); --text-heading:#ffffff;
  /* Discord Blurple accent — added 2026-07-19, per Mr T (was #7c5cfc/#5b8def,
     the same purple Day mode also used, which is why buttons looked
     identical between the two modes before this change). */
  --accent:#5865F2; --accent-2:#7289da;
  --accent-soft-bg:rgba(88,101,242,.16); --accent-soft-text:#b3b9fb;
  --field-bg:rgba(255,255,255,.05); --field-border:rgba(255,255,255,.11);
  --hover-bg:rgba(255,255,255,.05);
  --scroll-track:rgba(255,255,255,.05); --scroll-thumb:rgba(255,255,255,.18);
  /* Tells the browser to render NATIVE controls (the popped-open <select>
     listbox, checkboxes, date pickers) using dark OS chrome. Without this,
     Chrome/Edge render an open dropdown's option list using light native
     styling regardless of any color/background CSS put on <option> — this
     is what caused dropdown popups to show black-on-white even though the
     closed select box correctly showed the dark theme. */
  color-scheme: dark;
}

/* ============================================================
   DAY / LIGHT THEME — added 2026-07-17, per Mr T (account_settings.php
   "Appearance" tab, applied via a `theme-light` class on <html>, set
   server-side in _sidebar.php from users.theme so there's no flash).
   Literal spec: white background, black letters, black icons. Card/modal
   surfaces stay a hair off pure white (border color instead of a tinted
   fill) purely so stacked cards remain visually separable on a plain
   white page — no color tint is introduced. Brand/accent colors
   (purple/blue) are intentionally left unchanged from the Dark palette;
   only the accent-soft text got darkened since the Dark palette's pale
   lavender is unreadable on white.
   Because `html.theme-light` (element + class) always outweighs the
   bare `:root` pseudo-class in specificity, this block wins regardless
   of where it sits in the file, and dark mode (no class) is completely
   unaffected. ============================================================ */
html.theme-light {
  --bg:#ffffff; --surface:#ffffff; --surface-2:#f2f2f4;
  /* Bumped 2026-07-18, per Mr T — low-opacity black lines on white read as
     "no line at all" much more easily than the same opacity in white-on-dark
     (which is why the Dark theme's much fainter .07/.13 borders still read
     fine there). Raised so table/card dividers stay clearly visible. */
  --border:rgba(0,0,0,.18); --border-strong:rgba(0,0,0,.32);
  --text:#000000; --text-dim:rgba(0,0,0,.68); --text-faint:rgba(0,0,0,.45); --text-heading:#000000;
  /* Google Blue accent — added 2026-07-19, per Mr T (was #7c5cfc/#5b8def,
     the same purple Dark mode also used). accent-soft-text is a darkened
     Google Blue (not the raw brand blue) so it stays readable as small text
     on a white surface, same convention as the previous purple's #5a3fd6. */
  --accent:#4285F4; --accent-2:#1a73e8;
  --accent-soft-bg:rgba(66,133,244,.12); --accent-soft-text:#1a56c4;
  --field-bg:rgba(0,0,0,.035); --field-border:rgba(0,0,0,.18);
  --hover-bg:rgba(0,0,0,.045);
  --scroll-track:rgba(0,0,0,.05); --scroll-thumb:rgba(0,0,0,.2);
  /* Native controls (open <select> listbox, checkboxes, date pickers)
     render with light OS chrome instead of dark — same mechanism as the
     dark theme's color-scheme:dark above, just flipped. */
  color-scheme: light;
}

/* Google's full brand palette on the shared semantic button classes
   (.btn-danger/.btn-success/.btn-warning, defined earlier in this file) —
   added 2026-07-19, per Mr T's request for Google-colored Day-mode buttons.
   Flat colors (not the generic gradient the dark-based themes use) to match
   Google's own flat Material button style; warning uses dark text since
   Google Yellow (#FBBC05) is too light for white text to read on. */
html.theme-light .btn-danger  { background:#EA4335 !important; color:#fff !important; }
html.theme-light .btn-success { background:#34A853 !important; color:#fff !important; }
html.theme-light .btn-warning { background:#FBBC05 !important; color:#202124 !important; }

/* ============================================================
   PINK MODE — added 2026-07-19, per Mr T. Rebuilt 2026-08-25, per Mr T:
   *"day theme 에 핑크를 추가하는 느낌으로"* — it used to be a dark theme
   (pink-tinted near-black) and he found it too dark.

   🔴 THIS THEME IS A DAY VARIANT, NOT A THEME OF ITS OWN. _sidebar.php puts
   BOTH `theme-light` and `theme-pink` on <html> for it (see ERP_LIGHT_THEMES
   there). That is deliberate and it is the whole design:

     - Everything that makes a white background readable is keyed on
       `html.theme-light` — ~129 rules in this file plus ~10 more injected at
       runtime by assets/global_search.js. They exist because the app is full
       of hardcoded dark-navy inline backgrounds and white inline text that
       would be invisible on white. Carrying the class means Pink inherits all
       of it for free; duplicating it for `html.theme-pink` would create a
       second copy of a 139-rule definition that silently drifts (AI_RULES 11).
     - This block sits AFTER `html.theme-light` in the file and has identical
       specificity (element + class), so the later block wins and these pink
       variables replace Day's neutral/Google-Blue ones. 🔴 If anyone ever
       moves this block above html.theme-light, Pink silently becomes Day.

   So: Day's layout and readability, retinted. Surfaces stay white so cards
   still separate from the page; only the page base, the borders, the accent
   and the hover/field tints go pink. Contrast checked against white —
   accent #db2777 is 4.6:1 (AA for white button text and for small text),
   accent-soft-text #9d174d is 8.0:1.
   ============================================================ */
html.theme-pink {
  --bg:#fff5f9; --surface:#ffffff; --surface-2:#fce7f0;
  /* Same .18/.32 alpha tier as Day's borders — a low-opacity line on a light
     page reads as "no line at all" otherwise (see the Day block) — just
     tinted with the pink's own dark tone instead of pure black. */
  --border:rgba(157,23,77,.18); --border-strong:rgba(157,23,77,.34);
  --text:#18080f; --text-dim:rgba(24,8,15,.68); --text-faint:rgba(24,8,15,.45); --text-heading:#000000;
  /* Pink 600/500. accent-soft-text is a much darker pink (Pink 800), not the
     raw accent, so small text stays readable on a white surface — same
     convention Day uses for its darkened Google Blue. */
  --accent:#db2777; --accent-2:#ec4899;
  --accent-soft-bg:rgba(219,39,119,.12); --accent-soft-text:#9d174d;
  --field-bg:rgba(219,39,119,.05); --field-border:rgba(157,23,77,.20);
  --hover-bg:rgba(219,39,119,.07);
  --scroll-track:rgba(0,0,0,.05); --scroll-thumb:rgba(219,39,119,.32);
  /* Light OS chrome for native controls, same as Day — this used to be
     `dark` back when Pink was a dark theme. */
  color-scheme: light;
}

/* ============================================================
   GREEN MODE — added 2026-07-19, per Mr T. Rebuilt 2026-08-25 alongside Pink,
   same request: a Day variant, not a dark theme. See the PINK MODE header
   above for why these blocks must stay BELOW html.theme-light and why
   _sidebar.php emits `theme-light` with them ($_lightThemes there).
   🔴 Accent is Green 700 (#15803d), NOT the obvious Green 500/600 — on white,
   #22c55e is 2.0:1 and #16a34a is 3.3:1, both below the 4.5:1 that white
   button text and small accent text need. 700 measures 5.0:1.
   ============================================================ */
html.theme-green {
  --bg:#f3fcf6; --surface:#ffffff; --surface-2:#d8f3e3;
  --border:rgba(6,78,59,.18); --border-strong:rgba(6,78,59,.34);
  --text:#08150e; --text-dim:rgba(8,21,14,.68); --text-faint:rgba(8,21,14,.45); --text-heading:#000000;
  --accent:#15803d; --accent-2:#16a34a;
  --accent-soft-bg:rgba(21,128,61,.12); --accent-soft-text:#14532d;
  --field-bg:rgba(21,128,61,.05); --field-border:rgba(6,78,59,.20);
  --hover-bg:rgba(21,128,61,.07);
  --scroll-track:rgba(0,0,0,.05); --scroll-thumb:rgba(21,128,61,.32);
  color-scheme: light;
}

/* ============================================================
   BLUE MODE — added 2026-07-19, per Mr T. Rebuilt 2026-08-25 alongside Pink.
   🔴 THE PROBLEM THIS BLOCK HAS TO SOLVE: Day's own accent is already Google
   Blue (#4285F4). Make Blue "Day but blue" the way Pink is "Day but pink" and
   the two themes become indistinguishable — the picker would offer the same
   look twice. So Blue is separated on the SURFACES, not the accent: the page
   base and the sidebar carry a clear blue tint where Day stays neutral
   white/grey, and the accent goes to a deeper Blue 700 (#1d4ed8, 6.7:1) that
   reads as navy next to Day's brighter Google Blue. If anyone later flattens
   --bg/--surface-2 back to neutral here, Blue silently becomes Day again.
   ============================================================ */
html.theme-blue {
  --bg:#f3f8ff; --surface:#ffffff; --surface-2:#dbeafe;
  --border:rgba(23,37,84,.18); --border-strong:rgba(23,37,84,.34);
  --text:#0a1020; --text-dim:rgba(10,16,32,.68); --text-faint:rgba(10,16,32,.45); --text-heading:#000000;
  --accent:#1d4ed8; --accent-2:#2563eb;
  --accent-soft-bg:rgba(29,78,216,.12); --accent-soft-text:#1e3a8a;
  --field-bg:rgba(29,78,216,.05); --field-border:rgba(23,37,84,.20);
  --hover-bg:rgba(29,78,216,.07);
  --scroll-track:rgba(0,0,0,.05); --scroll-thumb:rgba(29,78,216,.32);
  color-scheme: light;
}

/* Extra hardcoded dark-navy backgrounds found across the app that the
   Dark-theme override list above doesn't catch (it only lists the 4
   shades actually used near variable-driven components). Scoped to
   theme-light only, so Dark mode's look is completely untouched. */
html.theme-light [style*="background:#0f0f1a"], html.theme-light [style*="background: #0f0f1a"],
html.theme-light [style*="background:#1d1d38"], html.theme-light [style*="background: #1d1d38"],
html.theme-light [style*="background:#16162a"], html.theme-light [style*="background: #16162a"],
html.theme-light [style*="background:#1a1a30"], html.theme-light [style*="background: #1a1a30"],
html.theme-light [style*="background:#20203a"], html.theme-light [style*="background: #20203a"],
html.theme-light [style*="background:#181830"], html.theme-light [style*="background: #181830"],
html.theme-light [style*="background:#252542"], html.theme-light [style*="background: #252542"],
html.theme-light [style*="background:#13132b"], html.theme-light [style*="background: #13132b"] {
  background:var(--surface) !important;
}

/* Hardcoded light-on-dark inline text colors, flipped to black so they
   stay legible once the background behind them turns white. Note: a
   badge/pill that hardcodes BOTH a colored background and color:#fff
   (e.g. a status chip) will also get its text flipped here — if any
   specific badge looks wrong in Day mode, tell me which page/label and
   I'll carve out an exception for it. */
html.theme-light [style*="color:#fff"], html.theme-light [style*="color: #fff"],
html.theme-light [style*="color:#ffffff"], html.theme-light [style*="color: #ffffff"],
html.theme-light [style*="color:#e8e8f0"], html.theme-light [style*="color: #e8e8f0"],
html.theme-light [style*="color:#e2e8f0"], html.theme-light [style*="color: #e2e8f0"] {
  color:var(--text) !important;
}

/* ── Day theme, round 2 — added 2026-07-18, per Mr T's report that clock.php,
   leave.php, announcements.php, customer_form.php, deals.php, estimate_form.php,
   invoice_form.php, and price_history.php still looked broken in Day mode.

   Root cause: this app has no shared component naming convention — almost
   every page defines its OWN local CSS classes for what is conceptually a
   "card" or "panel" (e.g. announcements.php uses .a-item/.a-title while
   dashboard.php's announcement widget uses .ann-item/.ann-title for the same
   idea). The round-1 override list above only covered the shared class names,
   so any page with its own bespoke styling was untouched. Scanned all ~220
   PHP files for hardcoded dark backgrounds and light text to close the gap:
   ============================================================ */

/* 145 page-local classes found with a hardcoded dark background (#0f0f1a,
   #1e1e35, #1a1a2e, and ~45 other near-black shades used 1-20 times each
   across different pages) that don't match any round-1 selector. Mapped to
   var(--surface) — same treatment as the shared .card/.tbl-section list
   above, just covering the page-specific names too. */
html.theme-light #cdOverlay .cd-panel, html.theme-light #priceTip, html.theme-light #toast,
html.theme-light .a-item, html.theme-light .adv-panel, html.theme-light .ai-out,
html.theme-light .ai-panel, html.theme-light .aicust-list, html.theme-light .ais-box,
html.theme-light .attr-menu, html.theme-light .autocomplete, html.theme-light .bc-table th,
html.theme-light .bottom-bar, html.theme-light .btn-add, html.theme-light .btn-add:hover,
html.theme-light .btn-login, html.theme-light .btn-login:hover, html.theme-light .btn-save,
html.theme-light .btn.sec, html.theme-light .btn:hover, html.theme-light .bucket,
html.theme-light .bulk-bar, html.theme-light .cal-cell, html.theme-light .card img,
html.theme-light .card-img-wrap, html.theme-light .cat-card, html.theme-light .cc-panel,
html.theme-light .center, html.theme-light .chat-box, html.theme-light .clock-widget,
html.theme-light .cmp-img-wrap, html.theme-light .cmp-table, html.theme-light .col,
html.theme-light .compose-card, html.theme-light .cp-list, html.theme-light .cpanel,
html.theme-light .css-editor, html.theme-light .ctools-panel, html.theme-light .cu-frame,
html.theme-light .cust-ac, html.theme-light .cust-box, html.theme-light .cust-prev-item img,
html.theme-light .cust-results .drop, html.theme-light .custom-panel, html.theme-light .cvtools,
html.theme-light .deal-modal-panel, html.theme-light .deal-table, html.theme-light .detail-modal,
html.theme-light .dm-row, html.theme-light .dm-row:hover, html.theme-light .doc-card,
html.theme-light .dp-panel, html.theme-light .drawer, html.theme-light .drop,
html.theme-light .edit-panel, html.theme-light .em-box, html.theme-light .em-modal,
html.theme-light .email-body, html.theme-light .fb-cust .drop, html.theme-light .fc-table th,
html.theme-light .fcard, html.theme-light .feat-card, html.theme-light .fg-pop,
html.theme-light .filter-btn.on, html.theme-light .filterbar, html.theme-light .filters,
html.theme-light .filters-bar, html.theme-light .fp3d-opt .ky, html.theme-light .gitem,
html.theme-light .gtable, html.theme-light .gtable img, html.theme-light .help-section,
html.theme-light .inv-menu, html.theme-light .lib-card, html.theme-light .list-row,
html.theme-light .list-row img, html.theme-light .list-thumb-empty, html.theme-light .live-captions,
html.theme-light .mail-compose-panel, html.theme-light .mail-list-head, html.theme-light .menu-panel,
html.theme-light .mg-day.drag-over, html.theme-light .mini-card, html.theme-light .mini-card img,
html.theme-light .modal-bx, html.theme-light .modal-panel, html.theme-light .modal-perms-foot,
html.theme-light .modal-role-foot.modal-btns, html.theme-light .move-panel, html.theme-light .mp-panel,
html.theme-light .new-pipe, html.theme-light .oc-table th, html.theme-light .p-card,
html.theme-light .p-thumb, html.theme-light .panel .seg button, html.theme-light .paybar,
html.theme-light .pcard, html.theme-light .pcard-img, html.theme-light .picker,
html.theme-light .picker-drop, html.theme-light .pill, html.theme-light .pipe-card,
html.theme-light .pk-list, html.theme-light .pp-list, html.theme-light .preview-item .main-badge,
html.theme-light .print-bar, html.theme-light .prod-card, html.theme-light .product-ac,
html.theme-light .pv-card, html.theme-light .pw-form .ok, html.theme-light .rail,
html.theme-light .recon .card, html.theme-light .recv-section, html.theme-light .rpt-tab,
html.theme-light .scan-item, html.theme-light .search-box, html.theme-light .search-results,
html.theme-light .sec-card, html.theme-light .section-card, html.theme-light .seg button,
html.theme-light .setup-card, html.theme-light .slidethumb, html.theme-light .ss-table th,
html.theme-light .stat-box, html.theme-light .stat-box.active, html.theme-light .state-list,
html.theme-light .step, html.theme-light .stmt-head, html.theme-light .sum-card,
html.theme-light .ta-drop, html.theme-light .task-form, html.theme-light .toast,
html.theme-light .toolbar, html.theme-light .top-bar, html.theme-light .topbar, html.theme-light .site-top-bar,
html.theme-light .wk-col.drag-over, html.theme-light form.filters, html.theme-light header,
html.theme-light pre, html.theme-light table.grid th, html.theme-light table.pm-table th,
html.theme-light th, html.theme-light tr:hover td {
  background: var(--surface) !important;
}

/* Text color is the bigger problem: color:#fff alone is hardcoded across 439
   different page-local classes (833 uses) with no shared name to hook into —
   individually listing every one isn't practical or reliable. Instead: a
   single default-black-text rule for Day mode, using :where() so it carries
   ZERO CSS specificity of its own. That means:
     - it still beats every page's own non-!important `color:#fff`-style rule
       (an !important declaration always wins over a non-!important one,
       regardless of specificity), fixing the invisible-text bug everywhere
       at once without listing 439 selectors, but
     - it still LOSES to any of our own more-specific !important rules above
       (like .btn-primary's white-on-purple), which keep working normally.
   Trade-off: page-local color-coded text (a green "success" label, a purple
   link, a yellow warning) that isn't one of our own shared/branded rules will
   also turn plain black in Day mode instead of staying colored — still fully
   readable, just less visually distinct than Dark mode. Dark mode itself is
   completely unaffected either way. If a specific color-coded label matters
   to you, tell me which page/label and I'll add it back as an exception. */
html.theme-light :where(body *) {
  color: var(--text) !important;
}

/* ── Large / X-Large font size — Large added 2026-07-17, X-Large added
   2026-07-19 (per Mr T, account_settings.php "Appearance" tab). Most pages
   use fixed px values scattered across per-page inline <style> blocks
   rather than one shared rem/em scale, so a single "bump the base
   font-size" rule can't reach everything. `zoom` scales the whole rendered
   page (text, buttons, spacing, icons) instead, which reaches every page
   uniformly with one rule. Supported in Chrome/Edge/Safari and current
   Firefox (126+). ── */
html.font-large body { zoom: 1.15; }
html.font-xlarge body { zoom: 1.3; }

/* ── Fine-grained font size — 2026-09-07, per Mr T (조금더 세밀하게).
   The two rules above were the entire scale (115% / 130%); this adds a 5%-step
   ladder from 80% to 150% driven by the very same mechanism — users.font_size
   holds 'z<percent>', _sidebar.php turns it into html.font-z<percent>, and the
   rule zooms <body>. Same reason as above for using `zoom` rather than a base
   font-size: this app's px values live in ~170 per-page inline <style> blocks,
   so nothing but zoom reaches them all. font-large / font-xlarge are kept above
   so rows and sessions saved before today keep working unchanged. ── */
html.font-z80 body { zoom: 0.8; }
html.font-z85 body { zoom: 0.85; }
html.font-z90 body { zoom: 0.9; }
html.font-z95 body { zoom: 0.95; }
html.font-z100 body { zoom: 1; }
html.font-z105 body { zoom: 1.05; }
html.font-z110 body { zoom: 1.1; }
html.font-z115 body { zoom: 1.15; }
html.font-z120 body { zoom: 1.2; }
html.font-z125 body { zoom: 1.25; }
html.font-z130 body { zoom: 1.3; }
html.font-z135 body { zoom: 1.35; }
html.font-z140 body { zoom: 1.4; }
html.font-z145 body { zoom: 1.45; }
html.font-z150 body { zoom: 1.5; }


/* ── Font family — added 2026-07-19, per Mr T (account_settings.php
   "Appearance" tab, next to Font Size). Every page hardcodes its own
   `body { font-family:'Segoe UI',-apple-system,sans-serif; ... }` in an
   inline <style> block rather than reading a shared variable, so (like the
   color themes above) this overrides it via a higher-specificity
   `html.font-<name> body` selector rather than a CSS variable — no
   !important needed since `html.font-arial body` already outweighs a page's
   own bare `body` selector regardless of load order. font-family is
   inherited by default, so this alone reaches nearly everything on the
   page; a handful of elements that set their own explicit font-family
   (rare in this codebase) will keep it. 'default' (Segoe UI/system) needs
   no override — it's already what every page's own inline style sets. ── */
html.font-arial body     { font-family: Arial, Helvetica, sans-serif; }
html.font-verdana body   { font-family: Verdana, Geneva, sans-serif; }
html.font-georgia body   { font-family: Georgia, 'Times New Roman', serif; }
html.font-trebuchet body { font-family: 'Trebuchet MS', sans-serif; }

/* ── Page background + base text ── */
body { background:var(--bg) !important; color:var(--text) !important; }

/* ── Sidebar note: the sidebar's OWN styles (_sidebar.php) now reference
   these same variables directly, so it themes along with everything else —
   no override needed here. Its avatar/logo badges intentionally keep a
   fixed accent gradient with white text, which stays readable against a
   light or dark sidebar background either way. ── */

/* ── Page chrome / headings (note the !important — several pages set these
   via a plain element selector like `h1{color:#fff}`, which otherwise ties
   with this rule and can lose depending on source order) ── */
.page-title, .as-title, .page-header h2, .cal-title, .modal-head h3,
h1, h2, h3 { color:var(--text-heading) !important; }
.page-header p, .pane-sub { color:var(--text-faint) !important; }

/* ── Cards / panels / tiles / tables (shared across every list/board page) ── */
.tbl-section, .as-head-card, .act-tabs, .tab-body, .settings-panel, .vsp-panel,
.view-panel, .cd-panel, .sig-preview, .tbl-card, .card, .stat-card, .mod-card,
.ann-board, .chip, .rc-panel {
  background:var(--surface) !important; border-color:var(--border) !important;
}
.modal-box, .modal, .ann-modal, .del-card, .mg-day, .wk-col {
  background:var(--surface-2) !important; border-color:var(--border) !important;
}
/* Catches the many one-off `style="background:#1e1e35..."` boxes on pages
   (like floorplan.php) that don't use a shared class name at all. */
[style*="background:#1e1e35"], [style*="background: #1e1e35"] { background:var(--surface) !important; }
[style*="background:#1a1a2e"], [style*="background: #1a1a2e"],
[style*="background:#12122a"], [style*="background: #12122a"],
[style*="background:#161628"], [style*="background: #161628"] { background:var(--surface-2) !important; }

table th { color:var(--text-faint) !important; background:rgba(127,127,127,.05) !important; }
table td { color:var(--text-dim) !important; border-color:var(--border) !important; }
tr:hover td { background:var(--hover-bg) !important; }
.empty { color:var(--text-faint) !important; }

/* Day theme, round 3 — added 2026-07-18, per Mr T ("need a visible thin
   line for charts/tables"). border-color alone (the rule right above) only
   renders if the page's own CSS already declared a border-style on that
   element — most of this app's tables never did (dark-theme rows were
   separated by background contrast alone, not a drawn line), so on a flat
   white Day-mode background rows ran together with nothing to show. This
   forces an actual visible row divider regardless of what the page itself
   declared. */
html.theme-light table td, html.theme-light table th {
  border-bottom: 1px solid var(--border) !important;
}

/* ── Tile / card text (stat cards, module tiles, announcement board, delivery cards) ── */
.stat-value, .ct-status, .mod-name, .ann-title, .ann-head h3, .section-title,
.del-info .cust {
  color:var(--text-heading) !important;
}
.stat-label, .stat-icon, .ct-sub, .mod-desc, .ann-meta, .ann-body, .card-title,
.del-info .addr, .del-info .notes, .mg-num, .wk-hour, .wk-headcell, .chip-lbl,
.cal-legend, .mg-head {
  color:var(--text-dim) !important;
}
.ann-item { border-color:var(--border) !important; }
.ann-item.is-pinned { background:var(--accent-soft-bg) !important; }
.stat-link { color:var(--accent) !important; }

/* ── Buttons ── */
.btn-primary, .btn-purple, .tab.active { background:linear-gradient(135deg,var(--accent),var(--accent-2)) !important; color:#fff !important; }
.btn-ghost, .back-btn, .ann-btn, .btn-gray, .time-btn { background:var(--field-bg) !important; color:var(--text-dim) !important; border-color:var(--border) !important; }
.time-btn:hover { background:var(--accent-soft-bg) !important; color:var(--accent-soft-text) !important; }

/* Shared semantic button classes — added 2026-07-19, per Mr T, alongside the
   Google/Discord button-color request. Any page can opt into these (class=
   "btn btn-danger" etc.) to get theme-aware delete/save/warning coloring
   instead of a hardcoded inline color. Universal defaults here work against
   any dark-based theme (Dark/Pink/Green/Blue); Day mode overrides them below
   with Google's exact brand colors per Mr T's request. This does NOT
   retroactively recolor pages that already hardcode their own red delete
   button etc. via inline styles — only pages using these class names. */
.btn-danger  { background:linear-gradient(135deg,#ef4444,#dc2626) !important; color:#fff !important; }
.btn-success { background:linear-gradient(135deg,#22c55e,#16a34a) !important; color:#fff !important; }
.btn-warning { background:linear-gradient(135deg,#eab308,#ca8a04) !important; color:#111 !important; }

/* ── Accent-tinted highlight boxes (date badges, "today" markers) stay
   accent-colored rather than neutral, since they're meant to draw the eye ── */
.del-date-box { background:var(--accent-soft-bg) !important; border-color:var(--accent) !important; }
.del-date-box .day, .chip-num { color:var(--accent) !important; }
.del-info .time { color:var(--accent) !important; }
.wk-headcell.today { background:var(--accent-soft-bg) !important; }
.mg-day.today { border-color:var(--accent) !important; }

/* ── Form fields (covers every page using these shared classes or bare inputs) ── */
.search-input, .select-filter, .sf-input, .sf-textarea, .fg input, .fg textarea,
input[type="text"], input[type="email"], input[type="password"], input[type="tel"],
input[type="number"], input[type="date"], input[type="time"], select, textarea {
  background:var(--field-bg) !important; border-color:var(--field-border) !important; color:var(--text) !important;
}

/* ── Dropdown popup options — the closed <select> box picks up the themed
   colors above automatically, but the OPEN option list is a separate native
   control that browsers only theme correctly when color-scheme (set on
   :root per theme above) AND explicit option colors are both present.
   This used to be hardcoded to color:#000/background:#fff (pre-dating the
   theme system), which forced every dropdown's option list to light mode
   no matter what theme was active — that's why it's themed via variables now. */
select option {
  background:var(--surface-2) !important; color:var(--text) !important;
}

/* ── Date/time picker icon — DO NOT add filter:invert() here, even though
   that seems like the obvious fix for a dark icon on a dark field.
   `color-scheme: dark` on :root (see COLOR THEME above) already tells the
   browser to draw this icon in a light color suited to dark backgrounds —
   confirmed live: with no filter at all, the icon renders light and is
   clearly visible. Adding invert() flips that already-light icon back to
   dark/invisible, which is exactly what caused this icon to silently go
   black before (an earlier version of this rule had the invert filter and
   that was the bug, not a fix for it). Only cursor needs to be set here. ── */
input[type="date"]::-webkit-calendar-picker-indicator,
input[type="datetime-local"]::-webkit-calendar-picker-indicator,
input[type="month"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator {
  cursor: pointer;
}

/* ── Pagination ── */
.pagination a, .pagination span { background:var(--field-bg) !important; color:var(--text-dim) !important; border-color:var(--border) !important; }
.pagination .cur { background:var(--accent-soft-bg) !important; color:var(--accent-soft-text) !important; border-color:var(--accent) !important; }
.page-info { color:var(--text-faint) !important; }

/* ── Modal scrims stay dark regardless of theme, for contrast ── */
.view-overlay, .modal-overlay, #cdOverlay, .mod-ov { background:rgba(0,0,0,.7) !important; }

/* ── Dashboard clock-in bar (dashboard.php) — was omitted from the card
   list above, so it kept its hardcoded navy gradient in every theme ── */
.clock-bar { background:var(--surface) !important; border-color:var(--border) !important; }

/* ── Deal Stages page (deal_stages.php) — its table has its own hardcoded
   dark background, and its inputs/selects have no type="" attribute so the
   input[type="text"] rule above never matched them ── */
.stage-table { background:var(--surface) !important; border-color:var(--border) !important; }
.sub-note, .mv button { color:var(--text-faint) !important; }
.stage-table input, .stage-table select, .add-row input, .add-row select {
  background:var(--field-bg) !important; border-color:var(--field-border) !important; color:var(--text) !important;
}

/* ── Admin Tools tab bar (admin_tools.php) — inactive tab labels were
   rgba(255,255,255,.4), i.e. near-invisible light text on a light page ── */
.tab-btn { color:var(--text-faint) !important; }
.tab-btn:hover:not(.active) { color:var(--text-dim) !important; }
.tab-btn.active { color:var(--accent-soft-text) !important; border-bottom-color:var(--accent) !important; }

/* ── Floor Plan editor (floorplan.php?id=…) — this whole tool never linked
   custom.css until now and every panel/input color was hardcoded. The
   drawing canvas (.fp-canvas) and the white icon/preview swatches (.lib-ico,
   .cub-sty) are deliberately left alone — they represent the actual drawing
   surface and printed-paper previews, which stay neutral/white in any
   theme, the same way design tools like Figma keep their canvas fixed. ── */
.fp-top, .panel, .panel-l, .panel-r, .sc-help, .mod, .ctx, .props, .align-bar, .zoom-ui button {
  background:var(--surface-2) !important; border-color:var(--border) !important;
}
.fp-top .back, .fp-top input.name, .fp-top select { background:var(--field-bg) !important; border-color:var(--field-border) !important; color:var(--text) !important; }
.cat { border-color:var(--border) !important; }
.cat-h { background:var(--hover-bg) !important; color:var(--text-dim) !important; }
.cat-h:hover { color:var(--text-heading) !important; }
.mod h3, .fi .nm { color:var(--text-heading) !important; }
.p-title, .hint, .save-state, .tpl-sz-row .x, .fld label, .fi .sz {
  color:var(--text-faint) !important;
}
.sc-row, .lib-grp, .room-row, .menu-cfg-row, .ctx-i, .tpl-sz-row {
  color:var(--text-dim) !important; background:var(--field-bg) !important;
}
.mini, .tool, .fi, .room-row button, .menu-cfg-row button {
  background:var(--field-bg) !important; color:var(--text-dim) !important; border-color:var(--border) !important;
}
.mini:hover, .tool:hover { background:var(--hover-bg) !important; }
.mini.active, .tool.active, .cub-sty.active {
  background:var(--accent-soft-bg) !important; border-color:var(--accent) !important; color:var(--accent-soft-text) !important;
}
.rev-badge { background:var(--accent-soft-bg) !important; color:var(--accent-soft-text) !important; }
.fld input, .fld select, .tpl-sz-row input, .dimfill input, .dimfill select,
.seg-table input, .seg-table select, .sc-row kbd {
  background:var(--field-bg) !important; border-color:var(--field-border) !important; color:var(--text) !important;
}

/* ── Floor Plan list view (floorplan.php, before opening a plan) — a plain
   <table> tag with its own hardcoded panel color, plus small icon buttons
   that were pure-white-on-white in Light theme ── */
table { background:var(--surface) !important; }
.bulk { background:var(--surface-2) !important; }
.act { background:var(--field-bg) !important; color:var(--text-dim) !important; }
.thumb-none { color:var(--text-faint) !important; border-color:var(--border) !important; }

/* ── Scrollbars ── */
::-webkit-scrollbar-track { background:var(--scroll-track) !important; }
::-webkit-scrollbar-thumb { background:var(--scroll-thumb) !important; }

/* ── Add your custom styles below ────────────────────────── */

/* Dropdown option lists — dark background so light option text stays
   readable when a <select> menu is open (fixes white-on-white). */
select option,
select optgroup {
  background: #1e1e35;
  color: #e8e8f0;
}
/* Day theme: same fix, flipped — dark text on a light option list. */
html.theme-light select option,
html.theme-light select optgroup {
  background: #ffffff;
  color: #000000;
}

/* ══════════════════════════════════════════════════════════════════
   MOBILE UI  (≤768px) — added 2026-07-11
   Turns wide list tables into stacked cards, single-column forms,
   full-width filters, and bigger tap targets. The card transform ONLY
   applies to tables the sidebar script tags with .mob-cards (the main
   list tables), so line-item / detail / modal tables are untouched.
   Everything lives inside the media query — desktop is unaffected.
   ══════════════════════════════════════════════════════════════════ */
@media (max-width: 768px) {

  /* ── Card-style list rows ─────────────────────────────────────── */
  table.mob-cards thead { display: none; }
  table.mob-cards, table.mob-cards tbody { display: block; width: 100%; }
  table.mob-cards tr {
    display: block;
    background: var(--surface-1, #1e1e35);
    border: 0.5px solid var(--border, rgba(255,255,255,.12));
    border-radius: 12px;
    padding: 11px 13px;
    margin: 0 0 10px;
  }
  table.mob-cards td {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 4px 0 !important; border: none !important;
    white-space: normal !important; text-align: right; font-size: 13px;
    max-width: 100% !important; overflow: hidden; text-overflow: ellipsis;
  }
  table.mob-cards td::before {
    content: attr(data-label);
    color: var(--text-secondary, rgba(255,255,255,.45));
    font-weight: 500; text-align: left; flex: 0 0 42%; font-size: 12px;
  }
  table.mob-cards td.cb-col { display: none !important; }
  /* Cells with no header label (Actions / Linked / icon columns) → full-width button row */
  table.mob-cards td:not([data-label]) {
    justify-content: flex-start; flex-wrap: wrap; gap: 6px;
    margin-top: 6px; padding-top: 8px !important;
    border-top: 0.5px solid var(--border, rgba(255,255,255,.08)) !important;
  }
  table.mob-cards td:not([data-label])::before { display: none; }
  table.mob-cards td[data-label="Actions"], table.mob-cards td[data-label="Linked"] {
    flex-wrap: wrap; justify-content: flex-start; text-align: left;
    margin-top: 6px; padding-top: 8px !important;
    border-top: 0.5px solid var(--border, rgba(255,255,255,.08)) !important;
  }
  table.mob-cards td[data-label="Actions"]::before, table.mob-cards td[data-label="Linked"]::before { flex-basis: 100%; margin-bottom: 4px; }
  table.mob-cards td .btn, table.mob-cards td .btn-sm { margin: 0; }
  table.mob-cards td select { max-width: 60%; }

  /* ── Filters: search full width, dropdowns share rows ─────────── */
  .search-input { width: 100% !important; }
  .select-filter { flex: 1 1 42%; }

  /* ── Single-column forms (collapse equal-column field grids) ──── */
  [style*="grid-template-columns:1fr 1fr"],
  [style*="grid-template-columns: 1fr 1fr"],
  .adv-grid { grid-template-columns: 1fr !important; }

  /* ── Bigger, easier tap targets + iOS niceties ────────────────── */
  .btn, .btn-sm { min-height: 40px; }
  select, input, textarea { font-size: 16px; }        /* 16px stops iOS zoom-on-focus */
  .bottom-bar { padding-bottom: calc(10px + env(safe-area-inset-bottom)); }
  main.main, .main { padding-bottom: calc(24px + env(safe-area-inset-bottom)); }
}

/* ── Estimate line-item row dividers — added 2026-07-18, per Mr T ──────
   .item-row's own border-bottom is rgba(255,255,255,.045) (estimate_form.php),
   nearly invisible even in Dark mode and completely invisible in Day/Light
   mode (white-on-white). Using var(--border-strong) (already bumped for this
   exact "faint divider" problem elsewhere today) makes the line between each
   product/service row clearly visible in Light mode, while Dark mode is
   intentionally left alone — its own faint divider already reads fine there,
   and this rule is scoped to html.theme-light only. */
html.theme-light .item-row,
html.theme-light .items-cols {
  border-bottom: 1px solid var(--border-strong);
}

/* ── Price type color coding (2026-07-19, per Mr T) ─────────────────
   Retail = green, B2B = blue, Cost = yellow/amber, Promotion = red.
   Apply one of these classes directly to whatever element renders the
   number (a helper, priceTypeClass($type) in config.php, returns the
   right class name given 'retail'|'b2b'|'cost'|'promo').

   IMPORTANT for print pages: an element's own explicit color does NOT
   get overridden by a `body { color:#000 }` print rule — CSS resolves
   an element's own declared color before it ever looks at an ancestor's
   value, @media print or not. So every page that uses these classes
   needs the print override below (or its own equivalent) to actually
   go black when printed; don't assume the existing print rules on
   invoice_form.php/estimate_form.php/etc. already cover this — they
   were written before any element had its own explicit price color. */
.price-retail    { color: #7ee787; }
.price-b2b       { color: #5eb8f5; }
.price-wholesale { color: #fb923c; }
.price-cost      { color: #f5d76e; }
.price-promo     { color: #f57e7e; }
.price-type-note { font-size: 10px; font-weight: 600; opacity: .7; text-transform: uppercase; letter-spacing: .03em; }

@media print {
  .price-retail, .price-b2b, .price-wholesale, .price-cost, .price-promo {
    color: #000 !important;
  }
}

/* ── Linked column compact buttons (2026-07-25, per Mr T) ────────────
   estimates.php + invoices.php's "Linked" column (Deal/Inv/PO/Delivery
   buttons, rendered by linked_info.php) was taking up excessive column
   width. This single shared rule tightens every button/link/dropdown in
   that column so the column can shrink to fit its content. Several of
   those elements also carry their own inline style="..." for per-type
   color-coding (purple=Deal, green=Invoice, amber=PO, blue=Delivery) —
   !important is used here deliberately so this sizing always wins over
   those inline styles without having to hand-edit every one of them in
   linked_info.php. Loaded after every page's own inline <style> block
   (see the cascade note earlier in this file), so it applies on both
   estimates.php and invoices.php with this one rule. */
.linked-btn {
  padding: 3px 7px !important;
  font-size: 11px !important;
  gap: 3px !important;
  border-radius: 6px !important;
  line-height: 1.4 !important;
}
select.linked-btn { padding: 3px 5px !important; }


/* == Day-theme gaps found by a live audit (2026-08-07, per Mr T: "when I do day theme, some
      of the divs color doesn't change") =============================================
   Method: loaded 16 pages with theme-light applied and measured COMPUTED background colours,
   flagging anything darker than 0.28 relative luminance and larger than 2500px. That is how
   these were found rather than by eye - .add-line is #1a1a2e while the inline-style list
   above already carries #1a1a30, one hex digit away, which is exactly the kind of near-miss
   an allow-list architecture produces.
   Both set their dark background in page-level <style> rules (not inline styles), so neither
   the [style*=...] list nor the class list above could catch them.
   Appended at the END of the file on purpose: same specificity as the lists above, so being
   last is what guarantees these win.

   FALSE POSITIVE, do not re-add: dashboard's .mod-card. The scanner reported it dark on every
   run, but a screenshot showed the tiles are white, and the element would not change colour
   even with an inline background:#fff !important - i.e. the element being measured is not the
   one being painted (the dashboard keeps drag-reorder copies). Ground-truth with a screenshot
   before trusting a computed-style reading.

   DELIBERATELY NOT INCLUDED - verified as intentional, not theme bugs:
   - estimate_print / invoice_print / inventory_count: print documents with their own paper
     palette (light body, dark group rows, dark on-screen toolbar). They do not follow the
     app theme by design.
   - Modal backdrops (rgba(0,0,0,.55) etc.): meant to stay dark in every theme. */
html.theme-light .add-line,   /* sticky add-line bar - estimate/invoice/po forms (#1a1a2e) */
html.theme-light #pgnoteFab { /* floating page-note pin (the "Admin" bubble) - every page */
  background: var(--surface) !important;
  border-color: var(--border) !important;
}

/* ============================================================
   DAY THEME, ROUND 4 — added 2026-08-14, per Mr T ("when user using
   day theme, all pop up window colors are still dark theme").

   ROOT CAUSE (verified live on invoices.php, not inferred from the repo):
   the worst offenders are modal panels built as a BARE <div> carrying an
   inline style="background:#14142c;..." and NO class at all. Neither
   earlier mechanism could ever reach them:
     - the round-1/2/3 class lists need a class name to hook onto, and
       these elements have none;
     - the inline-shade attribute list above enumerates 12 dark hexes,
       and #14142c was simply never one of them.
   A full scan of every PHP file found 21 dark shades used in inline
   styles: 12 were already covered, 14 were not. This closes those 14,
   plus the handful of pop-ups reachable only through an ID selector.

   Scoped entirely to html.theme-light, so Dark / Pink / Green / Blue are
   byte-for-byte unaffected. The ` i` flag makes each attribute match
   case-insensitive, so an uppercase #14142C is caught too — the old
   rules would silently miss it.

   DELIBERATELY NOT TOUCHED: the rgba(0,0,0,.5-.75) backdrops behind
   modals. Those SHOULD stay dark in Day mode — the dim scrim is what
   makes a modal read as a modal. Whitening them would flood the screen.
   ============================================================ */

/* ── 4a. Neutral dark surfaces set via an inline style with no class.
   Mapped to --surface-2 (the same value the shared .modal/.modal-box
   rule uses) so a pop-up panel stays a hair off pure white and still
   separates visually from the page behind it. ── */
html.theme-light [style*="background:#14142c" i], html.theme-light [style*="background: #14142c" i],
html.theme-light [style*="background:#15152a" i], html.theme-light [style*="background: #15152a" i],
html.theme-light [style*="background:#12121e" i], html.theme-light [style*="background: #12121e" i],
html.theme-light [style*="background:#12121f" i], html.theme-light [style*="background: #12121f" i],
html.theme-light [style*="background:#1a1a24" i], html.theme-light [style*="background: #1a1a24" i],
html.theme-light [style*="background:#0d0d1c" i], html.theme-light [style*="background: #0d0d1c" i],
html.theme-light [style*="background:#1c1c36" i], html.theme-light [style*="background: #1c1c36" i],
html.theme-light [style*="background:#1b1e27" i], html.theme-light [style*="background: #1b1e27" i],
html.theme-light [style*="background:#1b1b34" i], html.theme-light [style*="background: #1b1b34" i],
html.theme-light [style*="background:#14141c" i], html.theme-light [style*="background: #14141c" i],
html.theme-light [style*="background:#0f1420" i], html.theme-light [style*="background: #0f1420" i],
html.theme-light [style*="background:#2a2a44" i], html.theme-light [style*="background: #2a2a44" i] {
  background: var(--surface-2) !important;
  border-color: var(--border) !important;
}

/* ── 4b. Pop-ups styled through an ID selector, which no class list can
   reach. .fav-panel (the ⭐ Favorites dialog) lives in _sidebar.php and
   #pgnoteFab in notes_lib.php, so both appear on EVERY page — these two
   are why Day mode looked broken app-wide rather than on one screen. ── */
html.theme-light #favModalOverlay .fav-panel,
html.theme-light #poBulkBar,
html.theme-light .vpick-menu,
html.theme-light .files-modal,
html.theme-light .confirm-picker,
html.theme-light .modal-card,
html.theme-light .sheet-select,
html.theme-light .sheet-select option {
  background: var(--surface-2) !important;
  border-color: var(--border) !important;
}

/* ── 4c. The page-note button (notes_lib.php). It is gold-on-dark-navy by
   design; the Day theme's blanket black-text rule turns that gold text
   black, leaving black on near-black. Given an explicit Day pairing
   instead. The .on state keeps white text because it sits on the solid
   accent fill, which the blanket rule would otherwise black out. ── */
html.theme-light #pgnoteFab {
  background: var(--field-bg) !important;
  border: 1px solid var(--border) !important;
}
html.theme-light #pgnoteFab, html.theme-light #pgnoteFab * { color: var(--text) !important; }
html.theme-light #pgnoteFab.on { background: var(--accent) !important; }
html.theme-light #pgnoteFab.on, html.theme-light #pgnoteFab.on * { color: #fff !important; }
html.theme-light #pgnoteFab .fab-dot,
html.theme-light #pgnoteFab.on .fab-dot { background: currentColor !important; }

/* ── 4d. Error boxes are a SEMANTIC colour, not a surface — mapping them
   to plain white would throw away the "this is an error" signal. Dark
   maroon becomes a light red tint with dark red text instead. The colour
   rule needs the !important + real specificity to beat the blanket
   :where(body *) black-text rule above, which is itself !important. ── */
html.theme-light .err,
html.theme-light [style*="background:#450a0a" i], html.theme-light [style*="background: #450a0a" i],
html.theme-light [style*="background:#3a1010" i], html.theme-light [style*="background: #3a1010" i] {
  background: #fdecea !important;
  border-color: #f3b7b3 !important;
}
html.theme-light .err, html.theme-light .err *,
html.theme-light [style*="background:#450a0a" i] { color: #8c1d18 !important; }

/* ── 4e. clock.php's print-management panel is a solid brand purple; the
   Day equivalent is the soft accent wash, not white. ── */
html.theme-light .printing-manage,
html.theme-light [style*="background:#3d2b85" i], html.theme-light [style*="background: #3d2b85" i] {
  background: var(--accent-soft-bg) !important;
  border-color: var(--border) !important;
}

/* ============================================================
   DAY THEME, ROUND 5 — added 2026-08-14, per Mr T
   ("this pop up also dark for day theme" + "also hard to see
   the address lines to input").

   TWO ROOT CAUSES, both blind spots of the round-1..4 mechanisms.

   ── 1. Styles set from JavaScript via element.style.cssText ──
   lib/idle_timeout.js builds the "We kept what you had typed
   before you were signed out." restore bar with:

       bar.style.cssText = '...background:#1e1e35;...'

   Assigning cssText goes through the CSSOM, and the browser
   SERIALISES the result back into the style attribute in its own
   canonical form — the attribute ends up reading
   `background: rgb(30, 30, 53);`, NOT `background:#1e1e35`.
   Every `[style*="background:#..."]` rule in rounds 1-4 therefore
   misses it, permanently, no matter how many hex values are
   enumerated. The sibling warning modal and the draft "View"
   modal in the same file are built with innerHTML instead, where
   the hex survives verbatim in the attribute, which is exactly
   why those two already themed correctly and the bar did not.

   LESSON: the inline-hex attribute list can only ever catch
   styles written in the HTML source. Anything painted by
   JavaScript needs a real id/class hook. idle_timeout.js was
   given two ids (#pidDraftBar, #pidDraftModal) so this block can
   reach it; that edit is purely additive and changes no
   behaviour.

   ── 2. <input> elements with no type="" attribute ──
   The shared form-field rule near the top of this file matches
   input[type="text"], input[type="email"], … — an ATTRIBUTE
   selector, which does not match an element that omits the
   attribute entirely. `<input class="ship-in">` defaults to
   type=text for the browser but is invisible to that selector.
   The twelve Bill To / Ship To address boxes on estimate_form.php
   and invoice_form.php are exactly that, and their page-local
   .ship-in class paints them background:rgba(255,255,255,.04)
   with a border of rgba(255,255,255,.09) — white-on-dark values
   that vanish completely on a white Day-mode page, leaving what
   looks like plain text with no box to click into.

   This same trap was already patched by hand once (see the
   .stage-table rule for deal_stages.php above). `input:not([type])`
   closes it globally so it cannot come back a third time.

   Scoped entirely to html.theme-light — Dark / Pink / Green /
   Blue are byte-for-byte unaffected.
   ============================================================ */

/* ── 5a. The idle-timeout pop-ups (lib/idle_timeout.js). The two
   overlay scrims are deliberately left dark, same reasoning as
   round 4: the dim backdrop is what makes a modal read as a
   modal. Only the panels themselves are relit. ── */
html.theme-light #pidDraftBar,
html.theme-light #pidDraftModal > div,
html.theme-light #pidIdleWarn > div {
  background: var(--surface-2) !important;
  border-color: var(--border) !important;
  box-shadow: 0 16px 44px rgba(0,0,0,.18) !important;
}

/* Row dividers inside the "View" list were rgba(255,255,255,.07),
   i.e. white lines on a now-white panel. */
html.theme-light #pidDraftModal [style*="border-bottom"] {
  border-bottom-color: var(--border) !important;
}

/* ── 5b. Buttons. The blanket `:where(body *) { color:var(--text) }`
   rule turns ALL text black in Day mode, which blacks out the
   white label sitting on these solid purple/blue gradient
   buttons. Same exception pattern as #pgnoteFab.on in round 4. ── */
html.theme-light #pidDraftView,
html.theme-light #pidDraftClose,
html.theme-light #pidIdleStay {
  color: #fff !important;
}
html.theme-light #pidDraftX,
html.theme-light #pidIdleOut {
  color: var(--text-dim) !important;
  background: var(--field-bg) !important;
  border-color: var(--border) !important;
}
/* The countdown number is amber-on-dark by design; plain black
   would throw away the "this is a warning" signal, so it gets a
   dark amber that stays readable on a light panel. */
html.theme-light #pidIdleCount { color: #b45309 !important; }

/* ── 5c. Form fields that carry no type="" attribute, so the
   shared input[type="…"] rule above can never match them.
   .ship-in is named explicitly as well as covered by the
   :not([type]) rule, because it is the reported case and should
   stay obvious to the next person reading this file. The border
   is written as the full shorthand, not border-color alone — a
   bare input may have no border-style declared at all, and
   border-color on its own then renders nothing (the same lesson
   as round 3's table dividers). ── */
html.theme-light .ship-in,
html.theme-light input:not([type]) {
  background: var(--field-bg) !important;
  border: 1px solid var(--field-border) !important;
  color: var(--text) !important;
}
html.theme-light .ship-in::placeholder,
html.theme-light input:not([type])::placeholder {
  color: var(--text-faint) !important;
}

/* ============================================================
   DAY THEME, ROUND 5.1 — added 2026-08-14, same day, after
   Mr T uploaded round 5 and reported "still show dark".

   HE WAS RIGHT, AND THE UPLOAD WAS FINE. Verified live on
   erppid.com: `/custom.css` was serving 58,262 B and DID contain
   the ROUND 5 block, `/lib/idle_timeout.js` was serving 13,759 B
   and DID contain `bar.id = 'pidDraftBar'`. Both files were on
   the server, correct, and the round-5 rule was present in the
   stylesheet the page had parsed.

   The bar was still dark because the PAGE was not running the
   new JavaScript. `_sidebar.php` loads it as:

       /lib/idle_timeout.js?v=1

   That version parameter was never bumped, so every browser —
   and `sw.js`, the service worker, which keeps its own copy —
   goes on serving the OLD file from cache. The old file does not
   set `bar.id`, so the round-5 `#pidDraftBar` rule had nothing to
   attach to. Confirmed by reading the live DOM: the bar element
   carried NO id while the CSS rule for it was sitting in the
   parsed stylesheet, unused.

   The obvious fix — bump `?v=1` to `?v=2` — means uploading
   `_sidebar.php`, and 🔴 THE LOCAL COPY OF THAT FILE IS STALE:
   it predates ERP_THEMES and would silently delete Pink, Green
   and Blue for every user. Not worth it for a cache bust.

   So this block reaches the bar WITHOUT needing the JavaScript at
   all, using :has() to identify it by the button it contains:

       body > div:has(> #pidDraftView)

   `#pidDraftView`, `#pidDraftX` and `#pidDraftClose` are written
   into innerHTML, so they exist in the OLD cached file too — only
   the bar's own container ever needed the new id. :has() is
   supported in Chrome/Edge/Safari and Firefox 121+, and was
   confirmed live with CSS.supports() before shipping this.

   The round-5 `#pidDraftBar` / `#pidDraftModal` rules above are
   deliberately KEPT. They are the cleaner hook and they take over
   by themselves whenever the JS cache does eventually turn over.
   Belt and braces on purpose: these two mechanisms cost nothing
   and between them there is no cache state that shows a dark bar.

   LESSON: shipping a JS file is not the same as shipping a JS
   CHANGE. If a script is loaded with a `?v=` parameter, the file
   on the server is irrelevant until that number changes. Prefer a
   CSS-only fix whenever the version parameter lives in a file you
   cannot safely upload.
   ============================================================ */

html.theme-light body > div:has(> #pidDraftView) {
  background: var(--surface-2) !important;
  border-color: var(--border) !important;
  box-shadow: 0 16px 44px rgba(0,0,0,.18) !important;
}
html.theme-light div:has(> #pidDraftClose) {
  background: var(--surface-2) !important;
  border-color: var(--border) !important;
}
html.theme-light div:has(> #pidDraftClose) > div[style*="border-bottom"] {
  border-bottom-color: var(--border) !important;
}

/* ============================================================
   DAY THEME, ROUND 6 — added 2026-08-28, per Mr T
   ("THEME 에 아직도 칼라가 적용이 안되는 곳이 있네", screenshots of
   ladder_game.php's How-to-play box and sales_reports.php staying dark).

   TWO separate causes were found, and this file can only fix the second one.

   CAUSE 1 (fixed in PHP, not here): 23 pages that `require _sidebar.php`
   never linked this stylesheet at all, so the whole Appearance picker —
   theme, font size, font family — was inert on them. sales_reports.php was
   one of them; that is why its screenshot is fully dark while ladder_game.php
   (which does link it) is light with only one dark box. The missing
   `<link rel="stylesheet" href="/custom.css">` was added to the 11
   user-facing ones. ⚠️ If a new page is ever added without that link, no
   amount of CSS here can reach it — check the link first, always.

   CAUSE 2 (this block): the same gap round 2 closed in 2026-07-18 has
   reopened. Round 2 scanned ~220 PHP files and registered 145 page-local
   class names; the app is now 323 files, and the pages added since brought
   their own class names with hardcoded dark hexes. Re-scanned all 323 files
   (ignoring `var(--x, #fallback)` forms, which are already correct) and
   found 105 more dark-surface selectors. This block covers them.

   Severity is the same as every round before it: `html.theme-light
   :where(body *){color:var(--text)!important}` forces all text black, so a
   surface this file misses renders BLACK TEXT ON NEAR-BLACK NAVY.

   ⚠️ NOT touched, deliberately — same two exceptions as rounds 4 and 5:
     - the `rgba(0,0,0,.55–.86)` modal scrims (41 of them). The dim backdrop
       is what makes a modal read as a modal; whitening them floods the page.
     - solid semantic buttons (red delete/terminate). They keep their red and
       get white text back instead, because a red button is a signal, not a
       surface.

   ⚠️ STILL OPEN after this round: ~250 selectors whose background is a
   low-alpha white (`rgba(255,255,255,.03–.12)`). On a white page these lose
   their boundary — the box goes invisible but the text stays black and
   readable, so it is a cosmetic problem, not the unreadable one. Left for a
   round 7 so this round stays verifiable.
   ============================================================ */

/* 6a — page-local panels, cards, boxes and popovers → the card surface.
   `.sec` alone was NOT covered: round 2 registered `.btn.sec`, and a
   two-class compound cannot match an element carrying only one of them. */
html.theme-light .sec,           html.theme-light .tp-box,
html.theme-light .holders,       html.theme-light .ws-answer,
html.theme-light .ws-source,     html.theme-light .cpfix,
html.theme-light .bundle-card,   html.theme-light .add-form,
html.theme-light #pvBox,         html.theme-light #pvStage,
html.theme-light .ladder-wrap,   html.theme-light .howto,
html.theme-light .res-card,      html.theme-light .selbar,
html.theme-light .progress-wrap, html.theme-light .progress-card,
html.theme-light .block,         html.theme-light .add-block,
html.theme-light #agendaBox,     html.theme-light .agenda-tasks,
html.theme-light .tool-card,     html.theme-light .ne-pop,
html.theme-light .ne-src,        html.theme-light .ne-ipop,
html.theme-light .filter-bar,    html.theme-light table.pl-tbl,
html.theme-light #custPick,      html.theme-light .prop,
html.theme-light .stat,          html.theme-light .bar,
html.theme-light .note,          html.theme-light .box,
html.theme-light .vp-panel,      html.theme-light .vp-card,
html.theme-light #drawer,        html.theme-light #sketchCard,
html.theme-light .wbar,          html.theme-light .scard,
html.theme-light #saPanel,       html.theme-light #saPanelHead,
html.theme-light .sa-frame,      html.theme-light .tab,
html.theme-light .pp-list .pp-add, html.theme-light .part .ph,
html.theme-light.deals-tall .col-head,
html.theme-light .fp-canvas,     html.theme-light .vcb,
html.theme-light .ra-of.ra-open {
  background: var(--surface) !important;
  border-color: var(--border) !important;
}

/* 6b — secondary / "ghost" buttons that were dark chips. --field-bg keeps
   them reading as a button next to the accent-coloured primary, which a
   plain white fill would not. */
html.theme-light .btn-csv,  html.theme-light .btn-oa,
html.theme-light .agm-b,    html.theme-light .board-nav-btn,
html.theme-light button.ghost, html.theme-light .print-bar a.ghost {
  background: var(--field-bg) !important;
  border: 1px solid var(--field-border) !important;
  color: var(--text) !important;
}

/* 6c — form fields. Full `border` shorthand, not border-color: round 5
   learned that a bare field may declare no border-style at all, and
   border-color alone then draws nothing. */
html.theme-light textarea.notes,  html.theme-light .bom-pick-list,
html.theme-light .ctype-sel,      html.theme-light input[type=text].ip,
html.theme-light select.ip,       html.theme-light textarea.ip,
html.theme-light .pk-search,      html.theme-light .ac,
html.theme-light #poSearch,       html.theme-light #custPickInput,
html.theme-light select.task-st,  html.theme-light select.st {
  background: var(--field-bg) !important;
  border: 1px solid var(--field-border) !important;
  color: var(--text) !important;
}
html.theme-light textarea.notes::placeholder,
html.theme-light .pk-search::placeholder,
html.theme-light #poSearch::placeholder,
html.theme-light #custPickInput::placeholder { color: var(--text-faint) !important; }

/* 6d — code / JSON / raw-body blocks. --surface-2 rather than white so the
   block still reads as "quoted material" on a white page. */
html.theme-light code,        html.theme-light textarea.jsonbox,
html.theme-light .codebox,    html.theme-light .body-box,
html.theme-light .rec-card,   html.theme-light .v-note {
  background: var(--surface-2) !important;
  border-color: var(--border) !important;
}

/* 6e — semantic status tints. These are NOT surfaces: a green "OK" box and a
   red "BAD" box carry meaning, so they become light tints of the same hue
   instead of white, with text dark enough to read on them (all ≥ 7:1).
   Same reasoning as round 4d's `.err` treatment. */
html.theme-light .p-ok, html.theme-light .v-ok, html.theme-light .ro,
html.theme-light .aiem-conf.high {
  background:#e8f5ec !important; border-color:rgba(20,83,45,.28) !important;
  color:#14532d !important;
}
html.theme-light .p-warn, html.theme-light .warn,
html.theme-light .aiem-conf.medium {
  background:#fdf3e3 !important; border-color:rgba(124,74,3,.28) !important;
  color:#7c4a03 !important;
}
html.theme-light .p-bad, html.theme-light .v-bad,
html.theme-light .aiem-conf.low {
  background:#fdecea !important; border-color:rgba(140,29,24,.28) !important;
  color:#8c1d18 !important;
}

/* 6f — solid red action buttons and the dark tooltip keep their own colour;
   only the label is given back. The blanket black-text rule was painting
   these labels black on red / black on near-black. Round 5b did the same for
   #pidDraftView and #pidIdleStay. */
html.theme-light .terr,    html.theme-light .btn-co,
html.theme-light .btn-red, html.theme-light #ccOk,
html.theme-light #cdOk,    html.theme-light .icon-btn.rec,
html.theme-light #ra-tip {
  color:#ffffff !important;
}

/* 6g — button.primary was #111 on wp_credentials_setup.php: a black fill
   whose white label the blanket rule turned black. A primary button in a
   light theme belongs on the accent, not on white — mapping it to the
   surface would have made it indistinguishable from a ghost button. */
html.theme-light button.primary {
  background: var(--accent) !important;
  border-color: var(--accent) !important;
  color: #ffffff !important;
}

/* ============================================================
   MOBILE ROUND 2 — 2026-09-04
   Every rule below fixes a cause measured at a real 390px viewport,
   not a guess. Before → after numbers are in the comments.
   All of it lives inside @media (max-width:768px): the desktop is untouched.
   ============================================================ */
@media (max-width: 768px) {

    /* ── 20. Nothing may push the page sideways ──
       Root cause: `width: fit-content` on flex bars (clock.php `.tabs`) leaves
       rule 10's overflow-x:auto with no width to clamp to. clock.php 1,034px → 0. */
    .tabs, .nav-tabs, .tab-row, .seg-tabs {
        width: auto !important; max-width: 100% !important; min-width: 0 !important;
    }
    .main [style*="fit-content"], .page-wrap [style*="fit-content"] { max-width: 100% !important; }

    /* ── 21. Action bars wrap instead of running off the edge ──
       estimate_form.php 108px → 0. The offender was `.tb-right` (top bar), not the
       bottom bar — worth knowing before "fixing" the bottom bar again. */
    .top-bar, .tb-left, .tb-right, .bb-left, .bb-right,
    .doc-bottom, .doc-bottom-left, .doc-bottom-right, .hdr-right, .actions {
        flex-wrap: wrap !important; min-width: 0 !important; max-width: 100% !important;
    }
    .bottom-bar {
        left: 0 !important; padding: 8px 12px !important;
        height: auto !important; min-height: 60px;
        flex-wrap: wrap !important; gap: 8px !important;
    }

    /* ── 22. Month grids scroll inside themselves ── calendars.php 517px → 0. */
    .month-grid, .cal-grid, .calendar-grid {
        overflow-x: auto !important; max-width: 100% !important;
        -webkit-overflow-scrolling: touch;
    }

    /* ── 23. Let list tables wrap ──
       The nowrap at the top of this file is what made the Floor Plans table
       1,822px wide on a 390px screen; wrapping brings it to 1,042px. Calendar and
       clock grids keep nowrap — they are laid out, not tabular. */
    .main table td, .main table th,
    .page-wrap table td, .page-wrap table th { white-space: normal !important; }
    .month-grid td, .month-grid th,
    .cal-grid td, .cal-grid th { white-space: nowrap !important; }

    /* ── 24. A bar that is allowed to wrap must be allowed to GROW ──
       2026-09-04. Rule 21 above turned horizontal overflow into vertical
       overflow and stopped there. estimate_form.php pins `.top-bar` to
       height:54px; once `.tb-right` wrapped, 444px of content had to live in a
       54px box, so it painted straight over the form (measured at 411px:
       .doc-meta 183px + .tb-right 294px). Rule 21 gave `.bottom-bar`
       height:auto but never gave it to `.top-bar` — this is that missing half,
       and it applies to every page with a pinned bar height, not just this one.
       Bars keep vertical centring; only the fixed height goes. */
    .top-bar, .tb-left, .tb-right, .bb-left, .bb-right,
    .hdr-right, .actions, .toolbar, .action-bar {
        height: auto !important;
    }
}
/* ============================================================
   PID-MODAL-VIEWPORT-FIT
   25. POPUPS MUST FIT THE SCREEN WHEN THE FONT-SIZE SLIDER IS ON
   2026-09-08 — Mr T: "보기가 좀 불편하네 화면 싸이즈에 맞게 pop up 이 나오게 해줘"
   (delivery.php "Schedule Delivery" modal ran off the bottom of the screen).

   Cause, measured live on erppid.com/delivery.php at font-z120:
   the font-size slider works by `html.font-z### body { zoom: … }`. CSS `zoom`
   scales everything the element paints, but `vh` still resolves against the
   UNZOOMED viewport. So `.modal{max-height:92vh}` computed 0.92 × 911px =
   838px of layout and painted it at 838 × 1.2 = 1,006px — 95px TALLER than
   the 911px screen. Modal top was -17px, bottom 989px: the title bar and the
   Save button were both off-screen and the body could not scroll to them.
   Nothing was broken in delivery.php — every `vh` popup on the ERP has this,
   it just shows up first on the tallest form.

   Fix: cap the panel against its OVERLAY. The overlay is `position:fixed;
   inset:0`, so `100%` of it is already in the same zoomed coordinate space
   and needs no zoom math. Verified fitting at z80 / z100 / z120 / z130 / z150.
   `--pid-zoom` carries the same factor for any future rule that still needs a
   real viewport figure: `calc(92vh / var(--pid-zoom))`.

   Covers .modal-overlay pages — delivery.php, delivery_warehouse.php,
   calendars.php, customer_transactions.php, products.php,
   lib/product_quick_add.php — and media.php / color_library.php through the
   plain `.modal` rule (their overlay markup is named differently).
   AMENDMENT 2026-09-08: `overflow-y:auto` added on the same two rules.
   card_expenses.php's `.modal` is display:block with no inner scroller — a
   cap alone made its last 115px paint outside the box with no way to reach
   it. Panels that already scroll an inner `.modal-body` never overflow, so
   the extra scroller is inert for them.
   ============================================================ */
:root { --pid-zoom: 1; }
html.font-large  { --pid-zoom: 1.15; }
html.font-xlarge { --pid-zoom: 1.3; }
html.font-z80  { --pid-zoom: .8; }
html.font-z85  { --pid-zoom: .85; }
html.font-z90  { --pid-zoom: .9; }
html.font-z95  { --pid-zoom: .95; }
html.font-z100 { --pid-zoom: 1; }
html.font-z105 { --pid-zoom: 1.05; }
html.font-z110 { --pid-zoom: 1.1; }
html.font-z115 { --pid-zoom: 1.15; }
html.font-z120 { --pid-zoom: 1.2; }
html.font-z125 { --pid-zoom: 1.25; }
html.font-z130 { --pid-zoom: 1.3; }
html.font-z135 { --pid-zoom: 1.35; }
html.font-z140 { --pid-zoom: 1.4; }
html.font-z145 { --pid-zoom: 1.45; }
html.font-z150 { --pid-zoom: 1.5; }

.modal-overlay { box-sizing: border-box; }
.modal-overlay > .modal { max-height: 100% !important; overflow-y: auto; }
.modal { max-height: calc(92vh / var(--pid-zoom, 1)) !important; overflow-y: auto; }

/* ============================================================
   PID-MODAL-VIEWPORT-FIT-2
   26. RULE 25, APPLIED TO EVERY OTHER POPUP NAME ON THE ERP
   2026-09-08 — Mr T: "i just fixed pop up size but it is not fixed for deal
   pop up. can you check one more time all pop ups are fixed."
   (deal_view.php → email compose → "Manage templates": the panel ran off the
   bottom exactly like delivery.php did.)

   Rule 25 above only named `.modal-overlay > .modal` and `.modal`. A scan of
   the whole docroot found 34 different names for the same thing — every page
   that grew its own popup markup picked its own class. The ones below are the
   ones a script confirmed are `position:fixed` AND cover the whole viewport
   (`inset:0`, or top+left+right/width and bottom/height all pinned), so
   `100%` of them is the screen — in the SAME zoomed coordinate space as the
   panel inside, which is what makes this need no `vh` math at all.

   Deliberately NOT capped: fixed elements that are not full-screen (toasts,
   bulk/print/bottom bars, FABs, side drawers, tooltips, `.cpanel`, `.vp-panel`,
   `.g-composer`) — capping those to their own height would clip real content;
   and full-screen drawing surfaces (`#sketchWrap`, floorplan's `.kp`/`.pad`)
   plus pure backdrops (`.sb-overlay`, `.drop-veil`, `.g-mask`, `.g-qsmask`)
   where the panel is a SIBLING of the veil, not a child.

   Known trade-off, same as rule 25: `overflow-y:auto` makes the panel a scroll
   container, so an absolutely-positioned dropdown that wants to paint outside
   the panel gets clipped instead. Panels that already scroll an inner body
   never overflow, so for them this is inert.
   ============================================================ */
.ann-overlay, .cpanel-overlay, .detail-overlay, .drawer-bg, .edit-overlay,
.em-modal-ov, .em-overlay, .files-modal-overlay, .fp-overlay, .lb-overlay,
.lightbox, .mail-compose-overlay, .mbg, .mod-ov, .modal-back, .modal-bg,
.modal-ov, .modal-overlay, .mp-overlay, .overlay, .ovl, .rev, .tp-bg,
.view-overlay, .vp-overlay { box-sizing: border-box; }

.ann-overlay > *, .cpanel-overlay > *, .detail-overlay > *, .drawer-bg > *,
.edit-overlay > *, .em-modal-ov > *, .em-overlay > *, .files-modal-overlay > *,
.fp-overlay > *, .lb-overlay > *, .lightbox > *, .mail-compose-overlay > *,
.mbg > *, .mod-ov > *, .modal-back > *, .modal-bg > *, .modal-ov > *,
.modal-overlay > *, .mp-overlay > *, .overlay > *, .ovl > *, .rev > *,
.tp-bg > *, .view-overlay > *, .vp-overlay > * {
    max-height: 100% !important;
    overflow-y: auto;
}
/* An image inside a lightbox must keep its aspect ratio, not scroll. */
.lightbox > img, .lb-overlay > img { overflow: visible !important; height: auto !important; }

/* ============================================================
   PID-MODAL-VIEWPORT-FIT-3
   27. THE POPUPS RULE 26 STILL COULD NOT SEE
   2026-09-08, same request. Rules 25-26 name CSS CLASSES, so they miss two
   kinds of popup:
     (a) panels positioned by an INLINE style="position:fixed;inset:0" in the
         markup — there is no class to hook, only an id;
     (b) panels built in JS by the shared sidebar (#cdOverlay customer detail,
         #favModalOverlay favourites) which appear on EVERY page.
   Found by stress-testing live: force each fixed full-screen overlay open at
   font-z150, drop a 3000px spacer inside its panel, and see whether the panel
   still ends inside the screen. The ones below did not.

   Two nets, on purpose:
     - the id list caps whatever the panel is (several are anonymous <div>s);
     - the panel-class list (.modal-box/.modal-card/.modal-inner/.cd-panel/
       .fav-panel/.cc-panel) catches the same panels wherever else they are
       reused, using the zoom-corrected vh from rule 25 so it works even when
       the panel is NOT inside a full-screen overlay.
   ============================================================ */
#calEditModal, #ccOverlay, #ccOverlay2, #cdOverlay, #custDealModal, #erpModal,
#evInfoModal, #favModalOverlay, #gEvInfoModal, #gsOverlay, #libBrowseModal,
#libSaveModal, #mergeModal, #mgrEditBg, #payModal, #pgInsertModal,
#photoLightbox, #pidEmailModal, #shareBack, #tplModal, #vDelModal,
#verSaveOverlay { box-sizing: border-box; }

#calEditModal > *, #ccOverlay > *, #ccOverlay2 > *, #cdOverlay > *,
#custDealModal > *, #erpModal > *, #evInfoModal > *, #favModalOverlay > *,
#gEvInfoModal > *, #gsOverlay > *, #libBrowseModal > *, #libSaveModal > *,
#mergeModal > *, #mgrEditBg > *, #payModal > *, #pgInsertModal > *,
#photoLightbox > *, #pidEmailModal > *, #shareBack > *, #tplModal > *,
#vDelModal > *, #verSaveOverlay > * {
    max-height: 100% !important;
    overflow-y: auto;
}
/* A lightbox image scales, it does not scroll. */
#photoLightbox > img { overflow: visible !important; height: auto !important; }

/* Same cap, expressed against the real viewport, for these panels wherever
   they are used. `--pid-zoom` comes from rule 25. */
.modal-box, .modal-card, .modal-inner, .cd-panel, .fav-panel, .cc-panel {
    max-height: calc(92vh / var(--pid-zoom, 1)) !important;
    overflow-y: auto;
}

/* ============================================================
   PID-MODAL-VIEWPORT-FIT-4
   28. THE CAP HAS TO INCLUDE THE PADDING — and must not trust the overlay
   2026-09-08, same session as 26/27. Measured on calendars.php at font-z150:
   #calEditModal is exactly 911px (the screen), its .modal-box had
   max-height:100% applied and STILL painted 966px. Cause: that panel is
   `box-sizing: content-box`, so `max-height` caps the CONTENT box and the
   panel's own padding + border (55px there) are added on top. Every page with
   a global `*{box-sizing:border-box}` reset was already fine, which is why
   only two pages failed the sweep — the rule was right, the box model was not.

   Also switched from `100%` to `min(100%, 92vh/zoom)`: `100%` is only
   trustworthy when the overlay itself is pinned top AND bottom. An overlay
   pinned top/left/right with height:auto grows with its content, and then
   `100%` of it is whatever the panel already is — no cap at all.

   Same list as 26 + 27, so this block is the one that actually decides the
   height; the earlier two stay for their comments and their box-sizing on the
   overlay itself.
   ============================================================ */
.ann-overlay > *, .cpanel-overlay > *, .detail-overlay > *, .drawer-bg > *,
.edit-overlay > *, .em-modal-ov > *, .em-overlay > *, .files-modal-overlay > *,
.fp-overlay > *, .lb-overlay > *, .lightbox > *, .mail-compose-overlay > *,
.mbg > *, .mod-ov > *, .modal-back > *, .modal-bg > *, .modal-ov > *,
.modal-overlay > *, .mp-overlay > *, .overlay > *, .ovl > *, .rev > *,
.tp-bg > *, .view-overlay > *, .vp-overlay > *,
#calEditModal > *, #ccOverlay > *, #ccOverlay2 > *, #cdOverlay > *,
#custDealModal > *, #erpModal > *, #evInfoModal > *, #favModalOverlay > *,
#gEvInfoModal > *, #gsOverlay > *, #libBrowseModal > *, #libSaveModal > *,
#mergeModal > *, #mgrEditBg > *, #payModal > *, #pgInsertModal > *,
#photoLightbox > *, #pidEmailModal > *, #shareBack > *, #tplModal > *,
#vDelModal > *, #verSaveOverlay > *,
.modal, .modal-box, .modal-card, .modal-inner, .cd-panel, .fav-panel, .cc-panel {
    box-sizing: border-box !important;
    max-height: min(100%, calc(92vh / var(--pid-zoom, 1))) !important;
    overflow-y: auto;
}
/* Images scale, they do not scroll. */
#photoLightbox > img, .lightbox > img, .lb-overlay > img {
    overflow: visible !important; height: auto !important;
}

/* ============================================================
   DAY THEME, ROUND 7 — added 2026-09-10, per Mr T
   ("new menus last few days … some pages color doesn't change with day
   and pink themes", starting from fun_quote.php).

   Found by a LIVE sweep, not a source scan: 103 menu pages were loaded in
   Mr T's signed-in session inside a hidden iframe, the theme class was
   switched to Day and to Pink, transitions were frozen, and every visible
   element was measured (near-black surface / text contrast < 2.2 against its
   real background). Pink results were identical to Day on every page —
   Pink/Green/Blue all carry `theme-light`, so a Day gap is always a Pink gap.
   Every fix below therefore uses the theme VARIABLES, never Day's own
   white/blue, so Pink stays pink, Green green, Blue blue.

   Scope guarantee: every rule is either `html.theme-light`-scoped, or scoped
   to a class that exists on exactly one page (.pn-* / .dan-* / .cn-* /
   body:has(.agents|.dgrp|.chead)). No other page's Dark look can change.

   ⚠️ Same as round 6 CAUSE 1: six new pages never linked this stylesheet
   (agent_console, deal_drafts, deal_research, payment_notify_settings,
   container_notify_settings, deal_assign_settings). The link was added in the
   PHP; 7f/7g below exist only because those pages can now see this file.
   A new page without `<link rel="stylesheet" href="/custom.css">` is
   unreachable from here — check the link first, always.
   ============================================================ */

/* 7a — REGRESSION from round 6: `html.theme-light .tab` (0,2,1) out-ranks the
   shared `.tab.active` gradient (0,2,0), so the selected tab went white while
   its label stayed #fff — the active tab label vanished on tasks, meetings,
   meeting_threads, clock, calendars, leave, delivery, delivery_warehouse,
   packing_list, sample_list_view and marketing_email. */
html.theme-light .tab.active {
  background: linear-gradient(135deg, var(--accent), var(--accent-2)) !important;
  border-color: transparent !important;
  color: #ffffff !important;
}
html.theme-light .tab.active * { color: #ffffff !important; }
/* bom_manager.php fills its active .tab-btn with the accent, but the shared
   underline-tab rule paints the label --accent-soft-text → pink on pink. */
html.theme-light .tab-btn.active[onclick^="switchBomTab"] { color: #ffffff !important; }

/* 7b — type="search" / type="url" were never in the shared form-field list
   (shows.php + trips.php search box, fun_playlist.php URL box). */
html.theme-light input[type="search"], html.theme-light input[type="url"] {
  background: var(--field-bg) !important;
  border-color: var(--field-border) !important;
  color: var(--text) !important;
}
html.theme-light input[type="search"]::placeholder,
html.theme-light input[type="url"]::placeholder { color: var(--text-faint) !important; }

/* 7c — page-local dark surfaces on the pages added 2026-09-05 → 09-10 */
/* fun_quote.php — `.hero` is also a class on design_basis pages, so it is
   pinned to the page that owns #arcSearch. */
html.theme-light body:has(#arcSearch) .hero {
  background: linear-gradient(160deg, var(--surface) 0%, var(--surface-2) 100%) !important;
  border-color: var(--border) !important;
}
html.theme-light .qcard { background: var(--surface) !important; border-color: var(--border) !important; }
html.theme-light .qcard:hover { background: var(--surface-2) !important; border-color: var(--border-strong) !important; }
html.theme-light .qcard.is-today { background: var(--accent-soft-bg) !important; border-color: var(--accent) !important; }
html.theme-light .qcard mark { background: rgba(234,179,8,.30) !important; }
html.theme-light .datepop { background: var(--surface-2) !important; border-color: var(--border) !important; }
html.theme-light .datepop input[type="date"] { color-scheme: light; }

/* fun_fortune.php */
html.theme-light .saju-score, html.theme-light .tm-chip, html.theme-light .wux-chip {
  background: var(--surface-2) !important;
}

/* org_structure.php — background only on the plain node; dept / vacant /
   drag-target nodes keep their own tints, and a selected node keeps its
   highlight border. */
html.theme-light .node:not(.dept-node):not(.vacant):not(.drop-target):not(.drop-bad) {
  background: var(--surface) !important;
}
html.theme-light .node:not(.dept-node):not(.vacant):not(.drop-target):not(.drop-bad):not(.selected) {
  border-color: var(--border-strong) !important;
}
html.theme-light .org-panel { background: var(--surface) !important; border-color: var(--border) !important; }
html.theme-light .n-collapse-btn.active { color: var(--accent-soft-text) !important; }

/* roles.php permission matrix — sticky cells MUST stay opaque or the
   scrolled rows show through them, hence --surface / --surface-2 and
   color-mix() rather than a translucent tint. */
html.theme-light .mx-wrap { background: var(--surface) !important; border-color: var(--border) !important; }
html.theme-light table.mx thead th, html.theme-light table.mx thead td { background: var(--surface-2) !important; }
html.theme-light table.mx .mx-first { background: var(--surface) !important; }
html.theme-light table.mx thead .mx-first { background: var(--surface-2) !important; }
html.theme-light table.mx tr.mx-sec td.mx-first { background: color-mix(in srgb, var(--accent) 12%, var(--surface)) !important; }
html.theme-light table.mx tr.mx-row:hover td.mx-first { background: color-mix(in srgb, var(--accent) 6%, var(--surface)) !important; }
html.theme-light .mx-person { background: var(--field-bg) !important; }
html.theme-light .modal-role-foot.modal-btns { background: var(--surface-2) !important; }

/* sns.php / po_containers.php / data_management.php / estimate_reports.php */
html.theme-light .chan-card { background: var(--surface) !important; border-color: var(--border) !important; }
html.theme-light .chan-card.active { border-color: var(--accent) !important; }
html.theme-light .acct-tile, html.theme-light .bsCard, html.theme-light .kpi > div:has(> .l) {
  background: var(--surface-2) !important;
  border-color: var(--border) !important;
}

/* vendor_emails.php — the two plain (non-primary) buttons */
html.theme-light a.btn[href="vendor_emails.php"], html.theme-light #composeModal .btn:not(.btn-primary) {
  background: var(--field-bg) !important;
  border-color: var(--field-border) !important;
}

/* admin_tools.php — the "🔒 Built-in" badge is painted inline from JS
   innerHTML (hex survives there, see day-theme blind spot #1). */
html.theme-light .badge[style*="#3a3a5a" i] { background: var(--surface-2) !important; }

/* 7d — semantic, not surface: profit_margins.php "no cost on file" warning
   tag becomes the round-6e warn tint instead of white. */
html.theme-light a.tag[title*="no cost"] {
  background: #fdf3e3 !important;
  color: #7c4a03 !important;
}

/* 7e — inventory_count.php group header rows are a deliberate black band
   (the page is a printed count sheet). The band stays; its label comes back. */
html.theme-light tr.grp td, html.theme-light tr.grp td * { color: #ffffff !important; }

/* 7f — Agent Console / AI Drafts / AI Deal Research (agent_console.php,
   deal_drafts.php, deal_research.php) — hardcoded navy cards. */
html.theme-light .agents > .ag, html.theme-light .kpis > .kpi, html.theme-light .dgrp {
  background: var(--surface) !important;
}
html.theme-light .agents > .ag:not(.on), html.theme-light .kpis > .kpi, html.theme-light .dgrp {
  border-color: var(--border) !important;
}
html.theme-light .bodytxt { background: var(--surface-2) !important; border-color: var(--border) !important; }
html.theme-light .ag .sw .track { background: rgba(0,0,0,.18) !important; }
html.theme-light .ag .sw input:checked + .track { background: rgba(34,197,94,.75) !important; }
html.theme-light body:has(.dgrp, .chead) .tabs a { background: var(--field-bg) !important; }
html.theme-light body:has(.dgrp, .chead) .tabs a.on { background: var(--accent-soft-bg) !important; }
html.theme-light body:has(.agents, .dgrp, .chead) #t {
  background: var(--surface-2) !important;
  border-color: var(--border) !important;
}
/* These three pages use `.panel` as a plain content box, but the mobile block
   at the top of this file turns every `.panel` into a slide-up sheet
   (translateY(100%)). Undo that for these pages only. */
@media (max-width: 768px) {
  body:has(.agents, .dgrp, .chead) .panel { transform: none !important; border-radius: 14px !important; }
}

/* 7g — Payment Notifications / Container Notifications / Deal Assignment
   Emails (payment_notify_settings.php, container_notify_settings.php,
   deal_assign_settings.php). Built light-only with no link to this file, so
   they were white with Times New Roman in EVERY theme, Dark included. These
   rules are NOT theme-light-scoped on purpose — the pages must follow Dark
   too — and every selector carries the page's own .pn- / .cn- / .dan- prefix. */
body:has(.pn-wrap), body:has(.dan-wrap) {
  font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, Roboto, sans-serif;
}
.pn-wrap, .dan-wrap, .cn-wrap { color: var(--text) !important; }
.pn-sub, .dan-sub, .cn-sub,
.pn-f small, .dan-f small, .cn-check small,
.pn-kv div:nth-child(odd), .dan-kv div:nth-child(odd), .cn-kv div:nth-child(odd),
.cn-fld label, .cn-users .role,
.pn-card h2, .dan-card h2, .cn-card h2 { color: var(--text-faint) !important; }
.pn-card, .dan-card, .cn-card { background: var(--surface) !important; border-color: var(--border) !important; }
.pn-tbl th, .pn-tbl td, .dan-tbl th, .dan-tbl td, .cn-tbl th, .cn-tbl td { border-color: var(--border) !important; }
.pn-users, .cn-users { border-color: var(--border) !important; }
.pn-btn, .dan-btn, .cn-ghost {
  background: var(--field-bg) !important;
  border-color: var(--field-border) !important;
  color: var(--text) !important;
}
.pn-btn.primary, .dan-btn.primary, .cn-primary {
  background: var(--accent) !important;
  border-color: var(--accent) !important;
  color: #ffffff !important;
}
.pn-wrap a:not([class]), .dan-wrap a:not([class]), .cn-wrap a:not([class]), a.cn-back { color: var(--accent-soft-text); }
/* ON/OFF state words: the page's #059669 / #b91c1c are too dark on a Dark card. */
html:not(.theme-light) .pn-on, html:not(.theme-light) .dan-on, html:not(.theme-light) .cn-on { color: #34d399 !important; }
html:not(.theme-light) .pn-off, html:not(.theme-light) .dan-off, html:not(.theme-light) .cn-off { color: #f87171 !important; }
/* Big ACTIVE / INACTIVE banner: pastel box, so its text must be dark in every theme. */
.dan-big.on, .dan-big.on * { color: #065f46 !important; }
.dan-big.off, .dan-big.off * { color: #991b1b !important; }
/* Email preview is a picture of the email — it stays white paper in every theme. */
.cn-prev { background: #ffffff !important; color: #111827 !important; border-color: #e5e7eb !important; }
.cn-prev-h { background: #f9fafb !important; color: #4b5563 !important; }
.cn-prev td, .cn-prev th, .cn-prev h1, .cn-prev h2, .cn-prev h3 { color: #111827 !important; border-color: #e5e7eb !important; }

/* 7.1 — trip_view.php (Trip planner, added 2026-09-06). Found by the detail-page
   spot check after round 7 went live — the menu sweep cannot open id-only pages.
   `.day` / `.stop` / `.opt` / `.tab` are shared class names (delivery.php,
   delivery_warehouse.php, agent_console.php), so every rule is pinned to the page
   that owns #nearbyPanel. Borders are left alone where a state class (.pool, .on,
   :hover) colours them. */
html.theme-light body:has(#nearbyPanel) .day,
html.theme-light body:has(#nearbyPanel) .nearby,
html.theme-light body:has(#nearbyPanel) .mdl { background: var(--surface) !important; }
html.theme-light body:has(#nearbyPanel) .day:not(.pool),
html.theme-light body:has(#nearbyPanel) .nearby,
html.theme-light body:has(#nearbyPanel) .mdl { border-color: var(--border) !important; }
html.theme-light body:has(#nearbyPanel) .stop,
html.theme-light body:has(#nearbyPanel) .nrow,
html.theme-light body:has(#nearbyPanel) .prev,
html.theme-light body:has(#nearbyPanel) .toast,
html.theme-light body:has(#nearbyPanel) .leaflet-popup-content-wrapper,
html.theme-light body:has(#nearbyPanel) .leaflet-popup-tip { background: var(--surface-2) !important; }
html.theme-light body:has(#nearbyPanel) .opt:not(.on),
html.theme-light body:has(#nearbyPanel) .dchip:not(.on) {
  background: var(--field-bg) !important;
  border-color: var(--field-border) !important;
}
html.theme-light body:has(#nearbyPanel) .tab.on { background: var(--accent-soft-bg) !important; }
