/* ---------------------------------------------------------------------------
   National Reports — application styles.

   Direction: the "Card-based" option, chosen 2026-09-01. The report area is
   composed of distinct raised surfaces — a summary stat row, a controls card,
   and the table as a card — rather than elements floating on the page. That
   was the fix for the old build reading as "plain / unfinished".

   The identity is carried over from the legacy css/style5.css and kept
   deliberately:
     #4b76ab  header bar        #3a6193  active nav
     #c3daee  primary button    #5f89a6  its border
     #a5dea9 / #e4e093 / #e8b1b1  the traffic-light change cells

   What changed from the legacy is the plumbing: one stylesheet instead of
   five, custom properties instead of repeated hex codes, no layout tables, and
   no inline style attributes driving layout.
   --------------------------------------------------------------------------- */

:root {
  --blue-bar:      #4b76ab;
  --blue-active:   #3a6193;
  --blue-hover:    #40699e;
  --blue-ink:      #17324e;
  --btn-bg:        #c3daee;
  --btn-border:    #a3c1dd;
  --btn-border-on: #7ea6cd;

  /* Slate neutrals, from the "Data-dense pro" direction. The blue above is
     kept for the header bar, the primary button and links, so the app still
     reads as itself; everything grey around it got cooler and more precise. */
  --page-bg:       #f8fafc;
  --surface:       #fff;
  --surface-sub:   #f1f5f9;
  --panel:         #eef2f7;

  --line:          #e2e8f0;
  --line-soft:     #eef2f6;
  --line-row:      #f1f5f9;
  --line-mid:      #cbd5e1;

  /* Greys are darker than a typical slate ramp on purpose. The people reading
     these reports skew older, and contrast sensitivity falls with age well
     before acuity does — a pale grey label is harder for them than small text
     is. Every value below clears WCAG AA (4.5:1) on white; the old --text-dim
     was 3.9:1 and failed it outright. */
  --text:          #0f172a;   /* 17.9:1 */
  --text-head:     #0f172a;
  --text-muted:    #55606d;   /*  7.3:1 — was #64748b at 5.4:1 */
  --text-dim:      #5b6673;   /*  6.6:1 — was a pale #7b87xx at 3.9:1, below AA */
  --link:          #1d5296;   /*  7.1:1 — was #2563a8 at 5.9:1 */

  --ok:            #a5dea9;
  --warn:          #e4e093;
  --bad:           #e8b1b1;

  --radius:        10px;
  --radius-sm:     7px;
  --radius-xs:     6px;

  --shadow: 0 1px 2px rgba(16,24,40,0.05), 0 4px 10px -4px rgba(16,24,40,0.06);

  --font: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --font-num: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;
}

*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--page-bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 15px;
  -webkit-font-smoothing: antialiased;

  /* The PAGE never scrolls sideways — only the report's own scroller does.
     Without this the wide table drags the whole document with it on a phone,
     so the header and toolbar slide away while you are reading figures, and
     the row you are on scrolls off the left. The guard is here as well as on
     the individual containers because one missed min-width anywhere else
     would bring the behaviour straight back. */
  max-width: 100%;
  overflow-x: hidden;
}

a { color: var(--link); text-decoration: none; }
a:hover { color: #14396a; text-decoration: underline; }

:focus-visible { outline: 2px solid #1d4f8f; outline-offset: 2px; }

/* --- Header bar ---------------------------------------------------------- */

#topbar {
  background: var(--blue-bar);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
  color: #f5f5f5;
}

.topbar-inner {
  display: flex;
  align-items: stretch;
  padding: 0 18px;
  min-height: 48px;
  flex-wrap: wrap;
}

.brand {
  display: flex;
  align-items: center;
  color: #fff;
  font-weight: 700;
  font-size: 15px;
  padding-right: 26px;
  white-space: nowrap;
}
.brand:hover { text-decoration: none; }

/* The nav must stretch the full height of the bar, or the tabs sit at the top
   edge while the brand and the right-hand links stay centred — and the active
   item's underline floats away from the bottom of the bar. */
#topbar nav { display: flex; align-items: stretch; }

#topbar nav ul {
  display: flex;
  align-items: stretch;
  margin: 0;
  padding: 0;
  list-style: none;
  flex-wrap: wrap;
}
#topbar nav li { display: flex; }
#topbar nav li a {
  display: flex;
  align-items: center;
  padding: 0 15px;
  color: #eaf1f8;
  font-size: 14.5px;
  line-height: 1;
}
#topbar nav li a:hover { background: var(--blue-hover); color: #fff; text-decoration: none; }

/* The active item gets a light underline as well as the darker fill, so it
   still reads as selected in a screenshot or a black-and-white printout. */
#topbar nav li.active a {
  background: var(--blue-active);
  color: #fff;
  font-weight: 600;
  box-shadow: inset 0 -3px 0 #a8c8ea;
}

.topbar-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 14px;
  white-space: nowrap;
}
.topbar-right a { color: #eaf1f8; }
.topbar-right a:hover { color: #fff; text-decoration: none; }

/* Icon buttons in the header bar. 34px square keeps the target comfortable —
   the icon itself is 19px. */
.icon-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-xs);
  color: #dbe7f3;
}
.icon-btn:hover { background: var(--blue-hover); color: #fff; text-decoration: none; }

/* --- User menu ------------------------------------------------------------ */

.usermenu { position: relative; }
.usermenu > summary {
  display: flex;
  align-items: center;
  gap: 3px;
  height: 34px;
  padding: 0 7px 0 9px;
  border-radius: var(--radius-xs);
  color: #dbe7f3;
  cursor: pointer;
  list-style: none;
}
.usermenu > summary::-webkit-details-marker { display: none; }
.usermenu > summary::marker { content: ''; }
.usermenu > summary:hover { background: var(--blue-hover); color: #fff; }
.usermenu[open] > summary { background: var(--blue-active); color: #fff; }
.usermenu[open] .caret { transform: rotate(180deg); }
.usermenu .caret { transition: transform 0.12s ease; }

.usermenu-panel {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 190px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: 0 8px 24px -6px rgba(15, 23, 42, 0.30);
  padding: 6px;
  z-index: 40;
}
.usermenu-who { padding: 8px 10px 10px; border-bottom: 1px solid var(--line-soft); margin-bottom: 6px; }
.usermenu-name { font-weight: 700; color: var(--text); font-size: 14px; }
.usermenu-level { font-size: 14px; color: var(--text-muted); text-transform: capitalize; }
.usermenu-panel a {
  display: block;
  padding: 8px 10px;
  border-radius: var(--radius-xs);
  color: var(--text);
  font-size: 14px;
}
.usermenu-panel a:hover { background: var(--surface-sub); color: var(--text); text-decoration: none; }

/* --- Page body ----------------------------------------------------------- */

#content { padding: 20px; }

h1 { font-size: 21px; font-weight: 600; letter-spacing: -0.01em; margin: 0 0 14px; }
h2 { font-size: 15px; font-weight: 600; margin: 22px 0 9px; color: var(--text-head); }

footer {
  padding: 16px 20px 28px;
  color: var(--text-muted);
  font-size: 14px;
}

/* --- Card ---------------------------------------------------------------- */

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.card-head {
  padding: 12px 16px;
  border-bottom: 1px solid var(--line-soft);
  display: flex;
  align-items: center;
  gap: 10px;
}
.card-title { font-size: 14px; font-weight: 700; color: var(--text-head); }
.card-meta  { margin-left: auto; font-size: 14px; color: var(--text-muted); }
.card-body  { padding: 14px 16px 16px; }

.pill {
  font-size: 14px;
  color: var(--text-muted);
  background: #eef2f6;
  border-radius: 20px;
  padding: 2px 10px;
  white-space: nowrap;
}

/* --- Buttons ------------------------------------------------------------- */

.btn {
  display: inline-block;
  background: var(--surface-sub);
  border: 1px solid #e0e5ea;
  border-radius: var(--radius-xs);
  color: var(--text);
  padding: 5px 12px;
  font-size: 14px;
  font-family: var(--font);
  cursor: pointer;
  text-align: center;
}
.btn:hover { background: #eaeff4; text-decoration: none; }

.btn.is-on {
  background: var(--btn-bg);
  border-color: var(--btn-border-on);
  color: var(--blue-ink);
  font-weight: 700;
}

.btn-primary {
  background: var(--btn-bg);
  border-color: var(--btn-border);
  color: var(--blue-ink);
  font-weight: 600;
  font-size: 14.5px;
  padding: 10px 0;
  border-radius: var(--radius-sm);
}
.btn-primary:hover { background: #b4cfe6; }

.btn-wide { display: block; width: 100%; }
.btn-tall { line-height: 1.35; }

/* --- Forms --------------------------------------------------------------- */

.field { margin-bottom: 13px; }
.field label { display: block; margin-bottom: 5px; font-size: 14px; color: var(--text-muted); }
.field input[type=text],
.field input[type=password],
.field input[type=date],
.field select {
  font-family: var(--font);
  font-size: 14px;
  padding: 8px 10px;
  border: 1px solid var(--line-mid);
  border-radius: var(--radius-xs);
  width: 100%;
  background: #fff;
  color: var(--text);
}
/* Deliberately light. Everything else on the page was darkened for contrast,
   but a placeholder is the one thing that must NOT look like content — these
   are example numbers, and at label weight they read as values already
   entered. This is below the AA text threshold on purpose: it is a hint, not
   information, and nothing is lost if it goes unread. */
.field input::placeholder { color: #a3adb9; }
.field input:focus { border-color: #7ea6cd; outline: none; box-shadow: 0 0 0 3px rgba(126,166,205,0.18); }

/* Clear button inside a text field, shown only once there is something to
   clear. A native type=search X exists in WebKit but not Firefox, and cannot
   be styled to match, so it is built here instead. */
/* The × is positioned against `.ctl`, which wraps the INPUT alone. Anchoring
   it to `.field` centred it on the label and the box together, so it floated
   above the box on every field that has a label. */
.ctl { position: relative; display: block; }
.field.has-clear input { padding-right: 32px; }
.clear-x {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: #6b7480;
  cursor: pointer;
  padding: 0;
}
.clear-x:hover { background: #e8edf1; color: var(--text); }
.clear-x[hidden] { display: none; }

/* --- Toolbar strip ------------------------------------------------------- */
/* One 44px row replacing the two stacked button rows and the stat cards. */

#content.flush { padding: 0; }

.subbar {
  padding: 8px 18px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

/* ONE line that wraps only when it runs out of room. Everything sits in
   reading order — Period, its choices, Compare, its choice — and the two
   resolved ranges are pushed to the right. */
.subbar-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 12px;
}

.subbar-when {
  font-size: 14px;
  color: #475569;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.subbar-when b { color: var(--text); margin-right: 3px; }

/* A group is unbreakable. The row wraps between groups, never inside one, so
   a caption cannot be orphaned from its control nor TP from LP. */
.subbar-group {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: nowrap;
}

/* The Period group is the one exception: with eight segments it may have to
   break internally on a narrow screen rather than force a scrollbar. */
.subbar-group:first-child { flex-wrap: wrap; }

/* The readouts take the slack, so they sit right while the controls stay
   left — and travel together when the line wraps. */
.subbar-group--dates { margin-left: auto; gap: 16px; }


.subbar-label {
  font-size: 14px;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
  flex: 0 0 auto;
}

/* Segmented control: links, so everything stays bookmarkable and needs no JS. */
.seg {
  display: flex;
  border: 1px solid var(--line-mid);
  border-radius: var(--radius-xs);
  overflow: hidden;
  background: var(--surface);
}
.seg a {
  padding: 4px 11px;
  font-size: 14px;
  color: #334155;
  border-right: 1px solid var(--line);
  white-space: nowrap;
}
.seg a:last-child { border-right: 0; }
.seg a:hover { background: var(--surface-sub); text-decoration: none; }
.seg a.on { background: var(--blue-bar); color: #fff; font-weight: 600; }
.seg a.on:hover { background: var(--blue-active); }

.subbar-form { display: flex; align-items: center; gap: 6px; margin: 0; }
.subbar-form select {
  font-family: var(--font);
  font-size: 14px;
  padding: 4px 8px;
  border: 1px solid var(--line-mid);
  border-radius: var(--radius-xs);
  background: var(--surface);
  color: #334155;
  /* Sized to its longest ordinary label ("No comparison"), not to whatever
     the widest option happens to be — a select grows to fit its content and
     one long entry can push the whole strip into wrapping. */
  max-width: 170px;
}
.subbar-link { font-size: 14px; white-space: nowrap; }

/* A hairline between the report actions and the account menu, so they do not
   read as one undifferentiated row of icons. */
.topbar-sep {
  width: 1px;
  height: 20px;
  background: rgba(255, 255, 255, 0.22);
  margin: 0 5px;
}


/* --- Workspace: left panel + report area --------------------------------- */

.workspace { display: flex; align-items: flex-start; }

/* 360px, not the legacy's 425.
   425 was the width of the old `<td width="425">` and nothing in the panel
   needs it — the deepest thing the tree draws is a store indented one step
   under its group, which fits comfortably. The extra 65px came out of the
   report, which is the part with fourteen columns and a horizontal scrollbar.
   This was already the width below 1200px; now it is the width everywhere,
   so the panel stops changing size as the window crosses that line. */
.sidebar { flex: 0 0 360px; max-width: 360px; }

/* min-width:0 is doing real work: a flex item defaults to min-width:auto and
   so refuses to shrink below its content, which for a 14-column table means
   the whole column grows and takes the page with it. max-width:100% covers
   the column-direction case on mobile, where the same item is stretched. */
.mainarea { flex: 1 1 auto; min-width: 0; max-width: 100%; }

/* Flush layout: the panel is a rail against the left edge with its own
   border, not a floating card, and the report gets the rest. */
.workspace.flush .sidebar {
  background: var(--surface);
  border-right: 1px solid var(--line);
  min-height: calc(100vh - 140px);
}
.workspace.flush .sidebar > .card {
  border: 0;
  border-radius: 0;
  box-shadow: none;
  background: transparent;
}
.workspace.flush .mainarea { padding: 16px 18px 40px; }

/* ---------------------------------------------------------------------------
   RESPONSIVE

   The toolbar strip is the tightest thing on the page — it carries two range
   controls, both resolved date ranges and two actions on one 44px line. As
   width runs out it sheds detail in order of how little it is needed, so the
   controls themselves survive longest:

     <  950  the side rail narrows to 300px
     <  700  the rail becomes a slide-in drawer; the header nav is dropped and
             its items move into the drawer and the account menu
     <  760  padding tightens and toolbar groups may break internally

     The rail NEVER stacks full width above the report — a panel lying across
     the top pushes the figures below the fold and gives the tree width it has
     no use for. It narrows instead, then becomes a drawer.

   The order matters: a control you cannot reach is a broken page, a caption
   you cannot see is not.
   --------------------------------------------------------------------------- */


/* The rail NARROWS as room runs out — it never stacks full width above the
   report. A wide panel lying across the top pushes the figures below the fold
   and gives the tree width it has no use for. Below 700px it stops being a
   rail at all and becomes the drawer. */
@media (max-width: 950px) {
  .sidebar { flex: 0 0 300px; max-width: 300px; }
  .workspace.flush .mainarea { padding: 14px 14px 40px; }
}

/* --- The panel as a drawer on small screens ------------------------------- */
/* Below 700px, stacking the panel above the report buries the figures under a
   long tree. It slides in over the page instead, on demand, and the report
   keeps the whole screen the rest of the time.

   Note this state is NOT in the URL, unlike `hide=1` on the desktop layout:
   it is a property of the viewport and the moment, not of the report being
   looked at, and it should not travel in a shared link. */

.panel-backdrop { display: none; }
.drawer-head { display: none; }
.menu-pages { display: none; }

@media (max-width: 700px) {
  .workspace.flush .sidebar {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    width: min(88vw, 360px);
    z-index: 60;
    overflow-y: auto;
    background: var(--surface);
    border-right: 1px solid var(--line);
    border-bottom: 0;
    box-shadow: 0 0 34px rgba(15, 23, 42, 0.28);
    transform: translateX(-100%);
    transition: transform 0.18s ease;
  }
  body.panel-open .workspace.flush .sidebar { transform: none; }

  .panel-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.45);
    z-index: 55;
  }
  .panel-backdrop[hidden] { display: none; }

  /* Stop the page behind scrolling while the drawer is over it. */
  body.panel-open { overflow: hidden; }

  /* The header nav is gone on a phone: its four panel tabs are in the drawer
     below, and its two page links are in the account menu. That reclaims the
     two wrapped rows the tab strip was eating above the report. */
  #topbar nav { display: none; }
  .menu-pages {
    display: block;
    border-bottom: 1px solid var(--line-soft);
    padding-bottom: 6px;
    margin-bottom: 6px;
  }

  .drawer-head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 10px;
    border-bottom: 1px solid var(--line);
    position: sticky;
    top: 0;
    background: var(--surface);
    z-index: 2;
  }

  .drawer-tabs {
    display: flex;
    flex: 1 1 auto;
    border: 1px solid var(--line-mid);
    border-radius: var(--radius-xs);
    overflow: hidden;
  }
  .drawer-tabs a {
    flex: 1 1 0;
    text-align: center;
    padding: 7px 4px;
    font-size: 14px;
    color: #334155;
    border-right: 1px solid var(--line);
    white-space: nowrap;
  }
  .drawer-tabs a:last-child { border-right: 0; }
  .drawer-tabs a.on { background: var(--blue-bar); color: #fff; font-weight: 600; }
  .drawer-tabs a:hover { text-decoration: none; }

  .drawer-close {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    border: 1px solid var(--line);
    border-radius: var(--radius-xs);
    background: var(--surface);
    color: var(--text-muted);
    cursor: pointer;
  }
  .drawer-close:hover { background: var(--surface-sub); color: var(--text); }
}

@media (prefers-reduced-motion: reduce) {
  .workspace.flush .sidebar { transition: none; }
}

@media (max-width: 760px) {
  /* The TP/LP pair is 340px of nowrap text, which alone overflows a phone.
     Let the groups break internally once there is nothing left to give. */
  .subbar-group { flex-wrap: wrap; }
  .subbar-group--dates { margin-left: 0; gap: 6px 14px; }

  .subbar { padding: 6px 12px; }
  .seg a { padding: 6px 9px; }
  #content { padding: 14px; }
  .card-body { padding: 12px 13px 14px; }
  .card-head { padding: 11px 13px; }
  .topbar-inner { padding: 0 10px; }
  .brand { padding-right: 12px; font-size: 15px; }
  #topbar nav li a { padding: 0 11px; }
  .rep-head { gap: 6px; }
  .rep-title { font-size: 16px; }
}

.sidebar-actions { display: flex; gap: 10px; }

/* Hiding the panel is a class on <body>, not a server-side omission, so the
   toggle can flip it instantly. Scoped above the drawer breakpoint: below it
   the same panel is a fixed drawer, and display:none would stop it opening. */
@media (min-width: 701px) {
  body.panel-hidden .sidebar { display: none; }
}

/* Two icon states, one shown at a time. */
.panel-toggle .ico-show { display: none; }
body.panel-hidden .panel-toggle .ico-hide { display: none; }
body.panel-hidden .panel-toggle .ico-show { display: inline; }

/* Panel show/hide toggle, first thing in the header bar. */
.panel-toggle {
  display: flex;
  align-items: center;
  padding: 0 12px 0 0;
  margin-right: 12px;
  color: #cfe0f0;
  border-right: 1px solid rgba(255,255,255,0.18);
}
.panel-toggle:hover { color: #fff; text-decoration: none; }

/* Panel-wide options, at the foot of whichever panel is showing. */
.panel-foot {
  border-top: 1px solid var(--line-soft);
  padding: 13px 16px 15px;
  background: #fbfcfd;
  border-radius: 0 0 var(--radius) var(--radius);
}
.opt {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  cursor: pointer;
}
.opt input { margin: 0; }
.opt-hint {
  margin: 5px 0 0 24px;
  font-size: 14px;
  color: var(--text-muted);
  line-height: 1.7;
}
/* The same icon as the header toggle, so the sentence points at something the
   reader can actually recognise on screen. */
.opt-hint .ico {
  vertical-align: -3px;
  margin: 0 1px;
  color: #5c6570;
}
kbd {
  font-family: var(--font-num);
  font-size: 14px;
  background: #fff;
  border: 1px solid var(--line-mid);
  border-bottom-width: 2px;
  border-radius: 4px;
  padding: 0 5px;
  color: var(--text);
}

/* --- Report heading ------------------------------------------------------ */
/* The stat cards are gone: three of their four figures repeat the table's
   Total row. The one that did NOT — how many stores actually reported —
   survives in the meta line, because silence and a zero look identical in the
   table and only one of them is a problem. */

.rep-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
.rep-title { font-size: 17px; font-weight: 600; letter-spacing: -0.01em; }
.rep-meta { font-size: 14px; color: var(--text-muted); }

/* States what the rows were filtered to. Prints — on paper there is no panel
   beside it to check and no URL to read. */
.rep-filter {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  color: var(--blue-ink);
  background: #eaf1f8;
  border: 1px solid #c2d8ec;
  border-radius: 20px;
  padding: 3px 12px;
}
.rep-filter a { font-size: 13px; }

/* --- Saved views ---------------------------------------------------------- */
/* Beside the report title, not inside a panel: a saved view holds the whole
   report — selection, both periods, the open panel — not one panel's search. */

.saved { position: relative; margin-left: auto; }
.saved > summary {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 11px;
  border: 1px solid var(--line-mid);
  border-radius: var(--radius-xs);
  background: var(--surface);
  color: #334155;
  font-size: 14px;
  cursor: pointer;
  list-style: none;
  white-space: nowrap;
}
.saved > summary::-webkit-details-marker { display: none; }
.saved > summary::marker { content: ''; }
.saved > summary:hover { background: var(--surface-sub); }
.saved[open] > summary { background: var(--surface-sub); border-color: var(--btn-border-on); }

.saved-panel {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  width: 330px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: 0 8px 24px -6px rgba(15, 23, 42, 0.30);
  padding: 10px;
  z-index: 30;
}

.saved-list { list-style: none; margin: 0 0 10px; padding: 0; max-height: 46vh; overflow: auto; }
.saved-list li { display: flex; align-items: center; gap: 6px; }
.saved-list a {
  flex: 1 1 auto;
  display: block;
  padding: 7px 8px;
  border-radius: var(--radius-xs);
  font-size: 14px;
  color: var(--text);
}
.saved-list a:hover { background: var(--surface-sub); text-decoration: none; }
.saved-list form { flex: 0 0 auto; margin: 0; }

.saved-del {
  border: 0;
  background: none;
  color: var(--text-dim);
  font-size: 17px;
  line-height: 1;
  padding: 4px 7px;
  border-radius: var(--radius-xs);
  cursor: pointer;
}
.saved-del:hover { background: #fbe9e9; color: #a24b4b; }

.saved-empty, .saved-error { font-size: 14px; margin: 0 0 10px; }
.saved-empty { color: var(--text-muted); }
.saved-error { color: #a24b4b; }

.saved-add { display: flex; gap: 6px; border-top: 1px solid var(--line-soft); padding-top: 10px; }
.saved-add input[type=text] {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--font);
  font-size: 14px;
  padding: 7px 9px;
  border: 1px solid var(--line-mid);
  border-radius: var(--radius-xs);
}
.saved-add .btn { flex: 0 0 auto; }
.rep-meta .warn { color: #9a6b1e; font-weight: 600; }

/* --- Location treeview ---------------------------------------------------- */
/* Twisties are CSS triangles: the legacy needed Font Awesome for its +/- and
   jQuery for the widget, and both are gone. */

.tree-toolbar { display: flex; gap: 12px; align-items: center; font-size: 14px; margin-bottom: 10px; }
.tree-status { margin-left: auto; }

/* Divides the selection actions from the view actions. */
.tree-sep {
  width: 1px;
  height: 13px;
  background: var(--line-mid);
  margin: 0 2px;
}

.tree, .tree ul { list-style: none; margin: 0; padding: 0; }
/* No inner scrollbar: the panel grows and the page scrolls instead. With every
   branch collapsed by default the tree is nine rows, so there is nothing to
   scroll until you open something — and a nested scroll area inside a card is
   the thing that made it feel cramped. */
.tree {
  font-size: 14.5px;   /* matches the report table */
  border-top: 1px solid var(--line-soft);
  padding-top: 8px;
}
.tree ul { padding-left: 18px; }

.tree li { position: relative; line-height: 2.25; }
.tree li.collapsed > ul { display: none; }
.tree li[hidden] { display: none; }

.tree label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  padding-right: 5px;
  border-radius: 3px;
}
.tree label:hover { background: #eef4fa; }
.tree input[type=checkbox] { margin: 0; }
.tree label:has(input:checked) { font-weight: 700; }

.tree .tw {
  background: none; border: 0; padding: 0;
  width: 18px; height: 18px; cursor: pointer;
  vertical-align: middle; position: relative;
}
.tree .tw::before {
  content: '';
  position: absolute; top: 4px; left: 4px;
  border-left: 7px solid #64707d;
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  transform: rotate(90deg);
  transform-origin: 3px 5px;
}
.tree .tw:hover::before { border-left-color: var(--text); }
.tree li.collapsed > .tw::before { transform: rotate(0deg); }

.tree .lvl-region > label,
.tree .lvl-all > label { font-weight: 700; }

/* Stores are the only level with no twisty, so their label would start where
   the group's TWISTY sits rather than under the group's text — reading as the
   same level, or even outdented. This adds back the twisty's width plus its
   gap, so a store sits one clear step in from its group. It matters most when
   a state holds several groups, where the run of stores otherwise looks like
   a continuation of the group list. */
.tree .lvl-store { padding-left: 24px; }   /* twisty 18px + its 6px gap */
.tree .lvl-store > label { color: #3d454c; }

/* --- MIA panel ------------------------------------------------------------ */

/* A count on the card head, so the tab's own list tells you how bad it is
   without opening it. Amber, not red: a store that missed yesterday is worth
   a look, not an alarm — the ones that ARE alarming get .is-stale below. */
.badge-warn {
  margin-left: auto;
  background: var(--warn);
  color: #4a4413;
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
  padding: 4px 8px;
  border-radius: 999px;
  font-variant-numeric: tabular-nums;
}

/* The way back out. Clicking a store in this list narrows the page to it, and
   the tree that would widen it again is on another panel. */
.mia-scope {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding-bottom: 12px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--line);
}
.mia-scope-what { font-size: 14px; color: var(--text-muted); }
.mia-scope-what strong { color: var(--text); }
.mia-scope .btn { margin-left: auto; white-space: nowrap; }

.mia-lead  { margin: 0 0 10px; font-size: 14px; color: var(--text); }
.mia-sub   { font-size: 14px; margin: 18px 0 6px; padding-top: 14px;
             border-top: 1px solid var(--line); }
.mia-clear { margin: 0; font-size: 14px; color: var(--text); font-weight: 600; }

.mia-list { list-style: none; margin: 0; padding: 0; }
.mia-list li {
  padding: 8px 0;
  border-bottom: 1px solid var(--line-row);
}
.mia-list li:last-child { border-bottom: 0; }

/* The store currently loaded, matching how the tree marks a selection. */
.mia-list li.is-on {
  background: var(--line-soft);
  margin: 0 -16px;
  padding-left: 16px;
  padding-right: 16px;
}

.mia-list a { text-decoration: none; display: block; }
.mia-list a:hover .mia-name { text-decoration: underline; }

.mia-name  { display: block; font-size: 15px; color: var(--link); font-weight: 600; }
.mia-group { display: block; font-size: 13px; color: var(--text-dim); }

.mia-since {
  display: block;
  margin-top: 2px;
  font-size: 13px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

/* Past a month of silence this is not a late upload, it is a store nobody has
   noticed stopped — which is the whole reason to have this list. */
.mia-since.is-stale { color: #8a3535; font-weight: 600; }

/* --- Row detail (the old Info popup) -------------------------------------- */

.sp-info { width: 1%; padding-left: 4px; padding-right: 4px; }

.info-btn {
  display: inline-block;
  width: 20px;
  height: 20px;
  line-height: 18px;
  text-align: center;
  border: 1px solid var(--line-mid);
  border-radius: 50%;
  font-size: 13px;
  font-weight: 700;
  font-style: italic;
  font-family: Georgia, 'Times New Roman', serif;   /* a legible lowercase i */
  color: var(--blue-ink);
  background: var(--btn-bg);
  border-color: var(--btn-border);
  text-decoration: none;
}

/* NO hover fill. There is one of these on every row, so a background that
   lights up under the pointer means the table flickers all the way down as the
   mouse crosses it — distracting while reading figures, which is what the page
   is for. The button is already visibly a control standing still.

   Focus is a different case and keeps its ring: someone tabbing through needs
   to know where they are, and that is one element at a time, not a trail. */
.info-btn:hover { background: var(--btn-bg); text-decoration: none; }

/* Hidden until asked for, BY CSS ALONE. :target means the information button
   works with JavaScript off — js/info.js only upgrades it to a toggle that
   does not scroll or push history. */
.info-row { display: none; }
.info-row:target,
.info-row.is-open { display: table-row; }

/* An open panel has to read as a PANEL, not as more table.
   On the report's own slate tint it was near enough to the header and Total
   rows that its edges disappeared and you could not tell where the row's
   detail began or ended. Now it is a deeper ground, ruled top and bottom in
   the button blue, with a thick blue edge down the left tying it to the row
   it belongs to. */
/* NO RULE ALONG THE TOP.
   A line there separated the panel from the very row it belongs to, so it read
   as a new section rather than as that row opening up. Without it the tinted
   ground runs straight out of the row, and the blue edge down the left ties
   the two together. The bottom keeps a rule, because something has to say
   where the panel ends before the next row's figures start. */
/* The same tint a row shows under the pointer (#eef4fa). Using it here is not
   only a colour that works — it says the panel IS that row, opened. The row
   lights up in this shade when you point at it; opening it keeps the shade and
   grows. The white chart and the blue edge carry the definition, so the ground
   itself does not have to be dark to read as separate. */
/* Written as `.tbl.sp tbody tr.info-row > td` and not `.info-row > td`, which
   is what it was and why nothing appeared to happen: `.tbl.sp tbody td` paints
   every body cell white and outscores a lone class. This has to beat it. */
.tbl.sp tbody tr.info-row > td {
  background: #eef4fa;
  border-bottom: 2px solid var(--btn-border);
  padding: 0;
}

.info-card {
  padding: 14px 16px 16px 16px;
  border-left: 4px solid var(--blue-bar);

  /* The CARD is 900px and fits on screen; the CELL under it spans all fourteen
     columns and does not. Scroll right to reach Prod Qty and a statically
     placed card would slide off to the left with the Name column. Sticky keeps
     it against the left edge of the scrolling area, so the contacts stay
     readable wherever the table is scrolled to. */
  position: sticky;
  left: 0;
  max-width: 900px;
}


.info-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.info-head strong { font-size: 15px; }
/* Close sits in the action row with the others, at the end. It is a thing you
   do with this panel, not chrome bolted to its corner. */
.info-close::after { content: " \00d7"; }

/* (The panel's chart lived here and has been removed — see the note at the top
   of _info.php. The row's own sparkline is the trend; this panel is for who to
   call.) */

/* ONE COLUMN, down the left.
   This was two side-by-side columns — figures on the left, contacts on the
   right — and a group row emptied half of it, leaving a phone number stranded
   across an expanse of nothing. Stacked, the panel reads top to bottom in the
   order you want it: what it sold, who to call, what to do next. Capped so the
   lines stay short enough to scan rather than running the table's full width. */
.info-body { max-width: 460px; }

.info-fig-v { font-size: 20px; font-weight: 700; margin-right: 6px; }
.info-delta { margin: 4px 0 12px; font-size: 14px; }
.info-delta.is-up   { color: #1f6b33; }
.info-delta.is-down { color: #98342f; }

.info-facts { display: grid; grid-template-columns: auto 1fr; gap: 3px 14px; margin: 0 0 12px; font-size: 14px; }
.info-facts dt { color: var(--text-muted); }
.info-facts dd { margin: 0; font-variant-numeric: tabular-nums; }

.info-contact { margin-bottom: 12px; font-size: 14px; }
.info-contact a { display: block; }
.info-role { display: block; font-size: 13px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.03em; }
.info-name { display: block; font-weight: 600; }

.info-links { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 16px; }

/* Screen-reader-only text. Nothing uses it since the Trend heading was widened
   to cover the information column, but it is the standard way to label an
   unlabelled control and the next one will want it. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* --- Directory: director rows above their stores --------------------------- */

/* The group's own record, holding the director. Tinted and ruled above so the
   list reads as a hierarchy — the legacy's shape — rather than as one long
   run of rows where a director is indistinguishable from a store. */
.dir-group > td {
  background: var(--surface-sub);
  border-top: 2px solid var(--line-mid);
  font-size: 14px;
}
.dir-group-name { font-weight: 700; margin-right: 8px; }
.dir-group-note { font-size: 13px; font-style: italic; }

/* Its stores sit one step in, the same cue the tree uses for a store under
   its group. */
.dir-store > td:first-child { padding-left: 22px; }

/* --- Find similar ----------------------------------------------------------
   ONE form at every level, seeded from whatever is selected. A card showing
   the store's figures, a tolerance picker and a second button briefly appeared
   when a single store was open; they are gone, along with their styles. The
   seeded ranges already say what the card said. */
.sim-manual { margin-top: 4px; }

/* --- Feed owner badge ------------------------------------------------------ */

/* Which company uploads a store's figures: TW Thriftworks, SR Secure Retail.
   Two neutral colours, not a good/bad pair — neither provider is a problem. */
.feed {
  display: inline-block;
  min-width: 2.4em;
  text-align: center;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.03em;
  padding: 2px 6px;
  border-radius: var(--radius-xs);
  border: 1px solid transparent;
}
.feed-tw { background: #e3edf7; color: #1d4f7c; border-color: #c9dcee; }
.feed-sr { background: #efe9f7; color: #4b3a72; border-color: #ddd2ee; }
.feed-\? { background: var(--surface-sub); color: var(--text-dim); border-color: var(--line); }

/* --- Leaders panel -------------------------------------------------------- */

/* Four lists, one at a time. The legacy stacked all six open in a 425px column
   and you scrolled past the ones you did not want.

   This is the toolbar's .seg control, not the .btn.is-on the Dates panel uses,
   and the difference is load-bearing: on Dates, "selected" means THIS IS WHAT
   THE REPORT SHOWS. Here it only means "this is the list you are looking at" —
   loading these stores is the separate button below. Two meanings sharing one
   appearance is how a highlighted button starts telling people something that
   is not true. */
.tier-pick {
  display: grid;
  grid-template-columns: 1fr 1fr;
  margin-bottom: 14px;
}
.tier-pick a {
  text-align: center;
  padding: 7px 8px;
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
/* Right-hand column and bottom row carry no inner edge. */
.tier-pick a:nth-child(2n)  { border-right: 0; }
.tier-pick a:nth-last-child(-n+2) { border-bottom: 0; }

.tier-list .btn-primary { margin-top: 12px; }

.lead-list { list-style: none; margin: 0; padding: 0; counter-reset: none; }
.lead-list li {
  display: grid;
  grid-template-columns: 2.4em 1fr auto;
  align-items: baseline;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--line-row);
}
.lead-list li:last-child { border-bottom: 0; }
.lead-list li.is-on {
  background: var(--line-soft);
  margin: 0 -16px;
  padding-left: 16px;
  padding-right: 16px;
}
.lead-list a { text-decoration: none; min-width: 0; }
.lead-list a:hover .mia-name { text-decoration: underline; }

/* The store's true place in the ranking, not its position in this short list. */
.lead-rank {
  font-size: 14px;
  font-weight: 700;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.lead-value {
  font-size: 14px;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* --- Tables -------------------------------------------------------------- */

.tbl { border-collapse: separate; border-spacing: 0; width: 100%; font-size: 14.5px; }
.tbl th, .tbl td { padding: 9px 11px; text-align: left; border-bottom: 1px solid var(--line-row); }
.tbl thead th { background: #f6f8fa; font-weight: 600; font-size: 14px; color: #3a4a5a; border-bottom: 1px solid var(--line); }
.tbl td.num, .tbl th.num { text-align: right; font-variant-numeric: tabular-nums; }
.tbl tbody tr:last-child td { border-bottom: 0; }

/* --- Sales and Production report ----------------------------------------- */

.sp-wrap + .sp-wrap { margin-top: 18px; }

.sp-up { font-size: 14px; margin-bottom: 6px; }

/* White marks the DATA and nothing else.
   The card, its header, the column headers and the Total row all sit on the
   slate tint; only the body rows are white. That is what makes the figures
   read as the content and everything else as chrome — and it is the thing
   that was praised about direction C. */
.sp-wrap > .card { background: var(--surface-sub); }
.sp-wrap > .card > .card-head { background: transparent; border-bottom: 1px solid var(--line); }
.tbl.sp tbody td { background: var(--surface); }

/* Row hover, EXCEPT on an expanded detail row.
   Highlighting a one-line row under the pointer helps you track across
   fourteen columns. Doing it to an open detail panel repaints a whole card —
   chart, contacts and all — every time the mouse crosses it, which is movement
   with nothing to say. `hidden` rows are excluded for free by :not(). */
.tbl.sp tbody tr:not(.info-row):hover td,
.tbl.sp tbody tr:not(.info-row):hover td:first-child { background: #eef4fa; }

/* The section name lives in the CARD HEADER above the table, not in the table.
   (The legacy put it in the first header cell on a blue fill; the chosen
   design moved it out, which also frees the width that cell was taking.) */
.tbl.sp thead tr th.sp-name { min-width: 150px; }

/* Wide table scrolls inside its own card; the page never scrolls sideways.
   Capped so the header can stick — with 150+ stores the column labels used to
   scroll away and you lost track of which figure was which. */
.tbl-scroll { overflow: auto; max-height: 68vh; max-width: 100%; }

.tbl.sp { font-size: 14.5px; }
.tbl.sp th, .tbl.sp td { padding: 9px 11px; border-bottom: 1px solid var(--line-row); }
.tbl.sp thead th { text-align: center; background: #f6f8fa; font-size: 14px; }

/* Sticky header rows. */
.tbl.sp thead th { position: sticky; z-index: 2; }
.tbl.sp thead tr:first-child th { top: 0; }
.tbl.sp thead tr:nth-child(2) th { top: 30px; }

/* THE PINNED NAME COLUMN — and the selector bug that made it look broken.
   -----------------------------------------------------------------------
   `th:first-child` matches the first cell of EVERY row. The header has two
   rows: row 1 is Name | Trend | Sales Amt | ..., but row 2 is TP | LP | Chg,
   so row 2's first child is the Sales Amt TP header. The old rule pinned
   THAT to left:0 as well, parking it on top of the Name column — which is
   why "Name" and "TP" both appeared stuck at the left edge.

   Scoping the header half to `thead tr:first-child` fixes it. Only these
   three cells are ever pinned: the Name header, each body row's name, and
   the Total label. */
/* `tbody tr:not(.info-row)` matters as much as the thead scoping above: a
   detail row holds ONE cell spanning the table, so it is `td:first-child` too,
   and it was being pinned, shadowed and painted white as though it were a name
   cell. That white is what hid the panel's background. */
.tbl.sp thead tr:first-child th:first-child,
.tbl.sp tbody tr:not(.info-row) td:first-child,
.tbl.sp tfoot td:first-child {
  position: sticky;
  left: 0;
  background: var(--surface);
  box-shadow: 1px 0 0 var(--line);
}
.tbl.sp thead tr:first-child th:first-child { z-index: 5; background: var(--panel); }
.tbl.sp tbody tr:not(.info-row) td:first-child { z-index: 1; }
.tbl.sp tfoot  td:first-child { z-index: 1; background: var(--panel); }

/* THE SAME `th:first-child` TRAP AS THE STICKY COLUMN ABOVE, and it went
   unfixed here when that one was corrected.
   The header has two rows. Row 2 is TP | LP | Chg | TP | ..., so ITS first
   child is the Sales Amt TP heading — and this rule left-aligned it, leaving
   one numeric heading out of step with the eleven beside it while its own
   figures stayed right-aligned. Scoped to the first header row, which is the
   only one where "first child" means the Name column. */
.tbl.sp thead tr:first-child th:first-child,
.tbl.sp td:first-child { text-align: left; font-weight: 500; }
.tbl.sp thead tr:first-child th:first-child { vertical-align: bottom; font-weight: 600; }
.tbl.sp tfoot td:first-child { font-weight: 700; }

/* Every heading sits on the same baseline. Without this the rowspan headings
   (Name, Trend) centre themselves in a cell two rows tall while TP/LP/Chg sit
   in the shorter second row, so the words do not line up even though each is
   aligned correctly within its own cell. */
.tbl.sp thead th { vertical-align: bottom; }

/* TP / LP / Chg headings stay CENTRED — `.tbl.sp thead th` above already does
   it, and nothing here should override it.
   Right-aligning them to sit over their right-aligned figures was tried and
   was wrong: the headings are a row of labels and read as a row, so they want
   to agree with EACH OTHER. What actually looked broken was TP alone, pushed
   left by the `th:first-child` rule, and that is fixed at its source above. A
   centred "Sales Amt" over three centred sub-headings is the shape that reads
   as one block. */

/* Repeated after the sticky-column rules so hover still reaches the pinned
   first cell, which sets its own background. Same exclusion as above. */
.tbl.sp tbody tr:not(.info-row):hover td,
.tbl.sp tbody tr:not(.info-row):hover td:first-child { background: #eef4fa; }

/* Scrolled away from the left edge, the pinned column gains a real shadow so
   the sliver of the next column past its edge reads as passing underneath. */
.tbl-scroll.scrolled .tbl.sp thead tr:first-child th:first-child,
.tbl-scroll.scrolled .tbl.sp tbody tr:not(.info-row) td:first-child,
.tbl-scroll.scrolled .tbl.sp tfoot td:first-child {
  box-shadow: 6px 0 8px -4px rgba(15, 23, 42, 0.28), 1px 0 0 var(--line-mid);
}

/* A rule between metric groups so each metric reads as a unit.
   Marked with a class rather than nth-child: the group is three columns wide
   with LP shown and two without, so any positional selector would silently
   draw the lines in the wrong places when LP is toggled. */
.tbl.sp .sp-group { border-left: 1px solid var(--line); }
.tbl.sp .sp-sub { font-weight: 500; font-size: 14px; color: #5b6673; }
.tbl.sp td.gstart,
.tbl.sp th.gstart { border-left: 1px solid var(--line); }

/* Trend column. Narrow; the sparkline is a fixed 54x15 SVG, centred in the
   cell because a graphic pushed against the column border reads as clipped. */
.tbl.sp .sp-trend {
  width: 66px;
  text-align: center;
  border-left: 1px solid var(--line-row);
  padding: 4px 6px;
}

/* The HEADING, though, is left-aligned like Name.
   Centring it made "Trend" the only centred label on a row where every other
   heading is left (Name) or right (TP/LP/Chg), and one word out of step is
   what the eye catches. Aligning the graphic and aligning the word are
   separate questions, and only the word sits in a row of other words. */
/* The HEADING keeps the table's normal vertical padding, even though the cells
   below it are tight.
   The 4px above buys room for a 15px sparkline in a dense row; applied to the
   heading it dropped the word "Trend" five pixels below every other label,
   because they all sit on the bottom of their cell and this one's bottom was
   5px lower. That was the misalignment — vertical, not horizontal, which is
   why nudging it sideways changed nothing visible.

   Centred, like every other heading except Name, now that it spans the
   information column as well. */
.tbl.sp thead th.sp-trend {
  vertical-align: bottom;
  text-align: center;
  padding-top: 9px;
  padding-bottom: 9px;
}


/* Figures use the SAME face as everything else, with tabular-nums for fixed
   width digits. A monospace face aligns columns too, but Consolas at ~12px is
   thin and cramped and was what made these tables hard to read — the
   alignment was never the reason to use it. */
.tbl.sp td.num {
  font-variant-numeric: tabular-nums;
  font-size: 14.5px;
  letter-spacing: 0;
}
.tbl.sp td.lp { color: #5b6673; }
.tbl.sp .chg { font-weight: 700; white-space: nowrap; }
.chg-dir { font-size: 14px; margin-right: 2px; }

/* The Total row is not pinned either — it sits at the end of a short section,
   and pinning it was the other half of the overlap problem. */
.tbl.sp tfoot td { background: var(--panel); font-weight: 700; border-top: 1px solid var(--line); }

/* --- Users admin ---------------------------------------------------------- */

/* Page tabs. Plain links — the page reloads on save anyway, so a tab in the
   URL survives that and can be linked to. */
.tabs {
  display: flex;
  gap: 2px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}
.tabs a {
  padding: 9px 15px;
  font-size: 14px;
  color: var(--text-muted);
  border: 1px solid transparent;
  border-bottom: 0;
  border-radius: var(--radius-xs) var(--radius-xs) 0 0;
  margin-bottom: -1px;
}
.tabs a:hover { background: var(--surface-sub); text-decoration: none; color: var(--text); }
.tabs a.on {
  background: var(--surface);
  border-color: var(--line);
  color: var(--text);
  font-weight: 600;
}
.tab-n {
  font-size: 13px;
  color: var(--text-dim);
  background: var(--surface-sub);
  border-radius: 20px;
  padding: 1px 7px;
  margin-left: 3px;
}

/* The form column is capped so a long group list does not run off screen. */
.form-col { max-width: 620px; }

/* A filter sitting in a card header. */
.filter-form {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 0 18px;
}
.filter-form label {
  font-size: 13px;
  color: var(--text-muted);
  white-space: nowrap;
}
.filter-form select {
  font-family: var(--font);
  font-size: 14px;
  padding: 5px 8px;
  border: 1px solid var(--line-mid);
  border-radius: var(--radius-xs);
  background: var(--surface);
  color: #334155;
  max-width: 260px;
}
@media (max-width: 760px) {
  .card-head { flex-wrap: wrap; }
  .filter-form { margin-left: 0; width: 100%; }
  .filter-form select { flex: 1 1 auto; max-width: none; }
}

.inline { display: inline; margin: 0; }
.nowrap { white-space: nowrap; }
.muted  { color: var(--text-dim); }

tr.is-editing td { background: #eef4fa; }

.btn-danger { border-color: #d9a3a3; background: #fbe9e9; }
.btn-danger:hover { background: #f6dcdc; }

/* A generated password, shown once. Monospace and roomy because it gets read
   aloud down a phone. */
.pw {
  font-family: var(--font-num);
  font-size: 15px;
  letter-spacing: 0.08em;
  background: #fff;
  border: 1px solid var(--line-mid);
  border-radius: 4px;
  padding: 2px 8px;
}
.pw-warn { color: #a24b4b; font-weight: 600; }

/* A blank that matters — not the same as a dash meaning "nothing to show". */
.missing { color: #9a6b1e; font-size: 13px; }

.group-picker {
  max-height: 240px;
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-xs);
  padding: 8px 10px;
  background: #fff;
}
.group-picker .opt { margin-bottom: 2px; }

/* --- Sign in ------------------------------------------------------------- */

/* The sign-in page has no application chrome — see layout_bare_head(). The
   <body class="bare"> is the whole viewport and the card centres inside it,
   which is what fixes the old screen's real problem: the form sat near the top
   with a third of the page empty underneath it. */

body.bare {
  min-height: 100vh;
  min-height: 100dvh;   /* not the browser-chrome-inclusive height on phones */
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Sits a little above the true centre. Extra padding on the BOTTOM rather
     than a transform or a negative margin: the card stays centred inside the
     padding box, so on a short window the body simply grows and scrolls
     instead of the top of the card being clipped where nobody can reach it.
     Capped in px so a tall monitor does not push it into the ceiling. */
  padding: 24px 24px min(14vh, 120px);
  background: var(--page-bg);
}

/* The seal, very faint, very large, behind everything.
   The old sign-in page did this and it was the one part of it worth keeping:
   it says whose reports these are without a word of marketing. Kept under 4%
   so it reads as watermark rather than decoration, and pinned so it never
   competes with the card for attention. */
body.bare::before {
  content: "";
  position: fixed;
  inset: 0;
  background: url("../img/svdp_logo_black.png") no-repeat center / min(680px, 105vmin);
  /* Low enough to read as paper texture rather than as a picture. At 0.07 the
     lettering around the rim became legible and started competing with the
     card for attention, which is the opposite of what a watermark is for. */
  opacity: 0.045;
  pointer-events: none;
}

.signin {
  position: relative;   /* above the watermark */
  width: 100%;
  max-width: 400px;
}

.signin-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 34px 32px 28px;
  /* Two shadows rather than one: a tight contact shadow that keeps the edge
     crisp, and a wide soft one for lift. A single heavy shadow is what made
     the legacy look dated. */
  box-shadow:
    0 1px 2px rgba(15, 23, 42, 0.05),
    0 12px 32px -12px rgba(15, 23, 42, 0.16);
}

/* At 54px the seal's lettering turned to mush and read as a smudge above the
   title. It needs to be either legible or absent; 66px at full strength is the
   smallest size where it still looks like the seal. */
.signin-seal {
  display: block;
  margin: 0 auto 15px;
  width: 66px;
  height: 66px;
}

.signin h1 {
  text-align: center;
  font-size: 21px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--blue-ink);
  margin: 0 0 3px;
}

.signin-sub {
  text-align: center;
  font-size: 13px;
  color: var(--text-dim);
  margin: 0 0 24px;
}

.signin .field { margin-bottom: 15px; }

.signin .field label {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-muted);
  margin-bottom: 6px;
}

/* Bigger and calmer than the app's inline form controls. This is the one
   screen where somebody is typing rather than reading, and on a phone anything
   under 16px makes iOS zoom the page on focus. */
.signin .field input {
  width: 100%;
  font-size: 16px;
  padding: 11px 13px;
  border: 1px solid var(--line-mid);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text);
  transition: border-color .12s ease, box-shadow .12s ease;
}

.signin .field input:hover { border-color: #b3c1d1; }

.signin .field input:focus {
  outline: none;
  border-color: var(--blue-bar);
  box-shadow: 0 0 0 3px rgba(75, 118, 171, 0.18);
}

/* Solid blue here, unlike everywhere else in the app.
   The shared .btn-primary is a pale fill, which is right in a toolbar where
   several buttons sit side by side and none should shout. This screen has
   exactly one action, and a pale button as the only thing to press reads as
   disabled. Same blue as the header bar, so it is still the app's colour. */
.signin .btn-primary {
  margin-top: 9px;
  width: 100%;
  background: var(--blue-bar);
  border-color: var(--blue-bar);
  color: #fff;
  font-size: 15px;
  font-weight: 600;
  padding: 11px 16px;
  border-radius: 8px;
  transition: background-color .12s ease;
}
.signin .btn-primary:hover  { background: var(--blue-hover);  border-color: var(--blue-hover); }
.signin .btn-primary:active { background: var(--blue-active); border-color: var(--blue-active); }
.signin .btn-primary:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(75, 118, 171, 0.35);
}

@media (prefers-reduced-motion: reduce) {
  .signin .btn-primary { transition: none; }
}

.signin .error { margin-bottom: 18px; }

.signin-help {
  margin: 20px 0 0;
  padding-top: 17px;
  border-top: 1px solid var(--line-soft);
  text-align: center;
  font-size: 13px;
  color: var(--text-dim);
}

.signin-foot {
  margin: 18px 0 0;
  text-align: center;
  font-size: 12px;
  color: var(--text-dim);
}

@media (max-width: 420px) {
  .signin-card { padding: 28px 22px 24px; border-radius: 10px; }
}

@media (prefers-reduced-motion: reduce) {
  .signin .field input { transition: none; }
}

.error {
  background: #fbe9e9;
  border: 1px solid #e3bcbc;
  border-radius: var(--radius-xs);
  padding: 10px 13px;
  margin-bottom: 14px;
  font-size: 14.5px;
}
.notice {
  background: #eef4fa;
  border: 1px solid #c2d8ec;
  border-radius: var(--radius-xs);
  padding: 10px 13px;
  margin-bottom: 14px;
  font-size: 14.5px;
}
.hint {
  font-size: 14px;
  color: var(--text-muted);
  margin: 10px 0 0;
  max-width: 76ch;
}

/* --- Stub banner (removed as each page is finished) ---------------------- */

.stub {
  background: #fffbe9;
  border: 1px solid #e6d59a;
  border-radius: var(--radius-xs);
  padding: 11px 14px;
  margin-bottom: 16px;
  font-size: 14px;
}
.stub-src { color: var(--text-muted); font-size: 14px; }
.stub code { background: #f4edd6; padding: 1px 4px; border-radius: 3px; }

/* --- Print --------------------------------------------------------------- */

@media print {
  @page { size: landscape; }
  .noprint { display: none !important; }
  body { background: #fff; }
  #content { padding: 0; }
  .card { border: 0; box-shadow: none; }
  .workspace { display: block; }
  .tbl-scroll { overflow: visible; max-height: none; }
  .tbl.sp { font-size: 9.5pt; }
  .tbl.sp thead { display: table-header-group; }
  .tbl.sp thead th, .tbl.sp tfoot td, .tbl.sp td:first-child { position: static; }
  .tbl.sp tr { page-break-inside: avoid; }

  /* The information column keeps its CELL on paper but loses its button.
     Marking the cells .noprint instead would delete a column the "Trend"
     heading spans, and every heading after it would sit one column out. */
  .info-btn { visibility: hidden; }
  .tbl.sp .sp-info { width: 0; padding: 0; border: 0; }

  /* An open detail panel prints with the row it belongs to; a closed one is
     display:none already and never reaches the page. */
  .info-row .info-close { display: none; }
  .stats { page-break-inside: avoid; }
}
