/* Layout for the tech web app's screens. Colours, fonts, buttons, inputs,
   cards and lists come from theme.css (loaded first). Only things specific to
   this app's screens live here. */

.screen {
  max-width: 900px;
  margin: 0 auto;
  padding: 1rem;
}

/* --- Dev login: pick a person --------------------------------------------- */

.user-list { display: grid; gap: 0.5rem; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
.user-list button { text-align: left; background: var(--panel); text-transform: none; }
.user-list .role { display: block; color: var(--ink-soft); font-size: 0.8rem; text-transform: uppercase; }

/* --- Lists of big buttons (businesses, jobsites) -------------------------- */
/* Same look as the host's Employees list: --row grey boxes in a light-grey card. */

.jobsite-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.5rem; }
.jobsite-list button {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  text-align: left;
  background: var(--row);
  text-transform: none;
  font-weight: 400;
  letter-spacing: 0;
}
.jobsite-list button:hover:not(:disabled) { background: var(--row-hover); }

/* Jobsite rows: name big on the left, address small and stacked on the right. */
.jobsite-row { justify-content: space-between; }
.jobsite-name { font-size: 1.25rem; font-weight: 700; }
/* Always three lines tall (Address 1, Address 2, City/State/Zip), even when some
   are blank, so every row in the list is the same height. */
.jobsite-address { display: grid; align-content: center; text-align: right; font-size: 0.8rem; line-height: 1.35; min-height: calc(3 * 1.35em); }
.jobsite-list .role { color: var(--ink-soft); font-size: 0.8rem; text-transform: uppercase; }
.jobsite-list .status { margin-left: auto; }

/* --- Home screen inside a business (the mockup: logo, then a card of buttons) --- */

.home { max-width: 360px; margin: 1.5rem auto; display: grid; gap: 1rem; text-align: center; }
.home-logo { width: min(260px, 80%); margin: 0 auto; display: block; }
.home-business { font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; }
.home-menu { display: grid; gap: 0.75rem; padding: 1.5rem; margin: 0; }
.home-menu button {
  background: var(--row);
  min-height: 56px;
  font-size: 1.1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
}
.home-menu button:hover:not(:disabled) { background: var(--row-hover); }
.home-menu .chip { font-size: 0.7rem; background: var(--warn); }

/* Open lists: "Assigned to you" / "Other open". */
.open-section + .open-section { margin-top: 1.25rem; }
.open-section h3 { margin: 0 0 0.5rem; }
.open-count { margin-left: 0.6rem; vertical-align: middle; font-size: 0.75rem; background: var(--warn); }

/* --- Dashboard ----------------------------------------------------------- */

/* Businesses on the left, notifications on the right; stacked on phones. */
.dashboard { display: grid; gap: 1rem; grid-template-columns: 1fr; }
@media (min-width: 760px) { .dashboard { grid-template-columns: 2fr 1fr; } }
/* Your approved timesheets (dashboard): like a ticket row, but not a button. */
.record-row { display: flex; justify-content: space-between; align-items: center; gap: 1rem; background: var(--row); border: var(--outline-thin); padding: 0.5rem 0.75rem; }
/* Your profile sits in the narrow column: its boxes stack. */
.form-grid.profile-grid { grid-template-columns: 1fr; }
/* Your profile: license numbers as rows of [number] [which businesses]. The
   number sits in the middle (top to bottom) when the names wrap onto two lines;
   the names line up on the right. */
.license-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.3rem; }
.license-list li > span { text-align: right; }
.license-list li > b { white-space: nowrap; flex-shrink: 0; } /* the number never wraps */
.license-list li { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; padding: 0.35rem 0.6rem; background: var(--row); border: var(--outline-thin); }

.notification-list { list-style: none; padding: 0; margin: 0 0 1rem; display: grid; gap: 0.5rem; }
.notification-list li { background: var(--row); border: var(--outline-thin); padding: 0.75rem; display: grid; gap: 0.5rem; }

/* --- Team ------------------------------------------------------------------ */

.member-list { list-style: none; padding: 0; margin: 0 0 1rem; display: grid; gap: 0.5rem; }
.member-list li {
  background: var(--row);
  border: var(--outline-thin);
  padding: 0.6rem 0.8rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}
.member-list .who { flex: 1; min-width: 12rem; }
.member-list select { width: auto; }

/* --- Inside a jobsite ------------------------------------------------------ */

.jobsite-header { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; flex-wrap: wrap; }
#screen-jobsite .presence { margin-bottom: 0; }

/* --- Jobsite overview -------------------------------------------------------- */

.overview-top { margin-bottom: 1rem; }

/* Jobsite and property management boxes, equal width; stacked on phones.
   .single = property management is the same as the jobsite, so only the
   jobsite box shows, full width. */
.info-boxes { display: grid; gap: 1rem; grid-template-columns: 1fr; }
@media (min-width: 700px) { .info-boxes { grid-template-columns: 1fr 1fr; } }
.info-boxes.single { grid-template-columns: 1fr; }
.info-boxes .card { margin: 0; }
.info-box { line-height: 1.5; }
.info-label { font-size: 0.75rem; font-weight: 700; text-transform: uppercase; color: var(--ink-soft); margin-bottom: 0.25rem; }
.info-title { font-size: 1.3rem; font-weight: 700; margin-bottom: 0.25rem; }

/* View service / View inspections, side by side and equal width. */
.view-buttons { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: 1rem; }
/* A shade darker than the boxes above (#c7c7c7), with underlined text. */
.view-buttons button { min-height: 56px; font-size: 1.05rem; background: #bdbdbd; text-decoration: underline; }
.view-buttons button:hover:not(:disabled) { background: var(--row); }
/* New service / New inspection (managers), under the View buttons. */
.new-buttons { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: 1rem; }

/* --- Documents (service tickets, inspections) ---------------------------------- */

/* The list of tickets on a jobsite's Service page: summary left, date + status right. */
.doc-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.5rem; }
.doc-row {
  width: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  text-align: left;
  background: var(--row);
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
}
.doc-row:hover:not(:disabled) { background: var(--row-hover); }
.doc-row.closed { opacity: 0.75; }
.doc-row-main { display: grid; gap: 0.2rem; min-width: 0; }
.doc-summary { font-weight: 700; font-size: 1.05rem; overflow-wrap: anywhere; }
.doc-row-meta { display: grid; justify-items: end; gap: 0.25rem; font-size: 0.8rem; white-space: nowrap; }

.doc-header { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; flex-wrap: wrap; margin-bottom: 0.75rem; }
.doc-header h2 { margin: 0 0 0.2rem; }
.doc-header .chip { vertical-align: middle; margin-left: 0.4rem; }
.document.closed { opacity: 0.8; }
.assigned { margin-bottom: 0.75rem; }
/* Service ticket sections: one box per part of the paper ticket. */
.doc-box { margin-bottom: 0.75rem; background: var(--panel); }
.doc-box > .legend, .doc-box > .row-between .legend { margin-bottom: 0.5rem; }
.notes-box { background: var(--row); }
.small-btn { min-height: 34px; padding: 0.25rem 0.7rem; font-size: 0.8rem; }
.entry-list li { gap: 0.75rem; }
.entry-main { display: grid; gap: 0.15rem; min-width: 0; }
.entry-side { display: flex; align-items: center; gap: 0.75rem; margin-left: auto; text-align: right; }
/* Totals box: tax rates stacked in a narrow column on the left, the price
   summary on the right. On phones the summary drops underneath. */
.totals-layout { display: grid; gap: 0.75rem 1.5rem; grid-template-columns: 1fr; align-items: start; }
@media (min-width: 480px) { .totals-layout { grid-template-columns: 9rem 1fr; } }
.tax-fields { display: grid; gap: 0.75rem; }
.totals { width: 100%; max-width: 380px; margin-left: auto; border-collapse: collapse; }
.totals th { text-align: left; font-weight: 400; padding: 0.25rem 0; }
.totals td { text-align: right; padding: 0.25rem 0; font-weight: 700; }
.totals tr.strong th, .totals tr.strong td { border-top: var(--outline-thin); font-weight: 700; font-size: 1.1rem; padding-top: 0.4rem; }

/* Assign box: dropdown at the top, picked people anchored at the bottom. */
.box.assign-box { display: flex; flex-direction: column; gap: 0.6rem; min-height: 230px; }
.assignee-picked { margin-top: auto; display: flex; flex-direction: column; gap: 0.4rem; }
.assignee-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0.4rem; }
.assignee { display: flex; align-items: center; justify-content: space-between; gap: 0.4rem; background: var(--row); border: var(--outline-thin); padding: 0.25rem 0.25rem 0.25rem 0.6rem; font-size: 0.85rem; min-width: 0; }
.assignee span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.assignee .small-btn { min-height: 28px; padding: 0 0.55rem; font-size: 1rem; }

/* Delete in the Edit jobsite pop-up: set apart at the bottom so it's hard to hit by mistake. */
.dialog-delete-row { border-top: var(--outline-thin); padding-top: 1rem; margin-top: 0.75rem; }

/* --- Create jobsite pop-up: two boxes ------------------------------------------ */

.two-boxes { display: grid; gap: 1rem; grid-template-columns: 1fr; }
@media (min-width: 760px) { .two-boxes { grid-template-columns: 1fr 1fr; } }
.box { border: var(--outline-thin); padding: 0.75rem; display: grid; gap: 0.6rem; align-content: start; }
.legend { font-weight: 700; text-transform: uppercase; }
/* Both box headings get the same height (the checkbox row's), so the fields
   below them line up across the two boxes. */
.box-head { min-height: 1.9rem; align-items: center; }
label.check { display: flex; align-items: center; gap: 0.4rem; font-size: 0.8rem; cursor: pointer; }
fieldset.plain { border: 0; margin: 0; padding: 0; min-width: 0; }
/* Locked by "Same as jobsite": darker so it's clearly not for typing. */
fieldset.plain:disabled input { background: var(--row); color: var(--ink-soft); }
.presence { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; margin: 0.75rem 0; }

.document {
  background: var(--panel);
  border: var(--outline);
  padding: 1rem;
  margin-bottom: 1rem;
}

/* Fields stack on phones and sit two-across on wider screens. */
.fields { display: grid; gap: 0.75rem; grid-template-columns: 1fr; }
@media (min-width: 640px) {
  .fields { grid-template-columns: 1fr 1fr; }
  .field.wide { grid-column: 1 / -1; } /* textareas span both columns */
}
.field label { display: block; margin-bottom: 0.25rem; }

/* Service ticket addresses: two boxes side by side (the margin under each box
   spaces them when they stack, so the grid only needs a gap across). Inside,
   name and address lines take the full width; City / State / Zip share a row,
   City getting twice the room. */
.address-boxes { gap: 0 0.75rem; }
@media (min-width: 480px) {
  .address-fields { grid-template-columns: 2fr 1fr 1fr; }
  .address-fields .field.wide { grid-column: 1 / -1; }
}
/* Locked by "Same as physical": darker so it's clearly not for typing. */
.address-fields input:disabled:not([data-copies-from=""]) { background: var(--row); color: var(--ink-soft); }
.field.checkbox { display: flex; align-items: center; gap: 0.5rem; }
.field.checkbox label { margin: 0; }

/* Brief red highlight when someone else changes a field. */
.flash { animation: flash 1s ease-out; }
@keyframes flash { from { box-shadow: 0 0 0 4px var(--brand); } to { box-shadow: 0 0 0 4px transparent; } }

/* --- Signature pad (signature.js) ----------------------------------------------- */
/* A white box, three times as wide as it is tall, with a "sign here" line and
   an × near the bottom like a paper form. touch-action: none stops a finger
   from scrolling the page while signing. */
.signature-area { position: relative; background: #fff; border: var(--outline-thin); }
.signature-area::after { content: ''; position: absolute; left: 8%; right: 5%; bottom: 22%; border-bottom: 1px solid #999; pointer-events: none; }
.signature-x { position: absolute; left: 3%; bottom: 22%; color: #999; font-size: 1.3rem; line-height: 1; pointer-events: none; }
.signature-canvas { display: block; width: 100%; aspect-ratio: 3 / 1; touch-action: none; cursor: crosshair; }

/* --- Open service ticket: Back row and bottom buttons ----------------------------- */
/* Back on the left, the "Saved 3:15 PM" note beside it. */
.ticket-back-row { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.75rem; }
/* Close out across the full width and three times Delete's height (45px), then
   Delete (and Reopen) under it at normal size. */
.ticket-bottom { display: grid; gap: 0.75rem; justify-items: start; margin-top: 0.5rem; }
.ticket-bottom .closeout-btn { width: 100%; min-height: 135px; font-size: 1.4rem; }
.signed-off { margin: 0; }

/* --- Close out pop-up ------------------------------------------------------------- */
/* [Sign] button, then "Not signed yet" or a small picture of the signature. */
.sign-row { display: flex; align-items: center; gap: 0.75rem; min-height: 56px; }
.sign-preview { height: 48px; max-width: 60%; background: #fff; border: var(--outline-thin); }
/* "No license number on file yet" + Save, under the License # box. */
.license-entry { display: grid; gap: 0.4rem; justify-items: start; }
.license-entry p { margin: 0; }

/* Add / edit labor on a narrow screen (one column): Pay rate and Hours go
   last, after Time out, so the times come straight after the date. ("order"
   moves a box within the grid without changing the page's HTML; the
   two-column layout on wider screens is unchanged.) */
@media (max-width: 559px) {
  #list-form-fields > [data-field="payTier"] { order: 1; }
  #list-form-fields > [data-field="hours"] { order: 2; }
}

/* --- The closed ticket, on screen ------------------------------------------------- */
/* Nearly the whole screen: a bar with Done, then the ticket, scrolling. The
   ticket is drawn at its real paper size inside the <iframe>, then shrunk to
   fit the width (app.js fitTicketPreview sets the sizes and the scale). */
/* Height: "vh" on a phone is the screen with the browser's address bar
   hidden, so a 100vh box is taller than what's visible and its top (with
   Done) ends up off-screen. "dvh" (dynamic viewport height) is what's
   visible right now; the vh line is a fallback for browsers without dvh.
   It's pinned to the top (margin) rather than centred, so the bar always shows. */
dialog#ticket-preview-dialog {
  width: calc(100vw - 1rem); max-width: 1000px;
  height: calc(100vh - 1rem); height: calc(100dvh - 1rem);
  max-height: none; margin: 0.5rem auto; inset: 0;
  padding: 0; overflow: hidden; display: none; flex-direction: column;
}
dialog#ticket-preview-dialog[open] { display: flex; }
.preview-bar { display: flex; align-items: center; gap: 1rem; padding: 0.6rem 1rem; border-bottom: var(--outline-thin); }
.preview-bar h2 { flex: 1; margin: 0; font-size: 1.1rem; }
.preview-area { flex: 1; overflow: auto; background: #8a8f96; }
.preview-holder { overflow: hidden; }
.preview-holder iframe { display: block; border: 0; transform-origin: top left; }

/* --- Timesheets ----------------------------------------------------------------- */
/* Status tags: open = yellow (orange once its pay period is over), pending =
   cyan, rejected = red, closed = green (SPEC.md, "Timesheets"). */
.status.ts-open { background: var(--warn); }
.status.ts-overdue { background: #f2994a; }
.status.ts-pending { background: #56ccf2; }
.status.ts-rejected { background: var(--danger); }
.status.ts-closed { background: var(--good); }
#ts-sheet-view .card-header h2 { flex: 1; }
/* Why a timesheet was rejected: red, like its tag. */
.note.rejected-note { background: #f4b4aa; border-color: var(--danger); }
/* Space above each heading of the list after the first (Waiting / Hours from tickets / Your timesheets). */
#ts-list-view .card > div + div .legend, #ts-list-view .card > div + .legend, #ts-list-view .card > .stack + .legend { margin-top: 0.9rem; }
/* Days, like the equipment list on the host's Prices tab: [+/-] day ... hours,
   then that day's entries indented under it. */
.ts-days { display: grid; gap: 0.75rem; }
.ts-day { display: grid; gap: 0.4rem; }
.ts-day-head { display: flex; align-items: center; gap: 0.5rem; }
.ts-day-head h3 { margin: 0; flex: 1; font-size: 0.95rem; text-transform: uppercase; letter-spacing: 0.05em; }
.ts-day-hours { font-weight: 700; }
.collapse-btn { width: 30px; min-height: 30px; padding: 0; font-size: 1.1rem; line-height: 1; }
.ts-entries { display: grid; gap: 0.4rem; padding-left: 2.25rem; list-style: none; margin: 0; }
@media (max-width: 559px) { .ts-entries { padding-left: 0.75rem; } } /* phones: a smaller indent */
.ts-entry { width: 100%; display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 0.75rem;
  text-align: left; background: var(--row); text-transform: none; letter-spacing: 0; font-weight: 400; padding: 0.45rem 0.75rem; }
.ts-entry:hover:not(:disabled) { background: var(--row-hover); }
/* Hours from a service ticket waiting to be reviewed: a faint yellow tint. */
.ts-entry.ts-review-entry { background: #d9d2a6; }
.ts-entry.ts-review-entry:hover:not(:disabled) { background: #cfc794; }
.review-count { color: var(--ink); }
.ts-entry:disabled { opacity: 1; cursor: default; }
.ts-entry { align-items: stretch; }
/* Job number small at the top left, the jobsite at the bottom left; the kind
   of hours at the top right, the hours at the bottom right. */
.ts-entry-main { display: grid; align-content: space-between; gap: 0.1rem; min-width: 0; overflow-wrap: anywhere; }
.ts-job-number { font-size: 0.75rem; min-height: 0.9rem; }
.ts-entry-side { display: grid; align-content: space-between; justify-items: end; gap: 0.1rem; white-space: nowrap; }
.ts-totals { max-width: 420px; }
/* The entry pop-up: Delete on the left, Cancel/Save on the right. */
#ts-entry-dialog .spacer { flex: 1; }
