* { box-sizing: border-box; }
body {
    font-family: -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
    margin: 0;
    background: #eef0f4;
    color: #1f2430;
    -webkit-font-smoothing: antialiased;
}
.topnav {
    background: linear-gradient(180deg, #1f2937 0%, #17202e 100%);
    padding: 12px 24px;
    display: flex;
    align-items: center;
    gap: 18px;
    flex-wrap: wrap;
    box-shadow: 0 2px 8px rgba(0,0,0,0.18);
    position: sticky;
    top: 0;
    z-index: 20;
}
.topnav a {
    color: #cbd2e0;
    text-decoration: none;
    font-size: 14px;
    padding: 6px 4px;
    border-bottom: 2px solid transparent;
    transition: color .12s ease, border-color .12s ease;
}
.topnav a:hover { color: #fff; border-color: #3b82f6; }
.topnav .brand {
    font-weight: 700;
    font-size: 17px;
    color: #fff;
    margin-right: 6px;
    display: flex;
    align-items: center;
    gap: 10px;
    border-bottom: none;
    letter-spacing: .01em;
}
.logo-chip { background: #fff; border-radius: 7px; padding: 4px 8px; display: inline-flex; align-items: center; box-shadow: 0 1px 3px rgba(0,0,0,0.25); }
.logo-chip img { height: 22px; width: auto; display: block; }

/* Which Data Profile (see database.py) is currently loaded - always visible
   in the nav so Test data and Live data never get mixed up by accident. */
.profile-badge {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    padding: 4px 9px;
    border-radius: 20px;
    margin-right: 4px;
}
.profile-badge.profile-test { background: #78350f; color: #fde68a; }
.profile-badge.profile-live { background: #14532d; color: #bbf7d0; }

.nav-search { margin-left: auto; }
.nav-search input {
    background: rgba(255,255,255,0.1);
    border: 1px solid rgba(255,255,255,0.18);
    border-radius: 7px;
    padding: 6px 10px;
    color: #fff;
    font-size: 13px;
    width: 190px;
    transition: background .12s ease, width .15s ease;
}
.nav-search input::placeholder { color: #9aa3b5; }
.nav-search input:focus { background: rgba(255,255,255,0.16); outline: none; width: 230px; }

.container { max-width: 1120px; margin: 0 auto; padding: 30px 20px 70px; }
/* Dashboard only: wider + shorter-padded container so more fits per row on
   a normal monitor without the rest of the app (forms, print docs) getting
   stretched out too. */
.container.container-wide { max-width: 1600px; padding: 14px 24px 18px; }

.flash {
    background: #eff6ff;
    border: 1px solid #bfdbfe;
    border-left: 4px solid #2563eb;
    padding: 12px 16px;
    border-radius: 8px;
    margin-bottom: 20px;
    color: #1e3a8a;
}
.flash p { margin: 2px 0; }

h1 { font-size: 25px; margin-bottom: 4px; letter-spacing: -.01em; color: #111827; }
h2 { font-size: 17px; margin-top: 22px; color: #1f2937; letter-spacing: -.005em; }

.dashboard-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 16px;
    margin-top: 20px;
}
.dashboard-grid.big { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 18px; }
.card {
    background: #fff;
    border: 1px solid #e5e7eb;
    border-radius: 12px;
    padding: 18px 20px;
    box-shadow: 0 1px 3px rgba(16,24,40,0.06);
    transition: box-shadow .15s ease;
}
.card.big { padding: 24px 26px; border-radius: 16px; box-shadow: 0 2px 8px rgba(16,24,40,0.08); position: relative; }
.card-link { display: block; text-decoration: none; color: inherit; transition: transform .12s ease, box-shadow .12s ease; cursor: pointer; }
.card-link:hover { transform: translateY(-3px); box-shadow: 0 10px 22px rgba(16,24,40,0.12); border-color: #bfdbfe; }
.card-icon { font-size: 26px; margin-bottom: 8px; }
.card .label { font-size: 12px; color: #6b7280; text-transform: uppercase; letter-spacing: .06em; font-weight: 600; }
.card.big .label { font-size: 13px; }
.card .value { font-size: 28px; font-weight: 700; margin-top: 6px; color: #111827; }
.card.big .value { font-size: 36px; margin-top: 8px; }
.card .sub { font-size: 13px; color: #6b7280; margin-top: 4px; }
.card.big .sub { font-size: 14px; margin-top: 6px; }
.card.warn .value { color: #b45309; }
.card.money .value { color: #047857; }

.stage-row { display: flex; align-items: center; gap: 14px; padding: 9px 0; }
.stage-name { width: 220px; font-size: 14px; color: #374151; flex-shrink: 0; font-weight: 500; }
.stage-bar-track { flex: 1; background: #eef0f4; border-radius: 6px; height: 15px; overflow: hidden; }
.stage-bar-fill { background: linear-gradient(90deg, #2563eb, #3b82f6); height: 100%; border-radius: 6px; transition: width .3s ease; }
.stage-count { width: 32px; text-align: right; font-weight: 700; font-size: 14px; color: #1f2937; }

/* Dashboard: a wider left/main column and a narrower right/sidebar column
   (e.g. Upcoming This Week + Recent Jobs on the left, Jobs by Stage on the
   right) - stacks to one column on narrow screens instead of squeezing. */
.dashboard-columns {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 14px;
    align-items: start;
    margin-top: 14px;
}
/* Grid columns default to a min-width that fits their widest content, which
   would otherwise let something wide inside (a table, a long unbroken word)
   push the column - and the whole page on a phone - wider than intended. */
.dashboard-columns > * { min-width: 0; }
@media (max-width: 860px) {
    .dashboard-columns { grid-template-columns: 1fr; }
}
/* Jobs by Stage reads tighter in the narrow sidebar than its full-width form */
.dashboard-col-narrow .stage-name { width: auto; font-size: 12.5px; }
.dashboard-col-narrow .stage-row { gap: 8px; }
.dashboard-col-narrow .stage-count { width: 24px; font-size: 13px; }

/* Month-to-Date vs Year-to-Date Profit & Loss, side by side */
.pl-compare { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; margin-top: 10px; }
.pl-compare-col h3 { margin: 0 0 8px; font-size: 14px; color: #374151; }
.pl-line { display: flex; justify-content: space-between; padding: 5px 0; font-size: 14px; border-bottom: 1px solid #f3f4f6; }
.pl-line.total { font-weight: 700; border-bottom: none; border-top: 1px solid #e5e7eb; margin-top: 4px; padding-top: 8px; }
.pl-line .amt.profit-positive, .profit-positive { color: #047857; }
.pl-line .amt.profit-negative, .profit-negative { color: #b91c1c; }

/* Upcoming This Week list */
.upcoming-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid #f3f4f6; font-size: 14px; }
.upcoming-row:last-child { border-bottom: none; }
.upcoming-date { width: 90px; flex-shrink: 0; font-weight: 600; color: #374151; font-size: 13px; }
.upcoming-type { flex-shrink: 0; }
.upcoming-detail { color: #6b7280; font-size: 13px; }
/* min-width:0 lets this shrink below its content's natural width instead of
   forcing the row (and the whole page, on a phone) wider than the screen -
   a long unbroken job number like "LakeJohannaFireDepatment-2025-001" would
   otherwise blow out the row's width. overflow-wrap lets that same long job
   number actually wrap onto a second line instead of overflowing sideways. */
.upcoming-main { flex: 1; min-width: 0; overflow-wrap: break-word; }

/* Groups related section-boxes together on longer pages (currently the Job
   page) so it reads as organized sections instead of one long undifferentiated
   scroll - purely a visual label between groups, doesn't change any layout. */
.group-divider {
    margin: 26px 0 6px;
    padding-top: 14px;
    border-top: 2px solid #dbe1ea;
    font-size: 13px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: #475569;
}
.dashboard-compact .group-divider { margin: 16px 0 2px; padding-top: 8px; font-size: 11.5px; }

/* ------------------------------------------------------------------
   Dashboard compact mode: a denser version of cards/sections/tables used
   ONLY on the Dashboard page (see .dashboard-compact wrapper), aimed at
   fitting everything on one screen on a normal monitor without scrolling.
   Boxes that could grow long over time (Upcoming, Recent Jobs) get their
   own internal scrollbar instead of pushing the page taller, so nothing
   is ever hidden - just scrolled to within its own compact box.
   ------------------------------------------------------------------ */
.dashboard-compact h1 { font-size: 20px; margin-bottom: 1px; }
.dashboard-compact .job-header { margin-bottom: 2px; }
.dashboard-compact h2 { font-size: 14px; margin-top: 10px; margin-bottom: 5px; }
.dashboard-compact .section-box { padding: 10px 14px; margin-top: 5px; }

.dashboard-compact .dashboard-grid.big { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 8px; margin-top: 8px; }
.dashboard-compact .card.big { padding: 9px 12px; border-radius: 9px; }
.dashboard-compact .card-icon { font-size: 16px; margin-bottom: 2px; }
.dashboard-compact .card.big .label { font-size: 10.5px; }
.dashboard-compact .card.big .value { font-size: 20px; margin-top: 2px; }
.dashboard-compact .card.big .sub { font-size: 11px; margin-top: 1px; }

.dashboard-compact .pl-compare { gap: 10px; margin-top: 6px; }
.dashboard-compact .pl-compare-col h3 { font-size: 12.5px; margin-bottom: 4px; }
.dashboard-compact .pl-line { padding: 3px 0; font-size: 12.5px; }
.dashboard-compact .pl-line.total { padding-top: 5px; margin-top: 2px; }
.dashboard-compact .pl-intro { font-size: 11.5px; margin: -4px 0 6px; }

.dashboard-compact .dashboard-columns { margin-top: 8px; gap: 10px; }
.dashboard-compact .upcoming-row { padding: 5px 0; font-size: 12.5px; }
.dashboard-compact .upcoming-date { width: 76px; font-size: 11.5px; }
.dashboard-compact .upcoming-detail { font-size: 11.5px; }
.dashboard-compact .scroll-box { max-height: 155px; overflow-y: auto; }
.dashboard-compact table { margin-top: 6px; }
.dashboard-compact th, .dashboard-compact td { padding: 5px 9px; font-size: 12.5px; }
.dashboard-compact .stage-row { padding: 4px 0; gap: 6px; }
.dashboard-compact .stage-bar-track { height: 11px; }
.dashboard-compact .stage-name { font-size: 11.5px; }
.dashboard-compact .stage-count { font-size: 12px; }

table { width: 100%; border-collapse: collapse; margin-top: 10px; background: #fff; border-radius: 10px; overflow: hidden; box-shadow: 0 1px 2px rgba(16,24,40,0.05); }
th, td { text-align: left; padding: 8px 11px; border-bottom: 1px solid #eef0f3; font-size: 14px; }
th { background: #f9fafb; font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em; color: #6b7280; font-weight: 700; }
tbody tr:nth-child(even) { background: #fbfbfc; }
tr:hover { background: #f3f6fb; }
a.rowlink { color: #1d4ed8; text-decoration: none; font-weight: 600; }
a.rowlink:hover { text-decoration: underline; }

.btn {
    display: inline-block;
    background: #1d4ed8;
    color: #fff;
    padding: 9px 16px;
    border-radius: 7px;
    text-decoration: none;
    font-size: 14px;
    font-weight: 600;
    border: none;
    cursor: pointer;
    box-shadow: 0 1px 2px rgba(29,78,216,0.25);
    transition: background .12s ease, transform .1s ease, box-shadow .12s ease;
}
.btn:hover { background: #1e40af; transform: translateY(-1px); box-shadow: 0 4px 10px rgba(29,78,216,0.28); }
.btn:active { transform: translateY(0); }
.btn.secondary { background: #6b7280; box-shadow: 0 1px 2px rgba(107,114,128,0.2); }
.btn.secondary:hover { background: #4b5563; box-shadow: 0 4px 10px rgba(75,85,99,0.25); }
.btn:disabled { background: #d1d5db; color: #9ca3af; cursor: not-allowed; box-shadow: none; transform: none; }
.btn:disabled:hover { background: #d1d5db; transform: none; box-shadow: none; }

form.stacked label { display: block; margin-top: 14px; font-size: 14px; font-weight: 600; color: #374151; }
form.stacked input, form.stacked select, form.stacked textarea {
    width: 100%; padding: 8px 10px; margin-top: 4px; border: 1px solid #d1d5db; border-radius: 7px; font-size: 14px;
    transition: border-color .12s ease, box-shadow .12s ease;
}
form.stacked input:focus, form.stacked select:focus, form.stacked textarea:focus {
    outline: none; border-color: #93c5fd; box-shadow: 0 0 0 3px rgba(59,130,246,0.15);
}
form.stacked textarea { min-height: 70px; }
form.inline { display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; margin-top: 10px; }
form.inline label { font-size: 12.5px; font-weight: 600; color: #374151; }
form.inline input, form.inline select { padding: 7px 9px; border: 1px solid #d1d5db; border-radius: 7px; }
form.inline input:focus, form.inline select:focus { outline: none; border-color: #93c5fd; box-shadow: 0 0 0 3px rgba(59,130,246,0.15); }

.badge { display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: 12px; font-weight: 600; background: #e0e7ff; color: #3730a3; }

/* Stage badge colors - purely visual, grouped by where a job sits in the pipeline */
.badge.stage-bid { background: #dbeafe; color: #1e40af; }
.badge.stage-won { background: #dcfce7; color: #166534; }
.badge.stage-progress { background: #fef3c7; color: #92400e; }
.badge.stage-install { background: #ede9fe; color: #5b21b6; }
.badge.stage-complete { background: #ccfbf1; color: #0f766e; }
.badge.stage-lost { background: #fee2e2; color: #991b1b; }

.section-box { background: #fff; border: 1px solid #e5e7eb; border-radius: 12px; padding: 16px 18px; margin-top: 12px; box-shadow: 0 1px 2px rgba(16,24,40,0.05); }
.section-box h2 { margin-top: 0; }
.job-header { display: flex; justify-content: space-between; align-items: baseline; flex-wrap: wrap; gap: 10px; }
.job-header .jobnum { font-family: "SFMono-Regular", Consolas, monospace; background: #eef2ff; padding: 3px 9px; border-radius: 6px; color: #3730a3; font-size: 15px; }

/* A compact multi-column layout for the smaller job-page sections (Update
   Stage, Internal PM, Companies, Stage History, Notes) so they sit side by
   side instead of each taking a full-width row - same information, less
   scrolling. This uses CSS columns (a "waterfall" layout) rather than CSS
   grid on purpose: grid sizes an entire row to its tallest box, which left
   an awkward gap under any shorter box sharing a row with a taller one.
   Columns instead let each box stack directly under the next as soon as
   there's room, so short boxes don't leave dead space above the next row. */
.job-grid { column-width: 320px; column-gap: 12px; margin-top: 12px; }
.job-grid > .section-box {
    margin: 0 0 12px;
    break-inside: avoid;
    -webkit-column-break-inside: avoid;
}

/* Sections that are often empty (Permits, Site Visits, Outsourced/Material
   Orders, Change Orders) collapse down to one clickable line when there's
   nothing in them yet, instead of taking up a full section's worth of
   space - nothing is removed, it's all still one click away. */
summary.section-summary { cursor: pointer; color: #1d4ed8; font-weight: 600; font-size: 14px; list-style: revert; }
summary.section-summary::marker { color: #9ca3af; }

.calendar-table { table-layout: fixed; }
.calendar-table th { text-align: center; }
.calendar-cell { vertical-align: top; height: 100px; padding: 6px !important; }
.calendar-cell-outside { background: #f9fafb; color: #c0c4cc; }
.calendar-cell-today { background: #eff6ff; }
.calendar-day-number { font-size: 12px; font-weight: 700; color: #6b7280; margin-bottom: 4px; }
.calendar-event {
    display: block;
    font-size: 11px;
    color: #fff;
    padding: 2px 5px;
    border-radius: 4px;
    margin-bottom: 3px;
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.calendar-event:hover { opacity: 0.85; }

/* ---------------- Print / Install Sheet ---------------- */
/* The whole sheet always prints in portrait, EXCEPT each flagged plan/photo,
   which gets its own dedicated landscape page (see .print-landscape-page and
   the @page rules near the bottom of this file) - plans are almost always
   wider than tall, so this shows them as large/legible as possible instead
   of squeezed into a portrait-width column. This happens automatically when
   you print/Save as PDF - nothing to rotate or choose by hand. */
.print-doc {
    max-width: 780px;
    margin: 0 auto;
    background: #fff;
    border: 1px solid #e5e7eb;
    border-radius: 10px;
    box-shadow: 0 1px 3px rgba(16,24,40,0.06);
    padding: 44px 48px;
}
.print-doc table { width: 100%; border-collapse: collapse; }
.print-doc table th {
    text-align: left;
    font-size: 11.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: #fff;
    background: #1f2937;
    padding: 9px 12px;
}
.print-doc table td { padding: 8px 12px; border-bottom: 1px solid #eef0f4; font-size: 13.5px; color: #374151; }
.print-doc table tbody tr:nth-child(even) td { background: #f9fafb; }
/* Clean pagination for printed tables/panels - without this, a table row
   that happens to fall right at a page boundary gets sliced in half (half
   the row's text on one page, the rest on the next), which looks broken.
   break-inside:avoid on a row tells the browser "move this whole row to
   the next page rather than cutting it" - it only gives up and splits
   anyway if a single row is somehow taller than an entire page by itself.
   thead as table-header-group makes the column headers repeat at the top
   of every page a table spans, so page 2+ of a long table is still
   readable without scrolling back to page 1 to remember what a column means.
   NOTE: break-inside:avoid deliberately is NOT applied to .print-doc-panel
   itself - a panel can hold a table with dozens of rows, and telling the
   browser to keep that whole thing together just pushes the entire panel
   (table and all) onto the next page, leaving a mostly-blank page behind
   it. .print-stat is small and bounded (a handful of short lines) so it's
   safe to keep those together. */
.print-stat { break-inside: avoid; page-break-inside: avoid; }
.print-doc table tr, .bid-line-items tr { break-inside: avoid; page-break-inside: avoid; }
.print-doc table thead, .bid-line-items thead { display: table-header-group; }
.print-sheet-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    flex-wrap: wrap;
    gap: 20px;
    border-bottom: 3px solid #1f2937;
    padding-bottom: 20px;
    margin-bottom: 28px;
}
.print-sheet-title {
    font-size: 22px;
    font-weight: 800;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: #1f2937;
    margin: 0 0 10px;
}
.print-sheet-header img { height: 50px; width: auto; flex-shrink: 0; }
.print-section { margin-top: 18px; }
.print-doc-panel {
    background: #f9fafb;
    border: 1px solid #e5e7eb;
    border-radius: 8px;
    padding: 16px 20px;
    margin-top: 18px;
}
.print-doc-panel h2 {
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: #6b7280;
    margin: 0 0 10px;
    /* Without this, a panel's title can land as the very last line on a
       page with its table pushed entirely to the next one - the title
       ends up orphaned by itself with nothing under it. This tells the
       browser not to break the page immediately after the heading, so
       it's pulled down to the next page together with (at least the
       start of) its own table instead. */
    break-after: avoid;
    page-break-after: avoid;
}
.print-doc-panel table { background: transparent; }
.print-doc-panel table th { background: #1f2937; }
/* Each flagged file/page gets pushed onto its own fresh landscape page -
   "page: landscape" switches this box (and everything until the next forced
   break) to the named @page below; the very next section after it (there
   isn't one today, but just in case) would automatically fall back to the
   default portrait @page. */
.print-landscape-page {
    page: landscape;
    break-before: page;
    page-break-before: always;
    text-align: center;
}
.print-landscape-page .doc-label { font-weight: 700; font-size: 13px; margin-bottom: 6px; color: #1f2937; text-align: left; }
/* max-height needs a fixed unit, not a percentage - percentages only work
   against an ancestor with an explicit height, and .print-landscape-page
   doesn't have one, so max-height:100% silently did nothing and let tall
   images overflow onto extra blank-ish pages instead of being capped to
   fit the one landscape page they were meant for. Landscape letter is
   ~11in x 8.5in; minus margins and room for the label above, 6.3in of
   vertical space reliably fits under the label.
   IMPORTANT: this image must NOT be display:block. Chromium has a print-
   pagination bug where a block-level image following another block-level
   sibling inside a named @page (like "landscape" below) gets shoved onto
   an extra blank page of its own. Leaving the image at its default inline
   display and centering it with text-align on the parent instead avoids
   that bug entirely - tested against an actual generated PDF. */
.print-landscape-page img { max-width: 9.5in; max-height: 6.3in; width: auto; height: auto; }

@page { size: portrait; margin: 0.6in; }
@page landscape { size: landscape; margin: 0.5in; }

/* ---------------- Formal Bid Document (client-facing) ---------------- */
/* A more formal, "professional invoice" look than the crew Install Sheet -
   logo sits in the upper right, matching how most invoices/bids are laid
   out, with a clear BID PROPOSAL title and bid number/date block on the left.
   Presented as a crisp white "sheet of paper" (card + shadow on screen, flat
   on the printed page) rather than sitting directly on the app's gray
   background, so it reads as a real document rather than another app page. */
.bid-doc {
    max-width: 760px;
    margin: 0 auto;
    background: #fff;
    border: 1px solid #e5e7eb;
    border-radius: 10px;
    box-shadow: 0 1px 3px rgba(16,24,40,0.06);
    padding: 44px 48px;
}
.bid-print-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 20px;
    border-bottom: 3px solid #1f2937;
    padding-bottom: 20px;
    margin-bottom: 28px;
}
.bid-doc-title {
    font-size: 25px;
    font-weight: 800;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #1f2937;
    margin-bottom: 12px;
}
.bid-meta-table td { padding: 2px 0; font-size: 13px; }
.bid-meta-table td:first-child { color: #6b7280; padding-right: 18px; }
.bid-meta-table td:last-child { font-weight: 700; color: #1f2937; letter-spacing: .01em; }
.bid-print-from { text-align: right; flex-shrink: 0; }
.bid-print-logo { height: 58px; width: auto; }
.bid-print-from-info { margin-top: 8px; font-size: 12.5px; color: #6b7280; line-height: 1.5; }
.bid-print-parties {
    display: flex;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 30px;
    flex-wrap: wrap;
}
.bid-print-parties > div {
    flex: 1;
    min-width: 190px;
    background: #f9fafb;
    border: 1px solid #e5e7eb;
    border-radius: 8px;
    padding: 14px 18px;
    break-inside: avoid;
    page-break-inside: avoid;
}
.bid-print-parties h3 {
    font-size: 11.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: #9ca3af;
    margin: 0 0 8px;
}
.bid-print-parties p { margin: 0; font-size: 14px; line-height: 1.55; color: #1f2937; }
.bid-line-items { width: 100%; border-collapse: collapse; }
.bid-line-items th {
    text-align: left;
    font-size: 11.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: #fff;
    background: #1f2937;
    padding: 11px 14px;
}
.bid-line-items th:first-child { border-top-left-radius: 6px; }
.bid-line-items th:last-child { border-top-right-radius: 6px; }
.bid-line-items th:not(:first-child), .bid-line-items td:not(:first-child) { text-align: right; }
.bid-line-items tbody tr:nth-child(even) td { background: #f9fafb; }
.bid-line-items td { padding: 10px 14px; border-bottom: 1px solid #eef0f4; font-size: 14px; color: #374151; }
.bid-total-row td {
    font-weight: 800;
    font-size: 16.5px;
    color: #1f2937;
    background: #eef2ff !important;
    border-top: 2px solid #1f2937;
    border-bottom: none;
    padding-top: 12px;
    padding-bottom: 12px;
}
.bid-print-notes {
    margin-top: 26px;
    background: #fffbeb;
    border: 1px solid #fde68a;
    border-radius: 8px;
    padding: 14px 18px;
    break-inside: avoid;
    page-break-inside: avoid;
}
.bid-print-notes h3 {
    font-size: 11.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: #92400e;
    margin: 0 0 8px;
}
.bid-print-notes p { white-space: pre-wrap; font-size: 13.5px; color: #374151; line-height: 1.5; margin: 0 0 8px; }
.bid-print-notes p:last-child { margin-bottom: 0; }
.bid-print-footer {
    margin-top: 36px;
    padding-top: 16px;
    border-top: 1px solid #d1d5db;
    font-size: 12.5px;
    color: #6b7280;
    text-align: center;
    font-style: italic;
}

/* ---------------- Printable Reports (index page + the 6 report pages) ---------------- */
/* Reuses .print-doc/.print-doc-panel/.print-sheet-header from the Install
   Sheet above for the same look - these two classes are the report-specific
   extras: a row of summary numbers, and the highlighted total row some of
   the report tables end with. */
.print-stat-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    margin-top: 18px;
}
.print-stat {
    flex: 1;
    min-width: 150px;
    background: #f9fafb;
    border: 1px solid #e5e7eb;
    border-radius: 8px;
    padding: 14px 16px;
}
.print-stat .label {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: #6b7280;
    margin-bottom: 6px;
}
.print-stat .value { font-size: 20px; font-weight: 800; color: #1f2937; }
.print-stat .sub { font-size: 12px; color: #9ca3af; margin-top: 2px; }
.print-doc table tr.total-row td {
    font-weight: 800;
    background: #eef2ff !important;
    border-top: 2px solid #1f2937;
    border-bottom: none;
}

/* The Printable Reports menu (reports_print_index.html) isn't itself meant
   to be printed - it's a normal in-app page of links to the 6 report pages
   above, so it uses the app's regular card look rather than .print-doc. */
.print-report-links {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 14px;
    margin-top: 20px;
}
.print-report-link {
    display: block;
    background: #fff;
    border: 1px solid #e5e7eb;
    border-radius: 10px;
    padding: 18px 20px;
    text-decoration: none;
    transition: border-color .15s, box-shadow .15s;
}
.print-report-link:hover { border-color: #3730a3; box-shadow: 0 2px 8px rgba(55,48,163,0.08); }
.print-report-link .title { font-size: 15.5px; font-weight: 700; color: #1f2937; margin-bottom: 4px; }
.print-report-link .desc { font-size: 13px; color: #6b7280; line-height: 1.5; }
@media (max-width: 700px) {
    .print-report-links { grid-template-columns: 1fr; }
}

/* General-purpose "only show this on a phone" / "hide this on a phone"
   pair, for content that should appear in a different spot (or not at all)
   on a narrow screen - e.g. a quick-access widget moved to the top of a
   page on mobile, with the full version staying in its normal place for
   everyone else. Only one of a matching mobile-only/hide-mobile pair is
   ever visible at once - see the 640px flip below. */
.mobile-only { display: none; }

/* ------------------------------------------------------------------
   Phone/narrow-screen pass. NicheOps was built desktop-first, so this
   doesn't redesign anything - it just keeps every page usable (readable,
   scrollable instead of squished, tappable buttons) down to a phone-width
   screen, on top of all the desktop rules above.
   ------------------------------------------------------------------ */
@media (max-width: 640px) {
    .mobile-only { display: block; }
    .hide-mobile { display: none; }

    .container { padding: 16px 12px 50px; }
    .container.container-wide { padding: 10px 10px 14px; }

    .topnav { padding: 10px 12px; gap: 10px 14px; }
    .topnav a { font-size: 13px; padding: 4px 2px; }
    .topnav .brand { font-size: 15px; margin-right: 2px; }
    .nav-search { margin-left: 0; width: 100%; order: 99; }
    .nav-search input { width: 100%; }
    .nav-search input:focus { width: 100%; }

    h1 { font-size: 20px; }
    h2 { font-size: 15.5px; }

    /* Wide tables (most of this app) would otherwise force the whole page
       to scroll sideways - instead only the table itself scrolls, so
       everything else stays put and readable. max-width is the important
       part: a table sitting inside a CSS grid/flex column (like the ones
       on the Dashboard) can otherwise grow past its column's width and
       drag the whole page wider with it, since grid/flex columns don't
       shrink their content below its natural size by default. */
    table { display: block; overflow-x: auto; white-space: nowrap; max-width: 100%; }
    thead, tbody, tr { display: table; width: 100%; table-layout: auto; }

    form.inline { flex-direction: column; align-items: stretch; gap: 8px; }
    form.inline > div { width: 100% !important; }
    form.inline input, form.inline select, form.inline textarea { width: 100% !important; }

    .dashboard-grid, .dashboard-grid.big { grid-template-columns: 1fr; }
    .pl-compare { grid-template-columns: 1fr; }
    .job-grid { grid-template-columns: 1fr !important; }

    .stage-row { flex-wrap: wrap; }
    .stage-name { width: auto; }

    /* Date + badge on their own line, job description on the next -
       reads much better in a narrow column than squeezing all three onto
       one line the way the desktop layout does. */
    .upcoming-row { flex-wrap: wrap; }
    .upcoming-main { flex-basis: 100%; }

    /* Jobs list: Site Address and the (usually blank) Legacy-badge column
       are the least useful columns to have on screen on a phone - hiding
       them lets Job #, Project, Stage, and Bid Amount fit without needing
       to scroll the table sideways at all. The full table (including
       address) is still there on a normal-width screen. */
    .table-jobs .col-address, .table-jobs .col-legacy { display: none; }

    .card.big .value { font-size: 26px; }
}

@media print {
    .no-print { display: none !important; }
    body { background: #fff; }
    .container { max-width: none; padding: 0; margin: 0; }
    .section-box, table { box-shadow: none; }
    a { color: inherit !important; text-decoration: none !important; }
    /* On real paper/PDF the page edge already frames the document, so drop
       the on-screen "card" styling (border/shadow/rounded corners) that
       exists only to separate the bid visually from the app around it. */
    .bid-doc { box-shadow: none; border: none; border-radius: 0; padding: 0; max-width: none; }
    /* Same fix as .bid-doc above - .print-doc (Install Sheet + all the
       printable Reports below) was still printing with its on-screen card
       border/shadow/rounded corners and 780px-cap padding, wasting paper
       margin and looking boxed-in on an actual printed page/PDF. */
    .print-doc { box-shadow: none; border: none; border-radius: 0; padding: 0; max-width: none; }
    /* Browsers normally strip background colors/images when printing unless
       the person happens to check "Background graphics" in the print dialog
       (off by default in most browsers) - which is why the bid header, the
       highlighted total row, the yellow notes box, and badges were printing
       as plain white/black instead of matching the on-screen preview. This
       forces those colors to print either way, so what you see IS what
       prints - no dialog option to remember to check. */
    * {
        -webkit-print-color-adjust: exact !important;
        print-color-adjust: exact !important;
        color-adjust: exact !important;
    }
}
