/* ===========================================================================
   Pool Chemical Log

   Organised as: tokens, base, layout, then components grouped by the module
   they belong to. Class names are the contract with the JavaScript that
   renders them, so they are kept stable.
   =========================================================================== */

/* --- Brand and design tokens ----------------------------------------------
   One place for every colour, size and space. Nothing below this block
   hard-codes a value that belongs in it.

   A NOTE ON RED, WHICH IS NOT A BRAND COLOUR
   ------------------------------------------
   Red means one thing in this app: a chemical reading outside its safe
   range. It is a safety signal, not decoration, and it earns its weight by
   appearing nowhere else. The brand palette is deliberately navy, slate and
   amber - no red, and nothing warm enough to be mistaken for it at a glance
   or in peripheral vision.

   Amber is the only warm colour, and it sits at a hue far from the alert
   red. If a future colour choice needs thinking about, the test is: could
   someone scanning a log confuse this with an out-of-range value? If there
   is any doubt, do not use it. */

:root {
  /* Brand. */
  --brand-navy:       #1b2a4a;
  --brand-navy-deep:  #121d33;   /* pressed and hover states */
  --brand-navy-tint:  #eef1f6;   /* selected backgrounds */
  --brand-slate:      #5c6470;
  --brand-slate-tint: #eef0f2;
  --brand-amber:      #e8a33d;   /* fills, the logo mark, indicators */
  --brand-amber-deep: #8a5a00;   /* amber as TEXT, dark enough to read */
  --brand-amber-tint: #fdf4e3;

  /* Neutrals, tuned to sit under navy rather than the old teal. */
  --ink:        #16202b;
  --ink-soft:   #3d4a5c;
  --muted:      var(--brand-slate);
  --line:       #dee2e8;
  --line-soft:  var(--brand-slate-tint);
  --surface:    #ffffff;
  --canvas:     #f4f6f9;
  --raised:     #f9fafc;

  /* The primary interactive colour is the brand navy. These names are what
     the components use, so the mapping lives here and nowhere else. */
  --accent:       var(--brand-navy);
  --accent-deep:  var(--brand-navy-deep);
  --accent-tint:  var(--brand-navy-tint);

  /* RESERVED FOR OUT-OF-RANGE READINGS. Unchanged, and used nowhere else. */
  --danger:       #b3261e;
  --danger-tint:  #fdeceb;

  /* Amber, aliased so existing "needs attention but not an alert" uses keep
     working while pointing at the brand colour. */
  --warn:       var(--brand-amber-deep);
  --warn-tint:  var(--brand-amber-tint);

  /* Type scale. A small set of steps used consistently beats many sizes
     chosen ad hoc. */
  --t-xs:   0.6875rem;
  --t-sm:   0.8125rem;
  --t-base: 0.9375rem;
  --t-md:   1.0625rem;
  --t-lg:   1.25rem;
  --t-xl:   1.625rem;

  /* Spacing, on a 4px rhythm. */
  --s1: 0.25rem;  --s2: 0.5rem;   --s3: 0.75rem;  --s4: 1rem;
  --s5: 1.5rem;   --s6: 2rem;     --s7: 3rem;

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

  --shadow:    0 1px 2px rgba(27, 42, 74, 0.05), 0 1px 3px rgba(27, 42, 74, 0.07);
  --shadow-lg: 0 2px 8px rgba(27, 42, 74, 0.08), 0 8px 24px rgba(27, 42, 74, 0.08);

  --font: 'Public Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
          'Helvetica Neue', Arial, sans-serif;

  --page-width: 1120px;
}

/* --- Base ---------------------------------------------------------------- */

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: var(--t-base);
  line-height: 1.55;
  color: var(--ink);
  background: var(--canvas);
  -webkit-font-smoothing: antialiased;
}

/* Digits line up in columns. In a log read by scanning for anomalies,
   ragged numerals hide the very thing being looked for. */
input[type="number"], input[type="datetime-local"],
table, .crumb, .resume-path, .audit-when {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

h1, h2, h3 { margin: 0; font-weight: 600; letter-spacing: -0.011em; }
h1 { font-size: var(--t-xl); letter-spacing: -0.018em; }
h2 { font-size: var(--t-lg); }
h3 { font-size: var(--t-md); }
p  { margin: 0; }

a { color: var(--accent); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 3px;
}

/* --- Site header and navigation ------------------------------------------
   A top bar rather than a side rail: the readings table is wide and already
   scrolls sideways, and a fixed side nav would take width from exactly the
   thing that needs it most. */

/* ---------------------------------------------------------------------------
   The shell: a rail on the left, a bar across the top
   ---------------------------------------------------------------------------
   The navigation outgrew a row. Nine destinations fitted only because five
   were hidden in dropdowns, and there are more coming.

   The rail is position:fixed and <body> carries padding to clear it. That is
   what let this become a two-column layout without editing thirteen HTML
   files: every page is still <div id="site-header"></div> then <main>, and
   they are still siblings.

   Below --rail-breakpoint the rail slides off-canvas and the top bar's button
   brings it back. A real breakpoint, not a squeezed desktop - this is used at
   the poolside on a phone, where a permanent rail would eat the width the
   readings form needs. */

:root {
  --rail-width: 15.5rem;
  --rail-breakpoint: 900px;
}

.site-rail {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: var(--rail-width);
  z-index: 40;
  display: flex;
  flex-direction: column;
  gap: var(--s4);
  padding: var(--s4) var(--s3);
  overflow-y: auto;
  background: var(--brand-navy);
  color: #f2f5fa;
}

/* Set by renderSiteHeader(), so only pages that actually draw a rail clear
   space for one. A class rather than :has(.site-rail) - the renderer knows
   this for certain, and knowing beats inferring. */
body.has-rail { padding-left: var(--rail-width); }

.site-topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: var(--s3);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

/* The button appears below the breakpoint, and on a collapsed desktop. Above
   it, with the rail present, a control to reveal it would do nothing. */
.rail-toggle { display: none; }

body.rail-collapsed .rail-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 2.5rem;
  height: 2.5rem;
  margin-left: var(--s3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
  font-size: 1.05rem;
  cursor: pointer;
}

/* --- collapsed on desktop ------------------------------------------------

   HIDES the rail rather than narrowing it to icons. There are no icons, and
   nine text labels squeezed into 4rem is nine truncated words. The top bar's
   button brings it back - the same control the narrow breakpoint uses, so
   this is a remembered preference rather than a third layout. */

body.rail-collapsed { padding-left: 0; }

body.rail-collapsed .site-rail {
  transform: translateX(-100%);
  transition: transform 160ms ease;
}

/* The version, under the wordmark. Quiet: it is a fact you look up, not one
   you are being told. */
.rail-version {
  margin: calc(var(--s2) * -1) 0 0;
  padding: 0 var(--s2);
  font-size: var(--t-xs);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.03em;
  color: #7f92b0;
}

.rail-collapse {
  margin-top: var(--s3);
  padding: var(--s2) var(--s3);
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: #8598b5;
  font: inherit;
  font-size: var(--t-xs);
  text-align: left;
  cursor: pointer;
}

.rail-collapse:hover { background: #24365c; color: #ffffff; }

/* Below the breakpoint the rail is already a drawer, and an in-drawer control
   to hide the drawer is one more thing than the scrim and Escape already do. */
@media (max-width: 900px) { .rail-collapse { display: none; } }

/* The strip is the bar's content, so it fills it. Left to itself it drew its
   own raised panel that stopped partway across, which read as a stray box.
   The bar already carries the background and the rule underneath. */
.site-topbar .context-strip {
  flex: 1 1 auto;
  min-width: 0;
  background: none;
  border-bottom: 0;
}

.site-topbar .context-inner { margin: 0; max-width: none; }

.rail-scrim { display: none; }

/* --- the brand, on navy --------------------------------------------------- */

.brand {
  display: flex;
  align-items: center;
  gap: var(--s3);
  text-decoration: none;
  color: inherit;
  line-height: 1.25;
  padding: var(--s2);
}

.brand-words { display: flex; flex-direction: column; }

/* Sized to the wordmark rather than a round number, so the two read as one
   lockup instead of an icon sitting next to some text. */
.brand-mark {
  width: 30px;
  height: 30px;
  flex: 0 0 auto;
  display: block;
}

.brand-name {
  font-size: var(--t-md);
  font-weight: 700;
  letter-spacing: -0.015em;
  color: #ffffff;
}

.brand-sub {
  font-size: var(--t-xs);
  color: #9fb0c9;
  letter-spacing: 0.01em;
}

/* The shield's body is brand navy, which is also the rail's background - so on
   the rail it vanished and left a floating amber tick. Lightened here rather
   than by adding a second logo: one mark, recoloured for its ground.
   first-of-type is the shield; the second path is the tick, fill:none with an
   amber stroke, and must keep it. */
.site-rail .brand-mark path:first-of-type { fill: #f2f5fa; }

/* --- the links ------------------------------------------------------------ */

.site-nav {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

/* .nav-link is NOT only a rail link. The context strip uses it too - "Choose
   an attraction", "Start over" - and those sit on white in the top bar. So the
   base is the light-ground version it always was, and the rail overrides it
   below.
   Getting this backwards made "Choose an attraction" near-invisible: pale grey
   intended for navy, rendered on white. */
.nav-link {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  padding: var(--s2) var(--s3);
  border-radius: var(--radius-sm);
  font-size: var(--t-sm);
  font-weight: 560;
  color: var(--ink-soft);
  text-decoration: none;
  white-space: nowrap;
}

.nav-link:hover { background: var(--raised); color: var(--ink); }

.nav-link.is-current { background: var(--accent-tint); color: var(--accent-deep); }

/* --- the same links, on the rail's navy ---------------------------------- */

.site-rail .nav-link {
  display: flex;
  justify-content: space-between;
  color: #c8d4e4;
}

.site-rail .nav-link:hover { background: #24365c; color: #ffffff; }

.site-rail .nav-link.is-current {
  background: var(--brand-amber);
  color: var(--brand-navy);
  font-weight: 650;
}

/* A group is a labelled section now rather than a dropdown. The children are
   simply visible: a rail has the vertical room a header row did not. */
.nav-section { margin-top: var(--s3); }

.nav-section-label {
  margin: 0 0 var(--s1);
  padding: 0 var(--s3);
  font-size: 0.6875rem;
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: #8598b5;
}

/* A stubbed module reads as available but clearly not finished. */
.nav-soon {
  font-size: 0.625rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #9fb0c9;
  background: #24365c;
  border-radius: 3px;
  padding: 0.05rem 0.28rem;
}

.nav-link.is-current .nav-soon {
  color: var(--brand-navy);
  background: rgba(27, 42, 74, 0.16);
}

/* --- who is signed in, at the foot of the rail ---------------------------- */

/* margin-top:auto pins it to the bottom however short the nav is. */
.rail-foot {
  margin-top: auto;
  padding-top: var(--s3);
  border-top: 1px solid #2c3f66;
}

/* --- narrow: the rail becomes a drawer ------------------------------------ */

@media (max-width: 900px) {
  body.has-rail { padding-left: 0; }

  .site-rail {
    transform: translateX(-100%);
    transition: transform 160ms ease;
    box-shadow: 0 0 2rem rgba(9, 16, 31, 0.4);
  }

  body.rail-open .site-rail { transform: none; }

  .rail-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2.75rem;
    height: 2.75rem;
    margin-left: var(--s2);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--ink);
    font-size: 1.1rem;
    cursor: pointer;
  }

  .rail-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 35;
    background: rgba(9, 16, 31, 0.45);
  }

  .rail-scrim[hidden] { display: none; }

  /* The tagline crowds the wordmark in a drawer opened one-handed. */
  .brand-sub { display: none; }

  /* The strip is a caption on a phone, not a second header. Left at the
     desktop padding it wrapped to two lines and pushed the page down by
     roughly a fifth of the screen, which is a lot of a phone to spend saying
     which pool you are on. */
  .site-topbar .context-inner {
    padding: var(--s2) var(--s3);
    gap: var(--s1) var(--s3);
    font-size: var(--t-sm);
  }
}

/* --- the profile portal's own header -------------------------------------

   .site-header and .header-bar belong to the PROFILE PORTAL now, and only to
   it. The operational app used them until the rail replaced them; the portal
   never used the app's navigation on purpose - see profile-header.js - so it
   keeps a plain bar of its own.

   Left here rather than renamed because the portal's markup is the only thing
   that references them, and a rename would be churn in a file that is not
   changing. */

.site-header {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

.header-bar {
  max-width: var(--page-width);
  margin: 0 auto;
  padding: var(--s3) var(--s5);
  display: flex;
  align-items: center;
  gap: var(--s5);
  flex-wrap: wrap;
}

/* The portal's header sits on white, so the brand words need the app's ink
   colours back rather than the rail's light-on-navy. */
.site-header .brand-name { color: var(--ink); }
.site-header .brand-sub { color: var(--muted); }

/* --- the signed-in person, at the foot of the rail ------------------------ */

.rail-foot .user-chip {
  display: flex;
  align-items: center;
  gap: var(--s2);
  flex-wrap: wrap;
  padding: var(--s2);
  border-radius: var(--radius-sm);
  text-decoration: none;
}

.rail-foot .user-chip:hover { background: #24365c; }
.rail-foot .user-chip-name { color: #ffffff; }

/* The role badge keeps its own colours elsewhere in the app; on navy it needs
   enough contrast to stay legible without shouting. */
.rail-foot .role-badge {
  background: #24365c;
  color: #c8d4e4;
}

/* Motion is a nicety; being able to reach the navigation is not. */
@media (prefers-reduced-motion: reduce) {
  .site-rail { transition: none; }
}

/* --- Context strip: which facility everything on the page refers to ------- */

.context-strip { background: var(--raised); border-bottom: 1px solid var(--line); }

.context-inner {
  max-width: var(--page-width);
  margin: 0 auto;
  padding: var(--s3) var(--s5);
  display: flex;
  align-items: center;
  gap: var(--s4);
  flex-wrap: wrap;
}

.facility-summary {
  flex: 1 1 16rem;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.15rem;
  min-width: 0;
}

.context-label {
  flex-basis: 100%;
  font-size: var(--t-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--muted);
  margin-bottom: 0.1rem;
}

/* A facility name must never break across lines mid-name. */
.facility-summary .crumb {
  font-weight: 600;
  font-size: var(--t-base);
  white-space: nowrap;
  color: var(--ink-soft);
}

.facility-summary .crumb-last { color: var(--accent-deep); font-weight: 600; }
.crumb-sep { color: var(--muted); margin: 0 0.3rem; }

.summary-detail {
  flex-basis: 100%;
  font-size: var(--t-xs);
  color: var(--muted);
  margin-top: 0.1rem;
}

/* --- Page shell ---------------------------------------------------------- */

main {
  max-width: var(--page-width);
  margin: 0 auto;
  padding: var(--s6) var(--s5) var(--s7);
}

.page-head { margin-bottom: var(--s5); }
.page-head h1 { margin-bottom: var(--s1); }

/* The tagline, where the app introduces itself: the dashboard and sign-in.
   Amber rule to the left rather than amber text, which would be too light
   to read comfortably at this size. */
.tagline {
  font-size: var(--t-md);
  color: var(--brand-slate);
  font-weight: 500;
  letter-spacing: 0.01em;
  border-left: 3px solid var(--brand-amber);
  padding-left: var(--s3);
  margin: 0 0 var(--s3);
}

.page-lede {
  color: var(--muted);
  font-size: var(--t-base);
  max-width: 62ch;
}

.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: var(--s5);
  margin-bottom: var(--s5);
}

.panel > h2 { margin-bottom: var(--s2); }
.panel > h2 + .hint { margin-top: calc(var(--s2) * -1); }

.count { font-weight: 400; color: var(--muted); font-size: var(--t-sm); }

.hint {
  font-size: var(--t-sm);
  color: var(--muted);
  margin: 0 0 var(--s4);
  max-width: 70ch;
}

.empty { color: var(--muted); margin: 0; }

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

button { font-family: inherit; }

button.primary,
button.secondary,
button.danger-button {
  border-radius: var(--radius-sm);
  font-size: var(--t-base);
  font-weight: 600;
  padding: 0.55rem 1.05rem;
  cursor: pointer;
  border: 1px solid transparent;
  transition: background-color 0.12s ease, border-color 0.12s ease;
}

button.primary { background: var(--accent); color: #fff; }
button.primary:hover { background: var(--accent-deep); }
button.primary:disabled { opacity: 0.4; cursor: not-allowed; }

button.secondary {
  background: var(--surface);
  color: var(--accent-deep);
  border-color: var(--line);
}
button.secondary:hover { background: var(--accent-tint); border-color: var(--accent); }

button.secondary.small { padding: 0.35rem 0.7rem; font-size: var(--t-sm); }

/* Destructive actions are amber, not red.
   Red belongs to out-of-range readings alone. A red Delete sitting in the
   same table row as a red out-of-range value would blunt both: the alert
   stops meaning "this water is wrong" and starts meaning "something on this
   row is red". Amber still reads as caution, and the confirmation dialogs
   say what will be lost in words rather than relying on colour. */
button.danger-button {
  background: var(--surface);
  color: var(--brand-amber-deep);
  border-color: #e8d3a8;
}
button.danger-button:hover { background: var(--brand-amber-tint); }

button.link {
  background: none;
  border: none;
  padding: 0 0.3rem;
  font-size: var(--t-sm);
  font-weight: 550;
  color: var(--accent-deep);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}
button.link.danger { color: var(--brand-amber-deep); }

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

.field { margin-bottom: var(--s4); }

.field label {
  display: block;
  font-weight: 600;
  font-size: var(--t-sm);
  margin-bottom: var(--s1);
  color: var(--ink-soft);
}

.field input,
.field textarea,
.field select {
  width: 100%;
  padding: 0.5rem 0.65rem;
  font-family: inherit;
  font-size: var(--t-base);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}

.field textarea { line-height: 1.5; resize: vertical; }

.field input:hover, .field textarea:hover { border-color: var(--brand-slate); }

.range-hint {
  display: block;
  font-size: var(--t-sm);
  color: var(--muted);
  margin-top: var(--s1);
}

.optional-tag, .tree-type, .note-icon, .source-badge {
  display: inline-block;
  font-size: var(--t-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  border-radius: 3px;
  padding: 0.08rem 0.36rem;
  vertical-align: 1px;
}

.optional-tag { color: var(--muted); background: var(--line-soft); margin-left: var(--s2); }

/* A validation message, not a chemical alert - and it appears in the very
   form where red means "this reading is out of range". Amber. */
.form-error {
  color: var(--brand-amber-deep);
  font-weight: 600;
  font-size: var(--t-sm);
  margin: 0 0 var(--s3);
}

.form-actions { display: flex; gap: var(--s2); align-items: center; }

/* Out-of-range: colour is never the only signal - .warning carries words.
   .warning IS the chemical alert. It is the one red thing in this app and it
   means a reading is out of range right now. Do not reach for it because a
   fetch failed or a date was mistyped - use .profile-problem, which is amber.
   Two places did exactly that and were corrected. */
.field.out-of-range label { color: var(--danger); }

.field.out-of-range input {
  border-color: var(--danger);
  background: var(--danger-tint);
}

.warning {
  display: block;
  margin-top: var(--s1);
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--danger);
}

/* The form while editing an existing reading rather than creating one. */
.panel.editing { border-color: var(--accent); box-shadow: var(--shadow-lg); }

.panel.editing > h2::after {
  content: 'Editing';
  font-size: var(--t-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #fff;
  background: var(--accent);
  border-radius: 3px;
  padding: 0.12rem 0.4rem;
  margin-left: var(--s2);
  vertical-align: 2px;
}

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

.table-scroll { overflow-x: auto; margin: 0 calc(var(--s5) * -1); padding: 0 var(--s5); }

table.readings, .standards-table, .summary-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-sm);
}

table.readings { white-space: nowrap; }

table.readings th, table.readings td,
.standards-table th, .standards-table td {
  text-align: left;
  padding: 0.6rem 0.7rem;
  border-bottom: 1px solid var(--line-soft);
}

table.readings thead th, .standards-table thead th, .summary-table thead th {
  font-size: var(--t-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  border-bottom: 1px solid var(--line);
  background: none;
  vertical-align: bottom;
}

table.readings tbody tr:hover { background: var(--raised); }

.when { font-weight: 600; color: var(--ink); }

td.cell-out-of-range {
  color: var(--danger);
  background: var(--danger-tint);
  font-weight: 700;
}

td.cell-empty { color: var(--muted); }

.row-actions { white-space: nowrap; text-align: right; }

.header-source { display: block; margin-top: var(--s1); font-weight: 400; }
.header-source .source-badge { margin-left: 0; margin-right: 0.2rem; }

/* --- A reading's note, on its own row ------------------------------------ */

.note-row td {
  padding-top: 0;
  padding-bottom: 0.65rem;
  white-space: normal;
  background: var(--raised);
}

.note-icon { color: var(--muted); background: var(--line-soft); margin-right: var(--s2); }
.note-text { font-size: var(--t-sm); color: var(--ink-soft); line-height: 1.5; }

/* Keep a note visually tied to its reading. */
table.readings tbody tr:has(+ .note-row) td { border-bottom: none; }
table.readings tbody tr:has(+ .note-row):hover + .note-row td { background: var(--raised); }

/* --- Where a range came from ---------------------------------------------- */

.source-badge { margin-left: 0.35rem; white-space: nowrap; }
/* Five sources, told apart by weight and shape rather than by reaching for
   more hues. None of them may be red: these badges sit inches from the
   out-of-range cells they explain. */
.source-default        { background: var(--brand-slate-tint); color: var(--brand-slate); }
.source-classification { background: var(--brand-navy-tint); color: var(--brand-navy); }
.source-account        { background: var(--brand-navy); color: #fff; }
.source-facility       { background: var(--surface); color: var(--brand-navy);
                         box-shadow: inset 0 0 0 1px var(--brand-navy); }
.range-hint .source-badge { margin-left: 0.25rem; }

/* --- Facility tree (Organization) ---------------------------------------- */

.facility-tree, .facility-tree ul { list-style: none; margin: 0; padding-left: 0; }

.facility-tree ul {
  padding-left: var(--s4);
  border-left: 2px solid var(--line-soft);
  margin: var(--s2) 0 var(--s4) var(--s2);
}

.facility-tree li { margin: var(--s2) 0; }

.tree-name { font-weight: 600; }
.tree-account > .tree-name { font-size: var(--t-md); }
.tree-location > .tree-name { color: var(--ink-soft); }
.tree-attraction > .tree-name { font-weight: 500; }

.tree-type { color: var(--muted); background: var(--line-soft); margin-left: var(--s2); }

.facility-actions { white-space: nowrap; margin-left: var(--s1); }

.add-form { display: flex; gap: var(--s2); margin-top: var(--s1); flex-wrap: wrap; }

.add-form input, .add-form select, .classification-picker, #standards-classification {
  padding: 0.35rem 0.5rem;
  font-family: inherit;
  font-size: var(--t-sm);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}

.add-form input { flex: 1; max-width: 16rem; }
.classification-picker { margin-left: var(--s2); }

.transfer-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  margin-bottom: var(--s4);
  padding-bottom: var(--s4);
  border-bottom: 1px solid var(--line-soft);
}

/* --- Account standards ---------------------------------------------------- */

.standards-table { min-width: 30rem; }
.standards-table tbody th { font-weight: 600; color: var(--ink-soft); }

.standards-input {
  width: 5.5rem;
  padding: 0.32rem 0.45rem;
  font-family: inherit;
  font-size: var(--t-sm);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}

/* A box holding a real override, not an inherited placeholder. */
.standards-input.is-override {
  border-color: var(--accent);
  background: var(--accent-tint);
  font-weight: 600;
}

/* --- History -------------------------------------------------------------- */

.audit-list { list-style: none; margin: 0; padding: 0; }

.audit-event {
  display: flex;
  gap: var(--s4);
  padding: var(--s3) 0;
  border-bottom: 1px solid var(--line-soft);
}

.audit-event:last-child { border-bottom: none; }

.audit-when {
  flex: 0 0 11rem;
  font-size: var(--t-sm);
  color: var(--muted);
  padding-top: 0.08rem;
}

.audit-body { flex: 1; min-width: 0; }
.audit-summary { font-weight: 600; font-size: var(--t-base); }
.audit-context { margin-top: 0.1rem; font-size: var(--t-sm); color: var(--muted); }

/* Destructive entries are findable when scanning a long list. */
.audit-event[data-action-kind$='.deleted'] {
  border-left: 3px solid var(--brand-amber);
  padding-left: var(--s3);
}
.audit-event[data-action-kind='reading.restored'] {
  border-left: 3px solid var(--accent);
  padding-left: var(--s3);
}

.audit-changes { list-style: none; margin: var(--s2) 0 0; padding: 0; font-size: var(--t-sm); }

.audit-changes li {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  align-items: baseline;
  padding: 0.08rem 0;
}

.change-label { color: var(--muted); min-width: 8rem; }
.change-from { color: var(--brand-slate); text-decoration: line-through; }
.change-arrow { color: var(--muted); }
.change-to { font-weight: 600; }

.audit-body button { margin-top: var(--s2); }

/* --- Landing picker and dashboard ----------------------------------------- */

.landing-panel { max-width: 40rem; margin-left: auto; margin-right: auto; }

.picker-progress {
  font-size: var(--t-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--muted);
  margin-bottom: var(--s1);
}

.landing-panel h2 { margin-bottom: var(--s4); }

.picker-options {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: var(--s2);
  margin-bottom: var(--s5);
}

.picker-option {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  text-align: left;
  padding: var(--s3) var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  cursor: pointer;
  font: inherit;
  color: var(--ink);
  transition: border-color 0.12s ease, background-color 0.12s ease;
}

.picker-option:hover { border-color: var(--accent); background: var(--accent-tint); }

.picker-option.is-chosen {
  border-color: var(--accent);
  background: var(--accent-tint);
  box-shadow: inset 0 0 0 1px var(--accent);
}

.option-name { font-weight: 600; }
.option-detail { font-size: var(--t-sm); color: var(--muted); }

.picker-actions { display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; }
.picker-empty { padding: var(--s2) 0 var(--s4); }
.picker-empty .empty { margin-bottom: var(--s2); font-weight: 600; color: var(--ink); }

.resume-card {
  display: block;
  width: 100%;
  text-align: left;
  padding: var(--s4) var(--s5);
  margin-bottom: var(--s4);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  background: var(--accent-tint);
  cursor: pointer;
  font: inherit;
  color: var(--ink);
}

.resume-card:hover { background: #e3e9f2; }

.resume-label {
  display: block;
  font-size: var(--t-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--accent-deep);
  margin-bottom: var(--s1);
}

.resume-path { display: block; font-size: var(--t-md); }
.resume-path .crumb { font-weight: 600; }
.resume-path .crumb-last { color: var(--accent-deep); }
.resume-detail { display: block; font-size: var(--t-sm); color: var(--muted); margin-top: 0.2rem; }

/* Module shortcuts on the dashboard. */
.module-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--s3);
}

.module-card {
  display: block;
  padding: var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  text-decoration: none;
  color: inherit;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.module-card:hover { border-color: var(--accent); box-shadow: var(--shadow); }
.module-card h3 { margin-bottom: var(--s1); color: var(--accent-deep); }
.module-card p { font-size: var(--t-sm); color: var(--muted); }

/* --- Import and export ----------------------------------------------------- */

.import-dialog, .import-summary {
  max-width: 40rem;
  margin-left: auto;
  margin-right: auto;
  border-left: 3px solid var(--accent);
}

.import-choice {
  display: grid;
  grid-template-columns: 11rem 1fr;
  gap: var(--s3);
  align-items: start;
  padding: var(--s3) 0;
  border-top: 1px solid var(--line-soft);
}

.choice-detail { font-size: var(--t-sm); color: var(--muted); line-height: 1.5; }

.summary-table { min-width: 20rem; margin-bottom: var(--s4); }
.summary-table th, .summary-table td { text-align: left; padding: 0.35rem 1.2rem 0.35rem 0; border-bottom: 1px solid var(--line-soft); }
.summary-table tbody td { font-weight: 600; }
.summary-table tbody th { font-weight: 500; color: var(--ink-soft); }

.summary-heading { font-size: var(--t-sm); margin: var(--s3) 0 var(--s1); }
.summary-heading-warn { color: var(--brand-amber-deep); }

.summary-list {
  margin: 0 0 var(--s3);
  padding-left: var(--s4);
  font-size: var(--t-sm);
  color: var(--muted);
  line-height: 1.55;
}

.summary-list-warn { color: var(--brand-amber-deep); }

/* --- Stub pages ------------------------------------------------------------ */

.stub-panel { max-width: 44rem; text-align: left; }

.stub-badge {
  display: inline-block;
  font-size: var(--t-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--warn);
  background: var(--warn-tint);
  border-radius: 3px;
  padding: 0.15rem 0.45rem;
  margin-bottom: var(--s3);
}

.stub-panel h2 { margin-bottom: var(--s2); }
.stub-panel p { color: var(--muted); margin-bottom: var(--s3); max-width: 62ch; }
.stub-panel p:last-child { margin-bottom: 0; }

/* --- Narrow screens -------------------------------------------------------- */

@media (max-width: 640px) {
  .header-bar, .context-inner { padding-left: var(--s4); padding-right: var(--s4); }
  main { padding: var(--s5) var(--s4) var(--s6); }
  .panel { padding: var(--s4); }
  .table-scroll { margin: 0 calc(var(--s4) * -1); padding: 0 var(--s4); }
  .site-nav { margin-left: 0; width: 100%; }
  .import-choice { grid-template-columns: 1fr; }
  .audit-event { flex-direction: column; gap: var(--s1); }
  .audit-when { flex-basis: auto; }
}

/* Interim: the facility bar is replaced by the shared context strip when the
   navigation component lands. */
.facility-bar { display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap; }

/* --- Users, roles and sign-in --------------------------------------------- */

.role-badge {
  display: inline-block;
  font-size: var(--t-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  border-radius: 3px;
  padding: 0.1rem 0.4rem;
  white-space: nowrap;
}

.role-super_admin  { background: var(--brand-navy); color: #fff; }
.role-tenant_admin { background: var(--brand-navy-tint); color: var(--brand-navy); }
.role-user         { background: var(--brand-slate-tint); color: var(--brand-slate); }

/* Who is signed in, in the header. */
.user-chip {
  display: flex;
  align-items: center;
  gap: var(--s2);
  padding: var(--s1) var(--s2);
  border-radius: var(--radius-sm);
  text-decoration: none;
  white-space: nowrap;
}

.user-chip:hover { background: var(--raised); }
.user-chip-name { font-size: var(--t-sm); font-weight: 600; color: var(--ink); }

/* The sign-in list. */
.user-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: var(--s3);
}

.user-card {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  text-align: left;
  padding: var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  cursor: pointer;
  font: inherit;
  color: var(--ink);
  transition: border-color 0.12s ease, background-color 0.12s ease;
}

.user-card:hover { border-color: var(--accent); background: var(--accent-tint); }

.user-card.is-chosen {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}

.user-name { font-weight: 600; font-size: var(--t-md); }
.user-title { font-size: var(--t-sm); color: var(--muted); }

.user-meta {
  display: flex;
  align-items: center;
  gap: var(--s2);
  flex-wrap: wrap;
  margin-top: var(--s2);
}

.user-scope { font-size: var(--t-xs); color: var(--muted); }

/* Said plainly wherever the emulation could be mistaken for the real thing. */
.notice-strip {
  border: 1px solid #e8d3a8;
  background: var(--warn-tint);
  color: var(--warn);
  border-radius: var(--radius-sm);
  padding: var(--s3) var(--s4);
  margin-bottom: var(--s5);
  font-size: var(--t-sm);
  line-height: 1.5;
}

.notice-strip strong { color: var(--brand-amber-deep); }

/* Who made an audit entry. */
.audit-actor { font-weight: 600; color: var(--ink-soft); }
.audit-actor-unknown { font-weight: 400; font-style: italic; }

.emulated-tag {
  display: inline-block;
  font-size: 0.625rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--warn);
  background: var(--warn-tint);
  border-radius: 3px;
  padding: 0.05rem 0.3rem;
  margin-left: 0.2rem;
  vertical-align: 1px;
}

/* A standard shown to someone who may not change it. */
.standards-readonly {
  display: inline-block;
  min-width: 3rem;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
}

.standards-readonly.is-override { font-weight: 600; color: var(--accent-deep); }

/* --- Account Management ---------------------------------------------------- */

.cap-yes { color: var(--accent-deep); font-weight: 600; }
.cap-no  { color: var(--muted); }

.user-title-cell {
  display: block;
  font-size: var(--t-xs);
  font-weight: 400;
  color: var(--muted);
  margin-top: 0.1rem;
}

.org-tag {
  display: inline-block;
  font-size: var(--t-xs);
  font-weight: 600;
  color: var(--ink-soft);
  background: var(--line-soft);
  border-radius: 3px;
  padding: 0.1rem 0.4rem;
  margin: 0.1rem 0.15rem 0.1rem 0;
  white-space: nowrap;
}

/* An organization named by a user but not present in the data. */
.org-missing {
  background: var(--warn-tint);
  color: var(--warn);
  text-decoration: underline dotted;
}

.org-all { font-size: var(--t-sm); color: var(--accent-deep); font-weight: 600; }

code {
  font-size: 0.9em;
  background: var(--line-soft);
  border-radius: 3px;
  padding: 0.05rem 0.3rem;
}

/* Seat allocation on an organization. */
.allocation-tag {
  display: inline-block;
  font-size: var(--t-xs);
  font-weight: 600;
  color: var(--muted);
  background: var(--line-soft);
  border-radius: 3px;
  padding: 0.1rem 0.4rem;
  margin-left: var(--s2);
  white-space: nowrap;
}

.allocation-tag.is-full { background: var(--warn-tint); color: var(--warn); }

/* Which health code an organization answers to. */
.jurisdiction-picker { margin-left: var(--s2); }

.jurisdiction-tag {
  display: inline-block;
  font-size: var(--t-xs);
  font-weight: 600;
  color: var(--brand-amber-deep);
  background: var(--brand-amber-tint);
  border-radius: 3px;
  padding: 0.1rem 0.4rem;
  margin-left: var(--s2);
}

/* --- Jurisdictions --------------------------------------------------------- */

.citation {
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--brand-amber-deep);
  background: var(--brand-amber-tint);
  border-radius: 3px;
  padding: 0.15rem 0.45rem;
  display: inline-block;
  margin-bottom: var(--s3);
}

/* A legal bound this app has no field for yet. */
.row-unmeasured th, .row-unmeasured td { opacity: 0.75; }

/* A legal range, distinct from an operator's own target. */
/* Legal ranges carry the accent: notable, and nowhere near the alert red. */
.source-jurisdiction { background: var(--brand-amber-tint); color: var(--brand-amber-deep); }

/* --- Grouped navigation ---------------------------------------------------- */

.nav-group { position: relative; }

.nav-group-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  border: none;
  background: none;
  cursor: pointer;
  font-family: inherit;
}

.nav-group.is-current > .nav-group-toggle {
  background: var(--accent-tint);
  color: var(--accent-deep);
}

.nav-caret { font-size: 0.6rem; opacity: 0.6; }

.nav-menu {
  position: absolute;
  top: calc(100% + 0.35rem);
  left: 0;
  z-index: 20;
  min-width: 15rem;
  padding: var(--s1);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
}

.nav-menu[hidden] { display: none; }

.nav-menu-item {
  display: block;
  padding: var(--s2) var(--s3);
  border-radius: var(--radius-sm);
  text-decoration: none;
  color: var(--ink);
}

.nav-menu-item:hover { background: var(--raised); }
.nav-menu-item.is-current { background: var(--accent-tint); }

.nav-menu-label {
  display: block;
  font-size: var(--t-sm);
  font-weight: 600;
}

.nav-menu-item.is-current .nav-menu-label { color: var(--accent-deep); }

.nav-menu-blurb {
  display: block;
  font-size: var(--t-xs);
  color: var(--muted);
  margin-top: 0.05rem;
}

.nav-soon {
  font-size: 0.625rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  background: var(--line-soft);
  border-radius: 3px;
  padding: 0.05rem 0.28rem;
  margin-left: 0.3rem;
  vertical-align: 1px;
}

@media (max-width: 640px) {
  /* No room to float a panel: the group's pages sit inline instead. */
  .nav-menu {
    position: static;
    box-shadow: none;
    border: none;
    padding-left: var(--s3);
    min-width: 0;
  }
}

/* --- Breadcrumb segments as pickers ---------------------------------------- */

.crumb-wrap { position: relative; display: inline-block; }

.crumb-button {
  display: inline-flex;
  align-items: baseline;
  gap: 0.25rem;
  padding: 0.1rem 0.35rem;
  margin: -0.1rem -0.1rem -0.1rem -0.35rem;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: none;
  font: inherit;
  font-weight: 600;
  color: var(--ink-soft);
  cursor: pointer;
  white-space: nowrap;
}

.crumb-button:hover {
  background: var(--surface);
  border-color: var(--line);
  color: var(--ink);
}

.crumb-button.crumb-last { color: var(--accent-deep); font-weight: 600; }
.crumb-button.crumb-last:hover { border-color: var(--accent); }

.crumb-caret { font-size: 0.55rem; opacity: 0.55; }

.crumb-menu {
  position: absolute;
  top: calc(100% + 0.3rem);
  left: 0;
  z-index: 20;
  min-width: 13rem;
  max-height: 18rem;
  overflow-y: auto;
  padding: var(--s1);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
}

.crumb-menu[hidden] { display: none; }

.crumb-menu-head {
  font-size: var(--t-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  padding: var(--s2) var(--s3) var(--s1);
}

.crumb-menu-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: var(--s2) var(--s3);
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  font: inherit;
  color: var(--ink);
  cursor: pointer;
}

.crumb-menu-item:hover { background: var(--raised); }
.crumb-menu-item.is-current { background: var(--accent-tint); }
.crumb-menu-item.is-current .crumb-menu-name { color: var(--accent-deep); }

.crumb-menu-name { display: block; font-size: var(--t-sm); font-weight: 600; }
.crumb-menu-detail { display: block; font-size: var(--t-xs); color: var(--muted); }

/* Organizations a user belongs to that the reader cannot see. */
.org-elsewhere {
  background: transparent;
  border: 1px dashed var(--line);
  color: var(--muted);
  font-weight: 500;
}

/* An area, between a location and the things inside it. */
.tree-area > .tree-name { font-weight: 600; color: var(--ink-soft); }

/* --- Inspection template builder ------------------------------------------- */

.builder-fields, .builder-children { list-style: none; margin: 0; padding: 0; }

.builder-field {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: var(--s2) var(--s3);
  margin-bottom: var(--s2);
  background: var(--surface);
}

.builder-field.is-group { background: var(--raised); border-color: var(--accent); }

.builder-field-main {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--s2);
}

.builder-label { font-weight: 600; }

.field-key {
  font-size: var(--t-xs);
  color: var(--muted);
  background: var(--line-soft);
  border-radius: 3px;
  padding: 0.05rem 0.3rem;
}

.field-options { font-size: var(--t-xs); color: var(--muted); }

/* A statement of fact about a field, not a warning about a value. Slate,
   so it stays quiet and leaves amber for things that need acting on. */
.required-tag {
  font-size: var(--t-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--brand-slate);
  background: var(--brand-slate-tint);
  border-radius: 3px;
  padding: 0.05rem 0.32rem;
}

.builder-field-actions { margin-top: var(--s1); }

/* Fields inside a repeating group - the sub-table's columns. */
.builder-children {
  margin-top: var(--s2);
  padding-left: var(--s4);
  border-left: 2px solid var(--line);
}

.builder-children .empty { font-size: var(--t-sm); padding: var(--s1) 0; }

.add-field-form { margin-bottom: var(--s3); }

.add-field-grid {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  align-items: center;
}

.add-field-grid input[type="text"] {
  flex: 1 1 14rem;
  padding: 0.4rem 0.55rem;
  font-family: inherit;
  font-size: var(--t-sm);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}

.add-field-grid select {
  padding: 0.4rem 0.5rem;
  font-family: inherit;
  font-size: var(--t-sm);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
}

.inline-check {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: var(--t-sm);
  color: var(--ink-soft);
  white-space: nowrap;
}

/* --- Assigning a template -------------------------------------------------- */

.scope-group { margin-bottom: var(--s4); }

.scope-group h4 {
  font-size: var(--t-sm);
  margin: 0 0 var(--s2);
  color: var(--ink-soft);
}

.scope-options { display: flex; flex-wrap: wrap; gap: var(--s2); }

.scope-option {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  font-size: var(--t-sm);
  cursor: pointer;
}

.scope-option:hover { border-color: var(--accent); }

.scope-option.is-chosen {
  border-color: var(--accent);
  background: var(--accent-tint);
  color: var(--accent-deep);
  font-weight: 600;
}

/* --- Filling in an inspection ---------------------------------------------- */

.repeat-group {
  border: 1px solid var(--accent);
  border-radius: var(--radius-sm);
  padding: var(--s3);
  margin-bottom: var(--s4);
  background: var(--raised);
}

.repeat-group legend {
  font-weight: 600;
  font-size: var(--t-sm);
  padding: 0 var(--s2);
  color: var(--accent-deep);
}

.repeat-table input, .repeat-table select { width: 100%; min-width: 7rem; }

.repeat-table input[type="text"], .repeat-table input[type="number"],
.repeat-table input[type="date"], .repeat-table select {
  padding: 0.3rem 0.4rem;
  font-family: inherit;
  font-size: var(--t-sm);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}

.bool-group, .multi-group { display: flex; flex-wrap: wrap; gap: var(--s3); }

.photo-field { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.photo-state { font-size: var(--t-sm); color: var(--muted); }

.matched-via { font-size: var(--t-xs); color: var(--muted); margin: var(--s2) 0; }

/* --- Reading a submission -------------------------------------------------- */

.answer-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  padding: var(--s2) 0;
  border-bottom: 1px solid var(--line-soft);
}

.answer-label { flex: 0 0 16rem; font-weight: 600; color: var(--ink-soft); font-size: var(--t-sm); }
.answer-value { flex: 1; font-size: var(--t-sm); }

.answer-photo {
  display: block;
  max-width: 260px;
  max-height: 200px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
}

/* An invited person, whose record exists but whose access does not. */
.status-invited { background: var(--brand-amber-tint); color: var(--brand-amber-deep); }

/* ---------------------------------------------------------------------------
   My Profile
   ---------------------------------------------------------------------------
   Mobile-first, because this is opened one-handed on a pool deck between
   rotations far more often than at a desk. The base rules below are the phone
   layout; the single media query widens it for larger screens rather than the
   other way round.

   NO RED ANYWHERE ON THIS SCREEN. Red means a chemical reading is out of range
   and someone should act on the water now. A mistyped phone number is not
   that, so validation problems here are amber - the same amber the rest of the
   app uses for "needs attention, nobody is in danger". --danger is not
   referenced by any rule in this block.
   --------------------------------------------------------------------------- */

main.narrow { max-width: 34rem; }

.profile-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: var(--s4);
  margin-bottom: var(--s4);
}

.profile-card h2 {
  margin: 0 0 var(--s3);
  font-size: 1.05rem;
  color: var(--brand-navy);
}

/* --- one editable row --------------------------------------------------- */

.profile-row { padding: var(--s3) 0; border-bottom: 1px solid var(--line-soft); }
.profile-row:last-child { border-bottom: none; padding-bottom: 0; }
.profile-row:first-of-type { padding-top: 0; }

.profile-label {
  display: block;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--ink-soft);
  margin-bottom: 0.35rem;
}

/* Input and its button on one line. The button does not shrink, so a long
   value scrolls the input rather than squeezing "Save" into an ellipsis. */
.profile-control { display: flex; gap: var(--s2); align-items: stretch; }

.profile-input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 0.7rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  color: var(--ink);
  /* 16px exactly. Anything smaller and iOS Safari zooms the page when the
     field is focused, which on a phone reads as the layout breaking. */
  font-size: 16px;
  font-family: inherit;
}

.profile-input:focus {
  outline: 2px solid var(--brand-navy);
  outline-offset: 1px;
  border-color: var(--brand-navy);
}

.profile-input:disabled { background: var(--raised); color: var(--muted); }

.profile-save {
  flex: 0 0 auto;
  /* 44px minimum, which is the smallest target a thumb hits reliably. */
  min-height: 44px;
  padding: 0 var(--s3);
  border: 1px solid var(--brand-navy);
  border-radius: 8px;
  background: var(--brand-navy);
  color: #fff;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.profile-save:hover:not(:disabled) { background: var(--brand-navy-deep); }

/* Disabled until something changes, so the page says which rows have unsaved
   edits without needing a separate indicator. */
.profile-save:disabled {
  background: var(--brand-slate-tint);
  border-color: var(--line);
  color: var(--muted);
  cursor: default;
}

.profile-save.as-label { display: inline-flex; align-items: center; cursor: pointer; }

.profile-remove {
  min-height: 44px;
  padding: 0 var(--s3);
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  color: var(--ink-soft);
  font: inherit;
  cursor: pointer;
}
.profile-remove:hover { background: var(--raised); }

/* --- messages ------------------------------------------------------------ */
/* Reserves its line whether or not it has content, so saving a field does not
   shunt every row below it down the page. */
.profile-msg { margin: 0.4rem 0 0; font-size: 0.82rem; min-height: 1.15rem; }

.profile-hint { color: var(--muted); }
.profile-saved { color: var(--brand-amber-deep); font-weight: 600; }

/* Amber, not red. See the note at the top of this block. */
.profile-problem { color: var(--brand-amber-deep); font-weight: 600; }

.profile-row.has-problem .profile-input {
  border-color: var(--brand-amber-deep);
  background: var(--brand-amber-tint);
}

/* --- read-only rows ------------------------------------------------------ */
.profile-row.is-locked .profile-fixed {
  display: block;
  padding: 0.7rem 0;
  color: var(--ink-soft);
  font-size: 16px;
}

/* --- photo --------------------------------------------------------------- */
.photo-block { display: flex; gap: var(--s3); align-items: center; }

.photo-frame {
  flex: 0 0 auto;
  width: 5rem; height: 5rem;
  border-radius: 50%;
  overflow: hidden;
  background: var(--brand-navy-tint);
  border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center;
}

.photo-img { width: 100%; height: 100%; object-fit: cover; display: block; }

.photo-empty {
  font-size: 1.5rem; font-weight: 600;
  color: var(--brand-navy);
  letter-spacing: 0.02em;
}

.photo-actions { display: flex; flex-wrap: wrap; gap: var(--s2); }

/* --- wider screens ------------------------------------------------------- */
/* The label moves beside the field once there is room for it. Below this the
   label stays above, because a two-column row on a 375px screen leaves the
   input too narrow to read a phone number in. */
@media (min-width: 34rem) {
  .profile-row {
    display: grid;
    grid-template-columns: 10rem 1fr;
    gap: 0 var(--s3);
    align-items: center;
  }
  .profile-label { margin-bottom: 0; }
  .profile-msg { grid-column: 2; }
}

/* ---------------------------------------------------------------------------
   Employee record editor - Employee Management
   ---------------------------------------------------------------------------
   The organization's record of a person, opened underneath their row. It is
   deliberately styled as a distinct inset panel rather than as more table
   cells: this is a different record from the person's own profile, and it
   should not read as an extension of the row above it.

   No red here either. A mistyped hire date is not a water-quality alert.
   --------------------------------------------------------------------------- */

.record-row > td { background: var(--raised); padding: 0; }

.record-editor {
  padding: var(--s4);
  border-left: 3px solid var(--brand-amber);
}

.record-editor h3 {
  margin: 0 0 0.25rem;
  font-size: 1rem;
  color: var(--brand-navy);
}

.record-editor .page-lede { margin: 0 0 var(--s3); }

/* Two across where there is room, stacked where there is not. */
.record-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--s3);
}

.record-field label {
  display: block;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--ink-soft);
  margin-bottom: 0.3rem;
}

.record-field input {
  width: 100%;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 16px;
}

.record-field input:focus {
  outline: 2px solid var(--brand-navy);
  outline-offset: 1px;
  border-color: var(--brand-navy);
}

.record-field.has-problem input {
  border-color: var(--brand-amber-deep);
  background: var(--brand-amber-tint);
}

.record-msg { margin: 0.3rem 0 0; font-size: 0.8rem; min-height: 1.1rem; }

.record-actions {
  display: flex;
  align-items: center;
  gap: var(--s3);
  margin-top: var(--s3);
}

/* The employer's record on the person's own profile. Read-only, and it has to
   LOOK read-only at a glance - somebody scanning this page must not start
   typing into it and wonder why nothing saved. An amber edge and a tinted
   heading set it apart from the cards above, which are theirs to edit.

   Amber rather than red: this is "belongs to someone else", not an alert. */
.profile-card.employer-record {
  border-left: 3px solid var(--brand-amber);
  background: var(--raised);
}

.profile-card.employer-record h2 { color: var(--brand-amber-deep); }

/* No inputs live here, so nothing in this card should carry the affordances of
   one. Belt and braces: if an editable row is ever added by mistake, it is
   visibly inert rather than quietly broken. */
.profile-card.employer-record input,
.profile-card.employer-record .profile-save { display: none; }

.employer-record-note { margin-top: var(--s3); }

/* ---------------------------------------------------------------------------
   Certifications
   ---------------------------------------------------------------------------
   NO RED. Red means a chemical reading is out of range right now and someone
   should act on the water. A lapsed lifeguard certificate is serious and is
   not that, so the strongest state here is a solid navy fill with the word
   EXPIRED in it - unmissable, and reading as a state rather than an alarm.

   valid          neutral slate
   expiring soon  amber
   expired        solid navy + "EXPIRED"
   revoked        solid navy + "REVOKED"
   --------------------------------------------------------------------------- */

.cert-list { display: grid; gap: var(--s3); margin-bottom: var(--s4); }

.cert-card {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: var(--s3);
  background: var(--surface);
}

.cert-card.is-busy { opacity: 0.6; }

.cert-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--s3);
}

.cert-head h3 { margin: 0; font-size: 1rem; color: var(--brand-navy); }
.cert-issuer { margin: 0.15rem 0 0; font-size: 0.85rem; color: var(--muted); }

/* --- status badges ------------------------------------------------------- */

.cert-badge {
  flex: 0 0 auto;
  display: inline-block;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

/* Nothing to do about it. */
.cert-valid { background: var(--brand-slate-tint); color: var(--brand-slate); }

/* Book the course. */
.cert-expiring_soon { background: var(--brand-amber-tint); color: var(--brand-amber-deep); }

/* Solid navy rather than red. Loud without borrowing the water alert. */
.cert-expired,
.cert-revoked { background: var(--brand-navy); color: #fff; }

.cert-unknown { background: var(--brand-slate-tint); color: var(--muted); }

/* --- dates --------------------------------------------------------------- */

.cert-dates { display: flex; gap: var(--s4); margin: var(--s3) 0 var(--s2); }
.cert-dates dt { font-size: 0.75rem; color: var(--muted); margin: 0; }
.cert-dates dd { margin: 0.1rem 0 0; font-weight: 600; }

/* --- who can see it ------------------------------------------------------ */

.cert-shares { margin: 0 0 var(--s2); font-size: 0.85rem; }

.cert-share {
  display: inline-block;
  padding: 0.1rem 0.5rem;
  margin: 0.1rem 0.2rem 0.1rem 0;
  border-radius: 999px;
  background: var(--brand-navy-tint);
  color: var(--brand-navy);
  font-weight: 600;
}

/* A share to somewhere they no longer work. The row stays - it is a true
   record of what they did - but it is visibly not in effect. */
.cert-share.is-dormant {
  background: transparent;
  border: 1px dashed var(--line);
  color: var(--muted);
  font-weight: 400;
}

/* --- actions and forms --------------------------------------------------- */

.cert-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  align-items: center;
  margin-top: var(--s2);
}

.cert-actions .as-label { cursor: pointer; }

.cert-form {
  margin-top: var(--s3);
  padding: var(--s3);
  border-left: 3px solid var(--brand-amber);
  background: var(--raised);
  border-radius: 0 8px 8px 0;
}

.cert-form h3 { margin: 0 0 var(--s2); font-size: 1rem; color: var(--brand-navy); }

.cert-form label {
  display: block;
  margin-top: var(--s2);
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--ink-soft);
}

.cert-form input,
.cert-form select {
  width: 100%;
  margin-top: 0.25rem;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  /* 16px, or iOS Safari zooms the page when the field is focused. */
  font-size: 16px;
}

.cert-form input:focus,
.cert-form select:focus {
  outline: 2px solid var(--brand-navy);
  outline-offset: 1px;
  border-color: var(--brand-navy);
}

/* Amber, not red - a mistyped date is not a water alert. */
.cert-problem {
  margin: 0.35rem 0 0;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--brand-amber-deep);
}

@media (max-width: 34rem) {
  .cert-head { flex-direction: column; }
  .cert-dates { gap: var(--s3); }
}

/* ---------------------------------------------------------------------------
   In-service hours
   ---------------------------------------------------------------------------
   NO RED. Being behind on training hours is worth knowing about; it is not a
   chemical reading out of range. Behind pace is amber, on pace is slate,
   complete is navy.

   The progress indicator is a bar. One number against another - no chart
   library, no axes, no tooltips.
   --------------------------------------------------------------------------- */

.hours-progress {
  border: 1px solid var(--line);
  border-left: 3px solid var(--brand-slate);
  border-radius: 8px;
  padding: var(--s3);
  margin-bottom: var(--s4);
  background: var(--raised);
}

.hours-progress.is-behind { border-left-color: var(--brand-amber); }
.hours-progress.is-complete { border-left-color: var(--brand-navy); }

.hours-figures {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s2);
  align-items: baseline;
  margin-bottom: var(--s2);
}

.hours-bar {
  display: block;
  height: 0.6rem;
  border-radius: 999px;
  background: var(--brand-slate-tint);
  overflow: hidden;
}

.hours-bar-fill {
  display: block;
  height: 100%;
  background: var(--brand-slate);
  border-radius: 999px;
}

.hours-progress.is-behind .hours-bar-fill { background: var(--brand-amber); }
.hours-progress.is-complete .hours-bar-fill { background: var(--brand-navy); }

.hours-note { margin: var(--s2) 0 0; font-size: 0.85rem; color: var(--ink-soft); }

/* --- the list ------------------------------------------------------------ */

.hours-list { display: grid; gap: var(--s2); margin-bottom: var(--s3); }

.hours-row {
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: var(--s3);
  background: var(--surface);
}

.hours-row.is-busy { opacity: 0.6; }

.hours-row-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--s3);
}

.hours-row h3 { margin: 0; font-size: 0.95rem; color: var(--brand-navy); }
.hours-meta { margin: 0.15rem 0 0; font-size: 0.82rem; color: var(--muted); }

.hours-row-right {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.3rem;
}

.hours-amount { font-weight: 700; color: var(--brand-navy); }

.hours-notes {
  margin: var(--s2) 0 0;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

@media (max-width: 34rem) {
  .hours-row-head { flex-direction: column; }
  .hours-row-right { flex-direction: row; align-items: center; }
}

/* ---------------------------------------------------------------------------
   Notifications - the bell and its panel
   ---------------------------------------------------------------------------
   NO RED. Red means a chemical reading is out of range right now. A
   certificate expiring in three weeks deserves a nudge, not an alarm, so the
   unread count and the unread edge are amber.
   --------------------------------------------------------------------------- */

.bell { position: relative; }

.bell-button {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 44px, the smallest target a thumb hits reliably. */
  width: 44px; height: 44px;
  padding: 0;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
}

.bell-button:hover { background: var(--brand-navy-tint); color: var(--brand-navy); }
.bell-button:focus-visible { outline: 2px solid var(--brand-navy); outline-offset: 1px; }

.bell-icon { width: 22px; height: 22px; display: block; }

/* Amber. The one thing in the header asking to be looked at. */
.bell-count {
  position: absolute;
  top: 4px; right: 4px;
  min-width: 1.1rem;
  padding: 0 0.25rem;
  border-radius: 999px;
  background: var(--brand-amber);
  color: var(--brand-navy);
  font-size: 0.68rem;
  font-weight: 700;
  line-height: 1.1rem;
  text-align: center;
}

/* --- the panel ----------------------------------------------------------- */

.bell-panel {
  position: absolute;
  top: calc(100% + 0.4rem);
  right: 0;
  z-index: 40;
  width: min(22rem, calc(100vw - 2rem));
  max-height: min(28rem, 70vh);
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(22, 32, 43, 0.12);
}

.bell-panel-head {
  position: sticky;
  top: 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s3);
  padding: var(--s3);
  background: var(--surface);
  border-bottom: 1px solid var(--line-soft);
}

.bell-list { list-style: none; margin: 0; padding: 0; }

.bell-item {
  padding: var(--s3);
  border-bottom: 1px solid var(--line-soft);
  border-left: 3px solid transparent;
  font-size: 0.88rem;
}

.bell-item:last-child { border-bottom: none; }

/* Unread is amber-edged; read is quiet. */
.bell-item.is-unread { border-left-color: var(--brand-amber); background: var(--raised); }
.bell-item.is-read { color: var(--ink-soft); }

/* Kept, shown, and not something to act on. */
.bell-item.is-inert { opacity: 0.72; }
.bell-item.is-inert .bell-item-head strong { font-weight: 600; color: var(--muted); }

.bell-item-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s2);
}

.bell-when { flex: 0 0 auto; font-size: 0.75rem; color: var(--muted); }

.bell-org {
  display: inline-block;
  margin-top: 0.2rem;
  font-size: 0.75rem;
  color: var(--brand-navy);
  background: var(--brand-navy-tint);
  border-radius: 999px;
  padding: 0.05rem 0.45rem;
}

.bell-body { margin: 0.35rem 0 0; color: var(--ink-soft); }

.bell-inert { margin: 0.35rem 0 0; font-size: 0.8rem; color: var(--muted); font-style: italic; }

.bell-item-actions {
  display: flex;
  gap: var(--s3);
  align-items: center;
  margin-top: var(--s2);
  font-size: 0.82rem;
}

.bell-empty { margin: 0; padding: var(--s4); color: var(--muted); text-align: center; }

/* On a phone the panel spans the width rather than hanging off the right. */
@media (max-width: 34rem) {
  .bell-panel { right: auto; left: 50%; transform: translateX(-50%); }
}

/* ---------------------------------------------------------------------------
   Holding page - production and QA
   ---------------------------------------------------------------------------
   Served by functions/_holding.js, which the middleware returns INSTEAD of the
   application on production and QA. It was briefly done in the browser and
   that raced and lost - page-home.js redirects to /signin synchronously, long
   before an async tier check can answer. These styles are now for a page the
   server sends whole.
   --------------------------------------------------------------------------- */

.holding-card {
  max-width: 34rem;
  margin: 12vh auto var(--s5);
  padding: var(--s5);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  text-align: center;
}

.holding-card h1 { margin: 0 0 var(--s2); color: var(--brand-navy); }

.holding-card .tagline {
  margin: 0 0 var(--s4);
  color: var(--brand-amber-deep);
  font-weight: 600;
}

.holding-note { margin: 0 0 var(--s3); color: var(--ink); }
.holding-quiet { margin: 0; font-size: 0.9rem; color: var(--muted); }

/* Top right, on every tier. Quiet - it is a way through, not a call to
   action, and a client landing on the holding page should not read it as one. */
#dev-link {
  position: absolute;
  top: var(--s3);
  right: var(--s4);
  z-index: 30;
  font-size: 0.85rem;
}

.dev-link {
  color: var(--muted);
  text-decoration: none;
  padding: 0.3rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
}

.dev-link:hover { color: var(--brand-navy); border-color: var(--brand-navy); }

@media (max-width: 34rem) {
  .holding-card { margin-top: 8vh; padding: var(--s4); }
  #dev-link { top: var(--s2); right: var(--s2); }
}


/* The way back into the app from a profile page.
   Only rendered for a session that can actually use it - see
   profile-header.js - so it never promises a door that is locked. */
.profile-back {
  margin-left: auto;
  color: var(--brand-navy);
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

.profile-back:hover { text-decoration: underline; }
