/* ============================================================================
   mobile.css - shared mobile atoms
   ----------------------------------------------------------------------------
   Contract section 7. These atoms live inside `.view-mobile`, which layout.css
   renders as a centred column capped at var(--mobile-max). Nothing here may
   assume a fixed 390px viewport: every width is fluid, every horizontal metric
   comes from a spacing token, and the row atoms truncate instead of overflowing.

   The prototype's 390x844 device-frame mockup (.phone / .notch / .statusbar /
   .pinner / .sb-*) and its stray base `.tab` copy are deliberately absent -
   they were scaffolding for a pitch-deck screenshot, not app UI. Screen-specific
   mobile blocks (hero, snap, qact, mgrid, mtile, onshift) live in
   assets/css/screens/home.css.

   Motion follows components.css: colour and border on --t-fast, transforms on
   --t-base, the stepper's rail fill on --t-slow, --ease-spring only on the
   transform channel of a hover or selection. Touch is the primary input here,
   so pressed states (:active) matter more than hover: every tappable atom
   gives back a visible press on --t-fast, and hover lifts are gated behind
   (hover: hover) so a tap never leaves a phantom hover state behind.

   Nothing in this file changes a colour, a border, a shadow or a transform
   without a transition covering that exact property. A press that snaps and
   then eases back out is worse than one that never moved, so the :active rules
   below re-time the SAME property list on --t-fast rather than adding a
   shorthand that would drop a channel.

   Touch targets: contract section 4.5 puts the floor at 44px. .mbtn is 48,
   .dpill and the tappable .prow are pinned to 44, and .step buys its 44 with
   padding so the wizard rail keeps its slim look while the hit box grows.

   Safe area: this file owns the TOP inset, because .phead is the first thing
   under the notch on every mobile screen that has one. The bottom inset belongs
   to layout.css (--bottombar-safe) and must not be paid twice.
   ========================================================================== */


/* ---------------------------------------------------------------------------
   1. Page head - the mobile screen header
   ------------------------------------------------------------------------ */

/* A column, so a title row, a search field and a chip strip stack with one
   consistent gap instead of each child carrying its own margin-top. */
.phead {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding: var(--s-2) var(--s-5) var(--s-4);
  background: var(--white);
}

/* The notch inset, paid exactly once. index.html carries viewport-fit=cover so
   the WebView reaches under the status bar, which means the top of the first
   element on the screen is under it too and the screen title sits behind the
   clock. --safe-t is 0px in a desktop browser and on every phone without an
   inset, so this is arithmetic that costs nothing when there is nothing to pay.

   Scoped to the top of the mobile column on purpose: Home puts its hero above
   the head, and a .phead further down the page is not under the notch.

   The second selector is the Access screen, which wraps its head in a master
   pane. Its head is just as much under the notch as any other, and without the
   second line it was the one screen that paid nothing and let the cream ground
   show through beneath the clock. */
.view-mobile > .phead:first-child,
.view-mobile > :first-child > .phead:first-child {
  padding-top: calc(var(--s-2) + var(--safe-t));
}

/* Same landscape side insets as .pbody, so the head and the body under it keep
   a single gutter no matter which way the phone is held. */
.phead {
  padding-left: calc(var(--s-5) + var(--safe-l));
  padding-right: calc(var(--s-5) + var(--safe-r));
}

/* Only the screens that butt a scrolling body straight up against the head
   need the hairline; Home's hero supplies its own edge. */
.phead--bordered {
  border-bottom: 1px solid var(--gray-200);
}

/* Matches whichever heading level the partial uses - the mobile view may carry
   the screen's h1 or a section-level h2 depending on the screen. */
.phead :is(h1, h2) {
  margin: 0;
  font-family: var(--f-disp);
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.15;
  color: var(--ink);
}

/* Title on the left, icon actions on the right. */
.phead-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  min-width: 0;
}

/* The count belongs to the title. With the palette launcher appended at the
   end, space-between parked the pill in the middle of the row; an auto margin
   keeps it beside the h1 and pushes everything after it to the right. */
.phead-row > h1 + .pill {
  margin-right: auto;
}


/* ---------------------------------------------------------------------------
   2. Page body - the mobile content column
   ------------------------------------------------------------------------ */

/* No overflow or height clamp: on mobile the window is the scroller, so this
   pane simply grows. min-width:0 keeps long unbroken strings (URLs, hostnames)
   from forcing the column wider than var(--mobile-max).
   Bottom-bar clearance is owned by layout.css - never add it here as well. */
.pbody {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding: var(--s-4);
  /* The landscape side insets, added to the gutter rather than replacing it.
     Both are 0px in portrait and on every desktop, and today the centred column
     (max-width var(--mobile-max), margin-inline auto in layout.css) is usually
     wide of the cutout anyway. They are written here so that a full-bleed
     mobile screen, or a Median tablet build that lets the column run wider,
     inherits the correct gutter instead of rediscovering env() locally. */
  padding-left: calc(var(--s-4) + var(--safe-l));
  padding-right: calc(var(--s-4) + var(--safe-r));
}

/* Clearance for a floating action button, and only where one exists. The
   button is position:fixed, so it takes no space of its own: without this the
   last row of the list can never be scrolled out from under it. Clients,
   Inventory and Shifts each wrote their own copy of this with a literal 68px;
   the token says the same thing in terms of the button it is clearing, so
   changing the button size can no longer leave three stale numbers behind.
   Screens with no such button are deliberately left alone, because the empty
   strip it reserves is dead space when nothing floats above it. */
.pbody.has-fab {
  padding-bottom: calc(var(--s-4) + var(--fab-clear));
}


/* ---------------------------------------------------------------------------
   3. Section title - a group header carrying a count pill
   ------------------------------------------------------------------------ */

/* Written for a real heading element, hence the margin reset. Uppercasing is
   done here so the data layer can hold normal-case labels ("Morning").
   A small-caps label: 600 rather than 700, and the wide .08em tracking that
   uppercase needs to breathe. */
.sec-t {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin: 0;
  font-family: var(--f-ui);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

/* The count. Its ground eases if JS recolours it in place; when a screen
   re-renders the heading (Schedule does, on every day switch) the pill is a
   new node, so it also fades in rather than popping. */
.sec-t .pill {
  height: 18px;
  font-size: 10px;
  letter-spacing: 0;
  transition: background var(--t-fast), color var(--t-fast);
  animation: fade-in var(--t-base) both;
}


/* ---------------------------------------------------------------------------
   4. Property / person row
   ------------------------------------------------------------------------ */

/* FIX: the prototype re-declared .card's surface by hand and hardcoded a 12px
   radius. This is the row-shaped sibling of .card, driven by the same tokens,
   so `class="card prow"` and a bare `class="prow"` render identically - markup
   may compose or not without the two ever drifting apart. */
.prow {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  width: 100%;
  min-width: 0;
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--gray-200);
  border-radius: var(--r);
  background: var(--white);
  box-shadow: var(--sh-sm);
  /* Neutral resets so the same atom can render as div, anchor or button. */
  font: inherit;
  color: inherit;
  text-align: left;
  text-decoration: none;
  appearance: none;
  transition:
    transform var(--t-base),
    background var(--t-fast),
    border-color var(--t-fast),
    box-shadow var(--t-base);
}

/* FIX: .p-m already claims the free space with flex:1, so the old
   `.p-tail{margin-left:auto}` had nothing left to push against. One mechanism
   only - the middle grows, the tail stays intrinsic. */
.prow .p-m {
  flex: 1;
  min-width: 0;
  line-height: 1.3;
}

.prow .p-m b {
  display: block;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  /* The column can be as narrow as ~290px; long property names truncate. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The secondary meta line under the row title.
 *
 * SCOPE MATTERS HERE MORE THAN THE THREE DECLARATIONS DO.
 * This was written as `.prow .p-m span`, which caught every span anywhere
 * inside the middle column, chips and badges included. A chip is an inline
 * atom whose whole job is to be exactly as wide as its label; forced to
 * display:block it stretches the full width of the card and stops looking like
 * a chip at all. That is what made the Clients list unreadable on a phone on
 * 11 September 2026: "Active", "1 high" and "1 SLA" each took a full row as a
 * coloured bar. The screen was blamed, and the screen was innocent.
 *
 * Two changes keep it honest: direct children only, so nothing nested inside a
 * chip is reached, and an explicit exemption for the inline atoms themselves,
 * because this selector outranks their own class rules on specificity and
 * would otherwise win an argument it should never have been in.
 */
.prow .p-m > span:not(.bdg, .tag, .pill, .chip, .fchip, .av) {
  display: block;
  font-size: 12px;
  color: var(--muted);
}

.prow .p-tail {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--s-1);
  font-size: 12px;
  color: var(--muted);
  text-align: right;
}

/* Only genuinely tappable rows (the Access master list) get affordances. The
   element selector means no extra class has to be threaded through markup.

   min-height is the contract's 44px floor (section 4.5). A two-line row already
   measures about 58px, but a single-line one (a client with no subtitle, an
   empty group) came out at 41px and was the one row on the screen that was hard
   to hit. The floor makes every tappable row the same size to the thumb. */
a.prow,
button.prow {
  min-height: 44px;
  cursor: pointer;
}

a.prow:hover,
button.prow:hover {
  border-color: var(--gray-300);
  box-shadow: var(--sh-md);
}

/* The lift is a pointer-only affordance. On touch, :hover would stick to the
   last tapped row and leave it floating; the press below is the touch answer. */
@media (hover: hover) {
  a.prow:hover,
  button.prow:hover {
    transform: translateY(var(--lift));
    transition-timing-function: var(--ease-spring), var(--ease-out), var(--ease-out), var(--ease-out);
  }
}

/* Touch feedback: a faint canvas tint while the finger is down, and the row
   settles back to rest so the press reads as contact, not as a bounce. */
a.prow:active,
button.prow:active {
  background: var(--gray-50);
  transform: translateY(0);
  box-shadow: var(--sh-sm);
  transition:
    transform var(--t-fast),
    background var(--t-fast),
    border-color var(--t-fast),
    box-shadow var(--t-fast);
}

.prow.is-selected {
  border-color: var(--gold-600);
  box-shadow: var(--sh-md);
}

a.prow:focus-visible,
button.prow:focus-visible {
  box-shadow: var(--focus-ring);
}


/* ---------------------------------------------------------------------------
   5. Banner - a single-line inline notice
   ------------------------------------------------------------------------ */

/* Soft gold ground, gold text, a gold hairline. It arrives with the roster it
   belongs to, so it fades in on its own rather than popping into the column. */
.banner {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--gold-300);
  border-radius: var(--r);
  background: var(--gold-100);
  font-size: 13px;
  line-height: 1.35;
  color: var(--gold-700);
  animation: fade-in var(--t-base) both;
}

.banner b {
  font-weight: 600;
  color: var(--navy-900);
}

.banner .ic {
  color: var(--gold-600);
}


/* ---------------------------------------------------------------------------
   6. Date pills - the mobile schedule's day switcher
   ------------------------------------------------------------------------ */

/* Seven equal tracks that survive a 320px screen: flex-basis 0 plus min-width:0
   lets them shrink below their content width rather than overflow the column. */
.dpills {
  display: flex;
  gap: var(--s-2);
  min-width: 0;
}

.dpill {
  flex: 1 1 0;
  min-width: 0;
  min-height: 44px;
  padding: var(--s-2) var(--s-1);
  border: 0;
  border-radius: var(--r);
  background: var(--gray-100);
  font: inherit;
  text-align: center;
  cursor: pointer;
  transition:
    background var(--t-fast),
    color var(--t-fast),
    transform var(--t-base),
    box-shadow var(--t-base);
}

.dpill span {
  display: block;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--gray-600);
  transition: color var(--t-fast);
}

.dpill b {
  display: block;
  font-family: var(--f-disp);
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
  transition: color var(--t-fast);
}

.dpill:hover {
  background: var(--gray-200);
}

/* Pressed: a touch of compression on --t-fast, so the tap registers before
   the selection moves. */
.dpill:active {
  transform: scale(.97);
  transition: transform var(--t-fast), background var(--t-fast);
}

/* .is-on - a user-toggled selection, per the state-class convention. The
   selected day grows to 1.04 with the spring on its transform channel only;
   the navy ground still fades in on --t-fast. */
.dpill.is-on {
  background: var(--navy);
  box-shadow: var(--sh-sm);
  transform: scale(1.04);
  transition-timing-function: var(--ease-out), var(--ease-out), var(--ease-spring), var(--ease-out);
}

.dpill.is-on:hover {
  background: var(--navy);
}

.dpill.is-on span {
  color: var(--gray-400);
}

.dpill.is-on b {
  color: var(--gold);
}


/* ---------------------------------------------------------------------------
   7. Stepper - the mobile wizard progress rail
   ------------------------------------------------------------------------ */

.stepper {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  min-width: 0;
}

/* The 20px bullet plus a 12px label is a 20px-tall control, which is half the
   touch floor. Rather than inflate the bullet and lose the slim rail, the step
   pays for its hit box in vertical padding: 20 + 12 + 12 = 44. The rail sits
   in the middle of that box because .stepper centres its children, so the look
   is unchanged and only the thumb notices.

   box-shadow is in the transition list for the focus ring from base.css: a ring
   that appears instantly on a control whose colour fades is a visible seam. */
.step {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  min-width: 0;
  min-height: 44px;
  padding: var(--s-3) 0;
  border: 0;
  background: none;
  font-family: var(--f-ui);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  color: var(--muted);
  transition: color var(--t-fast), box-shadow var(--t-fast);
}

/* The numbered bullet. */
.step i {
  flex: none;
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--gray-200);
  font-family: var(--f-disp);
  font-size: 11px;
  font-style: normal;
  color: var(--ink);
  transition: background var(--t-fast), color var(--t-fast), transform var(--t-base);
}

/* Current step. */
.step.is-on {
  color: var(--ink);
}

.step.is-on i {
  background: var(--gold);
  color: var(--navy-900);
}

/* A step already completed - and therefore walkable back to. */
.step.is-done {
  color: var(--muted);
}

.step.is-done i {
  background: var(--gold-a30);
  color: var(--gold-700);
}

/* When a step is a real back-navigation button. */
button.step {
  cursor: pointer;
}

button.step:active i {
  transform: scale(.92);
  transition: transform var(--t-fast);
}

/* FIX: the prototype used height:1.5px, which the browser resolved to 1px or
   2px depending on device pixel ratio - the rail looked uneven between its two
   gaps on some phones. A whole even number renders identically everywhere.

   The rail is two layers: the grey track, and a gold fill drawn by ::before
   that scales in from the left. The fill is keyed off the step BEFORE the
   line (email.js renders step, line, step, line, step and toggles .is-done on
   completed steps), so advancing the wizard draws the segment on --t-slow and
   going back withdraws it the same way. */
.step-line {
  position: relative;
  flex: 1;
  min-width: var(--s-2);
  height: 2px;
  border-radius: 1px;
  background: var(--gray-200);
  overflow: hidden;
}

.step-line::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--gold);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--t-slow);
}

.step.is-done + .step-line::before {
  transform: scaleX(1);
}


/* ---------------------------------------------------------------------------
   8. Mobile button - full-width primary action
   Same press model as .btn in components.css: a 1px lift with the resting
   card shadow on hover, back to rest on press, no motion when disabled.
   Flat at rest, like .btn--gold: no gold halo under it (DESIGN.md 13).
   ------------------------------------------------------------------------ */

.mbtn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  width: 100%;
  min-height: 48px;
  padding: var(--s-3) var(--s-4);
  border: 0;
  border-radius: var(--r);
  background: var(--gold);
  font-family: var(--f-ui);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .005em;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  color: var(--navy-900);
  cursor: pointer;
  appearance: none;
  transition:
    background var(--t-fast),
    color var(--t-fast),
    box-shadow var(--t-base),
    transform var(--t-base);
}

.mbtn:hover {
  background: var(--gold-600);
  transform: translateY(-1px);
  box-shadow: var(--sh-sm);
}

.mbtn:active {
  transform: translateY(0);
  box-shadow: none;
  transition:
    background var(--t-fast),
    color var(--t-fast),
    box-shadow var(--t-fast),
    transform var(--t-fast);
}

/* Secondary weight: the same shape on the dark surface. */
.mbtn--dark {
  background: var(--navy);
  box-shadow: var(--sh-sm);
  color: var(--white);
}

.mbtn--dark:hover {
  background: var(--navy-600);
  box-shadow: var(--sh-md);
}

.mbtn--dark:active {
  box-shadow: var(--sh-sm);
}

/* Each of these declares its own box-shadow at (0,1,0) in a sheet that loads
   after base.css, so "Continue to compose", "Review" and "Back" had no visible
   focus mark at all. The pseudo-class is enough to win it back. */
.mbtn:focus-visible,
.mbtn--dark:focus-visible {
  box-shadow: var(--focus-ring);
}

/* Inert controls must look inert - the audit's complaint was that a disabled
   action was indistinguishable from a wired one. */
.mbtn:disabled,
.mbtn[aria-disabled="true"] {
  background: var(--gray-200);
  box-shadow: none;
  color: var(--gray-500);
  cursor: not-allowed;
}

.mbtn:disabled:hover,
.mbtn[aria-disabled="true"]:hover,
.mbtn:disabled:active,
.mbtn[aria-disabled="true"]:active {
  background: var(--gray-200);
  box-shadow: none;
  transform: none;
}
