/* The portal shell: one header, used by the homepage and by every app mounted
   inside the portal.
 *
 * Two rules govern everything here, both learned the hard way from the
 * scheduling app:
 *
 * 1. Every class is prefixed `shell-`. The scheduler already has .who,
 *    .who-name and .who-avatar of its own, which are exactly the names the
 *    portal's topbar used. Unprefixed, the two stylesheets fight and the loser
 *    depends on link order.
 *
 * 2. Colours are declared as --shell-* ON .shell, not on :root. Apps bring
 *    their own :root tokens -- the scheduler defines --bg and --accent, the
 *    same names the portal uses -- and a token defined at :root would be
 *    whichever stylesheet loaded last. Scoped to the component, the header is
 *    immune to whatever the page around it does.
 *
 * This file is served from the portal's public directory, so app pages link it
 * as /shell.css regardless of what path they are mounted at. */

.shell {
  --shell-surface: #ffffff;
  --shell-border: #e0dcd4;
  --shell-text: #1e1c19;
  --shell-muted: #6d675e;
  --shell-accent: #8a5a2b;
  --shell-accent-text: #ffffff;
  --shell-hover: #f4f2ee;

  /* Sticky, not static: "always present" has to survive scrolling. The week
     editor in the scheduling app is taller than a phone screen, so a header
     pinned only to the top of the document is gone the moment you look at
     Thursday. The z-index clears the app's own layers -- the scheduler's
     screens sit at 1 and its fixed save bar at 3. */
  position: sticky;
  top: 0;
  z-index: 10;
  border-bottom: 1px solid var(--shell-border);
  background: var(--shell-surface);
  color: var(--shell-text);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 16px;
  line-height: 1.55;
}

@media (prefers-color-scheme: dark) {
  .shell:not([data-tone="light"]) {
    --shell-surface: #201e1b;
    --shell-border: #34302b;
    --shell-text: #eeeae3;
    --shell-muted: #a39b8f;
    --shell-accent: #d9a066;
    --shell-accent-text: #1e1a15;
    --shell-hover: #2a2724;
  }
}

/* Apps that commit to a single look opt in explicitly, so the header does not
   sit light on a dark page for a viewer whose system is set to light. */
.shell[data-tone="dark"] {
  --shell-surface: #201e1b;
  --shell-border: #34302b;
  --shell-text: #eeeae3;
  --shell-muted: #a39b8f;
  --shell-accent: #d9a066;
  --shell-accent-text: #1e1a15;
  --shell-hover: #2a2724;
}

/* Full bleed on purpose: the brand sits at the left edge of the screen and the
   account controls at the right, however wide the window is. The page content
   below stays in its reading column -- a header is a chrome bar, not prose, so
   it does not want the same measure. */
.shell-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  /* No vertical padding: the wordmark is meant to reach the top and bottom
     edges of the bar, so the bar's height comes from min-height instead and
     the logo simply matches it. */
  padding: 0 clamp(1rem, 3vw, 2.5rem);
  min-height: 4.25rem;
}

/* ---------- left: where you are ---------- */

/* A single child since the tagline went, but kept as the left cell of the bar
   so the right-hand controls still push to the far edge. */
.shell-where {
  display: flex;
  min-width: 0;
}

.shell-crumbs {
  display: flex;
  /* Centred, not baseline: the root crumb is a full-height image now, and on a
     baseline the "/ Scheduling" beside it would sit against its bottom edge. */
  align-items: center;
  gap: 0.45rem;
  min-width: 0;
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.shell-crumbs a {
  color: inherit;
  text-decoration: none;
}

.shell-crumbs a:hover {
  text-decoration: underline;
}

/* The root crumb dims once you are inside an app, so the page you are on is
   the thing that reads first. Opacity rather than colour, because the crumb is
   an image now and colour does nothing to it. */
.shell-crumbs[data-depth="app"] .shell-crumb-root {
  color: var(--shell-muted);
  font-weight: 600;
  opacity: 0.65;
}

.shell-crumbs[data-depth="app"] .shell-crumb-root:hover {
  opacity: 1;
}

/* Full bar height. The artwork carries a lot of transparent margin -- the mark
   occupies roughly the middle half of its canvas -- so filling the bar puts the
   visible wordmark at a sensible size rather than an overbearing one. Width
   follows, which is what makes it wider than the text it replaced. */
.shell-logo {
  display: block;
  height: 4.25rem;
  width: auto;
}

/* The wordmark is cream on transparent: made for a dark ground, and all but
   invisible on the header's white one. Rather than filter it -- which would
   take the green swoosh with it -- it gets the dark ground it expects, which
   reads as a deliberate plate rather than a fix.
   A cropped or dark-ink variant of the asset would let this go away. */
@media (prefers-color-scheme: light) {
  .shell:not([data-tone="dark"]) .shell-logo {
    padding-inline: 0.6rem;
    background: #1e1c19;
  }
}

.shell[data-tone="light"] .shell-logo {
  padding-inline: 0.6rem;
  background: #1e1c19;
}

.shell-crumb-sep {
  color: var(--shell-muted);
  font-weight: 400;
}

.shell-crumb-current {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- right: apps and account ---------- */

.shell-right {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.shell-menu {
  position: relative;
}

.shell-menu > summary {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--shell-border);
  border-radius: 8px;
  color: var(--shell-muted);
  font-size: 0.875rem;
  list-style: none;
  cursor: pointer;
  user-select: none;
}

.shell-menu > summary::-webkit-details-marker { display: none; }

.shell-menu > summary::after {
  content: "";
  width: 0.4rem;
  height: 0.4rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
}

.shell-menu[open] > summary {
  color: var(--shell-text);
  border-color: var(--shell-accent);
}

.shell-menu-items {
  position: absolute;
  right: 0;
  top: calc(100% + 0.4rem);
  z-index: 20;
  min-width: 13rem;
  margin: 0;
  padding: 0.3rem;
  list-style: none;
  border: 1px solid var(--shell-border);
  border-radius: 10px;
  background: var(--shell-surface);
  box-shadow: 0 8px 28px rgb(0 0 0 / 18%);
}

.shell-menu-items a {
  display: block;
  padding: 0.5rem 0.65rem;
  border-radius: 6px;
  color: inherit;
  font-size: 0.9rem;
  text-decoration: none;
}

.shell-menu-items a:hover {
  background: var(--shell-hover);
}

.shell-menu-items a[aria-current="page"] {
  color: var(--shell-accent);
  font-weight: 600;
}

.shell-user {
  color: var(--shell-muted);
  font-size: 0.875rem;
  white-space: nowrap;
}

.shell-avatar {
  flex: 0 0 2rem;
  width: 2rem;
  height: 2rem;
  border: 1px solid var(--shell-border);
  border-radius: 50%;
  background: var(--shell-hover);
  /* The directory does not promise square photos; crop rather than squash. */
  object-fit: cover;
}

/* Same size and shape as a real photo, so the header does not shift depending
   on who is signed in. */
.shell-initials {
  display: grid;
  place-items: center;
  border-color: transparent;
  background: var(--shell-accent);
  color: var(--shell-accent-text);
  font-size: 0.75rem;
  font-weight: 700;
}

/* Sign out lives inside the account menu now, so it is styled as a row in that
   menu rather than as a button in the header. It stays a <button> in a <form>
   because signing out is a POST -- see the note in shell.ejs -- and this is
   what makes that button sit flush with the <a> above it. */
.shell-account-items form {
  margin: 0;
}

.shell-signout {
  display: block;
  width: 100%;
  padding: 0.5rem 0.65rem;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 0.9rem;
  text-align: left;
  cursor: pointer;
}

.shell-signout:hover {
  background: var(--shell-hover);
}

.shell :focus-visible {
  outline: 2px solid var(--shell-accent);
  outline-offset: 2px;
}

.shell form {
  margin: 0;
}

@media (max-width: 40rem) {
  .shell-inner { padding: 0 0.9rem; gap: 0.6rem; min-height: 3.4rem; }
  .shell-user { display: none; }
  .shell-crumbs { font-size: 1rem; }
  .shell-logo { height: 3.4rem; }
}

/* The admin menu holds many more entries than the app switcher and they are
   short names, so its rows are tighter and it can grow tall without becoming
   a page of its own. */
.shell-admin-items {
  min-width: 12rem;
  max-height: 70vh;
  overflow-y: auto;
}

.shell-admin-items a {
  padding: 0.34rem 0.6rem;
  font-size: 0.825rem;
}

@media (max-width: 40rem) {
  /* Two menus plus the account controls do not fit; the admin one goes,
     because a phone is not where anyone opens IPAM. */
  .shell-admin { display: none; }
}

/* ---------- network health ---------- */

/* Sits between the wordmark and the account controls, in what was empty bar.
   A fixed width so the two sites stay pinned to their own edges rather than
   drifting together when the names are short. */
.shell-health {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.05rem;
  flex: 0 0 auto;
  min-width: 11rem;
}

.shell-health-title {
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.01em;
}

/* One to each end: the row is the width of the block, not of its contents. */
.shell-health-sites {
  display: flex;
  justify-content: space-between;
  width: 100%;
  gap: 1rem;
}

.shell-site {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  color: var(--shell-muted);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  white-space: nowrap;
}

.shell-site-dot {
  flex: 0 0 0.45rem;
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background: var(--shell-muted);
}

/* Status drives the colour, so wiring this to real checks later is a data
   change rather than a styling one -- the same arrangement as the rail chips. */
.shell-site[data-status="up"] .shell-site-dot { background: #3f9c5a; }
.shell-site[data-status="down"] .shell-site-dot { background: #d1594c; }

@media (prefers-color-scheme: dark) {
  .shell:not([data-tone="light"]) .shell-site[data-status="up"] .shell-site-dot {
    background: #5cbd78;
  }
  .shell:not([data-tone="light"]) .shell-site[data-status="down"] .shell-site-dot {
    background: #e8776a;
  }
}

@media (max-width: 52rem) {
  /* The bar cannot hold the wordmark, this, and the account controls at once. */
  .shell-health { display: none; }
}
