/* MEDTRANS — the shared layer.
   Three screens ship in this app: the crew checkout, Fleet Command, and the
   portal sign-in. They were built at different times and it shows — the
   checkout had nineteen keyframes and a full easing scale, Fleet Command had
   two, the portal had one and no focus states at all. That is what makes an
   app feel like modules bolted together rather than one system: not the
   colours, which already matched, but the fact that a button in one place
   answers your finger differently than the same button somewhere else.

   Everything here is shared vocabulary — timing, easing, focus, press, entry.
   Page-specific styling stays in the page. Nothing in this file targets an
   element by name, so it can be dropped into any of the three without
   fighting what is already there. */

:root{
  /* One motion scale for the whole product. Named for what they are for, not
     for how long they last, so a later retune stays consistent everywhere. */
  --ez-out:cubic-bezier(.22,1,.36,1);      /* the default: fast out, settles  */
  --ez-pop:cubic-bezier(.34,1.45,.6,1);    /* arrival with a little overshoot */
  --ez-in-out:cubic-bezier(.65,0,.35,1);   /* symmetrical, for things that move both ways */
  --dur-1:140ms;   /* press, hover, colour — must not be perceptible as motion */
  --dur-2:240ms;   /* panels, chips, rows arriving                             */
  --dur-3:420ms;   /* screens, sheets, anything the eye should follow          */
  --lift:0 1px 2px rgba(15,23,42,.06), 0 4px 14px rgba(15,23,42,.07);
  --lift-lg:0 2px 6px rgba(15,23,42,.08), 0 18px 40px rgba(15,23,42,.10);
}

/* ---- focus -------------------------------------------------------------
   A keyboard ring on every interactive thing, drawn outside the element so it
   never nudges layout. :focus-visible rather than :focus so a mouse press does
   not light it up. This was missing across all three screens; on a tablet it
   costs nothing and on a desk it is the difference between usable and not. */
:where(a,button,input,select,textarea,[tabindex],[role="button"]):focus-visible{
  outline:2px solid var(--brand,#c8202e);
  outline-offset:2px;
  border-radius:inherit;
}
:where(button,[role="button"])::-moz-focus-inner{border:0}

/* ---- the press ---------------------------------------------------------
   Every control gives the same 2% under the finger. Consistency here is most
   of what "responsive" means — the hand learns one answer and gets it back
   everywhere. Anything that opts out sets its own transform. */
:where(button,[role="button"],.click){
  transition:transform var(--dur-1) var(--ez-out),
             background var(--dur-1) var(--ez-out),
             border-color var(--dur-1) var(--ez-out),
             color var(--dur-1) var(--ez-out),
             box-shadow var(--dur-2) var(--ez-out);
}
:where(button,[role="button"],.click):active:not(:disabled){transform:scale(.98)}
:where(button,[role="button"]):disabled{cursor:not-allowed}

/* ---- arrival -----------------------------------------------------------
   Data that appears should arrive, not blink into place. Rows carry --i so a
   list settles in sequence; the stagger is capped so a long list never turns
   into a wait. */
@keyframes mt-rise{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
@keyframes mt-fade{from{opacity:0}to{opacity:1}}
@keyframes mt-pop{0%{transform:scale(.92);opacity:0}100%{transform:scale(1);opacity:1}}
@keyframes mt-shimmer{100%{background-position:200% 0}}

.mt-rise{animation:mt-rise var(--dur-2) var(--ez-out) both;
  animation-delay:calc(min(var(--i,0),12) * 22ms)}
.mt-fade{animation:mt-fade var(--dur-2) var(--ez-out) both}
.mt-pop{animation:mt-pop var(--dur-2) var(--ez-pop) both}

/* ---- loading -----------------------------------------------------------
   A skeleton that says "this is coming" beats a spinner that says "something
   is happening somewhere". Sized by the caller. */
.mt-skel{
  background:linear-gradient(90deg,
    var(--soft,rgba(15,23,42,.05)) 25%,
    var(--line,rgba(15,23,42,.10)) 37%,
    var(--soft,rgba(15,23,42,.05)) 63%);
  background-size:200% 100%;
  animation:mt-shimmer 1.4s linear infinite;
  border-radius:8px;
}

/* ---- empty states ------------------------------------------------------
   An empty list should read as a settled answer, not a missing one. */
.mt-empty{
  padding:22px 16px;text-align:center;color:var(--muted,#5b6470);
  font-size:13px;line-height:1.5;
}

/* ---- reduced motion ----------------------------------------------------
   Honoured product-wide, not per page. Motion is removed; the states it was
   communicating are not — everything above also reads through colour, weight
   and position with the animation stripped out. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
    scroll-behavior:auto !important;
  }
}

/* ---- no stray horizontal scrollbar --------------------------------------
   Entry animations translate elements a few pixels before they settle. Those
   pixels push past the viewport for a frame, the page grows a horizontal
   scrollbar, the scrollbar shrinks the viewport, and the next frame does it
   again — a bar that appears, slides and disappears on its own. Nothing in any
   of these screens is meant to sit outside the page horizontally, so clamp it.
   Vertical scrolling is untouched. */
html{overflow-x:hidden}
body{overflow-x:clip}

/* ---- dark, once, for all three screens ----------------------------------
   The checkout, Fleet Command and the portal each handled dark differently —
   two palettes keyed to different selectors and one screen with none at all.
   All three toggle body.dark, so that is what this keys to. */

/* Brand red at full saturation is correct on white and shouts on near-black:
   the same hue that reads as authoritative in daylight reads as an alarm at
   2 AM. Pull it back for dark only — still unmistakably the brand, no longer
   the brightest thing on a screen someone is reading in a dim rig. */
body.dark{
  --brand:#d8323d;          /* was #e11420 — same hue, less glare */
  --brand-hot:#e84b55;      /* was #ff2b38 — hover, not a siren   */
}

/* Status colours: keep hue, drop the glare. On a dark surface a saturated
   fill reads brighter than the same fill on white, so soft backgrounds get
   thinner and rings get quieter — the state still reads, it just stops
   competing with the text sitting on top of it. */
body.dark{
  --ok-soft:rgba(90,169,232,.11);   --ok-ring:rgba(90,169,232,.30);
  --bad-soft:rgba(241,109,109,.11); --bad-ring:rgba(241,109,109,.30);
  --warn-soft:rgba(224,163,68,.11); --warn-ring:rgba(224,163,68,.30);
}

/* The portal had no dark mode at all — a white sign-in page at the start of a
   night shift, before the crew reaches anything that respects the setting. */
body.dark{
  --page:#0f1319; --card:#171b22; --sunk:#13161c; --soft:#1c212a;
  --line:#262b33; --line2:#333a44;
  --ink:#eef1f5; --ink2:#c3cad3; --muted:#98a1ad; --dim:#6f7884;
}
/* The company logos are never recoloured. This used to force any image with
   "logo" or "wordmark" in its name to solid white in dark mode
   (brightness(0) invert(1)) on the assumption they were dark ink on
   transparent. They are not — the Medtrans marks are brand red, which reads
   correctly on both grounds. The filter was flattening the brand to a white
   smudge, which is exactly what it looked like. Leave the marks alone. */
body.dark img[src*="wordmark"],
body.dark img[src*="logo"],
body.dark img[src*="emblem"],
body.dark img[src*="mark"]{filter:none}

/* The nav bar is a solid brand-red band across the top. On white that reads as
   the product's signature; on near-black at 2 AM it is a glowing stripe that
   pulls the eye away from the checklist every time you look up. Darken the band
   itself in dark mode — the colour is still unmistakably ours, it just stops
   being the brightest object on the screen. Text stays white, so contrast is
   unchanged. */
body.dark .navbar,
body.dark nav.navbar{
  background:linear-gradient(180deg,#8e1219,#6f0e14) !important;
  border-bottom:1px solid rgba(255,255,255,.06);
}
body.dark .navitem.on,
body.dark .navitem[aria-current="page"]{background:rgba(0,0,0,.28)}

/* ---- Fleet Command board, night ----------------------------------------
   Expanded lines and the station header they sit under were rendering on the
   same tone, so a header stopped reading as a header the moment a station was
   opened — you lose your place in a list of seventy-two. Two changes, both
   tonal rather than another border: the open station header sits slightly
   raised, its lines slightly sunk beneath it. In daylight the borders alone
   carried this; on a dark surface a hairline is nearly invisible and tone is
   what the eye actually reads. */
body.dark .board .row{background:rgba(0,0,0,.22)}
body.dark .board .row:hover{background:rgba(255,255,255,.035)}
body.dark .stn.open{background:rgba(255,255,255,.045)}
body.dark .stn:hover{background:rgba(255,255,255,.03)}
body.dark .rowhead{background:rgba(0,0,0,.30)}

/* Status lamps carry meaning that colour alone should not have to: on a dim
   screen a small red and a small grey dot are the same dot. Give the two that
   mean something a ring so they read by shape as well as hue. */
body.dark .lamp.late{box-shadow:0 0 0 2px rgba(241,109,109,.28)}
body.dark .lamp.warn{box-shadow:0 0 0 2px rgba(224,163,68,.28)}

/* ---- touch --------------------------------------------------------------
   Applied on coarse pointers only, so a mouse keeps the tighter desktop
   spacing. 44px is the size a thumb hits reliably; the nav icons and the
   account button were 35–37px tall, which is fine with a cursor and a miss
   with a gloved hand beside a running ambulance. Padding rather than width, so
   nothing reflows — the target grows, the layout does not. */
@media (pointer:coarse){
  :where(button,a[href],[role="button"],select,summary){min-height:44px}
  :where(input[type="text"],input[type="date"],input[type="number"],
         input[type="password"],input[type="email"],textarea){
    min-height:44px;
    font-size:16px;   /* under 16px, iOS zooms the page on focus */
  }
  /* controls sitting shoulder to shoulder need room between them, not just size */
  :where(.seg,.pf,.filters,.navright){gap:8px}
}

/* ---- the portal had no breakpoints at all -------------------------------
   It is the first screen of a night shift and the only one a crew might open
   on a phone before anything else. */
@media (max-width:560px){
  .card,.panel,.box{border-radius:14px}
  .wrap,main,.panel{padding-left:14px;padding-right:14px}
  h1{font-size:20px}
}

/* a disabled Begin explains itself under the button rather than in a tooltip
   nobody hovers on a tablet */
#begin[data-need]:not([data-need=""])::after{
  content:"Still needed: " attr(data-need);
  display:block;margin-top:7px;font-size:11.5px;font-weight:600;opacity:.75;
  text-transform:none;letter-spacing:0;
}

/* Confidentiality line: grey text at the foot of the page. Nothing else. */
/* 9px at 40% opacity was not a quiet confidentiality line, it was an
   unreadable one -- and this particular sentence ("Not a PHI system") is the
   one a compliance reviewer will actually want to read. Still the quietest
   thing on the page, just legible now. */
.mt-legal{
  margin:28px 0 0;padding:0 18px 18px;
  text-align:center;font-size:10.5px;line-height:1.55;letter-spacing:.3px;
  color:var(--dim,#9aa1ab);opacity:.62;
}
