/* ==================================================================
  DLSJBC Social Media Posting Queuing and Scheduling System
  Main stylesheet
  ================================================================== */

/* --- box sizing -----------------------------------------------------------
   Every layout rule in this file is written on the assumption that padding and
   border sit *inside* a declared width. Without this reset the browser's
   default content-box applies instead, and `width: 100%` plus horizontal
   padding silently makes an element wider than its parent.

   The cost was a constant 48px of horizontal overflow on every page: the
   content column carries `width: 100%` with `padding: 24px`, so its border box
   came out 48px past the sidebar and produced a horizontal scrollbar at 100%
   zoom on all twenty-odd pages. Zooming to 90% hid it by accident, because the
   extra CSS pixels happened to absorb the overhang.

   The print sheet and the calendar print view each carried their own local
   `box-sizing: border-box` to paper over the same defect on the pages where
   it happened to be noticed; those are left in place because they are correct
   on their own terms, but they were symptoms rather than the cause.

   ::before and ::after are included because generated content is boxed like any
   other element, and a component that genuinely needs content-box can still
   say so. */
*,
*::before,
*::after { box-sizing: border-box; }

:root {
  --green-900: #0f5132;
  --green-800: #116238;
  --green-700: #157347;
  --green-600: #198754;
  --green-100: #d8efe3;
  --green-50:  #edf7f2;
  --gold:      #f0a500;
  --ink:       #1f2937;
  --muted:     #6b7280;
  --line:      #e5e7eb;
  --bg:        #f3f5f8;
  --card:      #ffffff;
  --red:       #dc3545;
  --red-50:    #fdecec;
  --orange:    #fd7e14;
  --orange-50: #fff3e6;
  --blue:      #0d6efd;
  --blue-50:   #e8f0fe;
  --purple:    #6f42c1;
  --purple-50: #f1ebfb;
  --cyan:      #0aa2c0;
  --cyan-50:   #e5f6fa;
  --gray-50:   #f1f3f5;
  --radius:    10px;
  --shadow:    0 1px 3px rgba(16, 24, 40, .08), 0 1px 2px rgba(16, 24, 40, .05);
  --shadow-lg: 0 10px 30px rgba(16, 24, 40, .12);
  --sidebar-w: 252px;

  /* The revision pink, read by request-details.css's banner and by the
     "waiting for revision" pill on the status strip. These four were being
     referenced there but declared nowhere, so every property that used them
     was invalid at computed-value time and fell back: the banner rendered with
     no fill, no border and no accent bar, and the pill rendered as unstyled
     text. The values are not new - each is a literal that was already in that
     stylesheet, promoted to a name so the four rules agree:
       bg   the banner gradient's own first stop, rgba(252,231,243,.96)
       edge the .rd-revision-icon background, #FBCFE8
       fg   the .rd-revision-label text colour, #9D174D
       fx   the saturated accent in the banner's box-shadow, rgba(190,24,93,..)
     Revision is pink here and nowhere amber or orange, which is the one rule
     about these that is a decision rather than a recovery. */
  --ps-revision-bg:   #fce7f3;
  --ps-revision-edge: #fbcfe8;
  --ps-revision-fg:   #9d174d;
  --ps-revision-fx:   #be185d;
}

/* ------------------------------------------------------------------
   Account settings folder tabs (acct-*).

   These were rendered by admin/settings.php with no rules behind them at
   all: the tab strip and both panels fell back to unstyled buttons and
   divs, and the is-active class on the markup did nothing.

   It is a folder tab rather than a row of buttons. Three declarations do
   the work:

     .acct-tabs { margin-bottom: -1px }   pulls the strip down onto the
       panel's top border, so the active tab's own white bottom border
       covers it and the seam disappears
     .acct-tab.is-active { border-bottom-color: #fff }   the same seam, from
       the other side
     .acct-panel { border-radius: 0 12px 12px 12px }   a square top-left
       corner, so the panel tucks under the tab instead of leaving a notch
       where the tab's rounded corner would be

   The panel is square only at the top-left, which assumes the active tab is
   the left-hand one. With Security active the panel's square corner sits
   under the first tab instead and the join is a little off; that asymmetry
   is inherent to the folder-tab shape and is left as it is rather than
   papered over with extra rules.
   ------------------------------------------------------------------ */
.acct-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: -1px;
}
.acct-tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  border: 1px solid #d8e2dc;
  border-radius: 12px 12px 0 0;
  background: #eaf1ed;
  color: #5b6f66;
  font-size: 13.5px;
  font-weight: 700;
  line-height: 1.2;
  cursor: pointer;
  transition: background-color .18s ease, color .18s ease;
}
.acct-tab > svg,
.acct-tab [data-lucide] {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}
.acct-tab:hover {
  background: #e2ebe6;
  color: var(--green-800);
}
.acct-tab:focus-visible {
  outline: 2px solid var(--green-600);
  outline-offset: 2px;
}
/* The active tab is white, and so is its bottom border: that is what makes it
   read as continuous with the panel below instead of sitting on top of it. */
.acct-tab.is-active {
  background: #fff;
  border-color: #d8e2dc;
  border-bottom-color: #fff;
  color: var(--green-800);
}
.acct-panel {
  background: #fff;
  border: 1px solid #d8e2dc;
  /* Square top-left, to meet the active tab. Rounded everywhere else. */
  border-radius: 0 12px 12px 12px;
  padding: 22px 24px 24px;
}
/* After the is-active rule, so it wins on the shared specificity. A panel
   carries either is-active or hidden, never both, but the order makes the
   outcome independent of that. */
.acct-panel[hidden] { display: none; }
@media (max-width: 560px) {
  .acct-tabs { gap: 2px; }
  .acct-tab { padding: 9px 12px; font-size: 12.5px; }
  .acct-panel { padding: 18px 14px 20px; }
}

/* The root carries a height of its own so anything below it can be sized as a
   fraction of the viewport. Without this, `height: 100vh` on the app shell has
   no percentage ancestor to resolve against and the page falls back to
   scrolling the window. */
html, body { margin: 0; padding: 0; height: 100%; }

body {
  font-family: "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, Arial, sans-serif;
  color: var(--ink);
  background: var(--bg);
  font-size: 15px;
  line-height: 1.55;
}
.layout-app {
  background:
    radial-gradient(900px 420px at 8% 0%, rgba(207,238,220,.45), transparent 70%),
    radial-gradient(760px 420px at 100% 100%, rgba(247,222,157,.16), transparent 72%),
    var(--bg);
}

/* ------------------------------------------------------------------
   Staff top navigation.

   The app shell is a flex row so the admin sidebar can sit beside the
   content. When the first child is the top header there is nothing to sit
   beside, so the shell turns into a column and the header spans the full
   width. Keying off :has() rather than a body class keeps includes/header.php
   untouched and cannot drift from what is actually rendered. The project
   already relies on :has() elsewhere, so this is not a new requirement.

   The bar itself is deliberately plain: white, full-bleed, and separated from
   the page by one hairline and the faintest shadow. The menu is text only -
   five labels, medium weight, no icons, no borders, no fills. Only the current
   page carries a background, a soft green pill, so the eye finds it without the
   bar having to shout. Anything more turns navigation into a row of buttons.

   The header and the content column share one measure and one horizontal
   padding, so the brand lines up with the page text below it. Change one
   padding without the other and the nav drifts out of line with the content.
   ------------------------------------------------------------------ */
.app-shell:has(> .topnav) { flex-direction: column; }

/* --- one-screen app shell ---------------------------------------------------
   The window itself never scrolls. The shell is locked to exactly one screen
   and the content column becomes the scrollport, so a page that fits fills the
   screen instead of leaving a white band under it, and a page that overflows
   scrolls beneath a header that stays put.

   Two details make the lock work. `min-height: 0` on the flex items in between
   is what lets them shrink below their content instead of pushing the shell
   past the viewport; without it the automatic minimum size reinstates the page
   scrollbar this block exists to remove. And `overflow-y` alone leaves
   `overflow-x` computed to `auto` as well, so a wide table still scrolls
   sideways inside its own wrapper rather than dragging the page with it. */
.app-shell:has(> .topnav) { height: 100vh; overflow: hidden; }

.app-shell:has(> .topnav) .app-body,
.app-shell:has(> .topnav) .content { min-height: 0; }

.app-shell:has(> .topnav) .content {
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

/* The page heading is a fixed band; whatever follows it takes the rest. */
.app-shell:has(> .topnav) .content > .page-header { flex: 0 0 auto; }

/* Only a block that holds a table claims the leftover height, and it scrolls its
   own rows to do it. Cards without a table (forms, FAQs, detail panels) keep
   their natural height, or four stacked FAQ cards would each stretch to a
   quarter of the screen and leave the real content floating at the top. */
.app-shell:has(> .topnav) .content > .card:has(.table-wrap),
.app-shell:has(> .topnav) .content > .queue-management-container,
.app-shell:has(> .topnav) .content > .um-page {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

/* Both of these nest one level deeper than the block that claims the leftover
   height, so each needs its own `flex-grow` to carry it the rest of the way
   down. Without it the container fills the screen and the card inside it stays
   at its natural height, which looks identical to having changed nothing. */
.app-shell:has(> .topnav) .content > .queue-management-container > .queue-card,
.app-shell:has(> .topnav) .um-page > .um-panel { flex: 1 1 auto; }

/* A panel that clips is a panel that can lose content.
   `overflow: hidden` zeroes a flex item's automatic minimum size, so a clipping
   panel that is a direct child of the content column will shrink to whatever
   height the column can spare and silently discard the rest - there is no
   scrollbar, so nothing signals that anything is missing.

   staff/create-request.php is exactly this: it reuses .um-tabs and .um-panel
   for its form without the .um-page wrapper, so the rules above never matched
   it. The panel measured 2191px of content in a 638px box and 1553px of the
   form could not be reached at all.

   `flex: 0 0 auto` says "size to your content and do not shrink", which leaves
   the rounded-corner clipping that .um-panel needs doing its job and hands the
   overflow back to the content column, which is the scrollport. */
.app-shell:has(> .topnav) .content > .um-panel { flex: 0 0 auto; }

.app-shell:has(> .topnav) .queue-card,
.app-shell:has(> .topnav) .card:has(.table-wrap) { min-height: 0; display: flex; flex-direction: column; }

.app-shell:has(> .topnav) .card:has(.table-wrap) > .card-body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }

.app-shell:has(> .topnav) .card:has(.table-wrap) .table-wrap { flex: 1 1 auto; min-height: 0; overflow: auto; }

/* The account panel's table sits directly in the panel with no wrapper to
   scroll, so the panel is the scrollport instead and the heading rides along. */
.app-shell:has(> .topnav) .um-page > .um-panel { min-height: 0; overflow: auto; }

@media print {
  /* Paper has no viewport worth locking to. Release every bound above, or the
     shell clips the page and a multi-page form loses everything past the first
     sheet — an overflow with no scrollbar to reveal it in print. */
  html, body { height: auto; }
  .app-shell:has(> .topnav) { height: auto; overflow: visible; }
  .app-shell:has(> .topnav) .app-body,
  .app-shell:has(> .topnav) .content { min-height: 0; overflow: visible; display: block; }
  .app-shell:has(> .topnav) .content > .card:has(.table-wrap),
  .app-shell:has(> .topnav) .content > .queue-management-container,
  .app-shell:has(> .topnav) .content > .um-page,
  .app-shell:has(> .topnav) .queue-card,
  .app-shell:has(> .topnav) .card:has(.table-wrap),
  .app-shell:has(> .topnav) .card:has(.table-wrap) > .card-body,
  .app-shell:has(> .topnav) .um-page > .um-panel { display: block; overflow: visible; }
  .app-shell:has(> .topnav) .card:has(.table-wrap) .table-wrap { overflow: visible; }
}

.topnav {
  position: sticky;
  /* Matches the margin below, so the card rests exactly where it will stick and
     all four corners stay visible at every scroll position. */
  top: 14px;
  z-index: 45;
  /* Inset from both edges, because a rounded border flush with the viewport edge
     shows you two of its four corners. Capped at 1228px so the bar does not
     stretch the full way across a wide monitor. NOTE: this is deliberately not
     the page gutter. The column below stands a full inch in from each edge, so
     the card is wider than the page on a screen under about 1420px and narrower
     than it above that - the two part company either way. */
  width: calc(100% - 32px);
  max-width: 1228px;
  margin: 14px auto 0;
  background: #fff;
  /* A pill, which is what the contents already are: the menu trough, the links
     and the profile button are all 999px, and a 16px card around them read as a
     card with a menu in it rather than one continuous shape. */
  border: 1px solid rgba(214, 228, 219, .95);
  border-radius: 999px;
  box-shadow: 0 1px 2px rgba(15, 81, 50, .05), 0 8px 22px rgba(15, 81, 50, .07);
}
.topnav-inner {
  display: flex;
  /* Centres the brand, the menu and the controls on one line. */
  align-items: center;
  gap: 14px;
  /* The measure and the centring now live on the card, so this just fills it.
     Keeping a second max-width here would cap the card's contents at the same
     number twice and quietly do nothing. */
  width: 100%;
  padding: 11px 24px;
}

/* --- brand --- */
.topnav-brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  /* Takes an equal share of the leftover space with .topnav-right, which is what
     puts the menu in the middle. The two are grown from a zero basis so the
     split is exactly even even though the brand and the bell/profile cluster are
     different widths - giving the menu flex:1 instead would just push it back
     to the left of whatever the brand left over. */
  flex: 1 1 0;
  min-width: 0;
  text-decoration: none;
  color: var(--ink);
}
.topnav-brand:hover { text-decoration: none; }
.topnav-logo {
  width: 38px; height: 38px;
  object-fit: contain;
  background: #fff;
  border-radius: 9px;
  padding: 2px;
}
.topnav-logo-ico {
  display: grid;
  place-items: center;
  width: 38px; height: 38px;
  border-radius: 10px;
  background: linear-gradient(160deg, var(--green-700) 0%, var(--green-900) 100%);
  color: #fff;
  box-shadow: 0 2px 6px rgba(15, 81, 50, .22);
}
.topnav-logo-ico > svg.lucide { width: 20px; height: 20px; }
.topnav-brand-text { display: flex; flex-direction: column; line-height: 1.2; }
.topnav-brand-text strong { font-size: 15.5px; letter-spacing: .4px; color: var(--green-900); }
.topnav-brand-text small  { font-size: 11px; color: var(--muted); }

/* --- centre menu: a grey pill group, buttons inside it ---
   The grey belongs to the GROUP, not to each button: one rounded trough with the
   current page sitting in it as a raised pill. Giving every button its own grey
   instead reads as three separate chips rather than one control. */
.topnav-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 4px;
  background: #f5f5f5;
  border-radius: 999px;
  /* Inset ring, not a border: same reason as the label edges below - a border
     here would add two pixels and push the whole group out of line. */
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .04);
  /* Sized to its contents, never grown: the spare width belongs to the brand and
     the right cluster, which is what centres this group. */
  flex: 0 0 auto;
}
.topnav-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 10px 16px;
  border-radius: 999px;
  background: transparent;
  border: 0;
  /* Never shrink. These are flex items in a row that can get tight, and the
     default shrink of 1 squeezes the box while the nowrap label keeps its full
     width - so the text spills out past the hit area and the outer part of a
     label stops responding to clicks. The last item is squeezed first, which is
     why it looked like one specific link was dead. */
  flex-shrink: 0;
  color: #4b5563;
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
  /* Named properties, not `all`. Transitioning everything means a future
     declaration animates whether it was meant to or not, and layout properties
     in particular are the expensive ones to animate. */
  transition: background-color .2s ease, color .2s ease, box-shadow .2s ease;
}
.topnav-link:hover {
  background: rgba(255, 255, 255, .7);
  color: #147a4b;
  text-decoration: none;
}
.topnav-link:active { background: rgba(255, 255, 255, .85); }
/* The current page. Matched on aria-current as well as the class so the state
   survives if it is ever driven from markup instead of PHP. */
.topnav-link.active,
.topnav-link[aria-current="page"] {
  background: #e6f5ed;
  color: #147a4b;
  /* The snippet this came from declared .active twice with conflicting box-shadow
     values. Kept here rather than none: on the grey trough a hairline of shadow
     is what lifts the pill off the group instead of leaving it flat. */
  box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
}
.topnav-link.active:hover,
.topnav-link[aria-current="page"]:hover {
  background: #e6f5ed;
  color: #147a4b;
}
/* Keyboard only. Without this, tabbing to a menu item leaves the browser default
   ring, which is easy to lose against a pill on a grey trough. */
.topnav-link:focus-visible {
  outline: 2px solid var(--green-600);
  outline-offset: 2px;
}

/* --- right cluster: bell + profile --- */
.topnav-right {
  display: flex;
  align-items: center;
  gap: 10px;
  /* The mirror of .topnav-brand: same growth, so the free space either side of
     the menu is equal and the menu sits in the middle of the bar. */
  flex: 1 1 0;
  justify-content: flex-end;
  min-width: 0;
}
.topnav-user { position: relative; }
.topnav-user-btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 5px 10px 5px 6px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: #fff;
  color: var(--ink);
  font: inherit;
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
  transition: background-color .16s ease, border-color .16s ease;
}
.topnav-user-btn:hover { background: var(--green-50); border-color: rgba(21, 115, 71, .25); }
.topnav-user-btn .avatar { width: 30px; height: 30px; font-size: 12.5px; }
.topnav-user-name {
  max-width: 150px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.topnav-user-chevron { width: 15px; height: 15px; color: var(--muted); transition: transform .16s ease; }
.topnav-user-btn[aria-expanded="true"] .topnav-user-chevron { transform: rotate(180deg); }

/* --- profile dropdown --- */
.topnav-user-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 60;
  min-width: 214px;
  padding: 6px;
  border: 1px solid rgba(214, 228, 219, .95);
  border-radius: 12px;
  background: #fff;
  box-shadow: 0 14px 32px rgba(15, 81, 50, .16), 0 2px 6px rgba(15, 81, 50, .06);
}
.topnav-user-menu[hidden] { display: none; }
.topnav-user-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 11px;
  border-radius: 8px;
  color: var(--ink);
  font-size: 13.5px;
  font-weight: 600;
  text-decoration: none;
  transition: background-color .14s ease, color .14s ease;
}
.topnav-user-item:hover { background: var(--green-50); color: var(--green-800); text-decoration: none; }
.topnav-user-item > svg.lucide,
.topnav-user-item > [data-lucide] { width: 16px; height: 16px; color: #7c8f84; }
.topnav-user-item:hover > svg.lucide,
.topnav-user-item:hover > [data-lucide] { color: var(--green-700); }
/* Log Out is a different kind of action from the two above it. */
.topnav-user-item.is-danger { color: #b91c1c; }
.topnav-user-item.is-danger > svg.lucide,
.topnav-user-item.is-danger > [data-lucide] { color: #dc2626; }
.topnav-user-item.is-danger:hover { background: #fdecec; color: #991b1b; }
.topnav-user-item.is-danger:hover > svg.lucide,
.topnav-user-item.is-danger:hover > [data-lucide] { color: #b91c1c; }
.topnav-user-sep { height: 1px; margin: 5px 8px; background: var(--line); }

/* --- hamburger: hidden until the menu has to collapse --- */
.topnav-burger {
  display: none;
  align-items: center;
  justify-content: center;
  width: 38px; height: 38px;
  flex-shrink: 0;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: #fff;
  color: var(--ink);
  cursor: pointer;
}
.topnav-burger:hover { background: var(--green-50); border-color: rgba(21, 115, 71, .25); }
.topnav-burger > svg.lucide,
.topnav-burger > [data-lucide] { width: 19px; height: 19px; }

/* --- content: the page measure, inset from both edges of the screen ---
   The staff page stands a full inch in from each edge of the window, not merely
   that far in at the narrow end: there is no wider measure behind it, so on a
   large monitor the page grows out to the edges and stops exactly one inch short
   of them.

   The gutter lives on the page, not on the shell. It used to sit on the shell so
   the header card could share it, but the card has its own measure again, and a
   variable left on a common ancestor for the benefit of one descendant is a
   standing invitation to wire the header back up to it by accident.

   Only max-width moves here. The width, the padding, and every card, table and
   control inside the column are exactly as they were - the gutter is space
   around the page, not a change to the page. Note that the 1228px measure this
   rule used to be clamped to is gone, which is what "an inch each edge" costs on
   a wide screen: the column is as wide as the window allows. Nothing here reaches
   the admin shell, which has a sidebar instead of a .topnav and keeps the 1280px
   measure from the base .content rule, so admin pages do not move at all. */
.app-shell:has(> .topnav) .content {
  --content-gutter: clamp(20px, calc((100% - 900px) / 2), 96px);
  width: calc(100% - 32px);
  max-width: calc(100% - (var(--content-gutter) * 2));
  margin: 0 auto;
  padding: 24px;
}
.app-shell:has(> .topnav) .app-footer { border-top-color: rgba(214, 228, 219, .9); }

/* --- responsive: the menu collapses to a panel under the header --- */
@media (max-width: 1150px) {
  /* The content column keeps the card's horizontal padding, or the page text sits
     inside the nav rather than under it. */
  .topnav-inner { padding: 10px 18px; gap: 12px; }
  .app-shell:has(> .topnav) .content { padding: 24px 18px; }
  /* The card gives up the pill at the same point the menu does, for the same
     reason. Opening the menu drops the panel inside the card and makes it about
     220px tall, and a 999px radius on a box that tall bows the sides inward far
     enough that the panel's own white corners come out through the card's curve -
     the header ends up with two tabs sticking out of its waist. A pill only reads
     as a pill while it is pill-proportioned. */
  .topnav { border-radius: 16px; }
  .topnav-burger { display: inline-flex; order: 3; }
  .topnav-right { order: 2; }
  .topnav-brand { order: 1; }
  .topnav-nav {
    order: 4;
    flex: 1 0 100%;
    flex-direction: column;
    align-items: stretch;
    /* Back to the top of the panel: the base rule centres the group, which is
       right for the horizontal bar but would float the items in the middle of
       the open panel now that the main axis is vertical. */
    justify-content: flex-start;
    gap: 2px;
    /* The pill shape belongs to the horizontal trough. Stretched down a column
       a 999px radius and the inset ring read as a mistake, so both come off and
       it becomes a plain panel. */
    border-radius: 14px;
    box-shadow: none;
    max-height: 0;
    overflow: hidden;
    padding: 0;
    transition: max-height .22s ease, padding .22s ease;
  }
  /* The panel is a child of the flex row, so it wraps onto its own line and
     pushes the header taller rather than floating over the content. */
  .topnav-inner { flex-wrap: wrap; }
  .topnav-nav.is-open {
    max-height: 320px;
    padding: 6px 0 10px;
    overflow-y: auto;
  }
  .topnav-link { padding: 10px 12px; }
  .topnav-user-name { max-width: 104px; }
}
@media (max-width: 560px) {
  /* The card's own rule at phone width, matching the 32px inset it uses above
     rather than borrowing the page gutter - the two are separate measures now. */
  .topnav { width: calc(100% - 20px); margin-top: 10px; top: 10px; }
  .topnav-inner { padding: 10px 14px; }
  .topnav-brand-text small { display: none; }
  .topnav-user-name { display: none; }
  .topnav-user-btn { padding: 5px; gap: 0; }
  .app-shell:has(> .topnav) .content { width: calc(100% - 20px); padding: 16px 14px; }
}
/* Matched to the blocks already in this file. Without it the pill colours and the
   panel slide both animate for someone who has asked the system not to. */
@media (prefers-reduced-motion: reduce) {
  .topnav-link { transition: none; }
  .topnav-nav { transition: none; }
}

a { color: var(--green-700); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3, h4 { line-height: 1.3; margin: 0 0 .5em; }

img { max-width: 100%; }
svg.lucide,
[data-lucide] {
  width: 1em;
  height: 1em;
  stroke-width: 1.8;
}
.nav-ico > svg.lucide,
.brand-logo > svg.lucide { width: 18px; height: 18px; }
.auth-ico > svg.lucide { width: 26px; height: 26px; }
.toggle-pass > svg.lucide { width: 17px; height: 17px; }
.icon-btn > svg.lucide { width: 18px; height: 18px; }
.stat-ico > svg.lucide,
.empty-ico > svg.lucide { width: 1em; height: 1em; }
.notif-ico > svg.lucide { width: 18px; height: 18px; }
.btn > svg.lucide { width: 16px; height: 16px; }
h1 > svg.lucide,
h2 > svg.lucide,
h3 > svg.lucide,
h4 > svg.lucide { vertical-align: -.15em; }

/* ------------------------------------------------------------------
   Toast notifications — centered at top of screen
   ------------------------------------------------------------------ */
.toast-stack {
  position: fixed;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  right: auto;
  z-index: 300;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: 100%;
  max-width: 360px;
  pointer-events: none;
}
.toast {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  width: 100%;
  padding: 12px 14px;
  border-radius: 10px;
  background: #fff;
  border-left: 4px solid var(--green-600);
  box-shadow: 0 12px 28px rgba(16, 24, 40, .14);
  opacity: 0;
  transform: translateY(-16px);
  transition: opacity .22s ease, transform .22s ease;
  pointer-events: auto;
}
.toast.is-visible { opacity: 1; transform: translateY(0); }
.toast.is-leaving { opacity: 0; transform: translateY(-16px); }

.toast-icon {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  flex: 0 0 26px;
  border-radius: 50%;
  background: var(--green-50);
  color: var(--green-700);
}
.toast-icon svg,
.toast-icon [data-lucide] { width: 15px; height: 15px; }

.toast-body { flex: 1; display: flex; flex-direction: column; gap: 2px; font-size: 13px; line-height: 1.4; }
.toast-body strong { font-size: 13.5px; color: var(--ink); }
.toast-body span { color: #4b5563; }

.toast-close {
  background: none;
  border: 0;
  color: var(--muted);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  padding: 2px;
}
.toast-close:hover { color: var(--ink); }

.toast-info    { border-left-color: var(--blue); }
.toast-info .toast-icon { background: var(--blue-50); color: var(--blue); }
.toast-warning { border-left-color: var(--orange); }
.toast-warning .toast-icon { background: var(--orange-50); color: var(--orange); }
.toast-error   { border-left-color: var(--red); }
.toast-error .toast-icon { background: var(--red-50); color: var(--red); }

@media (max-width: 480px) {
  /* `width: auto` is load-bearing here. The base rule is centred with
     `left: 50%` + `translateX(-50%)`, which this block replaces with a plain
     `left`/`right` inset pair - but the base `width: 100%` is still in force,
     and a fixed box's percentage width resolves against the viewport, not its
     containing block. Keeping it meant the stack spanned 12px to viewport+12px
     and pushed 12px of horizontal scroll onto every narrow screen. With both
     edges set, `width: auto` lets the inset pair govern, which is the point of
     setting them. */
  .toast-stack { top: 10px; left: 12px; right: 12px; width: auto; transform: none; max-width: none; }
}
@media (prefers-reduced-motion: reduce) {
  .toast { transition: none; }
}

/* ------------------------------------------------------------------
   Reusable confirmation modal
   ------------------------------------------------------------------ */
.confirm-modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: 20px;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .2s ease, visibility .2s ease;
}
.confirm-modal.is-open { opacity: 1; visibility: visible; pointer-events: auto; }
.confirm-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(15, 35, 25, .45);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.confirm-modal-dialog {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 360px;
  padding: 28px 26px 24px;
  border-radius: 16px;
  background: #fff;
  box-shadow: 0 30px 70px rgba(15, 45, 30, .22);
  text-align: center;
  transform: translateY(14px) scale(.97);
  transition: transform .22s cubic-bezier(.2,.8,.2,1);
}
.confirm-modal.is-open .confirm-modal-dialog { transform: translateY(0) scale(1); }
.confirm-modal-icon {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  margin: 0 auto 14px;
  border-radius: 14px;
  background: var(--red-50);
  color: var(--red);
}
.confirm-modal-icon svg,
.confirm-modal-icon [data-lucide] { width: 24px; height: 24px; }
.confirm-modal-dialog h3 { margin: 0 0 6px; font-size: 17px; }
.confirm-modal-dialog p { margin: 0 0 20px; color: var(--muted); font-size: 13.5px; line-height: 1.5; }
.confirm-modal-actions { display: flex; gap: 8px; justify-content: center; }
.confirm-modal-actions .btn { flex: 1; }

/* ------------------------------------------------------------------
  App shell (sidebar + topbar + content)
  ------------------------------------------------------------------ */
.app-shell { display: flex; min-height: 100vh; }

.sidebar {
  width: var(--sidebar-w);
  flex-shrink: 0;
  background: linear-gradient(180deg, var(--green-900) 0%, #0c4529 100%);
  color: #e9f3ee;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  z-index: 50;
}
.sidebar::-webkit-scrollbar { width: 6px; }
.sidebar::-webkit-scrollbar-thumb { background: rgba(255,255,255,.2); border-radius: 3px; }

.sidebar-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 18px 18px 14px;
  border-bottom: 1px solid rgba(255,255,255,.12);
}
.brand-logo {
  width: 38px; height: 38px;
  display: grid; place-items: center;
  background: rgba(255,255,255,.12);
  border-radius: 10px;
  font-size: 20px;
}
.sidebar-logo { width: 38px; height: 38px; object-fit: contain; background: #fff; border-radius: 8px; padding: 2px; }
.sidebar-brand-text { display: flex; flex-direction: column; line-height: 1.2; }
.sidebar-brand-text strong { font-size: 15px; letter-spacing: .5px; color: #fff; }
.sidebar-brand-text small  { font-size: 11.5px; color: #a9d5bf; }

.side-nav { padding: 12px 10px; flex: 1; }
.nav-section {
  margin: 16px 10px 6px;
  font-size: 10.5px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: #86b8a0;
  font-weight: 700;
}
.nav-link {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  margin-bottom: 2px;
  border-radius: 8px;
  color: #d9ece3;
  font-size: 14px;
  text-decoration: none;
  border-left: 3px solid transparent;
  transition: background .15s;
}
.nav-link:hover { background: rgba(255,255,255,.09); color: #fff; text-decoration: none; }
.nav-link.active {
  background: rgba(255,255,255,.14);
  border-left-color: var(--gold);
  color: #fff;
  font-weight: 600;
}
.nav-parent { font-weight: 600; }
.nav-ico { width: 18px; text-align: center; font-size: 14px; }
.nav-badge {
  margin-left: auto;
  background: var(--gold);
  color: #3b2c00;
  font-size: 11px;
  font-weight: 700;
  border-radius: 999px;
  padding: 1px 7px;
  min-width: 20px;
  text-align: center;
}
.nav-badge-warn { background: var(--orange); color: #fff; }

/* ==================================================================
   System Settings — master / detail layout
   Column 1 lists the sections, column 2 the items inside the open
   section, column 3 the selected item's content. Content slides in
   from the right rather than pushing downwards.
   ================================================================== */
.settings-shell {
  display: grid;
  grid-template-columns: 260px minmax(0, 1fr);
  gap: 14px;
  align-items: start;
}
.settings-detail { min-width: 0; }

/* Column 1 — sections */
.settings-menu {
  display: flex;
  flex-direction: column;
  gap: 8px;
  position: sticky;
  top: 14px;
}
.settings-menu-tab {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 12px 13px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: rgba(255, 255, 255, .76);
  box-shadow: 0 4px 14px rgba(31, 78, 53, .05);
  font: inherit;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
  transition: border-color .18s ease, background-color .18s ease, transform .18s ease;
}
.settings-menu-tab:hover { border-color: var(--green-600); background: var(--green-50); }
.settings-menu-tab:focus-visible { outline: 2px solid var(--green-600); outline-offset: 2px; }
.settings-menu-tab.is-active {
  border-color: var(--green-600);
  background: linear-gradient(135deg, var(--green-700), var(--green-600));
  box-shadow: 0 8px 20px rgba(21, 115, 71, .22);
}
.settings-menu-tab.is-active .settings-toggle-copy strong,
.settings-menu-tab.is-active .settings-toggle-copy small { color: #fff; }
.settings-menu-tab.is-active .settings-panel-icon {
  background: rgba(255, 255, 255, .22);
}

/* Column 2 — the open section's content (subsettings now live in the left dropdown) */
.settings-pane-form {
  display: block;
}
.settings-panel-actions {
  margin-top: 14px;
}
/* Subsetting dropdowns nested below their section in column 1 */
.settings-sect { min-width: 0; }
.settings-submenu.settings-sublist {
  position: static;
  display: none;
  margin: 2px 0 6px 18px;
  padding-left: 12px;
  border-left: 2px solid var(--line);
}
.settings-sect.is-open > .settings-sublist { display: flex; }
.settings-chev {
  margin-left: auto;
  font-size: 17px;
  line-height: 1;
  color: var(--muted);
  transition: transform .2s ease, color .2s ease;
}
.settings-sect.is-open .settings-chev { transform: rotate(90deg); }
.settings-menu-tab.is-active .settings-chev { color: #fff; }
.settings-submenu {
  display: flex;
  flex-direction: column;
  gap: 6px;
  position: sticky;
  top: 14px;
}
.settings-submenu-tab {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: #fff;
  font: inherit;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
  transition: border-color .18s ease, background-color .18s ease;
}
.settings-submenu-tab:hover { border-color: var(--green-600); background: var(--green-50); }
.settings-submenu-tab:focus-visible { outline: 2px solid var(--green-600); outline-offset: 2px; }
.settings-submenu-tab.is-active {
  border-color: var(--green-600);
  background: var(--green-50);
  box-shadow: inset 3px 0 0 var(--green-600);
}
.settings-subtoggle-copy { display: flex; min-width: 0; flex-direction: column; gap: 1px; }
.settings-subtoggle-copy strong { font-size: 14px; font-weight: 400; }
.settings-subtoggle-copy small { color: var(--muted); font-size: 11.5px; }
.settings-submenu-tab.is-active .settings-subtoggle-copy strong { font-weight: 600; }

/* Column 3 — the open item's content */
.settings-subpane-host { min-width: 0; }
.settings-subpane { display: none; }
.settings-subpane .card { margin-bottom: 0; }
.settings-subpane.is-active { display: block; }

/* Nothing is selected until an item is clicked, so there is nothing to save. */
.settings-pane-placeholder {
  display: none;
  margin: 0;
  padding: 26px 18px;
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  background: rgba(255, 255, 255, .5);
  color: var(--muted);
  font-size: 13.5px;
  text-align: center;
}
.settings-pane:not(:has(.settings-subpane.is-active)) .settings-pane-placeholder { display: block; }
.settings-pane:not(:has(.settings-subpane.is-active)) .settings-panel-actions { display: none; }

.settings-pane { display: none; }
.settings-pane.is-active { display: block; }
.settings-pane .card { margin-bottom: 0; }

/* The reveal animation: content arrives from the right, not from below. */
@keyframes settingsSlideInRight {
  from { opacity: 0; transform: translate3d(18px, 0, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}
.settings-pane.is-active,
.settings-subpane.is-active {
  animation: settingsSlideInRight .26s cubic-bezier(.22, .61, .36, 1) both;
}
@media (prefers-reduced-motion: reduce) {
  .settings-pane.is-active,
  .settings-subpane.is-active { animation: none; }
}

.settings-panel-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  grid-column: 1 / -1;
  padding-top: 2px;
}
.settings-panel {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: rgba(255, 255, 255, .76);
  box-shadow: 0 8px 22px rgba(31, 78, 53, .06);
  overflow: hidden;
}
.settings-toggle-label { display: flex; align-items: center; gap: 11px; min-width: 0; }
.settings-panel-icon {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: 0 0 34px;
  border-radius: 9px;
  background: var(--green-50);
  font-size: 16px;
}
.settings-toggle-copy { display: flex; min-width: 0; flex-direction: column; gap: 2px; }
.settings-toggle-copy strong { font-size: 14px; font-weight: 400; }
.settings-toggle-copy small { color: var(--muted); font-size: 11.5px; }
.settings-menu-tab.is-active .settings-toggle-copy strong { font-weight: 600; }

/* Stack the columns on narrow screens. */
@media (max-width: 1100px) {
  .settings-shell { grid-template-columns: 1fr; }
  .settings-menu, .settings-submenu { position: static; }
  .settings-menu { flex-direction: row; flex-wrap: wrap; }
  .settings-menu > .settings-sect,
  .settings-menu > .settings-menu-tab { flex: 1 1 210px; min-width: 0; }
}
@media (max-width: 780px) {
  .settings-pane-form { grid-template-columns: 1fr; }
  .settings-submenu { flex-direction: row; flex-wrap: wrap; }
  .settings-submenu-tab { flex: 1 1 170px; }
}

/* Email notification event switches */
.radio-stack { display: flex; flex-direction: column; gap: 8px; }
.radio-row {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fff;
  cursor: pointer;
  transition: border-color .18s ease, background-color .18s ease;
}
.radio-row:hover { border-color: var(--green-600); background: var(--green-50); }
.radio-row input { width: auto; margin-top: 2px; flex: 0 0 auto; }
.radio-row span { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.radio-row strong { font-size: 13.5px; font-weight: 600; }
.radio-row small { color: var(--muted); font-size: 11.5px; }
.radio-row:has(input:checked) { border-color: var(--green-600); background: var(--green-50); }
.radio-row input:focus-visible { outline: 2px solid var(--green-600); outline-offset: 2px; }

.settings-menu-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}
.settings-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 66px;
  padding: 11px 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--card);
  color: var(--ink);
  text-decoration: none;
  transition: border-color .18s ease, background-color .18s ease, transform .18s ease;
}
.settings-menu-item:hover {
  border-color: var(--green-600);
  background: var(--green-50);
  color: var(--green-900);
  text-decoration: none;
  transform: translateY(-1px);
}
.settings-menu-icon {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  flex: 0 0 36px;
  border-radius: 9px;
  background: var(--green-50);
  font-size: 17px;
}
.settings-menu-copy {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 2px;
}
.settings-menu-copy strong { font-size: 13px; }
.settings-menu-copy small { color: var(--muted); font-size: 11px; line-height: 1.3; }
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}
@media (max-width: 520px) {
  .settings-menu-grid { grid-template-columns: 1fr; }
}

.sidebar-user {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px;
  border-top: 1px solid rgba(255,255,255,.12);
  background: rgba(0,0,0,.15);
}
.sidebar-user-text { display: flex; flex-direction: column; line-height: 1.25; overflow: hidden; }
.sidebar-user-text strong { font-size: 13px; color: #fff; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; }
.sidebar-user-text small  { font-size: 11px; color: #a9d5bf; }
.logout-link {
  margin-left: auto;
  color: #ffd7d7;
  font-size: 13px;
  font-weight: 600;
  padding: 4px 8px;
  border-radius: 6px;
  white-space: nowrap;
  flex-shrink: 0;
}
.logout-link:hover { background: rgba(220,53,69,.35); text-decoration: none; }

.app-body { flex: 1; display: flex; flex-direction: column; min-width: 0; }

.topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 14px;
  background: #fff;
  border-bottom: 1px solid var(--line);
  padding: 10px 22px;
}
.topbar-heading { flex: 1; min-width: 0; }
.topbar-title { font-size: 17px; font-weight: 600; margin: 0; }
.topbar-subtitle {
  margin: 2px 0 0;
  color: var(--muted);
  font-size: 12.5px;
  line-height: 1.25;
}
.topbar-right { display: flex; align-items: center; gap: 12px; }
@media (min-width: 861px) {
  .topbar { display: flex; }
}

.icon-btn {
  position: relative;
  background: none;
  border: 1px solid transparent;
  border-radius: 8px;
  padding: 7px 9px;
  cursor: pointer;
  font-size: 16px;
  color: var(--ink);
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}
.icon-btn:hover { background: var(--gray-50); text-decoration: none; }
#sidebar-toggle { display: none; }
.hamburger, .hamburger::before, .hamburger::after {
  content: ""; display: block; width: 18px; height: 2px; background: var(--ink); border-radius: 2px; position: relative;
}
.hamburger::before { position: absolute; top: -6px; }
.hamburger::after  { position: absolute; top: 6px; }

.count-badge {
  position: absolute;
  top: 0; right: 0;
  background: var(--red);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  border-radius: 999px;
  padding: 1px 5px;
  min-width: 16px;
  text-align: center;
}

.user-chip { display: flex; align-items: center; gap: 8px; color: var(--ink); border-radius: 8px; padding: 4px 8px; }
.user-chip:hover { background: var(--gray-50); text-decoration: none; }
.user-chip-text { display: flex; flex-direction: column; line-height: 1.2; }
.user-chip-text strong { font-size: 13px; }
.user-chip-text small  { font-size: 11px; color: var(--muted); }

.avatar {
  width: 36px; height: 36px;
  border-radius: 50%;
  background: var(--green-700);
  color: #fff;
  display: grid;
  place-items: center;
  font-weight: 700;
  font-size: 14px;
  flex-shrink: 0;
}
.avatar-sm { width: 30px; height: 30px; font-size: 12px; }
.avatar-lg { width: 64px; height: 64px; font-size: 24px; }

.content { flex: 1; padding: 24px; max-width: 1280px; width: 100%; margin: 0 auto; }

.app-footer {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  padding: 14px 24px;
  color: var(--muted);
  font-size: 12.5px;
  border-top: 1px solid rgba(218,230,222,.8);
  background: rgba(255,255,255,.68);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

.sidebar-backdrop { display: none; }

/* ------------------------------------------------------------------
  Page header / cards / stats
  ------------------------------------------------------------------ */
.page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 20px;
}
.page-header h2 { margin: 0; font-size: 21px; }
.page-header p  { margin: 4px 0 0; color: var(--muted); font-size: 13.5px; }
.page-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* Request details page */
.back-link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 13px;
  font-weight: 600;
  color: var(--green-700);
  text-decoration: none;
  margin-bottom: 4px;
}
.back-link:hover { text-decoration: underline; }
.page-subtitle {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
}
.subtitle-sep { color: #c3c9d0; }
.queue-info-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  margin-bottom: 16px;
  border-radius: 8px;
  background: var(--blue-50);
  border: 1px solid #c9dcff;
  color: #084298;
  font-size: 13.5px;
}
.section-label {
  font-size: 14px;
  font-weight: 700;
  margin: 0 0 8px;
  color: var(--ink);
}
.rd-main-col > .card:last-child { margin-bottom: 0; }
.rd-side-col > .card:last-child { margin-bottom: 0; }

/* ------------------------------------------------------------------
   Shared request-details components.

   These live here rather than in request-details.css on purpose: the
   Account Details modal on admin/staff.php reuses .rd-info-grid / .rd-info-item
   and does NOT load that sheet, so a definition placed there would style one
   page and leave the other unstyled. One definition, both consumers.

   They were previously announced as being here and never actually written, so
   every "Request Information" grid and the whole Account Details modal rendered
   as unstyled stacked text. The label is what makes a field readable as a field,
   so this is structure, not decoration.
   ------------------------------------------------------------------ */
.rd-info-grid {
  display: grid;
  /* auto-fit rather than a fixed column count: the same rule then serves a
     two-up row on a phone and a four-up row on a desktop without a breakpoint. */
  grid-template-columns: repeat(auto-fit, minmax(min(190px, 100%), 1fr));
  gap: 18px 26px;
}
.rd-info-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
  /* Without this a long unbroken value (an email, a file path) refuses to shrink
     and pushes its whole grid column wider than the track it sits in. */
  min-width: 0;
}
.rd-info-label {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: #94a3b8;
}
.rd-info-value {
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  min-width: 0;
  /* An unbroken token has to break somewhere: break-word would leave it
     overflowing, anywhere would leave a lone letter on the next line. */
  overflow-wrap: anywhere;
}

/* The five field rows inside that same dialog (.sv-grid on admin/staff.php).

   The shared rule above is what a request sheet wants: several columns of
   label-above-value fields filling the width of a wide page. This dialog shows
   five of them, read straight down as one block of detail, and stacked
   label-above-value costs a line each for a label that is shorter than its
   value. One column here, and label plus value share a line so the eye takes
   the list in one pass - with the labels holding a common floor so every value
   still starts on the same column instead of each row sizing itself. */
.sv-grid {
  /* max-content rather than 1fr, so the column is the widest ROW instead of the
     dialog. That is what makes the five rows a block of their own width: a 1fr
     column always filled the dialog, so the rows sat flush left with every pixel
     of slack dumped on the right of the values, and the group read as indented
     left rather than as a centred block.

     minmax(0, ...) keeps the floor at zero, which is the part that stops this
     overflowing. The track grows only as far as the smaller of its max-content
     and the space actually there, so a value too long to fit caps the column at
     the container and wraps - the protection the 1fr above was providing - while
     a value that fits leaves genuine slack for justify-content to centre. */
  grid-template-columns: minmax(0, max-content);
  justify-content: center;
  gap: 11px;
}
.sv-grid .rd-info-item {
  display: flex;
  flex-direction: row;
  align-items: baseline;
  gap: 12px;
}
.sv-grid .rd-info-label {
  /* Widest label in this list is "EMAIL ADDRESS"; the floor aligns the values
     without padding the shorter labels out by hand, and a floor rather than a
     width lets a longer label wrap instead of overflowing. */
  flex: 0 0 auto;
  min-width: 122px;
}

/* One inch (96px) of room either side of the five rows, so the list sits as a
   block of detail inside the dialog instead of running up to its walls.

   It is also the width the column above is allowed to reach before it stops
   growing and wraps, so a long value ends the row at the inch line rather than
   running the width of the dialog. The allowance can no longer push a label past
   the edge of its own row: minmax(0, ...) floors the track at zero, so a row that
   will not fit wraps inside the space instead of overflowing out of it.

   Gated on viewport width because .modal-dialog is min(720px, 100%): it only
   reaches its full 560px once the window is ~604px wide, and at 360px there is
   physically no inch to give, so there it is simply not applied. */
@media (min-width: 600px) {
  .sv-grid {
    padding-left: 96px;
    padding-right: 96px;
  }
}

/* The identity block at the top of the Account Details modal (admin/staff.php).

   The fields underneath reuse .rd-info-*, defined above because two pages share
   it. These .sv-* classes had no rules at all, so .sv-head fell back to
   display:block: the avatar sat on a line of its own above the name and the
   badges ran to the left edge. On a wide dialog that reads as a deliberate
   layout, which is how it lasted - but it was an accident, and a narrow one stacks
   the avatar, name, badges and five fields into a tall left-aligned column.

   Centred as one unit - avatar, name, badges - per the admin's request. The
   fields underneath deliberately keep the left-aligned label-above-value form they
   share with the request details sheet: centring each value would fight the
   uppercase-label, left-aligned-value idiom used across the app, and a centred
   grid of short values reads worse than a left-aligned one. */
.sv-head {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 10px;
  padding-bottom: 18px;
  margin-bottom: 20px;
  border-bottom: 1px solid var(--line);
}
.sv-head-copy {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  /* A long name has to wrap rather than push the block wider than the dialog. */
  min-width: 0;
  max-width: 100%;
}
.sv-head-copy h4 {
  /* The dialog's own heading already says "Account Details"; this line is the
     person. The default h4 margin would also shove it off centre. */
  margin: 0;
  font-size: 17px;
  font-weight: 700;
  line-height: 1.25;
  color: var(--ink);
  overflow-wrap: anywhere;
}
.sv-badges {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  min-width: 0;
  max-width: 100%;
}

/* An inline drawn signature.

   render_signature() wraps a drawn (SVG) signature in .sig-inline, and
   sanitize_signature_svg() strips width and height because they are not in its
   attribute allow-list - so the SVG arrives with a viewBox and nothing else.
   Unstyled that means the replaced-element default of 300x150, which is a
   signature several times the size of the box it sits in.

   .sig-overlay is the same wrapper with a class of its own, already capped at
   230x54 in request-details.css. Both are capped to the same size here so one
   signature looks identical wherever it appears on the page. */
.sig-inline {
  display: inline-block;
  max-width: 230px;
  vertical-align: middle;
  line-height: 0;
}
.sig-inline > svg {
  display: block;
  width: 100%;
  height: auto;
  max-height: 54px;
}

/* ------------------------------------------------------------------
   The request-details document.

   The page is a formal institutional request form, not a dashboard: one
   white sheet on a faintly tinted page, a wide measure, section headings
   centred and divided by thin rules, and no field in a box of its own.

   Lives here rather than in request-details.css because the Account Details
   modal and the shared .rd-info-* components live here too, and the form
   markup is built by the rd_* helpers in includes/functions.php.
   ------------------------------------------------------------------ */

/* The page behind the sheet. Scoped to this page's body class so no other
   screen in the app changes colour; .rd-page's siblings outside the sheet -
   the request header, the timeline - sit on this tint too. */
body.request-details-page .content {
  background: linear-gradient(180deg, #f2f7f4 0%, #eef4f1 100%);
  border-radius: 18px;
}

.rd-form {
  /* ~1040px: wide enough that paired fields have room for real values, narrow
     enough to stay a page rather than a spreadsheet. */
  max-width: 1040px;
  margin: 0 auto;
}

/* ---- fields ------------------------------------------------------ */
.rd-form-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 22px 56px;
  margin-bottom: 20px;
}
.rd-form-cell {
  display: block;
  min-width: 0;
}
.rd-form-cell-full { grid-column: 1 / -1; }
.rd-form-label {
  display: block;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--green-800);
  margin-bottom: 5px;
}
.rd-form-value {
  font-size: 14.5px;
  line-height: 1.65;
  color: var(--ink);
  font-weight: 500;
  min-width: 0;
  /* A long unbroken value - an email, a URL, a file path - has to break
     somewhere rather than widen the column it sits in. */
  overflow-wrap: anywhere;
  /* Every answer on this sheet sits on a rule, the way a filled paper form does.
     Without it the sheet reads as a web form with fields; with it, it reads as a
     document that has been filled in. Applied to the value block rather than to
     each row so a multi-line answer is ruled once underneath, not once per line. */
  border-bottom: 1px solid #cfd8d3;
  padding-bottom: 6px;
}
/* The value inside a packed row carries its own rule already, on the span that
   sits on the line; a second one under the block would double it. The descendant
   selector matters as much as the direct-child one: a block answer sits inside
   .rd-form-inline-value, one level further down, and a `>` selector stops there -
   which is how a single comment came to be underlined twice. */
.rd-form-inline-cell > .rd-form-value,
.rd-form-labelled > .rd-form-value,
.rd-form-inline-value .rd-form-value { border-bottom: 0; padding-bottom: 0; }
/* The signature block is not a field value and rules under a signature read as
   an approval box rather than as ink on a line. */
.rd-sig .rd-form-value { border-bottom: 0; padding-bottom: 0; }
/* Free text and the file cards get room of their own, and a floor so an empty
   one still holds its place in the flow. */
.rd-form-cell-block .rd-form-value { min-height: 30px; }
/* An unfilled field shows a mark, the way a blank line on a paper form does. */
.rd-form-value:empty::after {
  content: "\2014";
  color: #a9b4c2;
}
/* A second line under a value - the requester's email under their name. */
.rd-form-sub {
  display: block;
  font-size: 13px;
  font-weight: 500;
  color: var(--muted);
  margin-top: 2px;
}

/* ---- section headings and dividers -------------------------------- */
.rd-form-group {
  margin: 0 0 18px;
  text-align: center;
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--green-800);
}
/* On the left margin, for a group whose content beneath it is a run of
   full-width ruled lines. The other two groups sit above a centred signature
   block and stay centred; a heading centred over left-aligned fields reads as
   detached from the fields it names. */
.rd-form-group-left {
  text-align: left;
}
.rd-form-rule {
  height: 1px;
  margin: 30px 0;
  background: #dfe6e2;
  border: 0;
}

/* ---- the title block -------------------------------------------------
   On a paper form the title is the one centred line: bigger than anything
   around it and in capitals, because it names the request and nothing else on
   the sheet competes with it. The capitals are applied in PHP by rd_title()
   rather than here, so the value that reaches the printed sheet and the email
   summary is already uppercase - `text-transform` would leave those reading
   the stored lowercase string. */
.rd-form-title {
  margin: 0 0 26px;
  text-align: center;
  /* Deliberately smaller than .rd-card-title, which is 20px. A form's own heading
     must not outweigh the heading of the card that holds it: the card says what
     this is ("Request Information"), the title beneath it says what this one is. */
  font-size: 19px;
  font-weight: 800;
  line-height: 1.3;
  letter-spacing: .04em;
  color: var(--ink);
  /* A title long enough to wrap breaks on its own words rather than pushing the
     sheet past its measure. */
  overflow-wrap: anywhere;
}
/* The form's own name for the title, set above it. Centred like the group
   headings, so the block reads as "name of the field, then the answer" the way
   the rest of the sheet does. */
.rd-form-title-label {
  display: block;
  margin-bottom: 8px;
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--green-800);
}

/* ---- a label with its answer beneath it ------------------------------
   The default cell's label is the form's small letterspaced kind, which reads as
   a database column heading. The fields a respondent answers in prose need the
   label as prominent as the answer, so the label is promoted to body size and
   the answer sits under it. */
.rd-form-labelled { margin-bottom: 20px; }
.rd-form-labelled .rd-form-label {
  margin-bottom: 4px;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: .01em;
}

/* ---- the packed "label: ______" rows ---------------------------------
   Two form fields sharing one line, each with a rule its value sits on. The
   rule is what carries the eye from one column to the next, and it is why the
   value is inline here rather than under its label.

   The rule is drawn on the value span rather than on the cell, so it stops at
   the text rather than running under the label, and an unanswered field still
   shows the blank line a paper form would show. */
.rd-form-inline {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px 44px;
  margin-bottom: 20px;
}
.rd-form-inline-cell { min-width: 0; }
/* A row with one cell is a full-width field, not a half-empty pair. Without
   this a lone "description / post caption" occupied the left column and left the
   right one blank, which reads as a missing field rather than a wide one. */
.rd-form-inline-cell:only-child { grid-column: 1 / -1; }
.rd-form-inline-head {
  display: flex;
  /* Baseline, not flex-end. The two labels on a row must line up across it: that
     is the stronger convention and the one a paper form keeps. flex-end was tried
     here to level the two rules, and it does level them - but only while both
     values are one line. The moment one wraps, its head grows, and flex-end then
     pushes that cell's label down below its partner's while the rules still do
     not line up, because each is bottom-aligned inside its own head. Baseline
     costs the rules a line of alignment in that case, which is also what the
     paper form does: each answer is ruled directly beneath itself. */
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}
.rd-form-inline-label {
  flex: 0 0 auto;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .05em;
  /* Uppercase for the same reason .rd-form-label is: every label on this sheet is
     a label, and a row of lowercase ones next to uppercase ones reads as an
     oversight. Only the label is transformed - the value beside it is data. */
  text-transform: uppercase;
  color: var(--green-800);
}
.rd-form-inline-value {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 14.5px;
  color: var(--ink);
  border-bottom: 1px solid #cfd8d3;
  /* No bottom padding: the heads are bottom-aligned so the rules are level,
     and padding here would offset this rule below its partner's by exactly that
     much. */
  padding: 0 4px;
  overflow-wrap: anywhere;
}
/* The unfilled-value marker puts a dash in an empty cell, which is right for a
   field under a label. On a packed row the rule already reads as the blank
   field, so the dash would sit on top of it. */
.rd-form-inline-value:empty::after { content: none; }
/* Secondary detail inside a packed value - the platform a post went to, the
   published link. Smaller and quieter than the date beside it, because the date
   is what the field is asking for and the rest is context. */
.rd-inline-sub { font-size: 12.5px; color: var(--muted); }
.rd-inline-link { font-size: 12.5px; overflow-wrap: anywhere; }
/* Block content under one cell of a pair - the attachment cards in the
   accompanying-materials half. Rendered inside the cell so it stays under its
   own half of the row instead of below the whole grid. */
.rd-form-inline-cell .rd-form-value-block { margin-top: 12px; }
/* An attached URL is written on the cell's rule beside its label, like every
   other answer on the sheet, so it is sized like one and inherits the rule
   rather than carrying its own spacing. It used to sit above the cards as a
   separate block, which needed a bottom margin that would now push the rule
   down out of line with the label. */
.rd-materials-link {
  font-size: 13.5px;
  overflow-wrap: anywhere;
}

/* ---- the signature ------------------------------------------------
   The mark is laid over the upper part of the printed name, the way ink sits
   on a form someone has physically signed. Two rules make that work:

   .rd-sig-field is the positioning context and reserves the room the mark
   occupies, via padding-top on the name. Without that padding the mark, which
   is out of flow, would hang above the box and overlap whatever came before.

   The name and the mark carry different z-indexes, so the ink is on top of the
   type while the name stays readable through it. Both are pointer-transparent
   so the printed name underneath remains selectable and clickable. */
.rd-sig {
  margin: 8px 0 6px;
  text-align: center;
  /* The mark is absolutely positioned, so the page-break rules below are what
     stop a signature ending up on a different page from the name it signs. */
  break-inside: avoid;
  page-break-inside: avoid;
}
.rd-sig-field {
  position: relative;
  display: inline-block;
  min-width: 250px;
  padding-top: 36px;
  text-align: center;
}
.rd-sig-name {
  position: relative;
  z-index: 1;
  display: inline-block;
  padding: 0 16px 4px;
  font-size: 15px;
  font-weight: 700;
  color: var(--ink);
  /* The rule a signature is written on. */
  border-bottom: 1px solid #cfd8d3;
}
.rd-sig-mark {
  position: absolute;
  z-index: 2;
  left: 50%;
  top: 0;
  transform: translateX(-50%);
  width: 168px;
  max-width: 100%;
  height: 54px;
  background: transparent;
  pointer-events: none;
  /* Nothing here may be dragged, selected or clicked: it is decoration laid
     over text, not a control. */
  user-select: none;
  -webkit-user-drag: none;
}
/* A fixed box with the drawing fitted inside it, so a signature of any
   proportions is neither stretched nor cropped. The SVG path is scaled by its
   own viewBox, and the bitmap by object-fit, so both keep their natural
   aspect ratio. */
.rd-sig-mark > svg,
.rd-sig-mark .sig-inline,
.rd-sig-mark .sig-overlay,
.rd-sig-mark img {
  display: block;
  width: 100%;
  height: 100%;
  max-width: 100%;
  max-height: 100%;
  margin: 0;
  object-fit: contain;
  object-position: center bottom;
}
/* A drawn signature arrives as an inline SVG inside .sig-inline with no
   width or height at all - sanitize_signature_svg() strips both - so without
   this it falls back to the 300x150 replaced-element default. */
.rd-sig-mark .sig-inline > svg,
.rd-sig-mark .sig-overlay > svg {
  display: block;
  width: 100%;
  height: 100%;
  max-height: 100%;
}
.rd-sig-role {
  margin-top: 9px;
  font-size: 13px;
  color: var(--green-800);
  font-weight: 600;
}
.rd-sig-date {
  margin-top: 3px;
  font-size: 12.5px;
  color: var(--muted);
}

/* ---- responsive ---------------------------------------------------
   Below 900px the measure is no longer needed and the two-column pairs stop
   fitting, so both collapse. The sheet's own padding is adjusted in
   request-details.css, where the sheet is declared - these two sheets load in
   order, so a padding rule for the same class here would be overridden by the
   base rule over there and silently do nothing. */
@media (max-width: 900px) {
  .rd-form { max-width: none; }
  .rd-form-row { grid-template-columns: minmax(0, 1fr); gap: 18px; }
  /* The packed rows collapse for the same reason, and sooner than the cells
     would: two ruled fields on one line stop being readable once a value
     wraps, because there is nowhere for the second line to go but the rule. */
  .rd-form-inline { grid-template-columns: minmax(0, 1fr); }
  .rd-form-title { font-size: 21px; }
  .rd-form-rule { margin: 24px 0; }
  .rd-sig-field { min-width: 200px; }
  .rd-sig-mark { width: 140px; height: 46px; }
}
@media (max-width: 560px) {
  .rd-form-group { font-size: 11.5px; letter-spacing: .08em; }
  .rd-form-value { font-size: 14px; }
}

/* ---- print --------------------------------------------------------
   The sheet fills the paper and loses its own furniture, so what prints is the
   document and not the screen. The signature rules above are deliberately NOT
   reset here: the overlay is absolutely positioned, and a print engine that
   re-lays-out the containing block can separate a mark from the name it signs.
   Leaving .rd-sig-field's position, .rd-sig-name's z-index and .rd-sig-mark's
   offsets exactly as they are on screen is what keeps them together on paper. */
@media print {
  .rd-form { max-width: none; }
  .rd-form-rule { margin: 20px 0; background: #c8d2cc; }
  /* Section headings, dividers, signatures and paired rows are the parts that
     must not be split by a page break. */
  .rd-form-group,
  .rd-sig,
  .rd-form-row,
  .rd-form-title,
  .rd-form-labelled,
  .rd-form-inline,
  .rd-attachment,
  .rd-timeline-wrap {
    break-inside: avoid;
    page-break-inside: avoid;
  }
  .rd-form-group { break-after: avoid; page-break-after: avoid; }
  .rd-tl-item { break-inside: avoid; page-break-inside: avoid; }
}

/* User Management (um-*) — glass folder tabs */
.um-page { max-width: 1180px; margin: 0 auto; }

/* Tabs */
.um-tabs {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  overflow: visible;
  padding: 14px 12px 0;
  border-bottom: 1px solid rgba(218,230,222,.8);
  background: rgba(248,252,249,.42);
}
.um-tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-width: 142px;
  width: 100%;
  padding: 11px 13px 10px;
  border: 1px solid rgba(207,224,213,.9);
  border-bottom: 0;
  border-radius: 11px 11px 4px 4px;
  background: rgba(255,255,255,.5);
  color: #557164;
  font-size: 12.5px;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
  box-shadow: 0 5px 12px rgba(31,78,53,.05), inset 0 1px 0 rgba(255,255,255,.85);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  transition: background-color .28s ease, color .28s ease, border-color .28s ease, box-shadow .28s ease, transform .28s ease;
}
.um-tab:hover {
  background: rgba(255,255,255,.78);
  color: var(--green-800);
  text-decoration: none;
  transform: translateY(-1px);
}
.um-tab.is-active,
.um-tab[aria-selected="true"] {
  z-index: 1;
  margin-bottom: -1px;
  border-color: rgba(21,115,71,.8);
  background-color: rgba(15,81,50,.84);
  background-image: linear-gradient(135deg, rgba(255,255,255,.14), rgba(255,255,255,0));
  color: #fff;
  backdrop-filter: blur(16px) saturate(135%);
  -webkit-backdrop-filter: blur(16px) saturate(135%);
  box-shadow: 0 8px 18px rgba(31,78,53,.18), inset 0 1px 0 rgba(255,255,255,.18);
}
.um-tab.is-active:hover,
.um-tab[aria-selected="true"]:hover,
.um-tab:active,
.um-tab:focus-visible {
  background-color: rgba(15,81,50,.94);
  background-image: linear-gradient(135deg, rgba(255,255,255,.16), rgba(255,255,255,0));
  color: #fff;
}
.um-tab-content {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
.um-tab-icon { width: 16px; height: 16px; flex: 0 0 16px; }
.um-tab-count {
  display: inline-grid;
  place-items: center;
  min-width: 21px;
  height: 21px;
  padding: 0 6px;
  border-radius: 999px;
  background: #e5f1e9;
  color: #2b7650;
  font-size: 10.5px;
  font-style: normal;
  font-weight: 800;
  margin-left: auto;
}
.um-tab.is-active .um-tab-count,
.um-tab[aria-selected="true"] .um-tab-count,
.um-tab:active .um-tab-count,
.um-tab:focus-visible .um-tab-count {
  background: rgba(255,255,255,.2);
  color: #fff;
}

/* Panel */
.um-panel {
  position: relative;
  z-index: 2;
  margin-top: -1px;
  border: 1px solid rgba(255,255,255,.85);
  border-radius: 14px 16px 16px 16px;
  background: rgba(255,255,255,.72);
  box-shadow: 0 18px 42px rgba(31,78,53,.1), inset 0 1px 0 rgba(255,255,255,.95);
  backdrop-filter: blur(18px) saturate(125%);
  -webkit-backdrop-filter: blur(18px) saturate(125%);
  overflow: hidden;
}
.um-panel-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 22px 24px 18px;
  border-bottom: 1px solid var(--line);
}
.um-panel-heading { display: flex; align-items: flex-start; gap: 14px; }
.um-panel-icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  flex: 0 0 46px;
  border-radius: 12px;
  background: var(--green-50);
  color: var(--green-700);
}
.um-panel-icon svg { width: 22px; height: 22px; }
.um-panel-heading h2 { margin: 0; font-size: 20px; }
.um-panel-heading p { margin: 3px 0 0; color: var(--muted); font-size: 13.5px; }
.um-add-btn { display: inline-flex; align-items: center; gap: 8px; }

/* ------------------------------------------------------------------
   The form guide (staff/create-request.php).

   One guide per IMO form, rendered directly above the form it describes. It
   answers the two questions a requester has in the order they ask them - what
   is this form for, and is my post one of those - so the description takes the
   left column and the "Used for" list takes the right, and the two are split
   by a rule rather than by a line break so the block reads as one panel
   header.

   These classes shipped with no rules anywhere in the sheet, so the whole
   block fell back to browser defaults: an unstyled h3, a paragraph, the words
   "Used for:" and a bulleted list, all flush against the panel edge. It is
   guidance, so it is styled as the panel's own header strip - same padding as
   .um-panel-header, same bottom edge - rather than as a card floating above
   the cards.
   ------------------------------------------------------------------ */
.form-guide {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 16px;
  padding: 22px 24px 20px;
  border-bottom: 1px solid var(--line);
  background: linear-gradient(135deg, rgba(237, 247, 242, .95) 0%, rgba(255, 255, 255, .5) 65%);
}
.form-guide-head {
  display: flex;
  align-items: flex-start;
  gap: 13px;
  /* A long title has to wrap inside its column, not widen the whole row. */
  min-width: 0;
}
.form-guide-ico {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  flex: 0 0 40px;
  border-radius: 11px;
  background: #fff;
  border: 1px solid rgba(207, 224, 213, .95);
  color: var(--green-700);
  box-shadow: 0 6px 14px rgba(31, 78, 53, .09);
}
/* The icon's right-hand column. Keeping the title and the description together
   here is what makes them share a left edge: .um-panel-heading does the same
   for its own h2 and p, and the two blocks should not disagree about where a
   paragraph starts relative to the mark beside it. */
.form-guide-copy { min-width: 0; }
.form-guide-title {
  /* The default h3 margin would pull this line off the icon's centre. */
  margin: 3px 0 0;
  font-size: 16.5px;
  font-weight: 700;
  line-height: 1.35;
  color: var(--ink);
}
.form-guide-desc {
  margin: 7px 0 0;
  font-size: 13.5px;
  line-height: 1.62;
  color: var(--muted);
}
.form-guide-used {
  min-width: 0;
  padding-top: 14px;
  border-top: 1px dashed rgba(207, 224, 213, 1);
}
.form-guide-used-label {
  margin: 0 0 9px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: #94a3b8;
}
.form-guide-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.form-guide-chips li {
  padding: 5px 11px;
  border: 1px solid rgba(207, 224, 213, .95);
  border-radius: 999px;
  background: rgba(255, 255, 255, .9);
  color: var(--green-800);
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.35;
}
/* Side by side only when both columns have room for one; below this the chips
   drop under the description and the dashed rule between them flips to run
   across the block instead of down it. */
@media (min-width: 900px) {
  .form-guide {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    gap: 18px 34px;
    align-items: start;
  }
  .form-guide-head { grid-column: 1; grid-row: 1; }
  .form-guide-used {
    grid-column: 2;
    grid-row: 1;
    align-self: center;
    padding-top: 0;
    padding-left: 30px;
    border-top: 0;
    border-left: 1px dashed rgba(207, 224, 213, 1);
  }
}
/* The first card under the guide would otherwise butt straight up against the
   guide's bottom edge. */
#service-request-panel form .card:first-child { margin-top: 20px; }

/* Filters */
.um-filters {
  display: flex;
  gap: 10px;
  padding: 16px 24px;
  border-bottom: 1px solid var(--line);
  background: rgba(251, 252, 253, 0.6);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.um-select-wrap, .um-search-wrap {
  position: relative;
  display: flex;
  align-items: center;
}
.um-select-wrap svg, .um-search-wrap svg {
  position: absolute;
  left: 12px;
  color: var(--muted);
  pointer-events: none;
}
.um-select-wrap select {
  width: 200px;
  padding-left: 34px;
}
.um-search-wrap { flex: 1; }
.um-search-wrap input {
  width: 100%;
  padding-left: 34px;
}
.um-reset-btn { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; }

/* Table */
.um-table th { background: #fbfcfd; }
.um-empty {
  padding: 32px;
  text-align: center;
  color: var(--muted);
  font-size: 13.5px;
}

/* Footer */
.um-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 24px;
  color: var(--muted);
  font-size: 13px;
}

/* Icon buttons */
.icon-btn {
  display: inline-grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  border: 0;
  cursor: pointer;
  transition: filter .15s;
}
.icon-btn:hover { filter: brightness(.92); }
.um-edit-btn { background: var(--green-50); color: var(--green-700); }
.um-delete-btn { background: var(--red-50); color: var(--red); }

@media (max-width: 760px) {
  /* `.um-tabs` is a three-column grid at full width, and two of the declarations
     in this block are flex properties - which do nothing at all to a grid
     container. So the row kept its equal thirds while each tab's label stayed
     `nowrap`, and three labels fought over a phone's width, pushing the page
     sideways. Declaring the row as flex again is what makes the rest of this
     block mean what it says.

     `flex: 0 0 auto` deliberately replaces the `1 1 33%` these tabs had here.
     A third of a 480px screen is 148px, and the longest label needs 218px, so
     a 33% basis would squeeze every label past its own box instead of letting
     the row wrap. Sizing to content lets two tabs share a line and the third
     drop to the next, which is why `flex-wrap: wrap` is worth keeping. */
  .um-tabs {
    display: flex;
    flex-wrap: wrap;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
  }
  .um-tab { width: auto; flex: 0 0 auto; min-width: 142px; margin-right: -1px; }
  .um-filters { flex-wrap: wrap; }
  .um-select-wrap select, .um-search-wrap { width: 100%; }
}
.staff-page-actions { align-items: stretch; flex-wrap: nowrap; }
.staff-action-btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 52px;
  padding: 8px 13px;
  border: 1px solid transparent;
  border-radius: 12px;
  text-decoration: none;
  transition: border-color .18s ease, background-color .18s ease, box-shadow .18s ease, transform .18s ease;
}
.staff-action-btn:hover { text-decoration: none; transform: translateY(-1px); }
.staff-registration-btn {
  border-color: #f0d28e;
  background: #fff9e9;
  color: #805600;
}
.staff-registration-btn:hover { border-color: #e5b94f; background: #fff4d6; }
.staff-add-btn {
  border-color: var(--green-700);
  background: linear-gradient(135deg, var(--green-700), var(--green-600));
  color: #fff;
  box-shadow: 0 6px 14px rgba(21,115,71,.18);
}
.staff-add-btn:hover { background: linear-gradient(135deg, var(--green-800), var(--green-700)); }
.staff-action-icon {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  flex: 0 0 32px;
  border-radius: 9px;
  background: rgba(255,255,255,.62);
  font-size: 16px;
  font-weight: 700;
}
.staff-add-btn .staff-action-icon { background: rgba(255,255,255,.16); }
.staff-action-copy {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 2px;
  text-align: left;
}
.staff-action-copy strong { font-size: 13px; line-height: 1.2; }
.staff-action-copy small { font-size: 10.5px; line-height: 1.2; opacity: .78; }
.staff-action-count {
  display: inline-grid;
  place-items: center;
  min-width: 22px;
  height: 22px;
  margin-left: 2px;
  padding: 0 6px;
  border-radius: 999px;
  background: #e0a91b;
  color: #3c2b00;
  font-size: 11px;
  font-weight: 800;
}
.staff-management-page .staff-list-card {
  overflow: visible;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.staff-management-page .staff-list-card .table-wrap {
  position: relative;
  overflow-x: auto;
  overflow-y: visible;
}
.staff-management-page .staff-action-menu { z-index: 50; }
.staff-management-page .staff-action-menu[open] { z-index: 100; }
.staff-action-menu .queue-action-menu-panel { min-width: 190px; }
.staff-archived-btn {
  border-color: #d5dde4;
  background: #f7f9fa;
  color: #4b5563;
}
.staff-archived-btn:hover { border-color: #aebdc7; background: #eef2f4; color: var(--ink); }
.staff-archived-count { background: #dfe6eb; color: #53616d; }
.staff-archived-filter-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  white-space: nowrap;
}
.staff-archived-filter-btn .staff-action-count { margin-left: 1px; }
@media (max-width: 760px) {
  .staff-page-actions { flex-wrap: wrap; }
}
.staff-row-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
}
.staff-row-actions .inline-form { display: inline-flex; }
.dashboard-header-actions { align-items: flex-start; }
.dashboard-header-actions .notif-btn {
  width: 38px;
  height: 38px;
  border-color: #d6e5db;
  background: rgba(255,255,255,.62);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

.card {
  background: rgba(255,255,255,.76);
  border: 1px solid rgba(255,255,255,.86);
  border-radius: var(--radius);
  box-shadow: 0 12px 30px rgba(31,78,53,.08), 0 2px 8px rgba(31,78,53,.04), inset 0 1px 0 rgba(255,255,255,.9);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  margin-bottom: 20px;
  overflow: hidden;
}
.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 14px 18px;
  border-bottom: 1px solid rgba(218,230,222,.8);
  background: rgba(248,252,249,.58);
}
.card-header h3 { margin: 0; font-size: 15.5px; font-weight: 600; }
.card-header small { color: var(--muted); font-weight: 400; }
.card-body { padding: 18px; }
.card-body.tight { padding: 0; }

.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(170px, 100%), 1fr));
  gap: 14px;
  margin-bottom: 22px;
}
.stat-card {
  background: rgba(255,255,255,.72);
  border: 1px solid rgba(255,255,255,.86);
  border-left: 4px solid var(--green-600);
  border-radius: var(--radius);
  box-shadow: 0 10px 24px rgba(31,78,53,.07), inset 0 1px 0 rgba(255,255,255,.9);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  padding: 14px 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  text-decoration: none;
  color: var(--ink);
}
a.stat-card:hover { text-decoration: none; box-shadow: var(--shadow-lg); transform: translateY(-1px); }
.stat-card .stat-value { font-size: 26px; font-weight: 700; line-height: 1.1; }
.stat-card .stat-label { font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.stat-card .stat-ico { font-size: 22px; opacity: .8; }
.stat-card.c-blue   { border-left-color: var(--blue); }
.stat-card.c-orange { border-left-color: var(--orange); }
.stat-card.c-purple { border-left-color: var(--purple); }
.stat-card.c-cyan   { border-left-color: var(--cyan); }
.stat-card.c-green  { border-left-color: var(--green-600); }
.stat-card.c-red    { border-left-color: var(--red); }
.stat-card.c-gray   { border-left-color: #adb5bd; }
/* Revision, in the revision pink, and this class was simply missing: the
   dashboard's "For Revision" card asked for c-revision and got the default green
   border every other card overrides, so the one card that is not an ordinary
   queue state was the only one with no colour of its own.

   The four dashboard cards now read as the statuses they count, and each matches
   the colour that status wears elsewhere: blue for submitted/pending, green for
   approved, cyan for scheduled, and the pink the revision banner and the timeline
   already use. */
.stat-card.c-revision { border-left-color: var(--ps-revision-fx); }

/* Every track below is `minmax(0, Nfr)` rather than a bare `Nfr`, and the
   difference is the whole narrow-screen story. A bare `1fr` is shorthand for
   `minmax(auto, 1fr)`, and `auto` as a minimum resolves to the item's
   min-content width - so the track refuses to get narrower than its widest
   unbreakable descendant. `.dashboard-cards` measured 433px of available width
   and laid out a single 627px track, because something inside a card would not
   wrap. Naming the minimum as 0 states what was always meant: share the space,
   and let the wide content (tables, mostly, which live in their own scroller)
   deal with itself.

   The auto-fit grids use `min(Npx, 100%)` for the same reason in one step: a
   330px floor is wider than a 360px phone's content box, and `min()` lets the
   track collapse instead of overflowing. */
.grid-2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 20px; }
.grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
.grid-main { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 20px; }
.dashboard-cards { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; }
.dashboard-analytics-card { overflow: hidden; }
.analytics-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-bottom: 8px;
  color: var(--muted);
  font-size: 12px;
}
.analytics-legend > span { display: inline-flex; align-items: center; gap: 6px; }
.analytics-legend-dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
}
.analytics-legend-received { background: var(--green-600); }
.analytics-legend-published { background: var(--gold); }
.analytics-chart-wrap {
  width: 100%;
  overflow: hidden;
  padding: 4px 0 0;
}
.analytics-chart {
  display: block;
  width: 100%;
  height: auto;
  min-height: 210px;
}
.analytics-chart-grid {
  stroke: #e5e7eb;
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
.analytics-chart-axis-line {
  stroke: #cbd5e1;
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
.analytics-chart-axis {
  fill: #6b7280;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 11px;
}
.analytics-chart-line {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 3;
  vector-effect: non-scaling-stroke;
}
.analytics-chart-received { stroke: var(--green-600); }
.analytics-chart-published { stroke: var(--gold); }
.analytics-chart-point { stroke: #fff; stroke-width: 2; vector-effect: non-scaling-stroke; }
.analytics-chart-received-point { fill: var(--green-600); }
.analytics-chart-published-point { fill: var(--gold); }
@media (max-width: 600px) {
  .analytics-chart { min-height: 180px; }
  .analytics-chart-axis { font-size: 10px; }
}

.queue-analytics-card { overflow: hidden; }
.queue-analytics-card .card-header {
  flex-wrap: wrap;
  gap: 10px;
}
.qa-legend-toggle {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.qa-legend-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--gray-50);
  color: var(--ink);
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
  user-select: none;
  transition: opacity .15s ease;
}
.qa-legend-chip i {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--chip-color, var(--green-700));
}
.qa-legend-chip.off {
  opacity: .4;
  text-decoration: line-through;
}
.qa-metrics-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 16px;
}
.qa-metric-pill {
  padding: 6px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: #fff;
  color: var(--muted);
  cursor: pointer;
  font-size: 12.5px;
  font-weight: 600;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.qa-metric-pill:hover { border-color: var(--green-600); }
.qa-metric-pill.active {
  background: var(--green-50);
  border-color: #b8d8c3;
  color: var(--green-800);
}
.qa-chart-wrap {
  position: relative;
  width: 100%;
  height: auto;
}
.qa-chart-wrap.qa-chart-js { height: 320px; }
.qa-chart-wrap:not(.qa-chart-js) { height: auto; }
.qa-chart-wrap canvas {
  display: none;
  width: 100% !important;
  height: 100% !important;
}
.qa-chart-wrap.qa-chart-js canvas { display: block; }
.qa-fallback-chart {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 760 / 320;
}
.qa-chart-wrap.qa-chart-js .qa-fallback-chart { display: none; }
.qa-fallback-grid { stroke: #e5e7eb; stroke-width: 1; vector-effect: non-scaling-stroke; }
.qa-fallback-axis-line { stroke: #cbd5e1; stroke-width: 1; vector-effect: non-scaling-stroke; }
.qa-fallback-axis { fill: #6b7280; font-family: Arial, Helvetica, sans-serif; font-size: 11px; }
.qa-fallback-line { fill: none; stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.qa-fallback-pending { stroke: #dc3545; }
.qa-fallback-oldestAge { stroke: #f0a500; }
.qa-fallback-avgTurnaround { stroke: #198754; }
.qa-fallback-area { fill: rgba(220, 53, 69, .10); stroke: none; }
.qa-chart-wrap canvas,
.qa-chart-wrap .qa-fallback-chart {
  width: calc(100% - 1in) !important;
  margin-right: 0.5in;
  margin-left: 0.5in;
}
.qa-fallback-line.is-hidden,
.qa-fallback-area.is-hidden { display: none; }
.qa-chart-wrap {
  overflow: visible;
  border: 1px solid #e7eef0;
  border-radius: 12px;
  background: linear-gradient(180deg, #fbfdfd 0%, #f5faf8 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.9);
  padding: 8px 10px 4px;
}
.qa-chart-wrap canvas,
.qa-chart-wrap .qa-fallback-chart { position: relative; z-index: 1; }
.qa-hover-target { cursor: crosshair; pointer-events: all; }
.qa-hover-target:hover { fill: rgba(21,115,71,.045); }
.qa-hover-guide {
  stroke: #9aa8a2;
  stroke-width: 1;
  stroke-dasharray: 4 4;
  pointer-events: none;
  vector-effect: non-scaling-stroke;
}
.qa-hover-dot { pointer-events: none; stroke: #fff; stroke-width: 2; vector-effect: non-scaling-stroke; }
.qa-hover-pending { fill: #dc3545; }
.qa-hover-oldest { fill: #f0a500; }
.qa-hover-turnaround { fill: #198754; }
.qa-tooltip {
  position: absolute;
  z-index: 8;
  min-width: 190px;
  padding: 10px 12px;
  border: 1px solid rgba(255,255,255,.16);
  border-radius: 10px;
  background: rgba(15,35,25,.95);
  color: #fff;
  box-shadow: 0 10px 24px rgba(15,45,30,.2);
  pointer-events: none;
  font-size: 12px;
  line-height: 1.35;
}
.qa-tooltip[hidden] { display: none; }
.qa-tooltip-title {
  margin-bottom: 6px;
  color: #fff;
  font-size: 12px;
  font-weight: 700;
}
.qa-tooltip-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  color: #dcefe5;
}
.qa-tooltip-row + .qa-tooltip-row { margin-top: 3px; }
.qa-tooltip-row b { color: #fff; font-weight: 700; }
.qa-tooltip-row i {
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: 5px;
  border-radius: 50%;
  background: var(--tooltip-color);
}
@media (max-width: 600px) {
  .qa-chart-wrap.qa-chart-js { height: 260px; }
  .qa-metrics-row { gap: 6px; }
  .qa-metric-pill { padding: 5px 11px; font-size: 11.5px; }
}

.qa-fifo-alert {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-top: 16px;
  padding: 12px 14px;
  border: 1px solid #ffe0c2;
  border-radius: 8px;
  background: var(--orange-50);
  color: #92400e;
  font-size: 13px;
}
.qa-fifo-alert[hidden],
.qa-fifo-list[hidden] { display: none; }
.qa-fifo-alert strong { font-size: 15px; }
.qa-fifo-details-btn {
  margin-left: auto;
  padding: 5px 12px;
  border: 1px solid #f0c896;
  border-radius: 999px;
  background: #fff;
  color: #92400e;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.qa-fifo-details-btn:hover { background: var(--orange-50); }
.qa-fifo-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 10px 0 0;
  padding: 0;
  list-style: none;
}
.qa-fifo-list li {
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fbfcfd;
  color: var(--ink);
  font-size: 13px;
}

/* ------------------------------------------------------------------
  Buttons
  ------------------------------------------------------------------ */
/* ------------------------------------------------------------------
   Queue Pulse visual system
   ------------------------------------------------------------------ */
.queue-analytics-card { overflow: hidden; }
.queue-analytics-card .card-header { flex-wrap: wrap; gap: 10px; }
.qp-header { align-items: center; }
.qp-heading { display: flex; align-items: center; gap: 8px; }
.qp-heading h3 { margin: 0; }
.qp-heading small {
  color: var(--muted);
  font-weight: 500;
  font-size: 11.5px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--gray-50);
}
.qp-pulse-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--green-600);
  animation: qp-pulse 2s ease-out infinite;
}
@keyframes qp-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(25, 135, 84, .45); }
  70%  { box-shadow: 0 0 0 7px rgba(25, 135, 84, 0); }
  100% { box-shadow: 0 0 0 0 rgba(25, 135, 84, 0); }
}
.qa-legend-toggle { display: flex; flex-wrap: wrap; gap: 8px; }
.qa-legend-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--gray-50);
  color: var(--ink);
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
  user-select: none;
  transition: opacity .15s ease;
}
.qa-legend-chip i {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--chip-color, var(--green-700));
}
.qa-legend-chip.off { opacity: .4; text-decoration: line-through; }
.qa-metrics-row { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
.qa-metric-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: #fff;
  color: var(--muted);
  cursor: pointer;
  font-size: 12.5px;
  font-weight: 600;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.qa-metric-pill svg,
.qa-metric-pill [data-lucide] { width: 14px; height: 14px; stroke-width: 2.1; }
.qa-metric-pill:hover { border-color: var(--green-600); }
.qa-metric-pill.active {
  background: var(--green-50);
  border-color: #b8d8c3;
  color: var(--green-800);
}
.qa-chart-wrap {
  position: relative;
  width: 100%;
  height: 320px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}
.qa-chart-wrap.qa-chart-js { height: 320px; }
.qa-chart-wrap:not(.qa-chart-js) { height: auto; }
.qa-chart-wrap canvas {
  display: none;
  width: 100% !important;
  height: 100% !important;
  margin-right: 0;
  margin-left: 0;
}
.qa-chart-wrap.qa-chart-js canvas { display: block; }
.qa-chart-wrap .qa-fallback-chart {
  display: block;
  width: 100% !important;
  height: auto;
  aspect-ratio: 760 / 320;
  margin-right: 0;
  margin-left: 0;
}
.qa-chart-wrap.qa-chart-js .qa-fallback-chart { display: none; }
.qa-fifo-alert {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-top: 16px;
  padding: 12px 14px;
  border: 1px solid #ffe0c2;
  border-radius: 8px;
  background: var(--orange-50);
  color: #92400e;
  font-size: 13px;
}
.qa-fifo-alert[hidden],
.qa-fifo-list[hidden] { display: none; }
.qa-fifo-alert svg,
.qa-fifo-alert [data-lucide] { width: 18px; height: 18px; flex: 0 0 18px; color: #c2740a; }
.qa-fifo-alert span { flex: 1; }
.qa-fifo-alert strong { font-size: 15px; }
.qa-fifo-details-btn {
  margin-left: auto;
  padding: 5px 12px;
  border: 1px solid #f0c896;
  border-radius: 999px;
  background: #fff;
  color: #92400e;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.qa-fifo-details-btn:hover { background: var(--orange-50); }
.qa-fifo-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 10px 0 0;
  padding: 0;
  list-style: none;
  transition: opacity .15s ease, transform .15s ease;
}
.qa-fifo-list li {
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fbfcfd;
  color: var(--ink);
  font-size: 13px;
}
@media (max-width: 600px) {
  .qa-chart-wrap.qa-chart-js { height: 260px; }
  .qa-metrics-row { gap: 6px; }
  .qa-metric-pill { padding: 5px 11px; font-size: 11.5px; }
}

.qa-date-filter {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 7px;
  margin-bottom: 14px;
  color: var(--muted);
  font-size: 12px;
}
.qa-date-filter label { font-weight: 600; }
.qa-date-filter-header {
  justify-content: flex-end;
  flex-wrap: nowrap;
  margin-bottom: 0;
}
.qa-date-filter-header input[type="date"] { min-height: 30px; }
.qa-date-filter input[type="date"] {
  min-height: 32px;
  padding: 5px 8px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: #fff;
  color: var(--ink);
  font-size: 12px;
}
.qa-date-filter input[type="date"]:focus {
  border-color: var(--green-600);
  outline: 2px solid var(--green-100, #edf7f1);
}
.qa-date-separator { padding: 0 1px; }
@media (max-width: 900px) {
  .qa-date-filter-header {
    justify-content: flex-start;
  }
}
@media (max-width: 600px) {
  .qa-date-filter { gap: 5px; }
  .qa-date-filter input[type="date"] { flex: 1 1 120px; min-width: 0; }
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding: 9px 16px;
  border: 1px solid transparent;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  transition: filter .15s, background .15s;
  white-space: nowrap;
}
.btn:hover { text-decoration: none; filter: brightness(.95); }
.btn-primary   { background: var(--green-700); color: #fff; }
.btn-success   { background: var(--green-600); color: #fff; }
.btn-danger    { background: var(--red); color: #fff; }
.btn-warning   { background: var(--orange); color: #fff; }
.btn-secondary { background: #343a40; color: #fff; }
.btn-outline   { background: #fff; border-color: var(--line); color: var(--ink); }
.btn-outline:hover { background: var(--gray-50); }
.btn-outline-green { background: #fff; border-color: var(--green-700); color: var(--green-700); }
.btn-light     { background: var(--gray-50); color: var(--ink); }
.btn-sm        { padding: 6px 11px; font-size: 13px; }
.btn-lg        { padding: 12px 24px; font-size: 15px; }
.btn-block     { width: 100%; }
.btn:disabled  { opacity: .55; cursor: not-allowed; }

/* Glass action buttons (service request form) */
.btn-glass {
  background: rgba(255,255,255,.6);
  border-color: rgba(207,224,213,.9);
  color: var(--ink);
  box-shadow: 0 5px 12px rgba(31,78,53,.08), inset 0 1px 0 rgba(255,255,255,.85);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  transition: background-color .2s ease, color .2s ease, box-shadow .2s ease, transform .2s ease;
}
.btn-glass:hover { background: rgba(255,255,255,.85); filter: none; transform: translateY(-1px); }
.btn-glass-grey {
  background: rgba(238,241,244,.65);
  border-color: rgba(203,213,225,.9);
  color: #334155;
  box-shadow: 0 5px 12px rgba(31,78,53,.08), inset 0 1px 0 rgba(255,255,255,.85);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  transition: background-color .2s ease, color .2s ease, box-shadow .2s ease, transform .2s ease;
}
.btn-glass-grey:hover { background: rgba(238,241,244,.9); filter: none; transform: translateY(-1px); }
.btn-glass-green {
  border-color: rgba(21,115,71,.8);
  background-color: rgba(15,81,50,.84);
  background-image: linear-gradient(135deg, rgba(255,255,255,.14), rgba(255,255,255,0));
  color: #fff;
  box-shadow: 0 8px 18px rgba(31,78,53,.18), inset 0 1px 0 rgba(255,255,255,.18);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  transition: background-color .2s ease, box-shadow .2s ease, transform .2s ease;
}
.btn-glass-green:hover { background-color: rgba(15,81,50,.94); filter: none; transform: translateY(-1px); }
.btn .btn-ico { width: 15px; height: 15px; flex: 0 0 15px; }

.btn-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.btn-row.end { justify-content: flex-end; }
.form-actions .btn { flex: 1 1 0; min-width: 150px; }
/* Profile security row */
.security-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }

.signature-preview {
  width: 100%;
  max-width: 360px;
  margin-top: 10px;
  padding: 10px;
  border: 1px dashed #b8d8c3;
  border-radius: 9px;
  background: #fbfdfc;
}
.signature-preview img {
  display: block;
  width: 100%;
  max-height: 150px;
  object-fit: contain;
  background: #fff;
}
.signature-preview.compact { margin-top: 0; }
.signature-preview.compact img { max-height: 120px; }

.attachment-link-preview {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 11px 12px;
  border: 1px solid #cfe3d7;
  border-radius: 8px;
  background: var(--green-50);
}
.attachment-link-preview > span { font-size: 20px; line-height: 1.2; }
.attachment-link-preview > div { min-width: 0; }
.attachment-link-preview strong { display: block; font-size: 13px; }
.attachment-link-preview a {
  display: block;
  overflow-wrap: anywhere;
  font-size: 12.5px;
}

/* ------------------------------------------------------------------
  Tables
  ------------------------------------------------------------------ */
.table-wrap { overflow-x: auto; }

/* Queue folder tabs and compact row actions */
.queue-management-page .content { max-width: 1280px; }
.queue-management-container { width: 100%; }
.queue-management-page .queue-card {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.queue-card { overflow: visible; }
.queue-table-wrap {
  width: calc(100% - 24px);
  margin-right: 12px;
  margin-left: 12px;
  overflow-x: auto;
  overflow-y: visible;
}
.queue-table-wrap .table { min-width: 1180px; }
.queue-table-wrap::-webkit-scrollbar { height: 9px; }
.queue-table-wrap::-webkit-scrollbar-track { background: #eef2f0; border-radius: 0 0 8px 8px; }
.queue-table-wrap::-webkit-scrollbar-thumb { background: #a9c4b2; border-radius: 999px; }
.queue-table-wrap::-webkit-scrollbar-thumb:hover { background: var(--green-700); }
/* ------------------------------------------------------------------
   Posting Queue folder tabs.

   admin/staff.php reuses .queue-type-tab and .queue-tab-count for a
   single Archived control that sits OUTSIDE the strip, so the base
   rules below are a shared component and are left exactly as they
   were. Everything that makes the strip look the way it does is scoped
   to .queue-type-tabs, which only admin/queue.php renders. An earlier
   attempt folded the base selectors into the strip's own rules and
   repainted the staff control green along with it.

   The tabs overlap: each is pulled back over the one before it, so they
   read as a row of folders fanned out rather than four separate buttons.
   ------------------------------------------------------------------ */
.queue-type-tabs {
  display: flex;
  align-items: end;
  /* Visible, not clipped: the tabs overlap and the selected one is raised
     above them, and overflow:hidden here would cut the tuck off. */
  overflow: visible;
  gap: 8px;
  padding: 14px 14px 0;
  background-color: rgba(248, 252, 249, .5);
  /* The shelf they stand on: a soft light surface, not a header bar. */
  background-image: linear-gradient(180deg, rgba(255, 255, 255, .72), rgba(240, 247, 243, .2));
  border-bottom: 1px solid #dce8e0;
}

/* ---- shared base, unchanged: the staff list depends on these ---- */
.queue-type-tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-width: 142px;
  width: 100%;
  padding: 11px 13px 10px;
  border: 1px solid rgba(207, 224, 213, .9);
  border-bottom: 0;
  border-radius: 11px 11px 4px 4px;
  background: rgba(255, 255, 255, .5);
  color: #557164;
  font-size: 12.5px;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
  box-shadow: 0 5px 12px rgba(31, 78, 53, .05), inset 0 1px 0 rgba(255, 255, 255, .85);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  transition: background-color .28s ease, color .28s ease, border-color .28s ease, box-shadow .28s ease, transform .28s ease;
}
.queue-type-tab:hover {
  background: rgba(255, 255, 255, .78);
  color: var(--green-800);
  text-decoration: none;
  transform: translateY(-1px);
}
.queue-type-tab.active,
.queue-type-tab[aria-selected="true"] {
  z-index: 1;
  margin-bottom: -1px;
  border-color: rgba(21, 115, 71, .8);
  background-color: rgba(15, 81, 50, .84);
  background-image: linear-gradient(135deg, rgba(255, 255, 255, .14), rgba(255, 255, 255, 0));
  color: #fff;
  backdrop-filter: blur(16px) saturate(135%);
  -webkit-backdrop-filter: blur(16px) saturate(135%);
  box-shadow: 0 8px 18px rgba(31, 78, 53, .18), inset 0 1px 0 rgba(255, 255, 255, .18);
}
.queue-type-tab.active:hover,
.queue-type-tab[aria-selected="true"]:hover,
.queue-type-tab:active,
.queue-type-tab:focus-visible {
  background-color: rgba(15, 81, 50, .94);
  background-image: linear-gradient(135deg, rgba(255, 255, 255, .16), rgba(255, 255, 255, 0));
  color: #fff;
}
.queue-type-tab.active .queue-tab-count,
.queue-type-tab[aria-selected="true"] .queue-tab-count,
.queue-type-tab:active .queue-tab-count,
.queue-type-tab:focus-visible .queue-tab-count {
  background: rgba(255, 255, 255, .2);
  color: #fff;
}
.queue-tab-label { display: inline-flex; align-items: center; gap: 8px; }
.queue-type-tab .lucide { width: 16px; height: 16px; }
.queue-tab-count {
  display: inline-grid;
  place-items: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 999px;
  background-color: var(--green-50);
  color: var(--green-800);
  font-size: 10.5px;
  font-weight: 800;
}
.queue-tab-count-archived {
  background-color: var(--green-50);
  color: var(--green-800);
}
/* The staff page used to carry a lone .queue-archive-tab beside this filter
   bar - a single control outside .queue-type-tabs, which needed its own width
   and border override because the strip supplies those to its own members. The
   folder is now entered from the status dropdown instead, so no markup uses
   the class and the override went with it. The admin strip is untouched. */

/* ---- the strip, which is where the redesign lives ---- */
.queue-type-tabs .queue-type-tab {
  background-color: #fff;
  color: #4a5b52;
  border-radius: 13px;
  /* The 1px vertical overlap: the tab's bottom edge sits on the shelf's border
     so there is no hairline gap under it. */
  margin-bottom: -1px;
  z-index: 1;
}
/* The tuck. Each tab after the first is pulled back over its neighbour, so
   IMO Form 2 sits across IMO Form 1 and IMO Form 1 sits across All requests.
   The first keeps its place, or the whole row would hang off to the left. */
.queue-type-tabs .queue-type-tab + .queue-type-tab { margin-left: -14px; }

.queue-type-tabs .queue-type-tab:hover {
  background-color: #fff;
  color: var(--green-800);
  transform: none;
  z-index: 2;
}
.queue-type-tabs .queue-type-tab:hover .lucide { color: var(--green-600); }

/* The selected folder: green glass, a raised card standing on the shelf.

   It cannot do what a white version once did - drop its bottom border to merge
   into the panel - because a green surface with a transparent bottom is just a
   green tab with a hole under it. So it keeps a real bottom edge, becomes fully
   rounded, and comes forward over its neighbours. */
.queue-type-tabs .queue-type-tab.active,
.queue-type-tabs .queue-type-tab[aria-selected="true"] {
  position: relative;
  /* Stated here rather than inherited from the unselected rule: if the resting
     tab's margin ever changed, the selected one must not quietly lift off the
     shelf edge. */
  margin-bottom: -1px;
  z-index: 2;
  border-radius: 13px;
  border-color: rgba(255, 255, 255, .34);
  background-color: rgba(21, 115, 71, .84);
  /* Two gradients, because one value cannot do both jobs: the first gives the
     surface its depth, the second lays a light across the top-left. */
  background-image:
    linear-gradient(180deg, rgba(255, 255, 255, .18), rgba(255, 255, 255, 0) 62%),
    linear-gradient(135deg, rgba(255, 255, 255, .30), rgba(255, 255, 255, .02) 55%, rgba(0, 0, 0, .06));
  color: #fff;
  transform: none;
  backdrop-filter: blur(16px) saturate(135%);
  -webkit-backdrop-filter: blur(16px) saturate(135%);
  /* Highlight along the top, shade along the bottom, and a lift. Without all
     three a glass surface reads as a flat green block. */
  box-shadow:
    0 10px 22px rgba(15, 45, 27, .28),
    inset 0 1px 0 rgba(255, 255, 255, .26),
    inset 0 -1px 0 rgba(0, 0, 0, .16);
}

/* Press, focus and hover on the selected tab only deepen the green. They must
   NOT re-declare background-image: that would replace the sheen above with
   nothing and the tab would go flat the moment it was touched. */
.queue-type-tabs .queue-type-tab.active:hover,
.queue-type-tabs .queue-type-tab[aria-selected="true"]:hover,
.queue-type-tabs .queue-type-tab:active,
.queue-type-tabs .queue-type-tab:focus-visible {
  z-index: 3;
  background-color: rgba(21, 115, 71, .94);
  color: #fff;
}
/* A light ring, because a green one disappears against a green tab. */
.queue-type-tabs .queue-type-tab:focus-visible { outline: 2px solid rgba(255, 255, 255, .85); }

.queue-type-tabs .queue-type-tab .lucide,
.queue-type-tabs .queue-type-tab [data-lucide] { width: 17px; height: 17px; }
.queue-type-tabs .queue-type-tab .lucide { color: #7c8f84; }
.queue-type-tabs .queue-type-tab.active .lucide,
.queue-type-tabs .queue-type-tab[aria-selected="true"] .lucide { color: rgba(255, 255, 255, .94); }

/* A light chip on the glass tab, so the number stays readable on green. */
.queue-type-tabs .queue-type-tab.active .queue-tab-count,
.queue-type-tabs .queue-type-tab[aria-selected="true"] .queue-tab-count,
.queue-type-tabs .queue-type-tab:active .queue-tab-count,
.queue-type-tabs .queue-type-tab:focus-visible .queue-tab-count {
  background-color: rgba(255, 255, 255, .24);
  color: #fff;
}

@media (prefers-reduced-motion: reduce) {
  .queue-type-tabs .queue-type-tab,
  .queue-type-tabs .queue-type-tab:hover,
  .queue-type-tabs .queue-type-tab.active {
    transition: none;
  }
}

/* Narrow screens: the folders cannot overlap once there is no room for them to,
   so the strip becomes a horizontal scroller, the tuck is switched off and the
   bottom border comes back so no tab is left cut open along its lower edge. */
@media (max-width: 860px) {
  .queue-type-tabs {
    overflow-x: auto;
    overflow-y: hidden;
    /* Room for the shadows the scroller would otherwise clip. */
    padding: 12px 14px;
  }
  .queue-type-tabs .queue-type-tab + .queue-type-tab { margin-left: 0; }
  .queue-type-tabs .queue-type-tab { margin-bottom: 0; }
  .queue-type-tabs .queue-type-tab.active,
  .queue-type-tabs .queue-type-tab[aria-selected="true"] {
    margin-bottom: 0;
    /* Lighter at this width: the scroller's backdrop is less even than the
       shelf's, and the full-strength green reads as a solid block there. */
    background-color: rgba(21, 115, 71, .78);
    border-bottom: 1px solid rgba(255, 255, 255, .34);
  }
}
.queue-action-menu { position: relative; display: inline-block; }
.queue-action-menu[open] { z-index: 40; }
.queue-action-menu > summary {
  list-style: none;
  cursor: pointer;
}
.queue-action-menu > summary::-webkit-details-marker { display: none; }
.queue-action-menu > summary .lucide { width: 14px; height: 14px; }
.queue-action-menu-panel {
  position: fixed;
  z-index: 60;
  top: 0;
  right: auto;
  left: 0;
  display: flex;
  min-width: 148px;
  max-height: min(260px, 50vh);
  overflow-y: auto;
  flex-direction: column;
  gap: 4px;
  padding: 6px;
  border: 1px solid rgba(207,224,213,.95);
  border-radius: 10px;
  background: rgba(255,255,255,.92);
  box-shadow: 0 14px 28px rgba(31,78,53,.16), inset 0 1px 0 #fff;
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
}
.queue-action-menu-panel .btn,
.queue-action-menu-panel form .btn {
  width: 100%;
  justify-content: flex-start;
  border-color: transparent;
  background: transparent;
  color: var(--ink);
  text-align: left;
}
.queue-action-menu-panel .btn:hover,
.queue-action-menu-panel form .btn:hover { background: #edf7f1; filter: none; }
.queue-action-menu-panel .btn-primary { background: #e4f2e9; color: var(--green-800); }
.queue-action-menu-panel .btn-success { background: #e4f5ea; color: #237b4e; }
.queue-action-menu-panel .btn-warning { background: #fff2df; color: #a4610a; }
.queue-action-menu-panel .btn-danger { background: #fdeaea; color: #a33131; }
.queue-action-menu-panel form { margin: 0; }

table.table { width: 100%; border-collapse: collapse; font-size: 14px; }
.table th {
  text-align: left;
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: .6px;
  color: var(--muted);
  background: #f8fafb;
  padding: 10px 14px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.table td { padding: 11px 14px; border-bottom: 1px solid #eef1f4; vertical-align: middle; }
.table tbody tr:hover { background: #f9fbfa; }
.table tbody tr:last-child td { border-bottom: 0; }
.table .row-actions { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.table td.right, .table th.right { text-align: right; }
.table tr.row-highlight { background: var(--blue-50); }
.table tr.row-highlight:hover { background: #dfeafd; }

.cell-title { font-weight: 600; color: var(--ink); }
.cell-sub { display: block; font-size: 12px; color: var(--muted); }
.mono { font-family: Consolas, "Courier New", monospace; }
.nowrap { white-space: nowrap; }

/* ------------------------------------------------------------------
  Badges
  ------------------------------------------------------------------ */
.badge {
  display: inline-block;
  font-size: 11.5px;
  font-weight: 700;
  padding: 3px 9px;
  border-radius: 999px;
  white-space: nowrap;
}
.badge-draft        { background: var(--gray-50); color: #495057; }
.badge-under_review { background: var(--purple-50); color: #6f42c1; }
.badge-submitted    { background: var(--blue-50); color: var(--blue); }
.badge-queued       { background: var(--cyan-50); color: var(--cyan); }
.badge-for_revision { background: var(--orange-50); color: #c05600; }
.badge-approved     { background: var(--green-100); color: var(--green-800); }
.badge-scheduled    { background: var(--cyan-50); color: #087a94; }
.badge-posted       { background: #d9f2e5; color: var(--green-900); }
.badge-rejected     { background: var(--red-50); color: var(--red); }
.badge-cancelled    { background: var(--gray-50); color: #868e96; text-decoration: line-through; }
.badge-pending      { background: var(--orange-50); color: #c05600; }
.badge-active       { background: var(--green-100); color: var(--green-800); }
.badge-inactive     { background: var(--gray-50); color: #868e96; }
.badge-completed    { background: #d9f2e5; color: var(--green-900); }
.badge-info         { background: var(--blue-50); color: var(--blue); }
.badge-outline { background: #fff; border: 1px solid var(--line); color: var(--muted); }

/* Official IMO Service Request Form the request was filed under */
.badge-form1 { background: var(--blue-50); color: var(--blue); }
.badge-form2 { background: var(--purple-50); color: var(--purple); }
.badge-group { display: inline-flex; align-items: center; gap: 6px; }

/* ------------------------------------------------------------------
  Request type chooser (IMO Form 1 / IMO Form 2)
  ------------------------------------------------------------------ */
.request-type-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(330px, 100%), 1fr));
  gap: 20px;
}
.request-type-card {
  display: flex;
  flex-direction: column;
  background: rgba(255,255,255,.76);
  border: 1px solid rgba(255,255,255,.86);
  border-top: 4px solid var(--green-600);
  border-radius: var(--radius);
  box-shadow: 0 12px 28px rgba(31,78,53,.08), inset 0 1px 0 rgba(255,255,255,.9);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  padding: 22px;
}
.request-type-card:nth-child(2) { border-top-color: var(--purple); }
.rtc-head { display: flex; align-items: flex-start; gap: 14px; }
.rtc-ico { font-size: 30px; line-height: 1.1; }
.rtc-code {
  display: inline-block;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--green-700);
}
.request-type-card:nth-child(2) .rtc-code { color: var(--purple); }
.rtc-titles h3 { margin: 4px 0 0; font-size: 16px; line-height: 1.35; }
.rtc-desc { margin: 14px 0 0; font-size: 13.5px; color: var(--muted); }
.rtc-label {
  margin: 16px 0 6px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .6px;
  text-transform: uppercase;
  color: var(--muted);
}
.rtc-list { margin: 0 0 18px; padding-left: 18px; font-size: 13.5px; line-height: 1.8; }
.request-type-card .btn { margin-top: auto; }

/* ------------------------------------------------------------------
  Forms
  ------------------------------------------------------------------ */
.form-group { margin-bottom: 16px; }
.form-group > label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 6px;
  color: #374151;
}
.form-group > label .req { color: var(--red); }

input[type="text"], input[type="email"], input[type="password"], input[type="number"],
input[type="date"], input[type="time"], input[type="url"], input[type="file"],
select, textarea {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid #d3d9e0;
  border-radius: 8px;
  font-size: 14px;
  font-family: inherit;
  background: #fff;
  color: var(--ink);
}
textarea { resize: vertical; min-height: 110px; }
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--green-600);
  box-shadow: 0 0 0 3px rgba(25, 135, 84, .15);
}
input[readonly] { background: #f4f6f8; color: var(--muted); }
.office-department-input {
  background: #fbfdfc;
  border-color: #d5e2da;
}
.office-department-input:focus { background: #fff; }

.form-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0 16px; }
.form-grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0 16px; }
/*
 * First row: Username | First Name | M.I., all on one line.
 *
 * First Name must be exactly one .form-grid column wide or it stops lining up
 * with Email Address, Position and Confirm Password underneath, so --reg-col is
 * (100% - gap) / 2 -- the same figure the two-column rows resolve to. M.I. is a
 * fixed one-character box and Username takes whatever is left of the column, so
 * the three tracks still sum to the container exactly.
 */
.form-grid-name-row {
  display: grid;
  --reg-gap: 16px;
  --reg-mi: 80px;
  --reg-col: calc((100% - var(--reg-gap)) / 2);
  grid-template-columns:
    calc(var(--reg-col) - var(--reg-gap) - var(--reg-mi))
    var(--reg-col)
    var(--reg-mi);
  gap: 0 var(--reg-gap);
}
.name-inline-mi input { max-width: 80px; text-align: center; text-transform: uppercase; }
.help-text { font-size: 12px; color: var(--muted); margin-top: 5px; }
.error-text { font-size: 12.5px; color: var(--red); margin-top: 5px; }
.field-error input, .field-error select, .field-error textarea { border-color: var(--red); }

.checkbox-row { display: flex; align-items: center; gap: 8px; font-size: 14px; }
.checkbox-row input { width: auto; }

/* Checkbox groups (Type of Material / Platforms) */
.checkbox-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(190px, 100%), 1fr));
  gap: 10px 14px;
}
.checkbox-grid .checkbox-row { align-items: center; }
.checkbox-grid input[type="text"] {
  min-width: 0;
  padding: 7px 10px;
  font-size: 13.5px;
}
.radio-list { display: flex; flex-direction: column; gap: 8px; }
.radio-list .checkbox-row input[type="radio"] { accent-color: var(--green-700); }

/* Service Request Form (staff/create-request.php) */
.card-header-center { justify-content: center; text-align: center; }
.card-header-center h3 { font-weight: 800; }
.form-hr { border: 0; border-top: 1px solid var(--line); margin: 18px 0; }
.form-subhead { font-weight: 800; font-style: italic; font-size: 14px; margin: 20px 0 12px; color: var(--ink); }
.req-strong { font-weight: 800; font-style: italic; }
.type-request-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.type-request-row select { flex: 1 1 220px; min-width: 0; }
.type-custom-wrap { display: flex; align-items: center; gap: 8px; flex: 1 1 220px; min-width: 0; }
.type-custom-wrap input { flex: 1; min-width: 0; }
.type-back-btn {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  display: inline-grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fff;
  color: var(--muted);
  font-size: 14px;
  cursor: pointer;
  transition: background-color .18s ease, color .18s ease;
}
.type-back-btn:hover { background: var(--green-50); color: var(--green-800); }
select[multiple].platform-select { min-height: 132px; }
.platform-checks { margin-top: 8px; }
.platform-checks .checkbox-row span { color: var(--ink); }
.platform-other-row { display: flex; align-items: center; gap: 10px; margin-top: 10px; flex-wrap: wrap; }
.platform-other-row > label { margin: 0; white-space: nowrap; font-size: 13px; font-weight: 600; color: #374151; }
.platform-other-row input { flex: 1; min-width: 180px; }
.file-drop {
  display: block;
  border: 2px dashed #b9cec2;
  border-radius: 12px;
  background: #fbfdfc;
  padding: 24px 16px;
  text-align: center;
  cursor: pointer;
  transition: border-color .18s ease, background-color .18s ease;
}
.file-drop:hover, .file-drop:focus-visible, .file-drop.dragover {
  border-color: var(--green-600);
  background: #f2f8f4;
  outline: none;
}
.file-drop-icon { display: block; font-size: 26px; margin-bottom: 6px; }
.file-drop-text { display: block; font-size: 13.5px; color: var(--ink); }
.file-drop-list { display: block; margin-top: 8px; font-size: 12.5px; color: var(--muted); word-break: break-word; }
.sig-blank {
  min-height: 110px;
  display: grid;
  place-items: center;
  gap: 8px;
  padding: 14px;
  border: 1px dashed #b9cec2;
  border-radius: 10px;
  background: #fbfdfc;
  cursor: pointer;
  text-align: center;
  transition: border-color .18s ease, background-color .18s ease;
}
.sig-blank:hover, .sig-blank:focus-visible { border-color: var(--green-600); background: #f2f8f4; outline: none; }
.sig-blank-hint { font-size: 13px; color: var(--muted); }
.sig-blank-icon { font-size: 22px; }
.sig-current {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 10px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: #fff;
}
.sig-current img { max-height: 56px; max-width: 160px; border-radius: 6px; background: #fff; }
.sig-current[hidden] { display: none; }
/* The tick beside the signature status label. It is a sibling of the label rather
   than a child, because showSigPreview() assigns textContent on the label and
   would delete an icon nested inside it. Fixed rather than 1em, so it does not
   resize itself with whatever the status message happens to say. */
.sig-current-ico { flex: 0 0 auto; width: 15px; height: 15px; color: var(--green-700); }
.sig-current-text { flex: 1; font-size: 13px; font-weight: 600; color: var(--green-800); }
.sig-remove-btn {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  display: inline-grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fff;
  color: var(--muted);
  font-size: 13px;
  cursor: pointer;
  transition: background-color .18s ease, color .18s ease;
}
/* The button used to hold a bare multiplication glyph, which rendered as
   emoji next to the Lucide icons everywhere else. */
.sig-remove-btn > svg.lucide { width: 15px; height: 15px; }
.sig-remove-btn:hover { background: #fde8e8; color: #b91c1c; }
.sig-blank img { max-height: 110px; max-width: 100%; border-radius: 6px; background: #fff; }
.sig-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 14px 0;
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
}
.sig-divider::before, .sig-divider::after {
  content: "";
  flex: 1;
  border-top: 1px solid var(--line);
}
#signature-pad {
  width: 100%;
  height: 170px;
  display: block;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: #fff;
  touch-action: none;
  cursor: crosshair;
}
/* Unsaved-changes prompt: centered icon, title and actions */
.unsaved-centered { position: relative; text-align: center; padding-top: 26px; }
.unsaved-close { position: absolute; top: 12px; right: 12px; }
.unsaved-icon {
  width: 52px;
  height: 52px;
  margin: 0 auto 12px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: #fef3c7;
  color: #b45309;
  font-size: 26px;
}
.unsaved-icon svg.lucide,
.unsaved-icon [data-lucide] { width: 26px; height: 26px; }
.unsaved-centered h3 { margin: 0 0 6px; font-size: 17px; }
.unsaved-centered p { margin: 0 0 18px; color: var(--muted); font-size: 13.5px; line-height: 1.5; }
.unsaved-actions { justify-content: center; }

/* Action by the Institutional Marketing Office panel */
.action-panel { border-top: 3px solid var(--green-600); }
.action-panel .card-header { background: var(--green-50); }
.action-panel .btn-row { margin-top: 4px; }

.input-group { position: relative; }
.input-group input { padding-right: 42px; }
.input-group .toggle-pass {
  position: absolute;
  right: 6px; top: 50%;
  transform: translateY(-50%);
  background: none;
  border: 0;
  cursor: pointer;
  font-size: 15px;
  color: var(--muted);
  padding: 4px 6px;
}

.alert {
  padding: 12px 14px;
  border-radius: 8px;
  font-size: 13.5px;
  margin-bottom: 16px;
  border: 1px solid transparent;
}
.alert-success { background: var(--green-50); border-color: #bfe5d3; color: var(--green-900); }
.alert-error   { background: var(--red-50); border-color: #f5c2c7; color: #842029; }
.alert-warning { background: var(--orange-50); border-color: #ffe0c2; color: #92400e; }
.alert-info    { background: var(--blue-50); border-color: #c9dcff; color: #084298; }
/* The bold lead-in is a title and belongs on its own line; a bare <strong> in the
   same alert is emphasis inside a sentence and has to stay inline. Matching on
   `strong` alone caught both, so "Choose <strong>Approve Only</strong> to ..." was
   chopped across three lines. Block is opted into by class instead. */
.alert-lead { display: block; margin-bottom: 3px; }

.form-errors { list-style: none; padding: 0; margin: 0 0 16px; }
.form-errors li { padding: 3px 0; }

/* ------------------------------------------------------------------
  Filters / pagination / empty states
  ------------------------------------------------------------------ */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  padding: 12px 18px;
  border-bottom: 1px solid var(--line);
  background: #fbfcfd;
}
.filters select, .filters input { width: auto; min-width: 150px; padding: 7px 10px; }
.filters .spacer { flex: 1; }

.filter-chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 12px 18px; border-bottom: 1px solid var(--line); }
.filter-chip {
  font-size: 12.5px;
  font-weight: 600;
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: #fff;
  color: var(--muted);
  text-decoration: none;
}
.filter-chip:hover { background: var(--gray-50); text-decoration: none; }
.filter-chip.active { background: var(--green-700); border-color: var(--green-700); color: #fff; }

.pagination { display: flex; gap: 6px; padding: 14px 18px; flex-wrap: wrap; align-items: center; }
.page-link {
  padding: 6px 11px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: #fff;
  font-size: 13px;
  color: var(--ink);
  text-decoration: none;
}
.page-link:hover { background: var(--gray-50); text-decoration: none; }
.page-link.active { background: var(--green-700); border-color: var(--green-700); color: #fff; }
.page-link.disabled { opacity: .5; pointer-events: none; }

.empty-state {
  text-align: center;
  padding: 44px 20px;
  color: var(--muted);
}
.empty-state .empty-ico { font-size: 40px; display: block; margin-bottom: 10px; opacity: .7; }
.empty-state h4 { color: var(--ink); margin-bottom: 4px; }
.empty-state p { margin: 0 auto 14px; max-width: 440px; font-size: 13.5px; }

/* ------------------------------------------------------------------
  Detail pages
  ------------------------------------------------------------------ */
.detail-list { display: grid; grid-template-columns: 190px minmax(0, 1fr); gap: 0; font-size: 14px; }
.detail-list dt {
  padding: 9px 0;
  color: var(--muted);
  font-weight: 600;
  font-size: 13px;
  border-bottom: 1px dashed #edf0f3;
}
.detail-list dd {
  margin: 0;
  padding: 9px 0;
  border-bottom: 1px dashed #edf0f3;
  color: var(--ink);
}
.detail-list dd:last-of-type, .detail-list dt:last-of-type { border-bottom: 0; }
.detail-list code {
  padding: 1px 5px;
  border: 1px solid var(--line);
  border-radius: 5px;
  background: #f5f7f9;
  color: var(--ink);
  font-size: 12.5px;
}

.caption-box {
  background: #f8fafb;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 14px;
  white-space: pre-wrap;
  font-size: 14px;
}

.attachment-preview {
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 12px;
  display: flex;
  gap: 12px;
  align-items: center;
  background: #fbfcfd;
}
.attachment-preview img {
  width: 130px; height: 96px;
  object-fit: cover;
  border-radius: 6px;
  border: 1px solid var(--line);
}
.attachment-meta { overflow: hidden; }
.attachment-meta strong { display: block; font-size: 14px; word-break: break-all; }
.attachment-meta small { color: var(--muted); }

.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li {
  position: relative;
  padding: 0 0 18px 26px;
  border-left: 2px solid var(--line);
  margin-left: 8px;
}
.timeline li:last-child { padding-bottom: 4px; border-left-color: transparent; }
.timeline li::before {
  content: "";
  position: absolute;
  left: -7px; top: 3px;
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--green-600);
  border: 2px solid #fff;
  box-shadow: 0 0 0 2px var(--line);
}
.timeline li.t-revision::before { background: var(--orange); }
.timeline li.t-reject::before   { background: var(--red); }
.timeline .t-title { font-weight: 600; font-size: 13.5px; }
.timeline .t-time  { font-size: 12px; color: var(--muted); }
.timeline .t-body  { font-size: 13.5px; margin-top: 3px; }

.status-steps { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; font-size: 12px; }
.status-steps .step {
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--gray-50);
  color: var(--muted);
  font-weight: 600;
}
.status-steps .step.done { background: var(--green-100); color: var(--green-800); }
.status-steps .step.current { background: var(--green-700); color: #fff; }
.status-steps .arrow { color: #c3c9d0; }

/* The dashboard status banner.

   Neutral by default, and that default is load-bearing rather than a fallback.
   When several requests are live at once there is no single status to colour this
   card by, so the multi-request version has to stay untinted: a coloured card
   with three different statuses inside it claims one of them owns the banner.
   Only the single-request version takes a colour, from its own status class.

   The shape is unchanged from what this always was - same radius, padding and
   shadow - so the single banner looks like itself and only its colour now
   answers to the status beside the sentence. The purple gradient that used to be
   baked into the base rule was doing two jobs at once: it was the styling, and it
   was silently acting as the "under review" colour for every other status too. */
.queue-status-message {
  background: rgba(255, 255, 255, .74);
  border: 1px solid rgba(218, 230, 222, .9);
  border-radius: var(--radius);
  padding: 18px 22px;
  margin-bottom: 20px;
  display: flex;
  align-items: center;
  gap: 14px;
  box-shadow: 0 12px 30px rgba(31, 78, 53, .06), inset 0 1px 0 rgba(255, 255, 255, .9);
  backdrop-filter: blur(14px) saturate(125%);
  -webkit-backdrop-filter: blur(14px) saturate(125%);
}
.queue-status-message p { margin: 0; font-size: 14.5px; color: var(--ink); line-height: 1.5; }

/* One tint per status for the single-request banner. Each card tint is the same
   family as its badge, so the card and the badge beside it always agree, and the
   statuses that share a colour share a rule. */
.queue-status-message.is-submitted {
  background: var(--blue-50);
  border-color: rgba(13, 110, 253, .18);
  box-shadow: 0 12px 30px rgba(13, 110, 253, .05), inset 0 1px 0 rgba(255, 255, 255, .9);
}
.queue-status-message.is-under_review {
  background: var(--purple-50);
  border-color: rgba(111, 66, 193, .2);
  box-shadow: 0 12px 30px rgba(111, 66, 193, .06), inset 0 1px 0 rgba(255, 255, 255, .9);
}
.queue-status-message.is-queued,
.queue-status-message.is-scheduled {
  background: var(--cyan-50);
  border-color: rgba(10, 162, 192, .2);
  box-shadow: 0 12px 30px rgba(10, 162, 192, .05), inset 0 1px 0 rgba(255, 255, 255, .9);
}
.queue-status-message.is-for_revision {
  background: var(--orange-50);
  border-color: rgba(253, 126, 20, .22);
  box-shadow: 0 12px 30px rgba(253, 126, 20, .05), inset 0 1px 0 rgba(255, 255, 255, .9);
}
.queue-status-message.is-approved {
  background: var(--green-100);
  border-color: rgba(21, 115, 71, .18);
  box-shadow: 0 12px 30px rgba(21, 115, 71, .05), inset 0 1px 0 rgba(255, 255, 255, .9);
}
.queue-status-message.is-posted {
  background: #d9f2e5;
  border-color: rgba(15, 81, 50, .18);
  box-shadow: 0 12px 30px rgba(15, 81, 50, .05), inset 0 1px 0 rgba(255, 255, 255, .9);
}
.queue-status-message.is-rejected {
  background: var(--red-50);
  border-color: rgba(220, 53, 69, .18);
  box-shadow: 0 12px 30px rgba(220, 53, 69, .05), inset 0 1px 0 rgba(255, 255, 255, .9);
}
.queue-status-message.is-draft,
.queue-status-message.is-cancelled {
  background: var(--gray-50);
  border-color: rgba(134, 142, 150, .2);
  box-shadow: 0 12px 30px rgba(73, 80, 87, .04), inset 0 1px 0 rgba(255, 255, 255, .9);
}

/* --- several requests at once ---
   The list is the card: no tint, no single sentence, one row per request. The
   badge carries the status and the link carries the request, which is what makes
   the row both scannable and clickable without a second control. */
.queue-status-message.is-multi {
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  padding: 4px 0;
}
.queue-status-list { list-style: none; margin: 0; padding: 0; }
.queue-status-row {
  display: grid;
  /* auto for the badge, so the number and title start at the same x on every
     row whether the badge above says Submitted or Under Review. */
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 12px;
  padding: 9px 18px;
}
.queue-status-row + .queue-status-row { border-top: 1px solid rgba(218, 230, 222, .7); }
.queue-status-link {
  display: flex;
  align-items: baseline;
  gap: 10px;
  min-width: 0;
  text-decoration: none;
  color: var(--ink);
}
.queue-status-no {
  font-family: Consolas, "Courier New", monospace;
  font-size: 12.5px;
  color: var(--muted);
  white-space: nowrap;
}
/* min-width: 0 on the flex parent is what lets this truncate instead of pushing
   the row wider; without an ellipsis the title has nowhere to go when it is long. */
.queue-status-title {
  font-size: 13.5px;
  color: var(--ink);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.queue-status-link:hover .queue-status-title { text-decoration: underline; }
.queue-status-link:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; border-radius: 4px; }
.queue-status-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 18px;
  border-top: 1px solid rgba(218, 230, 222, .7);
}
.queue-status-more { font-size: 12.5px; color: var(--muted); }
.queue-status-all {
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
  text-decoration: none;
}

/* ------------------------------------------------------------------
  Notifications
  ------------------------------------------------------------------ */
.notif-list { list-style: none; margin: 0; padding: 0; }
.notif-item {
  display: flex;
  gap: 12px;
  padding: 14px 18px;
  border-bottom: 1px solid #eef1f4;
  align-items: flex-start;
}
.notif-item:last-child { border-bottom: 0; }
.notif-item.unread { background: var(--green-50); }
.notif-ico {
  width: 36px; height: 36px;
  border-radius: 50%;
  background: var(--green-100);
  display: grid; place-items: center;
  flex-shrink: 0;
  font-size: 15px;
}
.notif-body { flex: 1; min-width: 0; }
.notif-body .notif-title { font-weight: 600; font-size: 14px; }
.notif-body .notif-msg { font-size: 13.5px; color: #4b5563; }
.notif-body .notif-time { font-size: 12px; color: var(--muted); margin-top: 2px; display: block; }
.notif-actions { display: flex; flex-direction: column; gap: 6px; align-items: flex-end; }
.notif-modal-selectall { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--muted); cursor: pointer; white-space: nowrap; }
.notif-modal-selectall input { width: auto; accent-color: var(--green-700); }
.notif-select-toggle.is-active { background: var(--green-50); color: var(--green-800); }
#notif-modal .modal-header { gap: 8px; }
#notif-modal .modal-header-copy { flex: 1; }
.notif-select-toggle svg.lucide,
.notif-select-toggle [data-lucide] { width: 17px; height: 17px; display: block; }
.notif-modal-subbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 22px; border-bottom: 1px solid var(--line); }
.notif-modal-subbar[hidden] { display: none; }
#notif-modal-delete[hidden] { display: none; }
/* .btn sets display:inline-flex, and any author rule beats the browser's own
   [hidden] rule, so the attribute on its own leaves this button on screen.
   The delete button has carried a rule like this since it was added; the
   mark-read button arrived with Select All and never got one, which is why it
   showed whether or not anything was ticked. */
#notif-modal-mark-read[hidden] { display: none; }
#notif-modal .notif-check { display: none; }
#notif-modal.selection-on .notif-check { display: flex; }

/* The list scrolls inside the dialog body, not the dialog.

   Every dialog scrolls as one box - .modal-dialog carries max-height and
   overflow-y - so on a long notification list the scrollbar belonged to the whole
   panel and the header scrolled away with it. Here the dialog is a flex column
   instead: the header holds its place and only the body below it moves, which is
   what a list in a dialog should do. Scoped to this dialog rather than applied to
   all of them, because the rest are short forms that are better off scrolling as
   one piece. */
#notif-modal .modal-dialog {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
#notif-modal .modal-header { flex: 0 0 auto; }
#notif-modal .modal-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}
/* A thin bar: this panel is narrow, and a full-width scrollbar in a 480px dialog
   takes a noticeable bite out of the list for a control that is only ever needed
   once the notifications run past the panel. */
#notif-modal .modal-body { scrollbar-width: thin; scrollbar-color: #c3cdc8 transparent; }
#notif-modal .modal-body::-webkit-scrollbar { width: 7px; }
#notif-modal .modal-body::-webkit-scrollbar-track { background: transparent; }
#notif-modal .modal-body::-webkit-scrollbar-thumb {
  background: #c3cdc8;
  border-radius: 4px;
  border: 2px solid #fff;
}
#notif-modal .modal-body::-webkit-scrollbar-thumb:hover { background: #a9b6b0; }

/* ------------------------------------------------------------------
  Contact-message thread
  Shown by #reply-modal (the administrator's answer) and #message-modal
  (the staff member's read-only copy). One set of rules for both: the
  conversation is the same in either direction, and the only difference
  between the dialogs is the box to answer in, which is not one of these.
  ------------------------------------------------------------------ */
.msg-thread {
  display: grid;
  gap: 10px;
  padding: 14px 16px;
  background: #f7f9f8;
  border: 1px solid var(--line);
  border-radius: 10px;
  margin-bottom: 16px;
}
.msg-thread-empty { margin: 0; font-size: 13.5px; }
.msg-item { background: #fff; border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; }
/* Whichever side wrote it. The rule is the only thing that differs, so the
   two never read as two separate lists. */
.msg-item.msg-from-admin { border-left: 3px solid var(--green-700); }
.msg-item.msg-from-staff { border-left: 3px solid #cbd5e1; }
.msg-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; margin-bottom: 6px; }
.msg-who { font-size: 13.5px; font-weight: 700; color: var(--ink); }
.msg-role {
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
}
.msg-when { margin-left: auto; font-size: 12px; color: var(--muted); }
/* pre-wrap keeps the sender's own line breaks; break-word stops a pasted URL
   from widening the dialog past its own max-width. */
.msg-body { margin: 0; font-size: 13.5px; line-height: 1.65; color: #374151; white-space: pre-wrap; overflow-wrap: anywhere; }
.msg-reply-group { margin-bottom: 0; }

/* ------------------------------------------------------------------
  Bar chart (reports)
  ------------------------------------------------------------------ */
.bar-list { display: flex; flex-direction: column; gap: 10px; }
.bar-row { display: grid; grid-template-columns: 170px 1fr 54px; gap: 10px; align-items: center; font-size: 13.5px; }
.bar-row .bar-label { color: #374151; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-track { background: var(--gray-50); border-radius: 999px; height: 14px; overflow: hidden; }
.bar-fill { background: linear-gradient(90deg, var(--green-600), var(--green-700)); height: 100%; border-radius: 999px; min-width: 3px; }
.bar-fill.b-blue { background: linear-gradient(90deg, #3d8bfd, #0d6efd); }
.bar-fill.b-orange { background: linear-gradient(90deg, #ff9f43, #fd7e14); }
.bar-fill.b-purple { background: linear-gradient(90deg, #8b5cf6, #6f42c1); }
.bar-row .bar-value { text-align: right; font-weight: 700; color: var(--ink); }

/* ------------------------------------------------------------------
  Calendar
  ------------------------------------------------------------------ */
.calendar { background: #fff; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow); }
.cal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--line);
  background: #fbfcfd;
  flex-wrap: wrap;
}
.cal-title { font-size: 16px; font-weight: 700; margin: 0; }
.cal-nav { display: flex; gap: 6px; }
.cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
.cal-dow {
  padding: 8px 6px;
  text-align: center;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .8px;
  font-weight: 700;
  color: var(--muted);
  background: #f8fafb;
  border-bottom: 1px solid var(--line);
  border-right: 1px solid #eef1f4;
}
.cal-dow:nth-child(7) { border-right: 0; }
.cal-day {
  min-height: 108px;
  border-bottom: 1px solid #eef1f4;
  border-right: 1px solid #eef1f4;
  padding: 6px;
  background: #fff;
}
.cal-day:nth-child(7n) { border-right: 0; }
.cal-day.other { background: #fafbfc; }
.cal-day.other .cal-daynum { color: #c1c7cd; }
.cal-daynum {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--muted);
  display: inline-grid;
  place-items: center;
  width: 24px; height: 24px;
  border-radius: 50%;
}
.cal-day.today { background: var(--green-50); }
.cal-day.today .cal-daynum { background: var(--green-700); color: #fff; }
.cal-day.due-alert { background: #fef2f2; border: 2px solid #dc2626; animation: due-pulse 2s ease-in-out infinite; }
.cal-day.due-alert .cal-daynum { background: #dc2626; color: #fff; }
.cal-due-badge { position: absolute; top: 2px; right: 4px; background: #dc2626; color: #fff; font-size: 10px; font-weight: 700; width: 14px; height: 14px; border-radius: 50%; display: flex; align-items: center; justify-content: center; line-height: 1; }
.cal-day { position: relative; }
.cal-event-due { opacity: 0.85; border-left: 3px solid #dc2626 !important; }
@keyframes due-pulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(220, 38, 38, 0.4); } 50% { box-shadow: 0 0 0 6px rgba(220, 38, 38, 0); } }
.cal-day.selectable { cursor: pointer; }
.cal-events { margin-top: 4px; display: flex; flex-direction: column; gap: 3px; }
.cal-platform-dots {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 5px;
  min-height: 10px;
}
.cal-platform-dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  border: 1px solid rgba(255, 255, 255, .9);
  border-radius: 50%;
  box-shadow: 0 1px 3px rgba(31, 78, 53, .2);
  cursor: help;
  transition: transform .16s ease, box-shadow .16s ease;
}
.cal-platform-dot:hover { transform: scale(1.35); box-shadow: 0 2px 6px rgba(31, 78, 53, .3); }
.cal-dot-more { color: var(--muted); font-size: 10px; font-weight: 700; }
.cal-event {
  display: block;
  width: 100%;
  border: 0;
  font: inherit;
  font-size: 11px;
  text-align: left;
  cursor: pointer;
  padding: 3px 6px;
  border-radius: 5px;
  color: #fff;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-decoration: none;
  background: var(--green-700);
}
.cal-event:hover { text-decoration: none; filter: brightness(1.1); }
.cal-event .ev-time { font-weight: 700; margin-right: 4px; }
.cal-more { font-size: 10.5px; color: var(--muted); padding-left: 4px; }

.cal-legend { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; padding: 10px 16px; border-top: 1px solid var(--line); font-size: 12.5px; color: var(--muted); }
.cal-legend .dot { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 5px; vertical-align: middle; }

/* One entry in the platforms legend: a brand mark beside its name.
   Each of these is a plain inline <span> with no layout of its own, so the mark
   was aligned to the text baseline - and an inline SVG's baseline is its bottom
   edge, which put every icon a couple of pixels lower than the name beside it.
   The space between a mark and its name was coming from the whitespace in the
   PHP template, so it also changed whenever that file was re-indented. */
.cal-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  line-height: 1.4;
}
.cal-legend-name { line-height: 1.4; }

/* The brand marks themselves had no rule anywhere in the app. Their size is
   written onto the element by platform_icon_svg(), so all this has to do is
   stop them being squashed inside a flex row and stop them sitting on a
   baseline. Safe to state globally: platform_icon_svg() is rendered in one
   place, this legend, and tools/test_platform_icon_parity.php checks the
   emitted markup either way. */
.platform-ico {
  display: block;
  flex-shrink: 0;
}

/* Admin posting calendar: glass controls, date jump, and schedule modal */
.calendar-management-page .content { max-width: 1280px; }
.calendar-management-page .calendar-glass {
  width: 100%;
  max-width: 1280px;
  margin-right: auto;
  margin-left: auto;
}
.calendar-page-header { margin-bottom: 18px; }
.calendar-glass {
  border: 1px solid rgba(207, 224, 213, .9);
  border-radius: 18px;
  background: rgba(255, 255, 255, .72);
  box-shadow: 0 18px 42px rgba(31, 78, 53, .1), inset 0 1px 0 rgba(255, 255, 255, .95);
  backdrop-filter: blur(18px) saturate(125%);
  -webkit-backdrop-filter: blur(18px) saturate(125%);
}
.calendar-glass .cal-head {
  padding: 18px 20px;
  background: linear-gradient(135deg, rgba(237, 247, 242, .84), rgba(255, 255, 255, .56));
  border-bottom-color: rgba(207, 224, 213, .8);
}
.cal-heading { display: flex; flex-direction: column; gap: 3px; }
.cal-eyebrow,
.calendar-modal-eyebrow {
  color: var(--green-700);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 1.2px;
  text-transform: uppercase;
}
.calendar-glass .cal-title { font-size: 20px; letter-spacing: -.3px; }
.cal-nav { align-items: center; flex-wrap: wrap; }
.cal-nav-button { min-width: 36px; padding-right: 10px; padding-left: 10px; font-size: 18px; line-height: 1; }
.cal-nav-button#cal-today { min-width: auto; font-size: 13px; }
.cal-date-filter { display: inline-flex; align-items: center; }
.cal-date-filter input {
  min-width: 142px;
  padding: 7px 10px;
  border: 1px solid #d3e4d8;
  border-radius: 8px;
  background: rgba(255, 255, 255, .78);
  color: var(--ink);
  font: inherit;
  font-size: 12.5px;
}
.cal-date-filter input:focus { border-color: var(--green-600); box-shadow: 0 0 0 3px rgba(25, 135, 84, .12); }
.calendar-management-page .cal-grid {
  grid-template-columns: repeat(7, 1.5in);
  justify-content: center;
  overflow-x: auto;
  background: rgba(255, 255, 255, .42);
}
.calendar-management-page .cal-dow { background: rgba(248, 252, 249, .9); }
.calendar-management-page .cal-day {
  width: 1.5in;
  height: 1.5in;
  min-height: 1.5in;
  max-height: 1.5in;
  aspect-ratio: auto;
  overflow: hidden;
  padding: 5cqh;
  background: rgba(255, 255, 255, .58);
  transition: background-color .2s ease, box-shadow .2s ease, transform .2s ease;
}
.calendar-management-page .cal-day:hover,
.calendar-management-page .cal-day:focus-visible {
  position: relative;
  z-index: 1;
  outline: none;
  background: rgba(237, 247, 242, .92);
  box-shadow: inset 0 0 0 2px rgba(21, 115, 71, .3);
}
.calendar-management-page .cal-day.today { background: rgba(237, 247, 242, .74); }
.calendar-management-page .cal-day.selected,
.calendar-management-page .cal-day.selectable.selected,
.calendar-management-page .cal-day.selected.selected {
  position: relative;
  z-index: 2;
  background: rgba(216, 239, 227, .78);
  box-shadow: inset 0 0 0 3px rgba(21, 115, 71, .72), 0 0 0 3px rgba(21, 115, 71, .12);
}
.calendar-management-page .cal-day.selectable.selected .cal-daynum {
  width: 34px;
  height: 34px;
  margin: -3px 0 0 -3px;
  background: var(--green-700);
  color: #fff;
  font-size: 14px;
  box-shadow: 0 4px 10px rgba(15, 81, 50, .24);
}
.calendar-management-page .cal-day.other { background: rgba(248, 250, 249, .5); }
.calendar-management-page .cal-daynum { transition: background-color .2s ease, color .2s ease, transform .2s ease; }
.calendar-management-page .cal-day:hover .cal-daynum { transform: scale(1.08); }
.calendar-management-page .cal-event {
  border: 1px solid rgba(255, 255, 255, .45);
  box-shadow: 0 3px 8px rgba(31, 78, 53, .12);
  transition: transform .18s ease, filter .18s ease, box-shadow .18s ease;
}
.calendar-management-page .cal-event:hover { transform: translateY(-1px); box-shadow: 0 5px 12px rgba(31, 78, 53, .18); }
.calendar-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 80px;
  color: var(--muted);
  font-size: 13px;
}
.calendar-loading-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--green-600); animation: calendar-pulse 1s ease-in-out infinite; }
@keyframes calendar-pulse { 0%, 100% { opacity: .35; transform: scale(.85); } 50% { opacity: 1; transform: scale(1.15); } }

/* ------------------------------------------------------------------
   Generic modal (staff add account, etc.)
   ------------------------------------------------------------------ */
.modal {
  position: fixed;
  inset: 0;
  z-index: 150;
  display: grid;
  place-items: center;
  padding: 22px;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .22s ease, visibility .22s ease;
}
.modal.is-open { opacity: 1; visibility: visible; pointer-events: auto; }
/* A confirmation always belongs to the dialog beneath it, so it stacks above
   the form modals (150); toasts (.toast-stack, 300) sit above everything. */
#confirm-modal { z-index: 250; }
/* The signature pad is opened from inside #send-action-modal, and that dialog
   is included further down the same page (admin/request-details.php), so at the
   shared 150 it already paints above the pad that summoned it - the pad opened
   but sat behind the form and could not be clicked. One step up puts it in
   front of the dialog it belongs to while staying below the confirm dialog and
   the toasts, which is the order the comment above describes. */
#signature-modal { z-index: 200; }
.modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(15, 35, 25, .44);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.modal-dialog {
  position: relative;
  z-index: 1;
  width: min(720px, 100%);
  max-height: calc(100vh - 44px);
  overflow-y: auto;
  border: 1px solid rgba(255, 255, 255, .8);
  border-radius: 18px;
  /* Solid, not translucent: the backdrop behind it is already blurred, and
     dense table content otherwise shows through the dialog. */
  background: #fff;
  box-shadow: 0 28px 70px rgba(15, 45, 30, .26), inset 0 1px 0 rgba(255, 255, 255, .95);
  transform: translateY(16px) scale(.97);
  transition: transform .26s cubic-bezier(.2, .8, .2, 1);
}
.modal.is-open .modal-dialog { transform: translateY(0) scale(1); }
.modal-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  padding: 18px 22px 14px;
  border-bottom: 1px solid var(--line);
}
.modal-header-copy h3 { margin: 0; font-size: 17px; font-weight: 600; }
.modal-header-copy p { margin: 4px 0 0; color: var(--muted); font-size: 12.5px; }
.modal-close {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--muted);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  transition: background-color .18s ease, color .18s ease;
}
.modal-close:hover { background: var(--green-50); color: var(--green-800); }
/* The button's font-size: 20px above is sized for the &times; character that most
   of these buttons still carry. Where one holds a Lucide icon instead, the icon
   is given its own size: left to the global width: 1em rule it would scale with
   whatever font-size the button happened to carry, which is a coincidence rather
   than a decision. */
.modal-close > svg,
.modal-close [data-lucide] {
  width: 16px;
  height: 16px;
  stroke-width: 2.4;
}
.modal-body { padding: 18px 22px 20px; }
.modal-dialog-sm { width: min(430px, 100%); }
.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}
body.modal-open { overflow: hidden; }

.calendar-modal {
  position: fixed;
  inset: 0;
  z-index: 140;
  display: grid;
  place-items: center;
  padding: 22px;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .24s ease, visibility .24s ease;
}
.calendar-modal.is-open { opacity: 1; visibility: visible; pointer-events: auto; }
.calendar-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(15, 35, 25, .42);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.calendar-modal-dialog {
  position: relative;
  z-index: 1;
  width: min(680px, 100%);
  max-height: calc(100vh - 88px);
  margin-bottom: 20px;
  overflow-y: auto;
  border: 1px solid rgba(255, 255, 255, .8);
  border-radius: 20px;
  background: rgba(255, 255, 255, .74);
  box-shadow: 0 28px 70px rgba(15, 45, 30, .24), inset 0 1px 0 rgba(255, 255, 255, .95);
  backdrop-filter: blur(24px) saturate(140%);
  -webkit-backdrop-filter: blur(24px) saturate(140%);
  transform: translateY(18px) scale(.97);
  transition: transform .28s cubic-bezier(.2, .8, .2, 1);
}
.calendar-modal.is-open .calendar-modal-dialog { transform: translateY(0) scale(1); }
.calendar-modal-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 18px;
  padding: 22px 24px 18px;
  border-bottom: 1px solid rgba(207, 224, 213, .75);
  background: linear-gradient(135deg, rgba(237, 247, 242, .8), rgba(255, 255, 255, .35));
}
.calendar-modal-header h3 { margin: 4px 0 0; font-size: 20px; }
.calendar-modal-header p { margin: 5px 0 0; color: var(--muted); font-size: 13px; }
.calendar-modal-close {
  width: 32px;
  height: 32px;
  flex: 0 0 32px;
  border: 1px solid rgba(207, 224, 213, .9);
  border-radius: 9px;
  background: rgba(255, 255, 255, .7);
  color: var(--muted);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  transition: background-color .18s ease, color .18s ease, transform .18s ease;
}
.calendar-modal-close:hover { background: var(--green-50); color: var(--green-800); transform: rotate(5deg); }
.calendar-modal-body { padding: 20px 24px 24px; }
.calendar-schedule-form .form-group:last-of-type { margin-bottom: 18px; }
.calendar-modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 4px; }
.calendar-modal-empty { padding: 24px 12px; }

/* -- Request detail dialog / toolbar / scroll container -- */
#request-detail-modal { padding: 0; }
.request-detail-dialog {
  width: 10.5in;
  max-width: none;
  max-height: none;
  margin: 0;
  overflow: visible;
  zoom: var(--rf-zoom, 1);
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(31, 41, 55, .24) transparent;
}
.request-detail-dialog::-webkit-scrollbar { width: 6px; }
.request-detail-dialog::-webkit-scrollbar-track { background: transparent; }
.request-detail-dialog::-webkit-scrollbar-thumb {
  border: 1px solid transparent;
  border-radius: 999px;
  background: rgba(31, 41, 55, .22);
  background-clip: padding-box;
}
.request-detail-dialog::-webkit-scrollbar-thumb:hover { background: rgba(31, 41, 55, .36); }
.request-detail-content {
  position: relative;
  margin: 0;
  padding: 1in;
  background: rgba(15, 35, 25, .04);
}
.request-detail-toolbar {
  position: absolute;
  top: 14px;
  right: 18px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  margin: 0;
}
.request-detail-print,
.request-detail-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  box-shadow: none;
  line-height: 1;
  cursor: pointer;
}
.request-detail-print:hover,
.request-detail-close:hover {
  border: 0;
  background: transparent;
  color: var(--ink);
  filter: none;
}
.request-detail-print:focus-visible,
.request-detail-close:focus-visible {
  outline: 2px solid var(--green-600);
  outline-offset: 2px;
}
.request-detail-print-icon {
  display: block;
  width: 22px;
  height: 22px;
  flex: 0 0 22px;
  stroke: currentColor;
  stroke-width: 2.2;
}
.request-detail-close svg {
  width: 20px;
  height: 20px;
  stroke: currentColor;
  stroke-width: 2.2;
}

/* ==================================================================
   Request form — matches the physical IMO paper form (rf-* classes,
   matched to the current renderRequestForm() output)
   ================================================================== */
.request-print-page {
  width: 8.5in;
  height: 13in;
  margin: 0 auto;
  padding: 0.5cm;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  overflow: hidden;
  flex-shrink: 0;
  background: #fff;
  color: #111;
  font-family: "Times New Roman", Times, serif;
  font-size: 15px;
  line-height: 1.5;
  border: 1px solid #cfd4d8;
  box-shadow: 0 6px 20px rgba(0,0,0,.08);
}
.request-print-page > * { flex-shrink: 0; }

/* Letterhead */
.rf-letterhead {
  display: grid;
  grid-template-columns: auto 1px auto;
  justify-content: center;
  align-items: center;
  gap: 12px;
  padding-bottom: 4px;
}
.rf-seal {
  display: block;
  width: 48px;
  height: 48px;
  flex: 0 0 48px;
  object-fit: contain;
}
.rf-wordmark {
  min-width: 0;
  text-align: left;
}
.rf-wordmark-logo {
  display: block;
  width: 160px;
  max-width: 100%;
  height: 48px;
  object-fit: contain;
  object-position: left center;
}
.rf-letterhead-divider {
  width: 1px;
  min-height: 48px;
  align-self: stretch;
  background: #111;
}
.rf-schoolmark {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  min-width: 0;
  text-align: left;
}
.rf-office { text-align: left; }
.rf-office-main {
  display: block;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 18px;
  font-weight: 800;
  line-height: 1.1;
  color: #157347;
}
.rf-office-sub {
  display: block;
  margin-top: 2px;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 10px;
  letter-spacing: .3px;
  color: #157347;
}
@media (max-width: 600px) {
  .rf-letterhead {
    grid-template-columns: 1fr;
    gap: 8px;
  }
  .rf-letterhead-divider {
    width: 100%;
    height: 1px;
    min-height: 0;
  }
  .rf-schoolmark { justify-content: flex-start; }
  .rf-office { text-align: left; }
}

/* Title block */
.rf-titleblock {
  display: grid;
  grid-template-columns: 100px 1fr 100px;
  align-items: start;
  margin-top: 2px;
}
.rf-formno { font-weight: 700; font-style: italic; font-size: 13px; }
.rf-titlecenter { text-align: center; }
.rf-titlecenter h3 { margin: 0; font-size: 20px; font-weight: 700; letter-spacing: .3px; }
.rf-subtitle { margin: 1px 0 0; font-size: 12px; font-style: italic; }
.rf-statusline { margin: 2px 0 0; text-align: center; font-size: 11px; color: #555; }

.request-print-page .rf-rule {
  height: 0;
  background: none;
  border-top: 1px solid #111;
  margin: 5px 0;
}
.request-print-page .rf-rule.thick { border-top-width: 2px; margin: 6px 0 8px; }

/* Meta row */
.rf-meta { display: grid; grid-template-columns: 1fr 1fr; gap: 2px 30px; }
.rf-field, .rf-blankfield { display: flex; align-items: baseline; gap: 6px; padding: 1px 0; }
.rf-label { font-weight: 700; font-size: 13px; white-space: nowrap; }
.rf-underline { flex: 1; border-bottom: 1px solid #111; min-height: 14px; font-size: 13px; padding-bottom: 1px; }
.rf-underline-inline { border-bottom: 1px solid #111; padding: 0 4px; font-weight: 400; }

/* Sections */
.rf-section { margin-top: 8px; }
.rf-section h4 { margin: 0 0 5px; font-size: 14px; font-weight: 700; font-style: italic; }
.rf-note-inline { font-weight: 400; font-style: italic; font-size: 12px; }

.rf-blankfield { margin-bottom: 2px; }
.rf-blankmulti { margin: 3px 0 5px; }

.rf-row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 2px 30px; margin: 4px 0; }

/* Checkbox groups */
.rf-checkgrid { display: grid; gap: 3px 24px; margin: 2px 0 4px; }
.rf-checkgrid-2 { grid-template-columns: 1fr 1fr; }
.rf-check { display: inline-flex; align-items: baseline; gap: 5px; font-size: 13px; }
.rf-check.checked { font-weight: 700; }
.rf-box { font-family: Arial, sans-serif; font-size: 14px; }

.rf-inlinecheck-row { margin: 3px 0; }
.rf-checkinline { display: flex; flex-wrap: wrap; gap: 4px 18px; margin-top: 2px; }
.rf-others { margin-top: 2px; font-size: 13px; }

/* Approval line */
.rf-approval {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  margin-top: 8px;
  padding-top: 6px;
  border-top: 1px solid #111;
  font-size: 13px;
}
.rf-approval-label { font-weight: 700; white-space: nowrap; }
.request-print-page .rf-approval-sig {
  display: flex;
  flex-direction: column;
  align-items: center;
  border-bottom: 0;
  padding-bottom: 0;
}
.request-print-page .rf-approval-sig::after {
  content: "";
  order: 1;
  align-self: stretch;
  border-top: 1px solid #111;
  margin-top: 2px;
}
.request-print-page .rf-approval-sig em {
  order: 2;
  margin-top: 2px;
  line-height: 12px;
  font-size: 10px;
  font-style: italic;
}
.rf-headsig { max-width: 180px; max-height: 48px; margin-bottom: 1px; }
.request-print-page .rf-approval-label,
.request-print-page .rf-approval-date { padding-bottom: 14px; }
.rf-approval-date { white-space: nowrap; }

.rf-note-line { margin: 8px 0; font-size: 12px; border-top: 1px solid #111; padding-top: 6px; }

/* Action section */
.rf-action-title {
  margin-top: 6px;
  padding: 3px 0;
  border-top: 1px solid #111;
  border-bottom: 1px solid #111;
  text-align: center;
  font-weight: 700;
  font-style: italic;
  font-size: 13px;
}
.rf-action-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 18px;
  margin-top: 4px;
}
.rf-action-left { border-right: 1px solid #111; padding-right: 18px; }
.rf-action-taken-label { font-weight: 700; font-style: italic; text-align: center; font-size: 13px; margin-bottom: 2px; }
.rf-action-taken-row { display: flex; gap: 14px; justify-content: center; margin-bottom: 5px; font-size: 13px; }
.rf-actionbox.checked { font-weight: 700; }
.request-print-page .rf-commentbox {
  --rf-line: 22px;
  height: calc(var(--rf-line) * 4);
  min-height: 0;
  margin: 0 0 4px;
  overflow: hidden;
  line-height: var(--rf-line);
  background-image: repeating-linear-gradient(
    to bottom,
    transparent 0, transparent calc(var(--rf-line) - 1px),
    #111 calc(var(--rf-line) - 1px), #111 var(--rf-line));
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}
.rf-finaldate { font-size: 13px; border-top: 0; padding-top: 6px; }
.rf-action-right { padding-left: 4px; }
.rf-stampbox { min-height: 44px; border: 0; margin: 2px 0 6px; display: flex; align-items: center; justify-content: center; padding: 6px; }

/* Physical rubber "Date Received" stamp: blue ink pressed onto paper.
   Uneven transfer comes from an SVG-noise mask (solid ink where masks
   are unsupported). No shadow, no gradient, no rounded corners. */
.rf-stamp {
  --stamp-ink: #1e40af;
  display: inline-block;
  border: 2.5px solid var(--stamp-ink);
  border-radius: 0;
  padding: 7px 14px 8px 16px;
  transform: rotate(-.9deg);
  color: var(--stamp-ink);
  font-family: "Arial Narrow", "Roboto Condensed", "Helvetica Condensed", Arial, sans-serif;
  font-stretch: condensed;
  font-weight: 800;
  font-size: 21px;
  line-height: 1.2;
  letter-spacing: 2.5px;
  text-transform: uppercase;
  white-space: nowrap;
  opacity: .92;
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='ink'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='2' stitchTiles='stitch' result='n'/%3E%3CfeColorMatrix in='n' type='matrix' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0.45 0 0 0 0.62'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23ink)'/%3E%3C/svg%3E");
  -webkit-mask-size: 200px 200px;
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='ink'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='2' stitchTiles='stitch' result='n'/%3E%3CfeColorMatrix in='n' type='matrix' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0.45 0 0 0 0.62'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23ink)'/%3E%3C/svg%3E");
  mask-size: 200px 200px;
}
.rf-approvedby { margin-bottom: 6px; font-size: 13px; }
.rf-approvedby em { display: block; font-style: italic; margin-bottom: 4px; }
.rf-imosig { display: block; max-width: 220px; max-height: 70px; margin: 2px 0; }
.rf-approvedby strong { display: block; font-size: 13px; }
.rf-sigline { display: block; border-top: 1px solid #111; margin: 3px 0; }
.rf-approvedby small { display: block; font-style: italic; font-size: 10px; }
.rf-approvaldate2 { font-size: 13px; }

/* Important note */
.rf-important { margin-top: 8px; padding-top: 4px; border-top: 1px solid #111; font-size: 11px; }
.rf-important ul { margin: 2px 0 0; padding-left: 16px; }
.rf-important li { margin-bottom: 1px; }

/* Screen fill rules — taller writing areas so the page fills naturally */
.request-print-page .rf-stampbox   { min-height: 84px; }
.request-print-page .rf-titlecenter h3 { font-size: 22px; }
.request-print-page .rf-label,
.request-print-page .rf-underline,
.request-print-page .rf-check { font-size: 14px; }
.request-print-page .rf-important { font-size: 12px; }
.request-print-page .rf-section h4 { font-size: 15px; }

@media (max-width: 700px) {
  .request-print-page { padding: 0.5cm; }
  .rf-meta, .rf-row2, .rf-checkgrid-2, .rf-action-grid { grid-template-columns: 1fr; }
  .rf-action-left { border-right: 0; border-bottom: 1px solid #111; padding: 0 0 14px; margin-bottom: 14px; }
  .request-detail-dialog { max-height: calc(100vh - 24px); }
  .request-detail-content { padding: 14px; }
}

.request-detail-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }
.request-detail-loading { padding: 40px; color: var(--muted); text-align: center; }
.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;
}
body.modal-open { overflow: hidden; }

/* ------------------------------------------------------------------
  Public pages (landing / login / register)
  ------------------------------------------------------------------ */
.public-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  min-height: 72px;
  padding: 14px 42px;
  background: rgba(255,255,255,.94);
  border-bottom: 1px solid #e4ece8;
  position: sticky;
  top: 0;
  z-index: 30;
  backdrop-filter: blur(14px);
}
.public-system-name {
  flex: 1;
  min-width: 0;
  color: #123c2a;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -.15px;
  text-decoration: none;
}
.public-system-name:hover { color: var(--green-700); text-decoration: none; }
.public-home-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  padding: 8px 12px;
  border: 1px solid #d6e5db;
  border-radius: 8px;
  background: #f8fbf9;
  color: var(--green-700);
  font-size: 12px;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
}
.public-home-link:hover {
  border-color: #b8d8c3;
  background: var(--card);
  color: var(--green-900);
  text-decoration: none;
}
.public-nav { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.public-nav a { color: #374151; font-size: 14px; }
.public-nav a:hover { color: var(--green-700); }

.public-main { min-height: calc(100vh - 72px); }

/* Landing page: an editorial left column paired with a focused login card. */
.landing-body {
  background: #f7faf8;
  color: #173b2b;
}
.landing-page {
  position: relative;
  isolation: isolate;
  display: grid;
  grid-template-columns: minmax(0, 1.12fr) minmax(390px, .88fr);
  align-items: center;
  gap: clamp(48px, 7vw, 112px);
  max-width: 1440px;
  min-height: calc(100vh - 72px);
  margin: 0 auto;
  padding: clamp(38px, 5vw, 72px) clamp(30px, 7vw, 108px) 54px;
  overflow: hidden;
}
.landing-page::before,
.landing-page::after {
  content: "";
  position: absolute;
  z-index: 0;
  pointer-events: none;
  border-radius: 50%;
}
.landing-page::before {
  width: 520px;
  height: 520px;
  top: -250px;
  left: -210px;
  background: rgba(213,239,225,.72);
  filter: blur(2px);
}
.landing-page::after {
  width: 430px;
  height: 430px;
  right: -250px;
  bottom: -245px;
  background: rgba(245,218,151,.18);
}
.landing-copy { position: relative; z-index: 1; min-width: 0; max-width: 720px; }
.landing-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 19px;
  color: var(--green-700);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 1.65px;
  line-height: 1.2;
  text-transform: uppercase;
}
.landing-eyebrow-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #f0a500;
  box-shadow: 0 0 0 5px rgba(240,165,0,.12);
}
.landing-copy h1 {
  max-width: 650px;
  margin: 0 0 20px;
  color: #123c2a;
  font-size: clamp(40px, 4.8vw, 66px);
  font-weight: 750;
  letter-spacing: -2.8px;
  line-height: 1.04;
}
.landing-copy h1 span { color: var(--green-600); }
.landing-lead {
  max-width: 570px;
  margin: 0;
  color: #61776b;
  font-size: clamp(16px, 1.4vw, 18px);
  line-height: 1.65;
}
.landing-points {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 15px;
  max-width: 690px;
  margin: 24px 0 27px;
}
.landing-point {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  color: #315b47;
}
.landing-point-icon {
  display: grid;
  place-items: center;
  flex: 0 0 32px;
  width: 32px;
  height: 32px;
  border-radius: 9px;
  background: #e1f2e8;
  color: var(--green-700);
}
.landing-point-icon svg { width: 18px; height: 18px; }
.landing-point > span:last-child { display: flex; flex-direction: column; gap: 2px; }
.landing-point strong { font-size: 12px; line-height: 1.35; }
.landing-point small { color: #7b9084; font-size: 11.5px; line-height: 1.4; }

.queue-preview {
  position: relative;
  max-width: 650px;
  padding: 0 23px 20px 0;
}
.queue-preview-glow {
  position: absolute;
  right: 0;
  bottom: -22px;
  left: 20px;
  height: 70%;
  border-radius: 35px;
  background: rgba(31,126,82,.11);
  filter: blur(22px);
}
.queue-window {
  position: relative;
  z-index: 1;
  overflow: hidden;
  border: 1px solid #dce9e2;
  border-radius: 15px;
  background: #fff;
  box-shadow: 0 20px 44px rgba(26,78,52,.12), 0 3px 8px rgba(26,78,52,.05);
  transform: rotate(-.35deg);
}
.queue-window-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 40px;
  padding: 0 16px;
  border-bottom: 1px solid #edf2ef;
  background: #fbfdfc;
}
.queue-window-title {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: #355a47;
  font-size: 12px;
  font-weight: 700;
}
.queue-window-mark {
  width: 9px;
  height: 9px;
  border-radius: 3px;
  background: var(--green-600);
  box-shadow: 12px 0 0 #9ad1b4;
}
.queue-live {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: #4b9a6e;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .3px;
  text-transform: uppercase;
}
.queue-live i { width: 5px; height: 5px; border-radius: 50%; background: #35ad70; }
.queue-window-body { padding: 14px 16px 15px; }
.queue-overview {
  display: grid;
  grid-template-columns: 100px 100px 1fr;
  align-items: end;
  gap: 20px;
  padding: 0 0 16px;
  border-bottom: 1px solid #eef3f0;
}
.queue-overview > div { display: flex; flex-direction: column; gap: 2px; }
.queue-overview span { color: #82938a; font-size: 10px; }
.queue-overview strong { color: #173d2c; font-size: 23px; line-height: 1; }
.queue-progress { gap: 7px !important; }
.queue-progress > div {
  width: 100%;
  height: 5px;
  margin-top: 4px;
  overflow: hidden;
  border-radius: 999px;
  background: #e6f0ea;
}
.queue-progress b { display: block; height: 100%; border-radius: inherit; background: #35a86c; }
.queue-window-list { display: flex; flex-direction: column; gap: 5px; padding-top: 11px; }
.queue-window-row {
  display: grid;
  grid-template-columns: 25px 28px minmax(0,1fr) auto;
  align-items: center;
  gap: 9px;
  min-height: 42px;
  padding: 4px 7px;
  border-radius: 8px;
}
.queue-window-row:nth-child(2) { background: #f5faf7; }
.queue-order { color: #a3b1a9; font-family: Consolas, monospace; font-size: 10px; }
.queue-platform {
  display: grid;
  place-items: center;
  width: 27px;
  height: 27px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 800;
}
.queue-platform-fb { background: #e6f0ff; color: #4b78bf; }
.queue-platform-ig { background: #fce8f3; color: #c25387; }
.queue-platform-yt { background: #ffe8e8; color: #d65b5b; }
.queue-row-copy { display: flex; min-width: 0; flex-direction: column; gap: 1px; }
.queue-row-copy strong { overflow: hidden; color: #355447; font-size: 11.5px; font-weight: 700; text-overflow: ellipsis; white-space: nowrap; }
.queue-row-copy small { color: #91a097; font-size: 9.5px; }
.queue-row-status { padding: 4px 7px; border-radius: 999px; font-size: 9px; font-weight: 700; white-space: nowrap; }
.queue-row-status-done { background: #e1f4e8; color: #238352; }
.queue-row-status-review { background: #fff2d6; color: #a8740a; }
.queue-row-status-next { background: #e7effc; color: #5278b6; }
.queue-preview-note {
  position: relative;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin: 8px 0 0 27px;
  padding: 8px 13px 8px 9px;
  border: 1px solid #dcebe1;
  border-radius: 11px;
  background: rgba(255,255,255,.96);
  box-shadow: 0 9px 22px rgba(26,78,52,.1);
  transform: translateY(-10px);
}
.queue-note-check {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 8px;
  background: var(--green-600);
  color: #fff;
  font-size: 14px;
  font-weight: 800;
}
.queue-preview-note span:last-child { display: flex; flex-direction: column; gap: 1px; }
.queue-preview-note strong { color: #315a45; font-size: 11px; }
.queue-preview-note small { color: #83968a; font-size: 10px; }

.landing-login-column { position: relative; z-index: 1; width: 100%; max-width: 455px; justify-self: end; }

/* The registration page mirrors the landing page: the shared copy takes the
   right-hand column and the card arrives from the right, so it reads as the
   login card travelling across. The card is the grid item itself, and sits
   above the page blobs and the copy so it sweeps over them as it settles.
   Declared before the responsive rules further down, so they still win. */
.register-card { position: relative; z-index: 2; justify-self: start; }
.register-page .register-card { animation: registerCardIn .55s cubic-bezier(.2,.8,.2,1) both; }
.register-page .landing-copy { animation: registerCopyIn .5s ease-out both; }
@keyframes registerCardIn {
  from { transform: translate3d(18vw, 0, 0); }
  to   { transform: none; }
}
@keyframes registerCopyIn {
  from { opacity: 0; transform: translate3d(28px, 0, 0); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .register-page .register-card,
  .register-page .landing-copy { animation: none; }
}
.landing-login-card {
  position: relative;
  padding: 33px 40px 28px;
  border: 1px solid rgba(255,255,255,.88);
  border-radius: 20px;
  background: rgba(255,255,255,.78);
  box-shadow: 0 24px 60px rgba(30,82,55,.12), inset 0 1px 0 rgba(255,255,255,.95);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
}
.landing-login-card::before {
  content: "";
  position: absolute;
  top: 0;
  right: 42px;
  left: 42px;
  height: 3px;
  border-radius: 0 0 4px 4px;
  background: linear-gradient(90deg, var(--green-600), #74c394, #f0a500);
}
.landing-login-icon {
  display: grid;
  place-items: center;
  width: 45px;
  height: 45px;
  margin: 0 auto 16px;
  border-radius: 14px;
  background: #e3f3e9;
  color: var(--green-700);
}
.landing-login-icon svg { width: 25px; height: 25px; }
.landing-login-heading { margin-bottom: 21px; text-align: center; }
.landing-card-kicker {
  display: block;
  margin-bottom: 5px;
  color: #799184;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 1.3px;
  text-transform: uppercase;
}
.landing-login-heading h2 { margin: 0 0 5px; color: #173d2c; font-size: 25px; letter-spacing: -.55px; }
.landing-login-heading p { margin: 0; color: #7a8f83; font-size: 13.5px; }
.landing-login-form { display: flex; flex-direction: column; gap: 14px; }
.landing-field { display: flex; flex-direction: column; gap: 7px; }
.landing-field > label { color: #345646; font-size: 12.5px; font-weight: 700; }
.landing-input-wrap { position: relative; display: flex; align-items: center; }
.landing-input-wrap > svg {
  position: absolute;
  left: 13px;
  width: 18px;
  height: 18px;
  color: #92a69a;
  pointer-events: none;
}
.landing-input-wrap input {
  min-height: 44px;
  padding: 9px 42px 9px 41px;
  border-color: #d5e2da;
  border-radius: 9px;
  background: #fbfdfc;
  color: #1d3c2e;
  font-size: 13.5px;
}
.landing-input-wrap input::placeholder { color: #a5b3aa; }
.landing-input-wrap input:focus { border-color: var(--green-600); background: #fff; }
.landing-show-password {
  position: absolute;
  right: 8px;
  display: grid;
  place-items: center;
  width: 31px;
  height: 31px;
  padding: 0;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: #8ba095;
  cursor: pointer;
}
.landing-show-password:hover { background: #eaf4ee; color: var(--green-700); }
.landing-show-password svg { width: 18px; height: 18px; }
.landing-form-options { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: -3px; }
.landing-remember { display: inline-flex; align-items: center; gap: 8px; color: #71867a; font-size: 12px; cursor: pointer; }
.landing-remember input { width: 15px; height: 15px; margin: 0; accent-color: var(--green-700); }
.landing-form-options > a { color: var(--green-700); font-size: 12px; font-weight: 700; }
.landing-form-options > a:hover { color: var(--green-900); }
.landing-submit {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 45px;
  margin-top: 2px;
  border: 0;
  border-radius: 9px;
  background: linear-gradient(135deg, #1b8655, #116a3e);
  box-shadow: 0 8px 16px rgba(17,106,62,.18);
  color: #fff;
  font-size: 13.5px;
  font-weight: 700;
  cursor: pointer;
  transition: transform .16s ease, box-shadow .16s ease, filter .16s ease;
}
.landing-submit svg { width: 17px; height: 17px; transition: transform .16s ease; }
.landing-submit:hover { filter: brightness(1.05); box-shadow: 0 11px 20px rgba(17,106,62,.24); transform: translateY(-1px); }
.landing-submit:hover svg { transform: translateX(3px); }
.landing-submit:focus-visible { outline: 3px solid rgba(39,165,104,.25); outline-offset: 2px; }
.landing-error {
  margin: -4px 0 18px;
  padding: 11px 13px;
  border: 1px solid #f1c4c4;
  border-radius: 9px;
  background: #fff3f3;
  color: #9d3333;
  font-size: 12px;
}
.landing-error strong { display: block; margin-bottom: 3px; }
.landing-error .form-errors { margin: 0; }
.landing-register {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  margin-top: 20px;
  padding-top: 17px;
  border-top: 1px solid #edf2ef;
  color: #819187;
  font-size: 12.5px;
}
.landing-register a { color: var(--green-700); font-weight: 750; }
.landing-register a:hover { color: var(--green-900); }
.landing-login-footnote { margin: 15px 0 0; color: #a0afa5; font-size: 10.5px; text-align: center; }

.hero {
  background: linear-gradient(135deg, var(--green-900) 0%, var(--green-700) 55%, var(--green-600) 100%);
  color: #fff;
  padding: 64px 26px 70px;
  text-align: center;
}
.hero .hero-tag {
  display: inline-block;
  background: rgba(255,255,255,.15);
  border: 1px solid rgba(255,255,255,.3);
  border-radius: 999px;
  font-size: 12px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  padding: 5px 16px;
  margin-bottom: 18px;
}
.hero h1 { font-size: 34px; max-width: 780px; margin: 0 auto 14px; }
.hero p { font-size: 16px; color: #d7ece1; max-width: 640px; margin: 0 auto 26px; }
.hero .hero-actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
.hero .btn-light { background: #fff; color: var(--green-800); }
.hero .btn-outline-light { background: transparent; border-color: rgba(255,255,255,.6); color: #fff; }
.hero .btn-outline-light:hover { background: rgba(255,255,255,.12); }

.public-section { padding: 46px 26px; max-width: 1080px; margin: 0 auto; }
.public-section h2 { font-size: 24px; text-align: center; }
.public-section .section-sub { text-align: center; color: var(--muted); margin: -6px auto 28px; max-width: 620px; }

.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr)); gap: 16px; }
.step-card {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px;
  box-shadow: var(--shadow);
}
.step-card .step-no {
  width: 34px; height: 34px;
  border-radius: 50%;
  background: var(--green-700);
  color: #fff;
  display: grid; place-items: center;
  font-weight: 700;
  margin-bottom: 10px;
}
.step-card h3 { font-size: 15.5px; }
.step-card p { font-size: 13.5px; color: var(--muted); margin: 0; }

.guide-boxes { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); gap: 16px; }
.guide-box { background: #fff; border: 1px solid var(--line); border-radius: var(--radius); padding: 20px; box-shadow: var(--shadow); }
.guide-box h3 { font-size: 15.5px; color: var(--green-800); }
.guide-box ul { margin: 0; padding-left: 18px; font-size: 13.5px; color: #4b5563; }
.guide-box li { margin-bottom: 6px; }

.public-footer { background: #10231a; color: #cfe4da; margin-top: 30px; }
.public-footer-inner {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
  gap: 24px;
  padding: 34px 26px;
  max-width: 1080px;
  margin: 0 auto;
}
.public-footer strong { color: #fff; display: block; margin-bottom: 8px; font-size: 14px; }
.public-footer p { margin: 0 0 6px; font-size: 13.5px; }
.public-footer a { color: #9fd8bd; }
.public-footer-bottom {
  border-top: 1px solid rgba(255,255,255,.1);
  text-align: center;
  padding: 14px;
  font-size: 12.5px;
  color: #8ba89a;
}

/* Auth pages */
.auth-wrap {
  min-height: calc(100vh - 66px);
  display: grid;
  place-items: center;
  padding: 40px 20px;
  background:
    radial-gradient(1000px 400px at 15% -10%, rgba(21,115,71,.10), transparent),
    radial-gradient(800px 380px at 110% 110%, rgba(240,165,0,.10), transparent),
    var(--bg);
}
.auth-card {
  width: 100%;
  max-width: 440px;
  background: rgba(255,255,255,.82);
  border: 1px solid rgba(255,255,255,.9);
  border-radius: 14px;
  box-shadow: 0 24px 60px rgba(30,82,55,.12), inset 0 1px 0 rgba(255,255,255,.95);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  padding: 30px 30px 26px;
}
.auth-card.wide { max-width: 620px; }
.auth-card .auth-ico {
  width: 52px; height: 52px;
  border-radius: 14px;
  background: var(--green-50);
  display: grid; place-items: center;
  font-size: 24px;
  margin: 0 auto 12px;
}
.auth-card h2 { text-align: center; font-size: 20px; margin-bottom: 4px; }
.auth-card .auth-sub { text-align: center; color: var(--muted); font-size: 13.5px; margin: 0 0 20px; }
/* The same subtitle, rendered into #forgot-password-modal instead of the card
   above, so it loses the .auth-card-scoped rule it was written against. The
   dialog header already carries the title and the content beside it is left
   aligned, so the instruction is given the same treatment rather than the
   centring it has on the standalone page. */
.modal-body .auth-sub { color: var(--muted); font-size: 13.5px; margin: 0 0 16px; }
.auth-footer { text-align: center; font-size: 13.5px; color: var(--muted); margin-top: 16px; }
.auth-alt { text-align: center; margin-top: 14px; font-size: 13.5px; }

.demo-box {
  margin-top: 16px;
  background: var(--gray-50);
  border: 1px dashed #ccd3da;
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 12.5px;
  color: var(--muted);
}
.demo-box summary { cursor: pointer; font-weight: 600; color: #495057; }
.demo-box table { width: 100%; margin-top: 8px; font-size: 12px; border-collapse: collapse; }
.demo-box td { padding: 3px 6px; }

/* ------------------------------------------------------------------
  Misc
  ------------------------------------------------------------------ */
.text-muted { color: var(--muted); }
.text-small { font-size: 12.5px; }
.text-center { text-align: center; }
.mt-0 { margin-top: 0; } .mt-2 { margin-top: 16px; } .mb-0 { margin-bottom: 0; }
.right { text-align: right; }
.divider { height: 1px; background: var(--line); margin: 16px 0; }
.inline-form { display: inline; }
.hidden { display: none !important; }
.list-plain { list-style: none; margin: 0; padding: 0; }
.list-plain li { padding: 9px 0; border-bottom: 1px dashed #edf0f3; font-size: 13.5px; }
.list-plain li:last-child { border-bottom: 0; }

.faq details {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 12px 14px;
  margin-bottom: 10px;
}
.faq summary { font-weight: 600; cursor: pointer; font-size: 14px; }
.faq details p { margin: 8px 0 0; font-size: 13.5px; color: #4b5563; }

/* Help Center (staff/help.php) */
.help-center { font-size: 14px; }
.help-center .section-title { font-size: 16px; font-weight: 800; margin: 24px 0 12px; color: var(--ink); }
.help-center .section-title:first-of-type { margin-top: 4px; }
.help-search {
  display: flex;
  align-items: center;
  gap: 10px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 11px 14px;
  box-shadow: 0 6px 18px rgba(31,78,53,.06);
  cursor: text;
}
.help-search-ico { font-size: 17px; }
.help-search input { border: 0; padding: 0; font-size: 14.5px; background: transparent; flex: 1; min-width: 0; }
.help-search input:focus { border: 0; box-shadow: none; outline: none; }
.help-no-results { margin: 0 0 12px; color: var(--muted); font-size: 13.5px; }
.quick-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr)); gap: 14px; }
.quick-card {
  display: block;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 16px;
  color: inherit;
  box-shadow: 0 6px 18px rgba(31,78,53,.06);
  transition: transform .18s ease, box-shadow .18s ease;
}
.quick-card:hover { text-decoration: none; transform: translateY(-2px); box-shadow: 0 10px 24px rgba(31,78,53,.1); }
.quick-card .qc-ico { font-size: 22px; }
.quick-card .qc-ico svg.lucide,
.quick-card .qc-ico [data-lucide] { width: 22px; height: 22px; }
.help-search-ico svg.lucide,
.help-search-ico [data-lucide] { width: 17px; height: 17px; display: block; }
.quick-card h4 { margin: 8px 0 4px; font-size: 14.5px; }
.quick-card p { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.55; }
.quick-card .qc-link { display: inline-block; margin-top: 8px; font-size: 13px; font-weight: 700; color: var(--green-700); }
.help-acc { border-bottom: 1px solid var(--line); scroll-margin-top: 90px; }
.help-acc:last-child { border-bottom: 0; }
.help-center .faq .help-acc summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 14px 18px;
  font-size: 14.5px;
  font-weight: 700;
  list-style: none;
}
.help-acc summary::-webkit-details-marker { display: none; }
.help-acc summary::after {
  content: "+";
  flex: 0 0 auto;
  font-size: 18px;
  font-weight: 400;
  color: var(--green-700);
}
.help-acc[open] summary::after { content: "−"; }
.help-acc summary:hover { color: var(--green-800); }
.help-acc .acc-body { padding: 0 18px 16px; font-size: 14px; line-height: 1.7; color: #374151; animation: accIn .22s ease; }
.help-acc .acc-body ol, .help-acc .acc-body ul { padding-left: 20px; margin: 0 0 8px; display: grid; gap: 6px; }
.help-acc .acc-body ol:last-child, .help-acc .acc-body ul:last-child, .help-acc .acc-body p:last-child { margin-bottom: 0; }
@keyframes accIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.req-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.req-grid .card { margin-bottom: 0; }
.req-list { margin: 10px 0 0; padding-left: 20px; display: grid; gap: 6px; font-size: 14px; }
.help-contact { max-width: none; }
@media (max-width: 860px) {
  .req-grid { grid-template-columns: 1fr; }
}

.conflict-box {
  background: var(--red-50);
  border: 1px solid #f5c2c7;
  color: #842029;
  border-radius: 8px;
  padding: 12px 14px;
  font-size: 13.5px;
  margin-bottom: 14px;
}

/* ------------------------------------------------------------------
  Responsive
  ------------------------------------------------------------------ */
@media (max-width: 1024px) {
  .grid-main, .grid-2, .grid-3 { grid-template-columns: 1fr; }
  .form-grid, .form-grid-3, .form-grid-name-row { grid-template-columns: 1fr; }
  .bar-row { grid-template-columns: 120px 1fr 46px; }
}

@media (max-width: 860px) {
  .sidebar {
    position: fixed;
    left: 0; top: 0;
    height: 100vh;
    transform: translateX(-100%);
    transition: transform .22s ease;
    box-shadow: var(--shadow-lg);
  }
  .sidebar.open { transform: translateX(0); }
  .sidebar-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,.45);
    opacity: 0;
    pointer-events: none;
    transition: opacity .22s;
    z-index: 45;
  }
  .sidebar-backdrop.show { opacity: 1; pointer-events: auto; }
  #sidebar-toggle { display: inline-flex; }
  .content { padding: 16px; }
  .user-chip-text { display: none; }
  .detail-list { grid-template-columns: 1fr; }
  .detail-list dt { padding-bottom: 0; border-bottom: 0; }
  .detail-list dd { padding-top: 2px; }
  .cal-day { min-height: 74px; }
  .cal-event { font-size: 10px; }
  .hero h1 { font-size: 26px; }
  .public-nav { gap: 10px; }
  .public-nav a:not(.btn) { display: none; }
}

/* Landing page responsive layout */
@media (max-width: 1100px) {
  .landing-page {
    grid-template-columns: minmax(0, 1fr) minmax(340px, .86fr);
    gap: 42px;
    padding-right: 42px;
    padding-left: 42px;
  }
  .landing-copy h1 { font-size: clamp(40px, 5vw, 58px); }
  .landing-points { gap: 10px; }
  .landing-point small { font-size: 11px; }
  .queue-overview { grid-template-columns: 86px 86px 1fr; gap: 12px; }
}

@media (max-width: 860px) {
  .public-topbar { padding-right: 24px; padding-left: 24px; }
  .landing-page {
    grid-template-columns: 1fr;
    gap: 44px;
    max-width: 720px;
    min-height: auto;
    padding: 52px 24px 64px;
  }
  .landing-copy { max-width: none; }
  .landing-copy h1 { max-width: 570px; font-size: clamp(43px, 8vw, 62px); }
  .landing-lead { max-width: 620px; }
  .queue-preview { max-width: 650px; }
  .landing-login-column { justify-self: stretch; max-width: 530px; margin: 0 auto; }
}

@media (max-width: 600px) {
  .public-topbar {
    min-height: 64px;
    padding: 12px 18px;
  }
  .public-system-name { max-width: 100%; font-size: 13.5px; line-height: 1.3; }
  .landing-page {
    gap: 35px;
    padding: 39px 18px 50px;
  }
  .landing-copy h1 { font-size: clamp(39px, 12vw, 53px); letter-spacing: -2px; }
  .landing-lead { font-size: 15px; }
  .landing-points {
    grid-template-columns: 1fr;
    gap: 13px;
    margin-top: 27px;
    margin-bottom: 30px;
  }
  .landing-point strong { font-size: 12.5px; }
  .landing-point small { font-size: 11.5px; }
  .queue-preview { padding-right: 9px; padding-bottom: 14px; }
  .queue-window { border-radius: 12px; }
  .queue-window-body { padding: 14px 11px 13px; }
  .queue-overview { grid-template-columns: 1fr 1fr; gap: 12px; }
  .queue-progress { grid-column: 1 / -1; }
  .queue-window-row { grid-template-columns: 20px 26px minmax(0,1fr); gap: 6px; padding-right: 2px; padding-left: 2px; }
  .queue-row-status { display: none; }
  .queue-preview-note { margin-left: 12px; padding: 8px 10px 8px 8px; }
  .queue-preview-note strong { font-size: 10px; }
  .queue-preview-note small { font-size: 9px; }
  .landing-login-card { padding: 32px 22px 26px; border-radius: 16px; }
  .landing-login-card::before { right: 25px; left: 25px; }
  .landing-login-heading h2 { font-size: 23px; }
  .landing-form-options { align-items: flex-start; }
  .public-footer-inner { padding: 29px 20px; }
}

@media (max-width: 420px) {
  .public-home-link { padding: 7px 9px; font-size: 11px; }
}

@media (max-width: 860px) {
  .queue-type-tabs {
    display: flex;
    flex-wrap: wrap;
    overflow: visible;
  }
  .queue-type-tab {
    flex: 1 1 142px;
    width: auto;
  }
  .queue-table-wrap { overflow-x: auto; }
  .queue-action-menu-panel {
    position: static;
    top: auto;
    right: auto;
    left: auto;
    min-width: 148px;
    margin-top: 6px;
  }
}

@media (max-width: 600px) {
  .calendar-glass .cal-head { align-items: flex-start; padding: 15px; }
  .cal-nav { width: 100%; }
  .cal-date-filter { flex: 1 1 100%; }
  .cal-date-filter input { width: 100%; }
  .calendar-management-page .cal-day { min-height: 0; padding: 5px; }
  .calendar-management-page .cal-dow { padding: 7px 2px; font-size: 9px; letter-spacing: .2px; }
  .calendar-modal { padding: 12px; }
  .calendar-modal-dialog { max-height: calc(100vh - 24px); border-radius: 16px; }
  .calendar-modal-header { padding: 18px 17px 15px; }
  .calendar-modal-body { padding: 17px; }
}

@media print {
  @page { size: 8.5in 13in; margin: 0; }
  html, body { width: 8.5in; margin: 0; padding: 0; background: #fff; }
  body.printing-request .sidebar,
  body.printing-request .topbar,
  body.printing-request .calendar,
  body.printing-request .calendar-page-header,
  body.printing-request .app-footer,
  body.printing-request .toast-stack,
  body.printing-request .request-detail-toolbar,
  body.printing-request .calendar-modal-backdrop { display: none !important; }
  body.printing-request .app-shell,
  body.printing-request .app-body,
  body.printing-request .content { display: block !important; min-height: 0 !important; max-width: none !important; padding: 0 !important; }
  body.printing-request #request-detail-modal {
    position: static !important;
    display: block !important;
    inset: auto !important;
    padding: 0 !important;
    opacity: 1 !important;
    visibility: visible !important;
    pointer-events: auto !important;
    background: #fff !important;
  }
  body.printing-request .request-detail-dialog {
    width: 100% !important;
    max-height: none !important;
    overflow: visible !important;
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    background: #fff !important;
    backdrop-filter: none !important;
    transform: none !important;
    zoom: 1 !important;
  }
  body.printing-request .request-detail-content { margin: 0 !important; padding: 0 !important; background: #fff !important; }
  body.printing-request .request-print-page {
    width: 8.5in;
    height: 12.98in;
    min-height: 0;
    margin: 0;
    padding: 0.5in;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    overflow: visible;
    border: 0;
    box-shadow: none;
  }
  body.printing-request .rf-section,
  body.printing-request .rf-field,
  body.printing-request .rf-blankfield,
  body.printing-request .rf-blankmulti { break-inside: avoid; }
  body.printing-request .rf-letterhead { padding-bottom: 4px; }
  body.printing-request .rf-titleblock { margin-top: 2px; }
  body.printing-request .rf-rule { margin: 5px 0; }
  body.printing-request .rf-rule.thick { margin: 6px 0 8px; }
  body.printing-request .rf-meta { gap: 4px 30px; }
  body.printing-request .rf-section { margin-top: 8px; }
  body.printing-request .rf-section h4 { margin: 0 0 6px; }
  body.printing-request .rf-multiline { min-height: calc(var(--rf-line) * 4); }
  body.printing-request .rf-row2 { margin: 6px 0; }
  body.printing-request .rf-checkgrid { gap: 6px 24px; margin: 4px 0 6px; }
  body.printing-request .rf-inlinecheck-row { margin: 6px 0; }
  body.printing-request .rf-approval { margin-top: 10px; padding-top: 8px; }
  body.printing-request .rf-action-title { margin-top: 8px; padding: 5px 0; }
  body.printing-request .rf-action-grid { margin-top: 8px; flex: 0 0 auto; }
  body.printing-request .rf-stampbox { min-height: 70px; }
  body.printing-request .rf-important { margin-top: 10px; padding-top: 6px; }
}

/* ------------------------------------------------------------------
  Compact calendar-app visual system
  ------------------------------------------------------------------ */
.calendar-management-page {
  --bg: #f3f5f8;
  --card: #ffffff;
  --ink: #1f2937;
  --line: #e5e7eb;
  --accent: #157347;
  --accent-soft: #edf7f2;
  --muted: #6b7280;
  --danger: #dc3545;
  --radius: 10px;
  --shadow: 0 1px 3px rgba(16, 24, 40, .08), 0 1px 2px rgba(16, 24, 40, .05);
  --shadow-lg: 0 10px 30px rgba(16, 24, 40, .12);
  background: var(--bg);
  color: var(--ink);
  font-family: -apple-system, "Segoe UI", sans-serif;
}
.calendar-management-page .calendar-page-header,
.calendar-management-page .calendar-glass {
  width: 100%;
  max-width: none;
  margin-right: 0;
  margin-left: 0;
  padding-right: 0;
  padding-left: 0;
  box-sizing: border-box;
}
.calendar-management-page .calendar-page-header { margin-bottom: 16px; }
.calendar-management-page .calendar-page-header h2 { color: var(--ink); font-size: 1.2rem; font-weight: 600; }
.calendar-management-page .calendar-page-header p { color: var(--muted); }

.calendar-management-page .calendar-glass {
  overflow: visible;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--bg);
  color: var(--ink);
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.calendar-management-page .calendar-glass a,
.calendar-management-page .calendar-glass button {
  color: inherit;
  text-decoration: none;
}

.calendar-management-page .calendar-glass .cal-head {
  padding: 14px 16px;
  border-bottom: 1px solid var(--line);
  background: var(--card);
}
.calendar-management-page .cal-heading { gap: 0; }
.calendar-management-page .cal-eyebrow { display: none; }
.calendar-management-page .calendar-glass .cal-title { color: var(--ink); font-size: 1.05rem; font-weight: 600; }
.calendar-management-page .cal-nav { gap: 6px; }
.calendar-management-page .cal-nav .btn {
  width: 32px;
  height: 32px;
  min-width: 32px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: transparent;
  color: var(--ink);
  font-size: 1rem;
  box-shadow: none;
}
.calendar-management-page .cal-nav .btn:hover { border-color: var(--accent); background: var(--accent-soft); filter: none; }
.calendar-management-page .cal-nav #cal-today { width: auto; padding: 0 11px; font-size: .8rem; }
.calendar-management-page .cal-date-filter input {
  min-width: 140px;
  padding: 7px 9px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg);
  color: var(--ink);
  font-size: .8rem;
}
.calendar-management-page .cal-date-filter input:focus { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }

.calendar-management-page .cal-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  justify-content: stretch;
  gap: 6px;
  overflow: visible;
  padding: 12px;
  background: transparent;
  width: 100%;
}
.calendar-management-page .cal-dow {
  padding: 0 0 6px;
  border: 0;
  background: transparent;
  color: var(--muted);
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
}

.calendar-management-page .cal-day {
  position: relative;
  width: auto;
  height: auto;
  min-height: 84px;
  max-height: none;
  aspect-ratio: auto;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 30px 6px 6px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--card);
  color: var(--ink);
  transition: border-color .18s ease, background-color .18s ease, box-shadow .18s ease, transform .18s ease;
}
.calendar-management-page .cal-day:hover,
.calendar-management-page .cal-day:focus-visible {
  border-color: var(--accent);
  background: var(--card);
  box-shadow: none;
  outline: none;
  transform: translateY(-1px);
}
.calendar-management-page .cal-day.other { opacity: .55; background: var(--card); }

/* Today: outlined marker, pinned top-left — does not compete with selected */
.calendar-management-page .cal-day.today { background: var(--card); }
.calendar-management-page .cal-day.today .cal-daynum {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: transparent;
  border: 1.5px solid var(--accent);
  color: var(--accent);
  font-size: .7rem;
  font-weight: 600;
}

/* Day number pinned to the top-left corner of the card */
.calendar-management-page .cal-daynum {
  position: absolute;
  top: 8px;
  left: 8px;
  width: auto;
  height: auto;
  margin: 0;
  border-radius: 0;
  background: transparent;
  color: var(--muted);
  font-size: .78rem;
  font-weight: 500;
  transform: none;
}

/* Selected: the only marker with a solid green fill, moves with the click */
.calendar-management-page .cal-day.selected,
.calendar-management-page .cal-day.selectable.selected {
  width: auto;
  height: auto;
  min-height: 84px;
  max-height: none;
  border-color: var(--accent);
  background: var(--accent-soft);
  box-shadow: 0 0 0 2px var(--accent-soft);
}
.calendar-management-page .cal-day.selected .cal-daynum,
.calendar-management-page .cal-day.selectable.selected .cal-daynum {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: none;
  background: var(--accent);
  color: #fff;
  font-size: .7rem;
  font-weight: 600;
  box-shadow: none;
}

/* Other-month days: plain muted number, no circle, no color */
.calendar-management-page .cal-day.other .cal-daynum {
  display: block;
  border-radius: 0;
  border: none;
  background: transparent;
  color: var(--muted);
  font-size: .78rem;
  font-weight: 500;
}

.calendar-management-page .cal-platform-dots { gap: 3px; margin-top: 5px; min-height: 8px; }
.calendar-management-page .cal-platform-dot { width: 7px; height: 7px; border-color: var(--card); }
.calendar-management-page .cal-events { gap: 2px; margin-top: 4px; }
.calendar-management-page .cal-event {
  width: 100%;
  padding: 2px 5px;
  border: 0;
  border-left: 3px solid var(--event-color, var(--accent));
  border-radius: 5px;
  background: var(--accent-soft) !important;
  color: var(--ink);
  font-size: .68rem;
  line-height: 1.25;
  box-shadow: none;
}
.calendar-management-page .cal-event:hover { background: var(--accent-soft) !important; filter: none; transform: none; }
.calendar-management-page .cal-event .ev-time { font-size: .62rem; }
.calendar-management-page .cal-more,
.calendar-management-page .cal-dot-more { color: var(--muted); font-size: .65rem; }

.calendar-management-page .cal-legend {
  gap: 12px;
  padding: 10px 14px;
  border-top: 1px solid var(--line);
  background: transparent;
  color: var(--muted);
  font-size: .72rem;
}
/* The mark keeps its own size here rather than following the legend's smaller
   type: at .72rem a 1em icon would shrink below the platform's own detail, and
   the legend's job is to identify the marks at a glance. */
.calendar-management-page .cal-legend-item { gap: 5px; }
.calendar-management-page .cal-legend .dot { width: 8px; height: 8px; border-radius: 3px; }

@media (max-width: 480px) {
  .calendar-management-page .calendar-page-header,
  .calendar-management-page .calendar-glass { width: 100%; }
  .calendar-management-page .cal-grid { gap: 4px; padding: 8px; }
  .calendar-management-page .cal-day { min-height: 64px; padding: 26px 5px 5px; border-radius: 8px; }
  .calendar-management-page .cal-event { font-size: .62rem; }
  .calendar-management-page .cal-nav { width: 100%; }
  .calendar-management-page .cal-date-filter { flex: 1 1 100%; }
  .calendar-management-page .cal-date-filter input { width: 100%; }
}

/* Day schedule modal */
.day-schedule-dialog {
  max-width: 520px;
  max-height: 80vh;
  display: flex;
  flex-direction: column;
}
.day-schedule-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  padding: 18px 20px 12px;
  border-bottom: 1px solid var(--line);
}
.day-schedule-header h3 { font-size: 16px; margin: 2px 0 0; }
.day-schedule-header .request-detail-close { margin: 0; }
#day-schedule-content {
  padding: 12px 16px 16px;
  overflow-y: auto;
}
.day-schedule-empty {
  padding: 32px 16px;
  text-align: center;
  color: var(--muted);
  font-size: 14px;
}
.day-schedule-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.day-sched-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-left: 4px solid var(--event-color, var(--accent));
  border-radius: 10px;
  background: var(--card);
  cursor: pointer;
  text-align: left;
  font: inherit;
  transition: box-shadow .15s ease, transform .15s ease;
}
.day-sched-item:hover {
  box-shadow: var(--shadow);
  transform: translateY(-1px);
}
/* The mark and the time are one unit, kept together inside .day-sched-item's
   12px gap rather than being spaced by it. They need their own flex row: the
   wrapper is otherwise a plain inline span, and .platform-ico is display:block,
   which pushes the time onto a second line instead of sitting after the mark. */
.day-sched-when {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
}
.day-sched-time {
  flex-shrink: 0;
  min-width: 64px;
  font-size: 13px;
  font-weight: 700;
  color: var(--accent);
}
.day-sched-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.day-sched-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.day-sched-meta {
  font-size: 12px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.day-sched-dots {
  display: flex;
  gap: 4px;
  flex-shrink: 0;
}
.day-sched-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
}

/* ------------------------------------------------------------------
  Print (reports)
  ------------------------------------------------------------------ */
@media print {
  .sidebar, .topbar, .app-footer, .page-actions, .btn, .filters, .pagination, .filter-chips { display: none !important; }
  body { background: #fff; }
  .content { padding: 0; max-width: none; }
  .card { box-shadow: none; border-color: #ccc; break-inside: avoid; }
}

/* ------------------------------------------------------------------
   Ruled writing lines: always visible, screen and print
   ------------------------------------------------------------------ */
.request-print-page .rf-multiline,
.request-print-page .rf-commentbox {
  --rf-line: 24px;
  line-height: var(--rf-line);
  padding: 0;
  background-image: linear-gradient(to bottom, transparent calc(var(--rf-line) - 1px), #111 calc(var(--rf-line) - 1px));
  background-size: 100% var(--rf-line);
  background-repeat: repeat-y;
  background-color: transparent;
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
  white-space: pre-wrap;
}

.request-print-page .rf-multiline  { min-height: calc(var(--rf-line) * 5); }
.request-print-page .rf-commentbox { min-height: calc(var(--rf-line) * 4); }

.request-print-page, .request-print-page * {
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}

.request-print-page .rf-approval-sig { flex: 1 1 auto; min-width: 0; }

/* ==================================================================
   Printed request form: signature laid over the printed name.

   The screen overlay is in .rd-sig-* (assets/css/style.css, the request-details
   block). This is the same idea for the rf-* sheet, which is a separate document
   built by assets/js/calendar.js and is the only thing that reaches the paper.

   Three rules make it work:
     - the container is the positioning context, so the mark has something to be
       positioned against;
     - the name carries a lower z-index than the mark, so the ink is on top of the
       type while the name stays readable through it;
     - the mark is fitted into a fixed box rather than sized to its intrinsic
       dimensions, because a drawn signature arrives as an inline SVG with no
       width or height at all - sanitize_signature_svg() strips both - and would
       otherwise fall back to the 300x150 replaced-element default.
   ================================================================== */
.request-print-page .rf-approval-sig,
.request-print-page .rf-approvedby {
  position: relative;
  display: block;
  text-align: center;
  min-width: 220px;
  /* Room above the name for the mark to occupy, so it overlaps the upper part of
     the name rather than hanging off the top of the container. */
  padding-top: 30px;
}
/* The head block carries no label of its own, so the room above the name is all
   the mark needs. The Marketing Office block does carry one, and in flow it
   took the first 23px of content - which pushed the name down far enough that
   the mark landed on the words "Approved by:" instead of on the name it signs.
   Pinning the label to the top of the reserved band keeps it clear of the ink
   and lets the mark reach the name, so the band now has to hold both. */
.request-print-page .rf-approvedby {
  padding-top: 42px;
}
.request-print-page .rf-approvedby em {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  margin: 0;
  line-height: 16px;
}
.request-print-page .rf-approval-sig {
  border-bottom: 0;
}
/* The head block's rule. The container is display:block for the overlay, so the
   base rule's align-self:stretch no longer reaches it and an empty inline ::after
   has no width to paint on - it has to be a block box to draw at all. */
.request-print-page .rf-approval-sig::after {
  display: block;
}
.request-print-page .rf-approvedby strong {
  display: inline-block;
  position: relative;
  z-index: 1;
  padding: 0 10px 3px;
  font-size: 13px;
  /* No border here on purpose: .rf-sigline below is the rule the name is signed
     on, and two borders this close together read as one thick smudged line. */
}
.request-print-page .rf-headsig,
.request-print-page .rf-imosig {
  position: absolute;
  z-index: 2;
  left: 50%;
  top: 0;
  transform: translateX(-50%);
  order: 0;                 /* was -1, which stacked it above the name */
  display: block;
  width: 150px;
  max-width: 100%;
  height: 42px;
  max-height: 42px;
  margin: 0;
  background: transparent;
  pointer-events: none;
  user-select: none;
}
/* Down from top:0, which put the mark in the band above the name where the
   label now lives: 42px of padding, less the 16px the label holds, leaves the
   mark starting at 20px and ending on the rule - ink over the name, resting on
   the line, clear of both the label above and the role below. */
.request-print-page .rf-imosig { width: 165px; height: 46px; max-height: 46px; top: 20px; }
.request-print-page .rf-headsig > svg,
.request-print-page .rf-imosig > svg,
.request-print-page .rf-headsig img,
.request-print-page .rf-imosig img {
  display: block;
  width: 100%;
  height: 100%;
  max-width: 100%;
  max-height: 100%;
  margin: 0;
  object-fit: contain;
  object-position: center bottom;
}
/* The instruction line is gone: the mark is now genuinely over the name, so
   printing the words "Signature Over Printed Name" underneath it was both
   redundant and wrong. */
.request-print-page .rf-approval-sig em { display: none; }
/* The rule the name is signed on, and the role beneath it. This is the line
   that had gone missing: zeroing its border left the block with no line at all,
   because the name's own border had been taken away in favour of this one. */
.request-print-page .rf-sigline {
  display: block;
  border-top: 1px solid #111;
  margin: 3px 0;
}
.request-print-page .rf-approvedby small { display: block; font-style: italic; font-size: 10px; }

/* The two approval blocks must not be split by a page break, or the mark ends up
   on one sheet and the name it signs on the next. break-inside is the modern
   property; page-break-inside is kept for engines that still honour it. */
.request-print-page .rf-approval,
.request-print-page .rf-approvedby,
.request-print-page .rf-action-right,
.rd-sig {
  break-inside: avoid;
  page-break-inside: avoid;
}

/* ==================================================================
   STAFF RESPONSIVE LAYER - mobile first
   ==================================================================
   Scope. Every selector below carries `.app-shell:has(> .topnav)` or sits
   under `.topnav` itself, because that is how this stylesheet already
   separates the two roles: navbar.php hands staff over to
   includes/staff-topnav.php and returns before any sidebar markup, so a staff
   document has a <header class="topnav"> as a direct child of the shell and
   an admin document never does. No rule here can reach an admin page.

   Order. The declarations with no media query are the phone layout
   (320-767px), and each min-width block only hands back what the phone took
   away: 768px is the tablet, 1024px the original desktop sizing, 1151px the
   original desktop gutter. The rest of this file is desktop-first, so this
   block is appended rather than edited in place - at equal specificity the
   later rule wins, and the prefix gives these a higher specificity than the
   unprefixed rules they answer to.

   Breakpoints here are the brief's, not this file's. The header itself
   collapses at 1150px (a pinned, JS-mirrored number) and that is left alone;
   what changes below is what the content does while the header is collapsed.

   The gutter uses `padding-inline` rather than `padding` because the parity
   assertion between the header's inner padding and the content column is
   pinned against `.topnav-inner` and `.app-shell:has(> .topnav) .content` as
   literal selectors, and a logical property is outside what
   tools/css_cascade.php models. It changes the rendering without pretending
   to answer a question about `padding` or `padding-left`, and the values it
   produces are the ones those tests expect: 24px wide, 18px at 1150, equal on
   both elements at 560.
   ================================================================== */

/* ---- page gutter -------------------------------------------------------
   16px of horizontal padding on a phone, and the header card steps with it so
   the brand keeps lining up with the page text. Neither element may be changed
   without the other: they are one measure. */
.app-shell:has(> .topnav) .content { padding-inline: 16px; }
.topnav-inner { padding-inline: 16px; }

@media (min-width: 768px) {
  .app-shell:has(> .topnav) .content { padding-inline: 18px; }
  .topnav-inner { padding-inline: 18px; }
}

@media (min-width: 1151px) {
  .app-shell:has(> .topnav) .content { padding-inline: 24px; }
  .topnav-inner { padding-inline: 24px; }
}

/* ---- header controls at thumb size ------------------------------------
   A 32px bell and a 38px burger are comfortable for a pointer and not for a
   thumb. Below the desktop breakpoint everything in the header that is meant
   to be pressed is 44px on a side; above it the original sizes come back, so
   the desktop header is byte-for-byte what it was. */
.app-shell:has(> .topnav) .topnav-burger { width: 44px; height: 44px; }
.app-shell:has(> .topnav) .topnav-right .icon-btn { width: 44px; height: 44px; }
.topnav .topnav-user-btn { min-height: 44px; }
.topnav .topnav-user-item { padding: 13px 11px; }
.topnav-nav .topnav-link { min-height: 44px; }

@media (min-width: 1024px) {
  .app-shell:has(> .topnav) .topnav-burger { width: 38px; height: 38px; }
  .app-shell:has(> .topnav) .topnav-right .icon-btn { width: 32px; height: 32px; }
  .topnav .topnav-user-btn { min-height: 0; }
  .topnav .topnav-user-item { padding: 9px 11px; }
  .topnav-nav .topnav-link { min-height: 0; }
}

/* ---- the form picker may not be squeezed ------------------------------
   .content is a column of flex items and .page-header and .um-panel both
   declare `flex: 0 0 auto`, so when the column is over-full the whole squeeze
   lands on the one item between them. .um-tabs sets `overflow-y: hidden` for
   its horizontal scrollbar, which zeroes its automatic minimum size as well,
   and the result is a 15px-tall row clipping two 38px tabs out of existence.
   Giving it a basis of its own sends the overflow where it belongs: onto
   .content, which is the scrollport. */
.app-shell:has(> .topnav) .content > .um-tabs { flex: 0 0 auto; }

/* ---- buttons sized for a thumb -----------------------------------------
   One rule covers .btn-sm as well - a "Reset" that only fits a mouse is worse
   than a large one. The floor is dropped again at the desktop breakpoint,
   where a touch is not what the control is being asked to survive.

   The selector asks the question from body rather than from the shell because
   the shared confirmation dialog is a *sibling* of .app-shell, not a child of
   it: header.php opens #toast-stack and #confirm-modal before the shell starts,
   so the shell prefix stops short of them and the Cancel button would be the
   one 35px control left on the page. `body:has(> .app-shell > .topnav)` is the
   same role test seen from the outside, and it cannot match an admin page,
   which has no .topnav anywhere. */
body:has(> .app-shell > .topnav) .btn { min-height: 44px; }

@media (min-width: 1024px) {
  body:has(> .app-shell > .topnav) .btn { min-height: 0; }
}

/* ---- forms: one column by hand, two when the screen allows -------------
   The global `max-width: 1024px` block collapses every grid in the app to a
   single column, which is right for a phone and wasteful at tablet width. The
   columns come back at 768px, where two paired fields still have room for
   real values, and .grid-2 with them so the profile cards sit side by side
   again instead of stacking through the tablet range. */
.app-shell:has(> .topnav) .form-grid { grid-template-columns: minmax(0, 1fr); }
.app-shell:has(> .topnav) .form-grid-3 { grid-template-columns: minmax(0, 1fr); }
.app-shell:has(> .topnav) .form-grid-name-row { grid-template-columns: minmax(0, 1fr); }
.app-shell:has(> .topnav) .grid-2 { grid-template-columns: minmax(0, 1fr); }

@media (min-width: 768px) {
  .app-shell:has(> .topnav) .form-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }
  .app-shell:has(> .topnav) .form-grid-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .app-shell:has(> .topnav) .form-grid-name-row {
    grid-template-columns: minmax(0, .6fr) minmax(0, .6fr) minmax(0, 1fr);
  }
  .app-shell:has(> .topnav) .grid-2 {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }
}

/* ---- cards, headers and dialogs ----------------------------------------
   Nothing clamps itself on a phone. .card-header is `flex-wrap: nowrap` with
   a heading and a button that stop fitting around 340px; .modal-actions puts
   every action in one unwrapped row; and .modal's 22px of padding is a
   desktop amount of air that costs a narrow dialog its width. */
.app-shell:has(> .topnav) .card-header { flex-wrap: wrap; }
.app-shell:has(> .topnav) .modal { padding: 16px; }
.app-shell:has(> .topnav) .modal-actions { flex-wrap: wrap; }

@media (min-width: 768px) {
  .app-shell:has(> .topnav) .card-header { flex-wrap: nowrap; }
  .app-shell:has(> .topnav) .modal { padding: 22px; }
  .app-shell:has(> .topnav) .modal-actions { flex-wrap: nowrap; }
}

/* ---- table headers ------------------------------------------------------
   11.5px uppercase is a header size chosen for a screen that has room to
   spare; below the desktop breakpoint it is simply small. */
.app-shell:has(> .topnav) .table th { font-size: 12px; }

@media (min-width: 1024px) {
  .app-shell:has(> .topnav) .table th { font-size: 11.5px; }
}

/* ---- request details ----------------------------------------------------
   This page shares its sheet, its stepper and its cards with the admin copy
   through assets/css/request-details.css, so every rule below is scoped to
   the staff shell rather than written into that file.

   .rd-form-inline-head is the one that overflows. Its label is `flex: 0 0
   auto`, which means it refuses to shrink below its own widest word, so on a
   phone a label like "DEPARTMENT / DIVISION:" claims 274px of a 261px row and
   the value it sits beside is left with 8px - a column of characters, one
   per line. Stacking them gives the label the full width instead of a fight
   for it, and the ruled value reads as the field it is.

   The stepper's labels are `white-space: nowrap` inside five equal grid
   tracks. At 131px a track (768px) the longest of them still fits; below
   that it does not, and because nowrap forbids the break the labels just
   spill sideways into each other. Wrapping costs two lines and nothing else. */
.app-shell:has(> .topnav) .rd-card-body { padding: 16px; }
.app-shell:has(> .topnav) .rd-card-header { padding: 16px 14px 12px; }
.app-shell:has(> .topnav) .rd-form-inline-head {
  flex-direction: column;
  align-items: stretch;
  gap: 4px;
}
.app-shell:has(> .topnav) .rd-tl-label { white-space: normal; }

@media (min-width: 768px) {
  .app-shell:has(> .topnav) .rd-card-body { padding: 22px; }
  .app-shell:has(> .topnav) .rd-card-header { padding: 22px 24px 18px; }
  .app-shell:has(> .topnav) .rd-form-inline-head {
    flex-direction: row;
    align-items: baseline;
    gap: 8px;
  }
  .app-shell:has(> .topnav) .rd-tl-label { white-space: nowrap; }
}


