/* The client portal.
 *
 * The frame is not in here. A portal page loads dashboard.css and
 * dashboard-shell.css the same way an employee dashboard page does, and gets
 * the sidebar, the section header, the stat tiles (.dash-stats), the tables
 * (.quotes-table) and the form controls (.jf-group) from them. This file adds
 * only the things a client report has and the staff dashboard does not.
 *
 * Which means: before adding a rule here, check whether the dashboard already
 * has the component. Two nearly-matching cards is the thing this file exists
 * to avoid.
 *
 * Radii are 8px and surfaces are var(--bg-card) on var(--border), because that
 * is what every card in dashboard.css uses.
 */

.portal-page { background: var(--bg-primary); }

/* Stat tiles.
 *
 * .dash-stats is a four-column grid (two on a phone), because the dashboard's
 * own sections carry four figures. A client report carries three, which would
 * leave an empty column on a desktop and one tile alone on a phone's second
 * row, so the portal has three columns at every width. Scoped to .portal-page
 * so the staff dashboard keeps the grid it was built for. */
.portal-page .dash-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* Property switcher -------------------------------------------------------
 *
 * Top of the sidebar, for a login with more than one property: which one is
 * open, and the rest one tap away. The list scrolls on its own, so fifteen
 * properties do not push the menu under them off the screen. */
.pt-switch { margin: 0 12px 12px; flex-shrink: 0; }
.pt-switch-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  list-style: none;
}
.pt-switch-btn::-webkit-details-marker { display: none; }
.pt-switch-btn:hover { border-color: var(--accent); }
.pt-switch-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pt-switch-text { display: flex; flex-direction: column; min-width: 0; flex-grow: 1; }
.pt-switch-label {
  font-family: 'Rajdhani', sans-serif;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.pt-switch-current {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pt-switch-chev { flex-shrink: 0; color: var(--text-secondary); transition: transform 0.15s; }
.pt-switch[open] .pt-switch-chev { transform: rotate(180deg); }
.pt-switch-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 50vh;
  overflow-y: auto;
  margin-top: 6px;
}

/* Call us -----------------------------------------------------------------
 *
 * Foot of the sidebar, above the signed-in name: the office line and the
 * after-hours number, each the whole row as a tel: link so a thumb cannot
 * miss it. */
.pt-call {
  flex-shrink: 0;
  padding: 10px 12px 12px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.pt-call-row {
  display: flex;
  flex-direction: column;
  padding: 6px 10px;
  border-radius: 6px;
  text-decoration: none;
  color: var(--text-primary);
}
.pt-call-row:hover { background: rgba(147, 51, 234, 0.07); }
.pt-call-row:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.pt-call-what { font-size: 0.72rem; color: var(--text-secondary); }
.pt-call-num { font-size: 0.95rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.pt-call-after .pt-call-num { color: var(--accent-text); }

/* Sections ---------------------------------------------------------------- */

.pt-section { margin-top: 28px; }
.pt-section h2 { font-size: 1.15rem; margin: 0; }
.pt-sub {
  color: var(--text-secondary);
  font-size: 0.85rem;
  margin: 0.2rem 0 12px;
  max-width: 70ch;
}
.pt-panel {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 17px;
}
.pt-summary { margin: 0; }

/* A heading with no standfirst under it still needs the standfirst gap. On the
 * heading rather than on what follows it, because under a type filter the
 * first entry below a heading is often hidden and an adjacent-sibling rule
 * would land the margin on the hidden one. */
.pt-section h2:not(:has(+ .pt-sub)) { margin-bottom: 12px; }

/* The assurance line.
 *
 * Above the incidents on purpose: being there every night is the thing being
 * bought, and it is what makes a quiet week read as a good week rather than as
 * an empty report. The green edge is the one colour in here that is not a
 * theme token, because it means "covered" rather than "accent". */
/* The same shape as .pt-attention, the banner it stands in for: the text takes
   the row so Download PDF sits at the right, and the same gap to the figures
   below. */
.pt-assure {
  display: flex;
  gap: 12px 16px;
  align-items: center;
  flex-wrap: wrap;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-left: 3px solid #16a34a;
  border-radius: 0 8px 8px 0;
  padding: 16px 18px;
  margin-top: 18px;
  margin-bottom: 20px;
}
.pt-tick { color: #16a34a; font-size: 1.25rem; line-height: 1; flex: 0 0 auto; }
.pt-assure p { margin: 0; font-size: 0.92rem; flex: 1 1 280px; min-width: 0; }

/* Moving between reports ---------------------------------------------------
 *
 * Previous, the picker, next, on one line above the report. The arrows keep
 * their words on a wide screen and drop them on a phone, where the picker
 * between them already says which week this is. */
.pt-period {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px;
}
.pt-step {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  border-radius: 6px;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--accent-text);
  text-decoration: none;
  white-space: nowrap;
}
.pt-step:hover { background: var(--bg-secondary); }
.pt-step:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pt-step.is-off { color: var(--text-secondary); opacity: 0.45; }
.pt-pick { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; justify-content: center; min-width: 0; }
.pt-pick-select {
  min-width: 0;
  max-width: 100%;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-card);
  color: var(--text-primary);
  font: inherit;
  font-size: 0.92rem;
  font-weight: 600;
  cursor: pointer;
}
.pt-pick-select:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* The Go button is for when script is off. portal-report.js hides it. */
.pt-pick-go[hidden] { display: none; }
.pt-period-range { display: flex; flex-direction: column; padding: 4px 8px; }
.pt-period-range span { font-size: 0.8rem; color: var(--text-secondary); }
.pt-period-links { display: flex; gap: 8px; flex-wrap: wrap; }
.pt-period-more {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin: 6px 2px 0;
  font-size: 0.85rem;
  color: var(--text-secondary);
}
.pt-period-more a { color: var(--accent-text); font-weight: 600; text-decoration: none; }
.pt-period-more a:hover { text-decoration: underline; }
/* The switcher sits where the first banner used to, so the banner under it
   keeps a gap rather than touching it. */
.pt-period + .pt-attention, .pt-period + .pt-assure,
.pt-period-more + .pt-attention, .pt-period-more + .pt-assure { margin-top: 14px; }

@media (max-width: 600px) {
  /* Arrows either side of the picker on one line, the picker taking what is
     left, rather than three rows stacked. */
  .pt-period:has(.pt-pick) { flex-wrap: nowrap; gap: 4px; }
  .pt-pick { flex: 1 1 0; }
  .pt-pick-select { width: 100%; font-size: 0.85rem; padding: 8px; }
  .pt-step-label { display: none; }
  .pt-step { padding: 10px 8px; }
}

/* When we were there ------------------------------------------------------
 *
 * The hours, not a count of visits. "311 patrol visits" is a number nobody can
 * answer; an unbroken band from 9pm to 5am is the thing being bought.
 */
.pt-hours { display: flex; align-items: flex-end; gap: 5px; height: 150px; }
.pt-hour {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
  height: 100%;
  min-width: 0;
}
.pt-hour-fill { width: 100%; background: var(--accent); border-radius: 3px 3px 0 0; display: block; }
.pt-hour-label {
  font-size: 0.6rem;
  color: var(--text-secondary);
  margin-top: 6px;
  white-space: nowrap;
}

/* Week by week ------------------------------------------------------------ */

.pt-trend { display: flex; align-items: flex-end; gap: 10px; height: 150px; }
.pt-trend-col {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
  height: 100%;
  min-width: 0;
}
.pt-trend-n {
  font-family: 'Rajdhani', sans-serif;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--text-secondary);
  margin-bottom: 4px;
  font-variant-numeric: tabular-nums;
}
.pt-trend-fill {
  width: 100%;
  background: var(--border);
  border-radius: 3px 3px 0 0;
  display: block;
}
/* The week being read, against the ones either side of it. */
.pt-trend-col.current .pt-trend-fill { background: var(--accent); }
.pt-trend-col.current .pt-trend-n { color: var(--accent-text); }
.pt-trend-label {
  font-size: 0.62rem;
  color: var(--text-secondary);
  margin-top: 6px;
  white-space: nowrap;
}

/* Needs your attention ---------------------------------------------------- */

.pt-attention {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-left: 3px solid #d97706;
  border-radius: 0 8px 8px 0;
  padding: 16px 18px;
  margin-bottom: 20px;
}
.pt-attention > div { flex: 1 1 320px; min-width: 0; }
.pt-attention-n {
  flex: 0 0 auto;
  font-family: 'Rajdhani', sans-serif;
  font-size: 2.1rem;
  font-weight: 700;
  line-height: 1;
  color: #d97706;
  font-variant-numeric: tabular-nums;
}
.pt-attention p { margin: 0.2rem 0 0; font-size: 0.88rem; color: var(--text-secondary); }

/* Happening more than once ------------------------------------------------ */

.pt-repeats { list-style: none; margin: 0; padding: 0; }
.pt-repeats li + li { margin-top: 11px; }
.pt-repeats strong { display: block; font-size: 0.92rem; }
.pt-repeats span { display: block; font-size: 0.8rem; color: var(--text-secondary); }

/* Where we patrolled ------------------------------------------------------ */

.pt-sector + .pt-sector { margin-top: 11px; }
.pt-sector-top { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.pt-sector-n {
  font-family: 'Rajdhani', sans-serif;
  font-size: 1rem;
  color: var(--accent-text);
  font-variant-numeric: tabular-nums;
}
.pt-sector-bar {
  height: 6px;
  background: var(--bg-secondary);
  border-radius: 3px;
  overflow: hidden;
  margin-top: 0.35rem;
}
.pt-sector-bar i { display: block; height: 100%; background: var(--accent); }

/* The full log, closed by default ----------------------------------------- */

.pt-details {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.pt-details > summary {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding: 14px 17px;
  cursor: pointer;
  list-style: none;
}
.pt-details > summary::-webkit-details-marker { display: none; }
.pt-details > summary::after {
  content: "Show";
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--accent-text);
}
.pt-details[open] > summary::after { content: "Hide"; }
.pt-details > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.pt-details-title { font-family: 'Rajdhani', sans-serif; font-size: 1.05rem; font-weight: 700; }
.pt-details-n { font-size: 0.8rem; color: var(--text-secondary); margin-right: auto; }

/* Patrol notes: the checks a guard wrote something on. Inside .pt-details,
   capped like the patrol log so a busy month does not run for pages. */
.pt-pnotes {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--border);
  max-height: 440px;
  overflow-y: auto;
}
.pt-pnotes li { padding: 11px 17px; }
.pt-pnotes li + li { border-top: 1px solid var(--border); }
.pt-pnote-head { display: flex; justify-content: space-between; align-items: baseline; gap: 4px 12px; flex-wrap: wrap; }
.pt-pnote-head strong { font-size: 0.9rem; }
.pt-pnote-head span { font-size: 0.78rem; color: var(--text-secondary); }
.pt-pnotes p { margin: 0.3rem 0 0; font-size: 0.86rem; }

/* Themes ------------------------------------------------------------------ */

/* Each row is a link that filters the observations below, so it needs the hit
   area and the states a control has. The markup inside is all spans, which is
   what keeps an anchor wrapping it valid. */
.pt-theme {
  display: block;
  padding: 11px 12px;
  border: 1px solid transparent;
  border-radius: 6px;
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.15s, border-color 0.15s;
}
.pt-theme:hover { background: var(--bg-secondary); }
.pt-theme:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pt-theme.active { background: var(--bg-secondary); border-color: var(--accent); }

.pt-theme + .pt-theme { margin-top: 4px; }

/* Above the lists now, so it is laid out as tiles rather than a row each: the
   breakdown is still there at a glance, and "For you to fix" is not pushed a
   screen down by it. */
#ptThemes {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 4px 8px;
}
#ptThemes .pt-theme + .pt-theme { margin-top: 0; }
.pt-theme-top { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.pt-theme-n {
  font-family: 'Rajdhani', sans-serif;
  font-size: 1.05rem;
  color: var(--accent-text);
  font-variant-numeric: tabular-nums;
}
.pt-theme-bar {
  display: block;
  height: 6px;
  background: var(--bg-secondary);
  border-radius: 3px;
  overflow: hidden;
  margin: 0.35rem 0 0.25rem;
}
.pt-theme-bar i { display: block; height: 100%; background: var(--accent); }
.pt-theme-cats { display: block; font-size: 0.75rem; color: var(--text-secondary); }

/* Clearing the filter, beside the count it belongs to. */
.pt-obs-all { margin-left: 0.5rem; color: var(--accent-text); font-weight: 600; white-space: nowrap; }

/* Observations ------------------------------------------------------------ */

.pt-ob {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 15px;
  margin-bottom: 11px;
}
.pt-ob-head {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  align-items: flex-start;
  flex-wrap: wrap;
}
.pt-ob-head h3 { font-size: 1rem; margin: 0; }
.pt-ob-meta { margin: 0.2rem 0 0; font-size: 0.78rem; color: var(--text-secondary); }
.pt-ob-id { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.73rem; }
.pt-chip {
  flex: 0 0 auto;
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.12rem 0.45rem;
  color: var(--text-secondary);
}
/* Flagged by our own people as worth a look. Sorted to the top of its list as
   well as marked, because a flag below three routine entries is not a flag. */
.pt-ob.is-flagged { border-left: 3px solid #d97706; }
.pt-chip-flag { border-color: #d97706; color: #d97706; font-weight: 700; }

.pt-ob-note { margin: 0.65rem 0 0; font-size: 0.9rem; }
/* A remark left on a checkpoint rather than an account of an incident. */
.pt-ob-note.is-remark { color: var(--text-secondary); font-style: italic; }
.pt-ob-foot { margin-top: 0.75rem; display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.pt-ask {
  background: none;
  border: 1px solid var(--border);
  color: var(--text-secondary);
  border-radius: 6px;
  padding: 0.32rem 0.7rem;
  font-family: 'Barlow', sans-serif;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
}
.pt-ask:hover { border-color: var(--accent); color: var(--accent-text); }
.pt-ev { font-size: 0.75rem; color: var(--text-secondary); }

/* A night's log, under Night by night.
 *
 * The table itself is .quotes-table from dashboard.css. This only caps its
 * height, because a busy night runs to dozens of rows and the sections below
 * it should still be reachable. */
.pt-log { max-height: 440px; overflow-y: auto; }

/* Property list and empty states ------------------------------------------ */

.pt-empty { padding: 32px 0; color: var(--text-secondary); max-width: 60ch; }
.pt-empty p { margin: 0 0 0.6rem; }

.pt-site-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 12px;
}
.pt-site-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 18px;
  text-decoration: none;
  color: var(--text-primary);
  display: flex;
  flex-direction: column;
  gap: 10px;
  transition: border-color 0.15s;
}
.pt-site-card:hover { border-color: var(--accent); }
.pt-site-card h2 { font-size: 1.05rem; margin: 0; }
.pt-site-go { font-size: 0.82rem; color: var(--accent-text); font-weight: 600; }

/* A client's name over its properties, on an admin login's list. */
.pt-site-group {
  font-size: 0.82rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-secondary);
  margin: 24px 0 10px;
}
.pt-site-group:first-child { margin-top: 0; }

/* Call to action ----------------------------------------------------------- */

.pt-cta {
  background: var(--bg-card);
  border: 1px solid var(--accent);
  border-radius: 8px;
  padding: 22px;
  text-align: center;
  margin-top: 30px;
}
.pt-cta h2 { margin: 0 0 0.25rem; font-size: 1.15rem; }
.pt-cta p { color: var(--text-secondary); margin: 0 auto 14px; max-width: 56ch; }

/* Sign in.
 *
 * The page itself is built on login.css and the public header, so it matches
 * the employee sign-in instead of being a second card that does the same job
 * differently. This is the only rule login.css has no equivalent for: the note
 * telling somebody to ring the office, which sits between the button and the
 * back link. */
.login-help {
  margin: 1.25rem 0 0;
  padding-top: 1.25rem;
  border-top: 1px solid var(--border);
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--text-secondary);
  text-align: center;
}
.login-help a { color: var(--accent-text); font-weight: 600; white-space: nowrap; }

@media (max-width: 600px) {
  .pt-ob-head { flex-direction: column; }
  /* Nine hour labels will not fit side by side on a phone; the hover title
     and the shape of the band still carry it. */
  .pt-hour-label { display: none; }
  .pt-trend-label { font-size: 0.55rem; }
}

/* The period, on a phone.
 *
 * dashboard-shell.css hides .dash-main-desc below 900px, on the reasoning that
 * a section's description is the first thing to give up for space. Here that
 * line is not a description: it is which week this report covers, and without
 * it the page does not say what it is showing. So the portal keeps it. */
@media (max-width: 900px) {
  .portal-page .dash-main-desc {
    display: block;
    font-size: 0.8rem;
  }
}

/* Client services ---------------------------------------------------------
 *
 * The request form, moved in from the public site. The controls themselves are
 * the dashboard's (.jf-row, .jf-group), so what follows is only the page
 * around them.
 */

/* The phone callout above the form. Its border is the one warm colour in the
   portal, because it is the one block on the page saying "not this form". */
.pt-now {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-left: 3px solid #d97706;
  border-radius: 0 8px 8px 0;
  padding: 16px 18px;
  margin-bottom: 22px;
}
.pt-now-body { flex: 1 1 320px; min-width: 0; }
.pt-now-label {
  display: block;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 1.2px;
  font-weight: 700;
  color: #d97706;
  margin-bottom: 0.3rem;
}
.pt-now p { margin: 0; font-size: 0.9rem; }
.pt-now-call { flex: 0 0 auto; white-space: nowrap; }
.pt-now-calls { display: flex; flex-direction: column; gap: 8px; flex: 0 0 auto; }
.pt-now-calls .pt-now-call { text-align: center; }

/* Banners: the outcome of a request, and anything wrong with the form. Green
   and red are the two statuses this page has, on the same left edge the
   assurance line uses so the page has one shape for "here is a result". */
.pt-alert {
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: 0 8px 8px 0;
  padding: 15px 17px;
  margin-bottom: 20px;
  background: var(--bg-card);
}
.pt-alert h2 { margin: 0 0 0.3rem; font-size: 1.05rem; }
.pt-alert p { margin: 0; font-size: 0.9rem; }
.pt-alert.is-ok    { border-left-color: #16a34a; }
.pt-alert.is-error { border-left-color: #ef4444; font-weight: 600; }

/* The notice at the top of every signed-in page (portal/head.ejs).
 *
 * Meant to be noticed: a card in the page's own colours read as part of the
 * report and was scrolled past. A tint of the accent, a full accent border
 * with a heavier left edge, an icon and text a step larger than the body.
 * The tint is an alpha of the accent, so it holds in dark mode as well. */
.pt-notice {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 20px;
  padding: 14px 18px;
  background: rgba(147, 51, 234, 0.12);
  border: 1px solid rgba(147, 51, 234, 0.5);
  border-left: 5px solid var(--accent);
  border-radius: 8px;
  color: var(--text-primary);
}
.pt-notice p { margin: 0; font-size: 1rem; line-height: 1.45; }
.pt-notice strong { font-weight: 700; }
.pt-notice-icon { flex-shrink: 0; color: var(--accent-text); }

/* Form beside the "what you can ask for" list. One column until there is
   genuinely room for two, because the form is the page and a squeezed form is
   worse than a long one. */
.pt-svc { display: grid; gap: 24px; align-items: start; }
/* Grid children default to min-width:auto, which lets a long word or a wide
   control push the column past its track instead of wrapping. */
.pt-svc-form, .pt-svc-aside { min-width: 0; }
@media (min-width: 1240px) {
  .pt-svc { grid-template-columns: minmax(0, 1fr) 320px; }
}

/* The first section in a column sits against the block above it, which
   already has margin of its own. */
.pt-section-first { margin-top: 0; }

/* Patrol coverage: the charts and the full log, grouped under one heading
   below what needs acting on. Its sections are a level down, so their
   headings are h3 and sized a step under the page's h2s. */
.pt-group {
  margin-top: 40px;
  padding-top: 20px;
  border-top: 1px solid var(--border);
}
.pt-group-title { font-size: 1.15rem; margin: 0; }
.pt-group > .pt-sub { margin-bottom: 0; }
.pt-section > h3 { font-size: 1rem; margin: 0 0 12px; }
.pt-section > h3:has(+ .pt-sub) { margin-bottom: 0; }

/* Night by night ----------------------------------------------------------
 *
 * A tile per night, a calendar strip that wraps: seven to a row on a laptop,
 * three on a phone. A whole night with no visit has a red edge and one well
 * under the usual an amber one; the two ends of a report, which are only half
 * here, are dashed so they are not read as quiet.
 *
 * A night's log is in the page already and shown by :target, so the tile is a
 * plain link. scroll-margin keeps both clear of the sticky site header. */
#nights, .pt-night-log { scroll-margin-top: 90px; }
/* auto-fit rather than auto-fill, so a week's seven cards stretch to the full
   width of the tiles above instead of leaving empty columns at the end. */
.pt-nights {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
  gap: 8px;
}
.pt-night {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 12px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: inherit;
  text-decoration: none;
  min-width: 0;
}
a.pt-night:hover { border-color: var(--accent); }
a.pt-night:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pt-night-day { font-size: 0.78rem; font-weight: 700; color: var(--text-secondary); }
.pt-night-count { font-size: 0.8rem; color: var(--text-secondary); }
.pt-night-n {
  font-family: 'Rajdhani', sans-serif;
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.1;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.pt-night-times { font-size: 0.75rem; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.pt-night-flag {
  margin-top: 4px;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.pt-night--none { border-left: 3px solid #dc2626; }
.pt-night--none .pt-night-flag { color: #dc2626; }
.pt-night--low { border-left: 3px solid #d97706; }
.pt-night--low .pt-night-flag { color: #d97706; }
.pt-night--partial { border-style: dashed; }

.pt-night-log {
  display: none;
  margin-top: 14px;
  padding: 12px 14px;
  background: var(--bg-card);
  border: 1px solid var(--accent);
  border-radius: 8px;
}
.pt-night-log:target { display: block; }
.pt-night-log-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.pt-night-log-head strong { display: block; }
.pt-night-log-head .muted { font-size: 0.82rem; }
.pt-night-flagged td { background: rgba(217, 119, 6, 0.08); }
/* Where each visit begins in a night's log: a rule above it and its number
   under the time, so the rows read as the visits the tile counted. */
.pt-visit-start td { border-top: 2px solid var(--border); }
.pt-visit-no {
  display: block;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--accent-text);
}

.pt-asks { list-style: none; margin: 0; padding: 0; }
.pt-asks li + li { margin-top: 13px; }
.pt-asks strong { display: block; font-size: 0.88rem; }
.pt-asks span { display: block; font-size: 0.78rem; color: var(--text-secondary); line-height: 1.55; }

.pt-svc-send { margin-top: 24px; }
.pt-svc-note { margin: 0.8rem 0 0; font-size: 0.8rem; color: var(--text-secondary); max-width: 60ch; }

/* The hint under the chosen request type. Ported from clients.css, which the
   portal does not load. */
.client-hints {
  margin-top: 0.75rem;
  padding-left: 0.9rem;
  border-left: 2px solid var(--accent);
}
.client-hint {
  margin: 0 0 0.5rem;
  font-size: 0.82rem;
  line-height: 1.6;
  color: var(--text-secondary);
}
.client-hints.is-single .client-hint { margin-bottom: 0; }
.client-hint:last-child { margin-bottom: 0; }

/* The entry a request was opened from, named at the top of the form so the
   reader can see the page kept hold of it. */
.pt-about-line {
  margin: 0 0 1rem;
  padding-bottom: 0.9rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.85rem;
  color: var(--text-secondary);
}
.pt-about-line strong { color: var(--text-primary); }

/* "Ask about this" is a link now rather than a button opening a modal, so it
   needs the box shape a button had by default. */
a.pt-ask { display: inline-block; text-decoration: none; }

/* Your account ------------------------------------------------------------ */

.pt-account { max-width: 620px; }
.pt-details-list { margin: 0; display: grid; gap: 10px; }
.pt-details-list > div { display: grid; grid-template-columns: 110px minmax(0, 1fr); gap: 12px; }
.pt-details-list dt { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.8px; color: var(--text-secondary); padding-top: 2px; }
.pt-details-list dd { margin: 0; font-weight: 600; overflow-wrap: anywhere; }
.pt-account form .jf-group { margin-bottom: 14px; }

/* Vacancy Overview ---------------------------------------------------------
 * The same amber as a stale list, for any figure that wants somebody: a
 * long vacancy, a passed move-in, a down unit, a list nobody is keeping. */
.va-table .va-flag { color: #d97706; font-weight: 700; }
.va-table .va-live { color: #16a34a; font-weight: 600; }
